docker desktop 修改镜像容器存储位置

docker desktop 进入配置页,里面有可以设置存储位置的配置项,不过这个配置对于用windows WSL 的客户端来说并不会生效,每次设置后都会被重新修改回默认项。

要想修改这个存储位置只能修改wsl的存储位置才行

首先查看当前安装的wsl

wsl -l -v

  NAME                   STATE           VERSION
* docker-desktop-data    Running         2
  docker-desktop         Running         2

关闭wsl

wsl --shutdown

导出desktop-data镜像

wsl --export docker-desktop-data "临时存储地址"

取消注册

wsl --unregister docker-desktop-data

导入备份并指定新路径

wsl --import docker-desktop-data "目标存储路径" "备份地址" --version 2

手撸的一个阶段编辑的组件

element-ui + vue2

效果如下

为自己点赞

<template>
  <div class="stage-container">
    <el-popover
      v-for="(stage) in stageList" :key="stage.id"
      width="200"
      trigger="hover"
    >
      <div slot="reference" :class="stageState(stage)" class="stage">
        <div class="stage-title">{{ stage.name }}</div>
        <div :class="stageState(stage)" class="stage-side stage-left"/>
        <div :class="stageState(stage)" class="stage-side stage-right"/>
      </div>
      <div class="label-list">
        <div v-for="(label) in stage.labels" :key="label.id">
          <el-link :underline="false" :type="labelState(label)" class="label" @click="selectLabel(label)">{{ label.name }}</el-link>
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script>
import { customerStages } from '@/api/admin/crm'
export default {
  props: {
    stageId: Number,
    stageLabelId: Number
  },
  data() {
    return {
      stageList: []
    }
  },
  computed: {
    stageState() {
      return stage => {
        if (!this.currentStage.order) {
          return 'not-active'
        }
        return stage.order > this.currentStage.order ? 'not-active' : ''
      }
    },
    labelState() {
      return label => {
        return this.stageLabelId == label.id ? 'primary' : 'info'
      }
    },
    currentStage() {
      for (const stage of this.stageList) {
        if (stage.id == this.stageId) {
          return stage
        }
      }
      return {}
    }
  },
  async mounted() {
    const res = await customerStages()
    this.stageList = res.data
  },
  methods: {
    selectLabel(label) {
      this.$emit('selectLabel', label)
    }
  }
}
</script>

<style lang="scss">
.stage-container {
  margin-left: 50px;
  display: flex;
}

.stage-side {
  height: 38px;
  width: 38px;
  top: 0px;
  position: absolute;
  transform: rotate(45deg) scale(0.707);
  &.stage-left {
    z-index: 5;
    left: -19px;
    background-color: white;
  }
  &.stage-right {
    z-index: 10;
    right: -18px;
    background-color: $xr-color-primary;
  }
  &.not-active {
    background-color: white;
    border-top: 2px solid $xr-color-primary;
    border-right: 2px solid $xr-color-primary;
    top: -2px;
  }
}

.stage {
  color: #fff;
  position: relative;
  padding: 10px 20px 10px 37px;
  margin: 28px 2px;
  height: 38px;
  background-color: $xr-color-primary;
  cursor: pointer;
  &.not-active {
    color: $xr-color-primary;
    background-color: white;
    border-top: 2px solid $xr-color-primary;
    border-bottom: 2px solid $xr-color-primary;
  }
}

.label {
  padding: 5px;
  font-size: 13px;
  width: 100%;
}
</style>

随记

2022-12-28

clash 本地连接错误

修改profile 设置dns false

php版本切换(ubuntu)

安装apt install php8.1 php8.1-fpm
安装apt install php7.4 php7.4-fpm
update-alternatives — config php

systemctl start php7.4-fpm

/etc/nginx/conf.d/test.conf

        location ~ \.php$ {
                fastcgi_pass unix:/run/php/php8.1-fpm.sock;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
                include fastcgi_params;
        }

