Skip to content
On This Page

202404

每一个人都有不一样的闪光点,所以要找到属于自己的那一片麦田,然后挥酒汗水,彻彻底底的完成自我实现?

so,我的麦田在哪里?

INFO

春暖花开 万物复苏 20240222

横亘在前面的两座大山都解决的怎么样了

天天手写,总得有点思考吧,不能老是一成不变,死记硬背

0401

  • 1027 天,64
  • 浏览 2 个 npm 仓库,React DnDimmutability-helper
  • 一天天的,也不知道自己想做什么,乱的很,想做小程序,做了那么久,啥也没产出,为啥这么懒
  • 获取页面的 html 有多少个标签
js
new Set([...document.querySelectorAll("*")].map((ele) => ele.tagName)).size

0402

  • 1028,63
  • 面试经验积累小程序已经开始,现在手忙脚乱,一会接口,一会前端,一会设计,都不知道自己要忙啥。这两天先忙着接口开发和设计
  • 前端 pc 页面展示+小程序端页面展示+用户登录

0403

  • 1029,64
  • Nestjs 还是这么菜,看不懂大佬们写的逻辑,后端服务这块写的太少了,羡慕大佬 isme-nest-serve
  • unocss
  • 需要学习的内容有:vue3+pinia+unocss+nestjs
  • 最近先把前端所需的服务端上线
  • 为了写好自己的接口,不得不继续学习 nestjs+prisma/typeorm,只要干不死就往死里干

0404

  • 1030,63
  • 最近面试系列暂停,需要紧急支持下服务端接口这块,不然怎么成为全栈工程师

0405

bash
-bash-4.2# node -v
v16.16.0
-bash-4.2# npm -v
8.11.0
 ln -s  /etc/node/bin/node  /usr/bin/node
 ln -s  /etc/node/bin/npm  /usr/bin/npm 

0406

INFO

DTO=Data Transfer Object。Dto 和接口有些类似,但是它的主要目的是为了转换和验证数据。他们基本上在路由控制中被使用。 您可以他们简化您的 API 内容(body)和请求验证逻辑。例如,AuthDto 自动的整合用户的 email 和 password 进一个 dto 对象进行强制验证。

  • Nestjs 中的依赖注入原理怎么描述和解释

0407

  • 1033,60
  • typescript 项目中 tsconfig 设置别名

INFO

在 TypeScript 项目中,tsconfig.json 文件用于配置 TypeScript 编译器的选项。通过设置别名(paths),我们可以简化模块导入的路径,使其更加清晰易读,同时也可以解决一些模块解析的问题。