宝塔运行指定版本composer

php80 /www/server/php/80/bin/composer 

文档工具

mkdocs

生成随机id

uuid 雪花算法(php-snowflake)

du命令 du 命令用于显示文件或目录的磁盘使用情况。它会递归地显示指定文件或目录的大小,并可以按照不同的格式进行显示。常用的选项包括: -h:以人类可读的格式显示大小(例如,K、M、G)。 -s:仅显示总大小,而不显示每个子目录的大小。 -c:同时显示所有目录的总大小

swoole redis连接池应用

遇到问题

有一个cli应用,需要很多协程频繁访问redis,用swoole的redis连接池实现链接;
但是遇到问题,发现内存很快溢出,第一反应是变量没释放,unset了半天没有解决;
然后通过

use Swoole\Coroutine;
$coros = Coroutine::listCoroutines();

定时查看了一下协程数量,发现协程缓慢在增加,慢慢的内存就溢出了。
限制了一下协程数量,扩充了一下连接池大小,挂起的协程数量明显减少了,但还是越来越多,猜测是从redis连接池获取连接的时候获取的连接不可用,然后一直挂起了。

解决方式

从连接池中取出连接后测试一下,可以使用再取出,不然push(null)让连接池生成一个新的,接着继续取,知道连接可用,这样处理后协程数量就一直不会一直增长了。

    protected function redisOperation($callback) {
        $connection = $this->pool->get();
        while(!$connection->ping()) {
            $this->pool->put(null);
            $connection = $this->pool->get();
        }
        $result = call_user_func($callback, $connection);
        $this->pool->put($connection);
        return $result;
    }

问题顺利解决,撒花

git pull/push 速度慢

问题:

windows环境下,不知道为什么最近gitpush和pull速度很慢,经常连接超时;

解决方案:

搜了一下解决方案,大概记录一下

~/.ssh/config

Host github.com *.github.com *.codeup.aliyun.com
    User git
    # SSH默认端口22,git://, HTTPS默认端口443,https://
    Port 22
    Hostname %h
    # 这里放你的SSH私钥
    IdentityFile ~\.ssh\id_rsa
    # 设置代理, 127.0.0.1:10808 换成你自己代理软件监听的本地地址
    # HTTPS使用-H,SOCKS使用-S
    ProxyCommand connect -S 127.0.0.1:10808 %h %p

需要用到connect客户端
connect
解压exe文件后放到C:\Windows\System32目录下面

linux下编译安装php8

下载:

https://www.php.net/downloads

configure

从宝塔安装的php看下通用的一些扩展编译参数
# php -i |grep configure

./configure 
--prefix=/www/server/php/74  --with-config-file-path=/www/server/php/74/etc  --enable-fpm  --with-fpm-user=www  --with-fpm-group=www  --enable-mysqlnd  --with-mysqli=mysqlnd  --with-pdo-mysql=mysqlnd  --with-iconv-dir  --with-freetype  --with-jpeg  --with-zlib  --with-libxml-dir=/usr  --enable-xml  --disable-rpath  --enable-bcmath  --enable-shmop  --enable-sysvsem  --enable-inline-optimization  --with-curl  --enable-mbregex  --enable-mbstring  --enable-intl  --enable-ftp  --enable-gd  --with-openssl  --with-mhash  --enable-pcntl  --enable-sockets  --with-xmlrpc  --enable-soap  --with-gettext  --disable-fileinfo  --enable-opcache  --with-sodium  --with-webp

稍微修改以下

--prefix=/usr/local/php/81 --with-config-file-path=/usr/local/php/81/etc  --enable-fpm  --with-fpm-user=www  --with-fpm-group=www  --enable-mysqlnd  --with-mysqli=mysqlnd  --with-pdo-mysql=mysqlnd  --with-iconv-dir  --with-freetype  --with-jpeg  --with-zlib  --with-libxml-dir=/usr  --enable-xml  --disable-rpath  --enable-bcmath  --enable-shmop  --enable-sysvsem  --enable-inline-optimization  --with-curl  --enable-mbregex  --enable-mbstring  --enable-intl  --enable-ftp  --enable-gd  --with-openssl  --with-mhash  --enable-pcntl  --enable-sockets  --with-xmlrpc  --enable-soap  --with-gettext  --disable-fileinfo  --enable-opcache  --with-sodium  --with-webp

configure跑跑看缺什么就装对应软件

缺少 安装
libxml-2.0 libxml2-dev
libcurl libcurl4-openssl-dev
libpng libpng-dev
libwebp libwebp-dev
libjpeg libjpeg-dev
freetype2 libfreetype-dev
oniguruma libonig-dev
libsodium libsodium-dev

….

安装

执行make && make install

RFID卡号格式的常见样式

北京友我科技RFID读写器 转载请注明出处,本篇地址
http://www.youwokeji.com.cn/ywdn/NoteDetails.asp?id=11

由于各个厂家的读卡器译码格式不尽相同,在读卡输出时,读出的二进制或十六进制(Hex)结果应该是唯一的,但是又可以通过以下几种主要换算办法,输出不同结果的十进制卡号(Dec),因此,请您一定在购买卡片或卡片喷号时,注意卡号格式的一致性:

1、格式0:10位十六进制的ASCII字符串,即10 Hex格式。
如:某样卡读出十六进制卡号为:“01026f6c3a”。

2、格式1:将格式0中的后8位,转换为10位十进制卡号,即8H—10D。
即将“ 026f6c3a”转换为:“0040856634”。

此格式喷码喷码较为常见。

3、格式2:将格式0中的后6位,转换为8位十进制卡号,即6H—8D。
即将“ 6f6c3a”转换为:“07302202”。

4、格式3:将格式0中的倒数第5、第6位,转换为3位十进制卡号,再将后4位,转换为5位十进制卡号,中间用“,”分开,即“2H + 4H”。
即将2H“ 6f”转换为:“111”,4H “6c3a”转为“27706”。 最终将2段号连在一起输出为“111,27706”。

此格式为标准的韦根26(V26)格式,只使用最后6位编码,也有许多卡采用此格式喷码。

5、格式4:将格式0中后8位的前4位,转换为5位十进制卡号,再将后4位,转换为5位十进制卡号,中间用“,”分开,即“4Hex + 4Hec”。
照此推算结果为:00623,27706 (4H+4H)

BCC 异或校验 php实现

问题描述

对接一个硬件设备协议要求进行bcc校验,数据包是十六进制表示的,用php处理

实现方式

    public static function dec2hex($data, $wordLength) {
        return str_pad(dechex($data), $wordLength * 2, '0', STR_PAD_LEFT);
    }

    //十六进制数据生成bcc校验码(十六进制)
    public static function bcc($data) {
        $data = str_split($data, 2);
        $length = count($data);
        $result = intval($data[0], 16);
        for($i=0; $i<$length-1; $i++) {
            $result ^= intval($data[$i+1], 16);
        }
        return self::dec2hex($result, 1);
    }

其它

bcc校验工具

dcat admin 多文件上传

问题描述

需要解决dcat admin 表单多附件管理的(附件名和保存文件名分开保存)

解决方案