要在 tsconfig.json 中设置别名,你需要在 compilerOptions 对象中使用 paths 属性。paths 属性是一个对象,其中的键是路径的别名(例如 @components/*),值是一个包含具体路径的数组。下面是如何设置别名的一个例子:

json
{
  "compilerOptions": {
    "baseUrl": ".", // 这里设置基础路径,所有相对路径都是基于这个路径
    "paths": {
      "@components/*": ["src/components/*"],
      "@services/*": ["src/services/*"],
      "@utils/*": ["src/utils/*"],
      "@constants/*": ["src/constants/*"],
      "@models/*": ["src/models/*"]
    }
  }
}

0408

  • 1034,59
  • sse 是什么?
Details

SSE(Server-Sent Events)是一种允许服务器主动向客户端发送信息的技术。与传统的 HTTP 请求不同,SSE 在客户端建立一个到服务器的单向连接,服务器可以通过这个连接随时发送数据更新。

ts
import { Injectable } from "@nestjs/common"
import { InjectRepository } from "@nestjs/typeorm"
import { Repository } from "typeorm"
import { CreateUserDto } from "./dto/create-user.dto"
import { User } from "./user.entity"

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private readonly usersRepository: Repository<User>
  ) {}

  create(createUserDto: CreateUserDto): Promise<User> {
    const user = new User()
    user.firstName = createUserDto.firstName
    user.lastName = createUserDto.lastName
    return this.usersRepository.save(user)
  }

  async findAll(): Promise<User[]> {
    return this.usersRepository.find()
  }

  findOne(id: number): Promise<User> {
    return this.usersRepository.findOneBy({ id: id })
  }

  async remove(id: string): Promise<void> {
    await this.usersRepository.delete(id)
  }
}

0409

  • 1035, 58

  • nestjs 项目中的@nestjs/passport passport passport-local 分别有什么用

  • nestjs 项目中,对于参数定义,不能这么定义,这样对于控制器来说已哪个为准?

ts
export const UserController {
  constructor(
    private userService: Uservice
  ) {}

  @Get(':username')
  findByUsername(@Param('username') username: string) {
    console.log('name');
    return this.userService.findByUsername(username);
  }

  @Get(':id')
  findByUserId(@Param('id') id: number) {
    return this.userService.findOne(id);
  }
}

0410

分类可以嵌套其他分类,嵌套分类可以嵌套其他分类

ts
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
  OneToMany,
} from "typeorm"

@Entity()
export class Permission {
  @PrimaryGeneratedColumn()
  id: number

  @Column()
  title: string

  @ManyToOne(() => Permission, (permission) => permission.children, {
    createForeignKeyConstraints: false,
  })
  parent: Permission

  @OneToMany(() => Permission, (permission) => permission.parent, {
    createForeignKeyConstraints: false,
  })
  children: Permission[]
}

0411

  • 1037,56

小程序端微信登录相关

微信静默授权(snsapi_base)和非静默授权(snsapi_userinfo)区别

官网文档

  • 静默授权:只用来获取用户的 openid(用户相对于该服务号的唯一标识),用户不感知。并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
  • 非静默授权:用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
  • 用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户 OpenID 来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即 openid)关注了公众号后,才能调用成功的。

微信里 UnionID 机制

  • 请注意,网页授权获取用户基本信息也遵循 UnionID 机制。即如果开发者有在多个公众号,或在公众号、移动应用之间统一用户账号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用 UnionID 机制来满足上述需求。

  • UnionID 机制的作用说明:如果开发者拥有多个移动应用、网站应用和公众账号,可通过获取用户基本信息中的 unionid 来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众账号),unionid 是相同的。

  • forRootAsync 使用了 TypeORM 的异步工程模式,这样可以解决 imports 的顺序问题,也就是说,使用了 forRootAsync,可以不用在意 imports 这个数组中使用 TypeOrmModule 的顺序,可以任意放,不用在意其他模块引入的顺序

ts
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
  imports: [ TypeOrmModule.forRootAsync({})],
  controllers: [],
  providers: []
})

0412

  • 1038,55
  • 每天都是煎熬,最难过的莫过于表演,而我又不喜欢表演。
  • 降低一切无效社交,老老实实敲代码,搬砖
  • “有一个夜晚我烧毁了所有的记忆,从此我的梦就透明了;有一个早晨我扔掉了所有的昨天,从此我的脚步就轻盈了。——泰戈尔”

0413/0414

  • 1040,53
  • 认清自己,谦卑一点,发表意见的时候,仅供参考,多以数据和事实说话,还有就是自己那么忙,没有时间去处理琐事,还是不能放弃学习
  • 大模型能专注于只做某一领域吗,做深做透,比如高考规划,利用大模型,打破信息差,什么学校的强基政策以及高校专项计划等各种政策解读,让各种高考规划师面临失业,再比如保险领域,买什么保险是否需要保险等等
  • typeorm 进阶查询

0415

  • 1041,52
  • TypeORM 中的 Like 和 ILike 运算符都用于模糊查询,但它们的区别在于对大小写的敏感性。

Like 运算符是区分大小写的。例如,使用 Like '%abc%' 查询时,只会匹配包含 abc 的记录,而不会匹配包含 Abc、ABC 等大小写不同的字符串。

ILike 运算符是不区分大小写的。例如,使用 ILike '%abc%' 查询时,会匹配包含 abc、Abc、ABC 等字符串,无论大小写如何。

申请地址

  • 小程序打包面临问题?京东快递小程序打包面临问题如下

INFO

  • 采用运行时而不是构建时进行多端小程序代码兼容;
  • 分包路径问题,有些页面路径已经给到外部,分包后涉及外部系统改造上线;
  • 图片资源过大,影响主包体积;
  • 第三方包引入不规范,导致打包后引入冗余代码;
  • console、debugger 等测试代码未做优化,需要上线前手动删除;

0416

  • 1042,51
  • 每次的评优都跟你无关,没谁了,不给机会,彻底躺平

0417

  • 1043,50
  • 还没有收到合同续签的通知,估计凉凉,真特么尴尬,这个年纪不上不下,尴尬死了,啥也干不了,下辈子还是别做这行了,如果真喜欢,退休之后当个乐趣玩玩吧
  • 就歇息了 10 天,现在发现之前的手写题又基本忘记了,要命了,今天手写 lodash.get/set

0418

  • 1044,49

username@host 表示授予的用户以及允许该#### 用户登录的 IP 地址。其中 Host 有以下几种类型:

  • localhost:只允许该用户在本地登录,不能远程登录。
  • %:允许在除本机之外的任何一台机器远程登录。
  • 192.168.52.32:具体的 IP 表示只允许该用户从特定 IP 登录。

mysql 用户登录相关的语句

  • 添加新用户: CREATE USER 'cdp’@‘localhost' IDENTIFIED BY ‘password’;
  • 给该用户授权:GRANT ALL PRIVILEGES ON cost.* TO cdp@'localhost' identified by 'password';
  • 查询用户表信息: Select User,Host from mysql.user where user=‘cdp’;
  • 授权完刷新信息: flush privileges;

0419

  • 1045,48
  • 看过最简洁的 TSConfig 介绍
  • nestjs 项目如何把数据库密码账户等信息传递给服务端,然后再服务端跑起来?肯定要是加密的,不然谁都能看到密码,今天终于搞好了,通过 github+action+Pm2 中的 ecosystem.config.js 中的 env 参数,具体是要在自动化脚本中添加
yml
name: DeployAli
on:
  push:
    branches:
      - main

env:
  TARGET_DIR: /www/web/keepAccount
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Copy files to server
        uses: cross-the-world/ssh-scp-ssh-pipelines@latest
        env:
          DB_PWD: ${{ secrets.ALI_DB_PWD }}
          DB_USER: ${{ secrets.ALI_DB_USER }}
          DB_HOST: ${{ secrets.ALI_DB_HOST }}
          server_pass: ${{secrets.ALI_PASSWORD}}
          server_host: ${{secrets.ALI_ADDRESS}}
        with:
          host: $server_host
          user: "root"
          pass: $server_pass
          first_ssh: |-
            rm -rf $TARGET_DIR
            mkdir -p $TARGET_DIR
          scp: |-
            './*' => $TARGET_DIR/
          last_ssh: |-
            cd $TARGET_DIR
            pnpm install
            pnpm run build
            touch ecosystem.config.js
            echo "module.exports = { apps : [ { name: 'my-nestjs-ka', instances: 2,exec_mode: 'cluster', script: './dist/main.js', env: { NODE_ENV: 'production',DB_DATABASE: 'cost',DB_PWD: '${DB_PWD}',DB_USER: '${DB_USER}',DB_HOST: '${DB_HOST}',JWT_SECRET: 'cpp&wmh' } } ] };" > ecosystem.config.js
            pm2 restart ecosystem.config.js

0420/0421

  • 1047,46
  • 个人主动做 app 挺难的,前后端一把锁,还挺需要耐心和毅力的
  • typeorm 数据库迁移

    一旦上线生产环境,你将需要将模型更改同步到数据库中。 通常在数据库中获取数据后,使用 synchronize:true 进行生产模式同步是不安全的。 因此这时候使用迁移,可以解决此类问题。

0422

grid grid-rows-4 grid-cols-4 gap-5 来源于 tailwindcss

js
const Home = () => {
  const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
  return (
    <div id="container" className="grid grid-rows-4 grid-cols-4 gap-5">
      {nums.map((item) => {
        return (
          <div className="item" key={item}>
            {item}
          </div>
        )
      })}
      <div className="item col-span-2">0</div>
      <div className="item col-end-5 row-start-1">x</div>
      <div className="item ">.</div>
      <div className="item col-end-5 row-start-2 row-end-5">确定</div>
    </div>
  )
}

核心几个概念,区分容器和项目

  • grid-template-columns 属性: 定义每一列的列宽
  • grid-template-rows 属性: 每一行的行高
  • grid-template 属性是grid-template-columnsgrid-template-rowsgrid-template-areas这三个属性的合并简写形式。
css
// 容器属性
.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: repeat(3, 100px);
  grid-template-columns: 100px 1fr 2fr; // fr fraction 片段 比例关系
  grid-template-rows: 1fr 1fr minmax(100px, 1fr); // minmax长度范围 最小值和最大值
  grid-template-columns: 100px auto 100px; // auto 浏览器自己决定长度
  grid-template-columns: 70% 30%; // 两栏布局  左边70% 右边30%
  grid-template-columns: repeat(12, 1fr); // 传统十二网格布局
  gird-row-gap: 20px; // 设置行间距
  grid-column-gap: 20px; // 设置列间距
  grid-auto-flow: row; // 先行后列 先填满第一行 然后第二行
  grid-auto-flow: column; // 先列后行
  justify-items: start | end | center | stretch; // 单元格内容水平位置 左中右
  align-items: start | end | center | stretch; // 设置单元格内容的垂直位置(上中下)
  place-items: start end; // justify-items和align-items简写
  justify-content: start | end | center | stretch; // 整个内容在容器里水平位置
  align-content: start | end | center | stretch; // 整个内容在垂直位置
  place-content: space-around space-evenly; // align-content属性和justify-content属性的合并简写形式。
}
// 项目属性
.item {
  grid-column-start: 2; // 左边框所在的垂直网格线
  grid-column-end: 4; // 右边框所在的垂直网格线
  gird-row-start: 1; // 上边框
  grid-row-end: 5; // 下边框
  grid-column-start: span 2; // 左边框距离右边框跨越2个网格
  grid-column-end: span 2;
  grid-column: 1/3; // grid-column-start和grid-column-end的合并简写形式
  grid-row: 1/3; // grid-row-start属性和grid-row-end的合并简写形式
  // 等同于
  grid-column: 1 / span 2;
  grid-row: 1 / span 2;
  justify-self: start | end | center | stretch; // 单元格内容的水平位置(左中右)
  align-self: start | end | center | stretch; // 单元格内容的垂直位置(上中下)
  place-self: center center; // align-self属性和justify-self属性的合并简写
}

0423

  • 1049,44,今天继续加油,做自己想做的事
  • uniapp 使用 uni-popup 组件时,如何使底部的 tab 隐藏
js
uni.showTabBar() // show
uni.hideTabBar() // hidden

uniapp 中的点击效果:hover-class

指定按下去的样式类。当 hover-class="none" 时,没有点击态效果,hover-stay-time:手指松开后点击态保留时间,单位毫秒

html
<template>
  <view hoverClass="highlight" :hover-stay-time="100"></view>
</template>

0424

0425

  • 1051,42
  • 深耕于小程序开发,后面就靠它谋生了,今天继续完善小程序请求封装和全局拦截
  • PUT 和 Patch 区别

::: infos

HTTP 请求中的 PUT 和 PATCH 方法都是用于更新资源的,但它们在更新的粒度和行为上有所不同:

PUT 请求:

  • 幂等性:PUT 请求是幂等的,意味着多次执行同一个 PUT 请求(相同的 URL 和相同的数据)应该保持资源状态不变,不会产生副作用。
  • 整体替换:通常用于完全替换资源,如果资源不存在,服务器可以用请求的主体创建资源;如果资源已存在,则用请求的主体完全替换它。
  • 请求体:请求体中包含要创建或替换的整个资源的表示。

PATCH 请求:

  • 非幂等性:PATCH 请求是非幂等的,意味着多次执行相同的 PATCH 请求可能会对资源产生不同的副作用。
  • 部分更新:用于对资源进行部分修改,只包含需要修改的部分,而不是整个资源。
  • 请求体:请求体中包含要应用到资源上的一系列指令或补丁,这些指令指导服务器如何修改资源。

简单来说,PUT 通常用于完全替换一个资源,而 PATCH 用于对资源进行部分更新。在实际应用中,选择使用 PUT 还是 PATCH 取决于具体的业务逻辑和需求。

:::

0426

ts
// 项目中安装
pnpm i pinia-plugin-persistedstate
pnpm i pinia

// 项目中引入
import { createSSRApp } from 'vue'
import * as Pinia from 'pinia'
import { createPersistedState } from 'pinia-plugin-persistedstate'
import App from './App.vue'
export function createApp() {
  const app = createSSRApp(App)
  const pinia = Pinia.createPinia()
  pinia.use(
    createPersistedState({
      storage: {
        getItem(key: string) {
          return uni.getStorageSync(key)
        },
        setItem(key: string, value: string) {
          uni.setStorageSync(key, value)
        },
      },
    }),
  )
  app.use(pinia)
  return {
    app,
  }
}

// 项目中定义
import { defineStore } from "pinia"

export const useStore = defineStore("store", {
  state: () => ({
    someState: "你好 pinia",
  }),
  persist: {
    paths: ['someState']
  },
})

0427

0428

  • 1054, 39
  • 弃之可惜,食之无味,要命了
  • 小程序头像上传到哪个服务平台给你存着,上传之后获取 url,然后更新数据库里的头像路径?但这么多静态文件你存在哪里合适呢

0429

ts
// 子组件可以显式地通过 defineEmits() 宏来声明它要触发的事件:
<script setup>
  const emit = defineEmits(['inFocus', 'submit']);
  function buttonClick(){
     {emit("submit")}
  }
</script>

父组件引用

html
<parent-com @submit="parentsubmit" />
ts
// child-compoent
const childFun = () => {}
// 暴露方法
defineExpose({
  childFun,
})

父组件调用子组件暴露出的方法

html
<template>
  <Test ref="modal" />
  <button @click="openModal">Test</button>
</template>
<script>
  const modal = ref()
  const openModal = () => {
    if (modal && modal.value) {
      modal.value.childFun()
    }
  }
</script>

0430