上传文件管理

  • 首先是新建上传文件表

    Schema::create('uploads', function (Blueprint $table) {
    $table->string('disk', 30)->comment('存储位置');
    $table->string('type', 20)->default('file')->comment('文件类型');
    $table->string('name', 150)->nullable()->comment('文件名称');
    $table->string('path', 150)->comment('文件路径');
    });
  • 新建上传文件用的路由

    $router->any('/upload/handle/{disk}/{dir}', 'UploadController@handle');
  • 上传处理

    public function handle($diskName, $dir) {
        $disk =$this->disk($diskName);
    
        // 判断是否是删除文件请求
        if ($this->isDeleteRequest()) {
            Upload::where('path', request()->key)->delete();
            // 删除文件并响应
            return $this->deleteFileAndResponse($disk);
        }
    
        // 获取上传的文件
        $file = $this->file();
        $newName =  Common::uniqueID().'.'.$file->getClientOriginalExtension();
        $result = $disk->putFileAs($dir, $file, $newName);
        $path = "{$dir}/$newName";
        $upload = new Upload;
        $upload->name = request()->name;
        $upload->path = $path;
        $upload->disk = $diskName;
        $upload->save();
    
        return $result
            ? $this->responseUploaded($path, $disk->url($path))
            : $this->responseErrorMessage('文件上传失败');
    }
  • 扩展字段

    class CustomMultiFile extends MultipleFile
    {
    protected function initialPreviewConfig()
    {
        $previews = [];
        foreach ($this->value() as $path => $name) {
            $previews[] = [
                'id'   => $path,
                'path' => Helper::basename($name),
                'url'  => $this->objectUrl($path),
            ];
        }
    
        return $previews;
    }
    }
  • 注册扩展字段

    Form::extend('customMultiFile', CustomMultiFile::class);
  • 表单字段

    $form->customMultiFile('attachment', '附件')->disk('public')
     ->url('upload/handle/public/attachment')
     ->autoUpload()->autoSave(false)
     ->removable(true)->limit(10);

codesignal practice 4

10

You are given an array of non-negative integers numbers. You are allowed to choose any number from this array and swap any two digits in it. If after the swap operation the number contains leading zeros, they can be omitted and not considered (eg: 010 will be considered just 10).

Your task is to check whether it is possible to apply the swap operation at most once, so that the elements of the resulting array are strictly increasing.

Example

For numbers = [1, 5, 10, 20], the output should be makeIncreasing(numbers) = true.

The initial array is already strictly increasing, so no actions are required.

For numbers = [1, 3, 900, 10], the output should be makeIncreasing(numbers) = true.

By choosing numbers[2] = 900 and swapping its first and third digits, the resulting number 009 is considered to be just 9. So the updated array will look like [1, 3, 9, 10], which is strictly increasing.

For numbers = [13, 31, 30], the output should be makeIncreasing(numbers) = false.

The initial array elements are not increasing.
By swapping the digits of numbers[0] = 13, the array becomes [31, 31, 30] which is not strictly increasing;
By swapping the digits of numbers[1] = 31, the array becomes [13, 13, 30] which is not strictly increasing;
By swapping the digits of numbers[2] = 30, the array becomes [13, 31, 3] which is not strictly increasing;
So, it's not possible to obtain a strictly increasing array, and the answer is false.

Input/Output

[execution time limit] 4 seconds (php)

[input] array.integer numbers

An array of non-negative integers.

Guaranteed constraints:
1 ≤ numbers.length ≤ 103,
0 ≤ numbers[i] ≤ 103.

[output] boolean

Return true if it is possible to obtain a strictly increasing array by applying the digit-swap operation at most once, and false otherwise.

function makeIncreasing($numbers) {
    $hasChanged = false;
    for($i=1; $i< count($numbers); $i++){
        if($numbers[$i] > $numbers[$i-1]){
            continue;
        }
        if($numbers[$i] < 10 && $numbers[$i-1]< 10){
            return false;
        }
        $before = $i >= 2 ? $numbers[$i-2] : 0; 
        if(swapNumberSuccess($before, $numbers[$i-1], $numbers[$i]) && (!$hasChanged)){
            $hasChanged = true;
            continue;
        }else{
            return false;
        }
    }
    return true;
}

function swapNumberSuccess($number0, $number1, $number2){
    echo $number1,',', $number2, PHP_EOL;
    if($number1 == 1000){
        $min_1 = 1;
    }elseif($number1/100 > 1){
        $d1=floor($number1/100);
        $d2=(floor($number1/10)%10);
        $d3=$number1%10;
        $d_min = min($d1, $d2, $d3);
        $d_max = max($d1, $d2, $d3);
        $d_mid = mid($d1, $d2, $d3, $d_min, $d_max);
        $min_1 = 100 * $d_min + 10 * $d_mid + $d_max;
        echo $d_min,',', $d_mid,',',$d_max, PHP_EOL;
    }elseif($number1/10 > 1){
        $d1= floor($number1/10);
        $d2= $number1%10;
        $min_1 = min($d1, $d2)*10 + max($d1, $d2);
    }else{
        $min_1 = $number1;
    }
    echo $min_1, PHP_EOL;
    if($min_1 < $number2 && $min_1 > $number0){
        return true;
    }

    if($number2 == 1000){
        $max2 = 1000;
    }elseif($number2/100 > 1){
        $d1=floor($number2/100);
        $d2=(floor($number2/10)%10);
        $d3=$number2%10;
        $d_min = min($d1, $d2, $d3);
        $d_max = max($d1, $d2, $d3);
        $d_mid = mid($d1, $d2, $d3, $d_min, $d_max);
        $max_2 = 100 * $d_max + 10 * $d_mid + $d_min;
    }elseif($number2/10 > 1){
        $d1= floor($number2/10);
        $d2= $number2%10;
        $max_2 = max($d1, $d2)*10 + min($d1, $d2);
    }else{
        $max_2 = $number2;
    }
    echo $max_2, PHP_EOL;
    if($max_2 > $number1){
        return true;
    }
    return false;

}

function mid($n1, $n2, $n3, $d_min, $d_max){
    if($n1 < $d_max && $n1 > $d_min){
        return $n1;
    }

    if($n2 < $d_max && $n2 > $d_min){
        return $n2;
    }

    return $n3;
}

11

You are given a matrix of integers field of size n × m representing a game field, and also a matrix of integers figure of size 3 × 3 representing a figure. Both matrices contain only 0s and 1s, where 1 means that the cell is occupied, and 0 means that the cell is free.

You choose a position at the top of the game field where you put the figure and then drop it down. The figure falls down until it either reaches the ground (bottom of the field) or lands on an occupied cell, which blocks it from falling further. After the figure has stopped falling, some of the rows in the field may become fully occupied.

demonstration

Your task is to find the dropping position such that at least one full row is formed. As a dropping position you should consider the column index of the cell in game field which matches the top left corner of the figure 3 × 3 matrix. If there are multiple dropping positions satisfying the condition, feel free to return any of them. If there are no such dropping positions, return -1.

Note: When falling, the 3 × 3 matrix of the figure must be entirely inside the game field, even if the figure matrix is not totally occupied.

Example

For

field =  [[0, 0, 0],
          [0, 0, 0],
          [0, 0, 0],
          [1, 0, 0],
          [1, 1, 0]]
and

figure = [[0, 0, 1],
          [0, 1, 1],
          [0, 0, 1]]
the output should be findFullLine(field, figure) = 0.

The figure can be dropped only from position 0. When the figure stops falling, two fully occupied rows are formed, so dropping position 0 satisfies the condition.

example 1

For

field =  [[0, 0, 0, 0, 0],
          [0, 0, 0, 0, 0],
          [0, 0, 0, 0, 0],
          [1, 1, 0, 1, 0],
          [1, 0, 1, 0, 1]]
and

figure = [[1, 1, 1],
          [1, 0, 1],
          [1, 0, 1]]
the output should be findFullLine(field, figure) = 2.

The figure can be dropped from three positions - 0, 1, and 2. As you can see below, a fully occupied row will be formed only when dropping from position 2:

example 2

For

field =  [[0, 0, 0, 0],
          [0, 0, 0, 0],
          [0, 0, 0, 0],
          [1, 0, 0, 1],
          [1, 1, 0, 1]]
and

figure = [[1, 1, 0],
          [1, 0, 0],
          [1, 0, 0]]
the output should be findFullLine(field, figure) = -1.

The figure can be dropped from two positions - 0 and 1, and in both cases, a fully occupied line won't be obtained:

example 3

Note that the figure could technically form a full row if it was dropped one position further to the right, but in that case the figure matrix wouldn't be fully contained with the field.

Input/Output

[execution time limit] 4 seconds (php)

[input] array.array.integer field

A matrix of integers representing the game field. It's guaranteed that at the beginning there are no fully occupied rows on the game field and that the top three rows are fully free.

Guaranteed constraints:
4 ≤ field.length ≤ 100,
3 ≤ field[i].length ≤ 100,
0 ≤ field[i][j] ≤ 1.

[input] array.array.integer figure

A matrix of integers representing the figure. It's guaranteed that the figure's occupied cells are pairwise connected and there is at least one occupied cell at the bottom row of the figure.

Guaranteed constraints:
figure.length = 3,
figure[i].length = 3,
0 ≤ figure[i][j] ≤ 1.

[output] integer

The dropping position such that a full row is formed. If there are multiple possible positions, return any of them. If there is no such position, return -1.

12

You are given three arrays of integers a, b, and c. Your task is to find the longest contiguous subarray of a containing only elements that appear in b but do not appear in c.

Return this longest subarray. If there is more than one longest subarray satisfying these conditions, return any of these possible subarrays.

Example

For a = [2, 1, 7, 1, 1, 5, 3, 5, 2, 1, 1, 1], b = [1, 3, 5], and c = [2, 3], the output can be longestInversionalSubarray(a, b, c) = [1, 1, 5].

There is no contiguous subarray of length 4 satisfying all the requirements:

a[0..3] = [2, 1, 7, 1] contains the number a[2] = 7, which doesn't appear in b;
a[1..4] = [1, 7, 1, 1] contains the number a[2] = 7, which doesn't appear in b;
a[2..5] = [7, 1, 1, 5] contains the number a[2] = 7, which doesn't appear in b;
a[3..6] = [1, 1, 5, 3] contains the number a[6] = 3, which does appear in c (which is prohibited);
a[4..7] = [1, 5, 3, 5] contains the number a[6] = 3, which does appear in c;
a[5..8] = [5, 3, 5, 2] contains the number a[6] = 3, which does appear in c;
a[6..9] = [3, 5, 2, 1] contains the number a[6] = 3, which does appear in c;
a[7..10] = [5, 2, 1, 1] contains the number a[8] = 2, which doesn't appear in b;
a[8..11] = [2, 1, 1, 1] contains the number a[8] = 2, which doesn't appear in b.
There are two possible contiguous subarrays of length 3 satisfying all the requirements:

a[3..5] = [1, 1, 5]: both numbers 1 and 5 appear in b, and both of these numbers don't appear in c.
a[9..11] = [1, 1, 1]: the number 1 appears in b, and doesn't appear in c.
example

As you can see, the longest consecutive subarrays of a that fulfill the conditions are a[3..5] = [1, 1, 5] and a[9..11] = [1, 1, 1]. Both of these answers are acceptable.

For a = [1, 2, 3], b = [], and c = [], the output should be longestInversionalSubarray(a, b, c) = [].

Since b is empty, there are no elements that appear in b and not c. So the answer is [].

Input/Output

[execution time limit] 4 seconds (php)

[input] array.integer a

The first array of integers.

Guaranteed constraints:
0 ≤ a.length ≤ 105,
-109 ≤ a[i] ≤ 109.

[input] array.integer b

The second array of integers.

Guaranteed constraints:
0 ≤ b.length ≤ 105,
-109 ≤ b[i] ≤ 109.

[input] array.integer c

The third array of integers.

Guaranteed constraints:
0 ≤ c.length ≤ 105,
-109 ≤ c[i] ≤ 109.

[output] array.integer

Any of the longest contiguous subarrays of a which consists only of elements from b that don't appear in c.