uniapp-vue3-vite 搭建小程序、H5 项目模板

news/2024/10/3 18:08:46

uniapp-vue3-vite 搭建小程序、H5 项目模板

  • 特色
  • 准备
    • 拉取默认UniApp模板
    • 安装依赖
    • 启动项目测试
    • 结果
  • 配置自动化导入
    • 安装依赖
    • 在vite.config.js中配置
  • 引入 prerttier + eslint + stylelint
    • .editorconfig
    • .prettierrc.cjs
    • .eslintrc.cjs
    • .stylelintrc.cjs
  • 引入 husky + lint-staged + commitlint
    • Commitizen & cz-git
      • 更改提示消息模板 .cz-config.js
    • 检测
  • 配置UnoCss
    • 检测
  • 配置pinia 添加持久化
    • 检测
  • Axios接入配置
    • 在vite.config.js中配置自动化导入
    • 检测
  • 图标库
  • UI 方案
  • 模板
  • 敬请期待

1

作者GitHub:https://github.com/gitboyzcf 有兴趣可关注!!!

特色

  • ⚡️uni-app, Vue 3, Vite, pnpm

  • 📦 组件自动化引入

  • 🍍 使用 Pinia 的状态管理

  • 🎨 UnoCSS - 高性能且极具灵活性的即时原子化 CSS 引擎

  • 😃 各种图标集为你所用

  • 🔥 使用 新的 <script setup> 语法

  • 📥 API 自动加载 - 直接使用 Composition API 无需引入

  • 🌍 API 采用模块化自动导入方式 根据demo.js文件设置接口,以API_xxx_method的方式命名,在请求时无需导入 直接使用useRequest()函数返回参数以解构的方式获取,拿到即为写入的接口

准备

Vue3/Vite版要求 node 版本^14.18.0 || >=16.0.0

拉取默认UniApp模板

点击下载 默认模板,或者通过下面命令行拉取

npx degit dcloudio/uni-preset-vue#vite my-vue3-project

得到下面目录结构👇

1

安装依赖

我这里使用pnpm ,可以使用如npm、yarn、…

pnpm install

如有报下面错误👇

This modules directory was created using the following registries configuration:{“default”:“https://registry.npmjs.org/”}. The current configuration is {“default”:“https://registry.npm.taobao.org/”}. To recreate the modules directory using the new settings, run “pnpm install -g”.

解决方案 下载源切换

pnpm config set registry https://registry.npmjs.org

启动项目测试

执行该命令 会将此项目编译成微信小程序项目,该命令会持续监听修改并进行热更新

pnpm dev:mp-weixin

执行后会出现 dist\dev\mp-weixin文件夹结构

2

将此目录下的mp-weixin微信开发者工具进行打开

如未安装点击下面链接下载安装即可👇
https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

结果

结果

配置自动化导入

安装依赖

pnpm i unplugin-auto-import -D

在vite.config.js中配置

配置

import AutoImport from 'unplugin-auto-import/vite'AutoImport({imports: ["vue", "uni-app", "pinia"],dts: true,
})

配置完后 重新执行pnpm dev:mp-weixin此时会生成auto-imports.d.ts文件

此时在pages/index/index.vue中不用引入直接可以使用vue的api

<script setup>
const title = ref('Hello World!')
</script>

引入 prerttier + eslint + stylelint

安装相关依赖包👇

pnpm add -D eslint @babel/eslint-parser eslint-config-airbnb-base eslint-config-prettier eslint-plugin-import eslint-plugin-prettier eslint-plugin-vue vue-global-api stylelint stylelint-scss stylelint-config-standard-scss stylelint-config-prettier

.editorconfig

# .editorconfig 文件
root = true[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = space # 缩进风格(tab | space)
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行[*.md] # 表示仅 md 文件适用以下规则
max_line_length = off # 关闭最大行长度限制
trim_trailing_whitespace = false # 关闭末尾空格修剪

.prettierrc.cjs

module.exports = {// 一行的字符数,如果超过会进行换行,默认为80,官方建议设100-120其中一个数printWidth: 100,// 一个tab代表几个空格数,默认就是2tabWidth: 2,// 启用tab取代空格符缩进,默认为falseuseTabs: false,// 行尾是否使用分号,默认为true(添加理由:更加容易复制添加数据,不用去管理尾行)semi: false,vueIndentScriptAndStyle: true,// 字符串是否使用单引号,默认为false,即使用双引号,建议设true,即单引号singleQuote: true,// 给对象里的属性名是否要加上引号,默认为as-needed,即根据需要决定,如果不加引号会报错则加,否则不加quoteProps: 'as-needed',// 是否使用尾逗号,有三个可选值"<none|es5|all>"trailingComma: 'none',// 在jsx里是否使用单引号,你看着办jsxSingleQuote: true,// 对象大括号直接是否有空格,默认为true,效果:{ foo: bar }bracketSpacing: true,proseWrap: 'never',htmlWhitespaceSensitivity: 'strict',endOfLine: 'auto',
}

.eslintrc.cjs

// .eslintrc.cjs 文件
module.exports = {env: {browser: true,es2021: true,node: true,},extends: ['eslint:recommended','plugin:vue/vue3-essential',// eslint-plugin-import 插件, @see https://www.npmjs.com/package/eslint-plugin-import'plugin:import/recommended',// eslint-config-airbnb-base 插件, tips: 本插件也可以替换成 eslint-config-standard'airbnb-base',// 1. 接入 prettier 的规则'prettier','plugin:prettier/recommended','vue-global-api',],overrides: [{env: {node: true,},files: ['.eslintrc.{js}'],parserOptions: {sourceType: 'script',},},],parserOptions: {ecmaVersion: 'latest',parser: '@babel/eslint-parser',sourceType: 'module',},plugins: ['@babel/eslint-parser','vue',// 2. 加入 prettier 的 eslint 插件'prettier',// eslint-import-resolver-typescript 插件,@see https://www.npmjs.com/package/eslint-import-resolver-typescript'import',],rules: {// 3. 注意要加上这一句,开启 prettier 自动修复的功能'prettier/prettier': 'error',// turn on errors for missing imports'import/no-unresolved': 'off',// 对后缀的检测,否则 import 一个ts文件也会报错,需要手动添加'.ts', 增加了下面的配置后就不用了'import/extensions': ['error','ignorePackages',{ js: 'never', jsx: 'never', ts: 'never', tsx: 'never' },],// 只允许1个默认导出,关闭,否则不能随意export xxx'import/prefer-default-export': ['off'],'no-console': ['off'],// 'no-unused-vars': ['off'],// '@typescript-eslint/no-unused-vars': ['off'],// 解决vite.config.ts报错问题'import/no-extraneous-dependencies': 'off','no-plusplus': 'off','no-shadow': 'off','vue/multi-word-component-names': 'off','@typescript-eslint/no-explicit-any': 'off',},// eslint-import-resolver-typescript 插件,@see https://www.npmjs.com/package/eslint-import-resolver-typescriptsettings: {'import/parsers': {'@typescript-eslint/parser': ['.ts', '.tsx'],},'import/resolver': {typescript: {},},},globals: {uni: true,UniApp: true,wx: true,WechatMiniprogram: true,getCurrentPages: true,UniHelper: true,Page: true,App: true,},
}

.stylelintrc.cjs

// .stylelintrc.cjs 文件
module.exports = {root: true,extends: ['stylelint-config-standard','stylelint-config-standard-scss', // tips: 本插件也可以替换成 stylelint-config-recommended-scss'stylelint-config-recommended-vue/scss','stylelint-config-html/vue','stylelint-config-recess-order',],overrides: [// 扫描 .vue/html 文件中的<style>标签内的样式{files: ['**/*.{vue,html}'],customSyntax: 'postcss-html',},{files: ['**/*.{css,scss}'],customSyntax: 'postcss-scss',},],// 自定义规则rules: {// 允许 global 、export 、v-deep等伪类'selector-pseudo-class-no-unknown': [true,{ignorePseudoClasses: ['global', 'export', 'v-deep', 'deep'],},],'unit-no-unknown': [true,{ignoreUnits: ['rpx'],},],// 处理小程序page标签不认识的问题'selector-type-no-unknown': [true,{ignoreTypes: ['page'],},],'comment-empty-line-before': 'never',},
}

引入 husky + lint-staged + commitlint

说明
husky 用于git提交的钩子
lint-staged 一个在 git 暂存文件上(也就是被git add后的文件)运行已配置的格式工具;比如eslint、stylelintrc、…
commitlint 检查您的提交消息是否符合 常规提交格式 (Conventional commit format)
正确的提交格式:(): ,type 和 subject 默认必填
在这里插入图片描述

安装相关依赖包👇

pnpm i -D husky@6 lint-staged commitlint @commitlint/cli @commitlint/config-conventional

执行 npx husky install
并且在 package.json的scripts里面增加 "prepare": "husky install",(其他人安装后会自动执行) 根目录会生成 .hushy 文件夹。

package.josn 增加如下属性👇:

...
"scripts": {..."prepare": "husky install",
},
"lint-staged": {"**/*.{html,vue,ts,cjs,json,md}": ["prettier --write"],"**/*.{vue,js,ts,jsx,tsx}": ["eslint --fix"],"**/*.{vue,css,scss,html}": ["stylelint --fix"]
}

根目录新增 .commitlintrc.cjs,内容如下👇

module.exports = {extends: ['@commitlint/config-conventional'],rules: {'type-enum': [2,'always',['feat','fix','perf','style','docs','test','refactor','build','ci','init','chore','revert','wip','workflow','types','release',],],'subject-case': [0],},
}

通过下面命令在钩子文件中添加内容👇

npx husky add .husky/pre-commit "npx --no-install -- lint-staged"
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"

Commitizen & cz-git

说明
commitizen 基于Node.js的 git commit 命令行工具,辅助生成标准化规范化的 commit message
cz-customizable 标准输出格式的 commitizen 适配器

安装依赖包👇

pnpm add -D commitizen cz-customizable

修改 package.json指定使用的适配器

...
"scripts": {..."cz": "git-cz"
},"config": {"commitizen": {"path": "node_modules/cz-customizable"}}

更改提示消息模板 .cz-config.js

.cz-config.js

module.exports = {types: [{ value: 'feat', name: '✨ feat:     新功能' },{ value: 'fix', name: '🐛 fix:      修复' },{ value: 'init', name: '🎉 Init:     初始化' },{ value: 'docs', name: '📝 docs:     文档变更' },{ value: 'style', name: '💄 style:    代码格式(不影响代码运行的变动)' },{value: 'refactor',name: '♻️  refactor: 重构(既不是增加feature,也不是修复bug)',},{ value: 'perf', name: '⚡️ perf:     性能优化' },{ value: 'test', name: '✅ test:     增加测试' },{ value: 'revert', name: '⏪️ Revert:   回退' },{ value: 'build', name: '🚀‍ build:    构建过程或辅助工具的变动' },{ value: 'ci', name: '👷 ci:       CI 配置' },],// 消息步骤messages: {type: '请选择提交类型:',subject: '请简要描述提交(必填):',customScope: '请输入修改范围(可选):',body: '请输入详细描述(可选):',breaking: '列出任何BREAKING CHANGES(可选)',footer: '请输入要关闭的issue(可选):',confirmCommit: '确认使用以上信息提交吗?',},allowBreakingChanges: ['feat', 'fix'],skipQuestions: ['customScope'],subjectLimit: 72,
}

检测

在命令行中输入👇

git add .
pnpm cz

然后会出现本次提交选项
1

选择本次提交的类型,按要求写入然后回车即可

配置UnoCss

安装依赖👇

pnpm add -D unocss @unocss/preset-uno unocss-applet @unocss/preset-legacy-compat
pnpm add @uni-helper/unocss-preset-uni

然后配置 unocss.config.js

// uno.config.js
import {Preset,defineConfig,presetAttributify,presetIcons,transformerDirectives,transformerVariantGroup,
} from 'unocss'import {presetApplet,presetRemRpx,transformerApplet,transformerAttributify,
} from 'unocss-applet'
import { presetUni } from '@uni-helper/unocss-preset-uni'// @see https://unocss.dev/presets/legacy-compat
import presetLegacyCompat from '@unocss/preset-legacy-compat'const isH5 = process.env?.UNI_PLATFORM === 'h5'
const isMp = process.env?.UNI_PLATFORM?.startsWith('mp') ?? falseconst presets = []
if (!isMp) {/*** you can add `presetAttributify()` here to enable unocss attributify mode prompt* although preset is not working for applet, but will generate useless css* 为了不生产无用的css,要过滤掉 applet*/// 支持css class属性化,eg: `<button bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600" text="sm white">attributify Button</button>`presets.push(presetAttributify())
}
if (!isH5) {presets.push(presetRemRpx())
}
export default defineConfig({presets: [presetApplet({ enable: !isH5 }),...presets,// 支持图标,需要搭配图标库,eg: @iconify-json/carbon, 使用 `<button class="i-carbon-sun dark:i-carbon-moon" />`presetIcons({scale: 1.2,warn: true,extraProperties: {display: 'inline-block','vertical-align': 'middle',},}),// 将颜色函数 (rgb()和hsl()) 从空格分隔转换为逗号分隔,更好的兼容性app端,example:// `rgb(255 0 0)` -> `rgb(255, 0, 0)`// `rgba(255 0 0 / 0.5)` -> `rgba(255, 0, 0, 0.5)`presetLegacyCompat({commaStyleColorFunction: true,}),],/*** 自定义快捷语句* @see https://github.com/unocss/unocss#shortcuts*/shortcuts: [['center', 'flex justify-center items-center']],transformers: [// 启用 @apply 功能transformerDirectives(),// 启用 () 分组功能// 支持css class组合,eg: `<div class="hover:(bg-gray-400 font-medium) font-(light mono)">测试 unocss</div>`transformerVariantGroup(),// Don't change the following ordertransformerAttributify({// 解决与第三方框架样式冲突问题prefixedOnly: true,prefix: 'fg',}),transformerApplet(),],rules: [['p-safe',{padding:'env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)',},],['pt-safe', { 'padding-top': 'env(safe-area-inset-top)' }],['pb-safe', { 'padding-bottom': 'env(safe-area-inset-bottom)' }],],
})

src/main.js增加 import 'virtual:uno.css'

vite.config.js文件写入:

import UnoCSS from 'unocss/vite'// 其他配置省略
plugins: [UnoCSS()],

检测

<view class="text-area b-1px b-solid b-color-red"><text class="title mt-4">{{ title }}</text>
</view>

结果👇
res

配置pinia 添加持久化

首先安装依赖包:

pnpm add pinia pinia-plugin-persistedstate -S

然后写入文件:

// src/store/count.js
import { piniaStore } from '@/store'
export const useCountStore = defineStore('count', {state: () => {return {count: 0}},actions: {increment() {this.count++}},persist: true // 配置持久化
})export function useOutsideCountStore(){return useCountStore(piniaStore)
}

注意下面👇这个文件对持久化的处理,否则非h5环境不能正确持久化

// src/store/index.js
import { createPinia } from 'pinia'
import { createPersistedState } from 'pinia-plugin-persistedstate' // 数据持久化const store = createPinia()
store.use(createPersistedState({storage: {getItem: uni.getStorageSync,setItem: uni.setStorageSync,},}),
)
export default store
// src/main.js
import { createSSRApp } from 'vue'
import App from './App.vue'
import { setupStore } from './store'
import 'virtual:uno.css'
export function createApp() {const app = createSSRApp(App)setupStore(app)return {app}
}

如有报下面错误👇
vue pinia版本冲突问题

Not able to use pinia: No matching export in “node_modules/pinia/node_modules/vue-demi/lib/index.mjs” for import “hasInjectionContext”

解决方案

将vue3 和pinia更换成下面版本重新下载对应npm包
“pinia”: “2.0.32”,
“vue”: “3.2.47”,

pnpm install vue@3.2.47 pinia@2.0.32 -S

具体请看:https://github.com/vuejs/pinia/issues/2210

检测

<view><button type="primary" @click="useCountStore.count++">点击 {{ count }}</button>
</view><script setup>import { useOutsideCountStore } from '@/store/count'const useCountStore = useOutsideCountStore()const count = computed(() => useCountStore.count)
</script>

res

Axios接入配置

安装相关依赖包👇

pnpm add @uni-helper/axios-adapter axios

以下步骤创建对应文件粘贴代码即可

  1. src》api》index.js

    /*** 模块化方式处理 默认处理 modules文件夹下的所有js文件 内容以export default导出的文件* @param { 模块内容集合 } moduleContext* @returns modules集合*/
    const modulesHandle = (moduleContext = {}) => {if (!Object.keys(moduleContext).length) returnconst modules = {}Object.keys(moduleContext).forEach((v) => {for (let key in moduleContext[v].default) {modules[key] = moduleContext[v].default[key]}})return modules
    }const apis = modulesHandle(import.meta.glob('./modules/**/*.js', { eager: true }))
    export const useRequest = () => apis
    
  2. src》api》utils.js

    // 请求状态错误
    export const httpLogError = (error, msg) => {error.message = msguni.showToast({title: msg,icon: 'error',duration: 2000})
    }// api请求错误
    export const requestError = (response) => {return new Promise((_, reject) => {const { data } = responseconst msg = `api请求出错 ${response.config.url}${data.message}`uni.showToast({title: msg,icon: 'error',duration: 2000})reject(data)})
    }// 登录失效
    export const throttleToLogin = () => {// uni.navigateTo({ url: '/pages/login/login' })
    }
    
  3. src》api》service.js

    import axios from 'axios'
    import { createUniAppAxiosAdapter } from '@uni-helper/axios-adapter'
    import { httpLogError, requestError, throttleToLogin } from './utils'
    export function createService() {const request = axios.create({ adapter: createUniAppAxiosAdapter() })request.interceptors.request.use((request) => {return request},(err) => {return Promise.reject(err)})request.interceptors.response.use((response) => {const dataAxios = response.data// 这个状态码是和后端约定的const { code, data } = dataAxiosconsole.log(dataAxios);// 根据 code 进行判断if (code === undefined) {return dataAxios} else {// 目前和公司后端口头约定是字符串,以防万一强制转字符串switch (`${code}`) {// code === 200 | 2 代表没有错误case '200':return data// code === 400001004 代表token 过期打回登录页case '400001004':throttleToLogin()breakcase '400':// 不是正确的 codereturn requestError(response)case '401':// 错误登录return throttleToLogin()default:// 不是正确的 codereturn requestError(response)}}}, (error) => {console.log(error);const status = error.response?.statusswitch (status) {// TODO 再考虑下怎么判断是跨域问题case undefined:case null:httpLogError(error, '网路错误或跨域')breakcase 400:httpLogError(error, '请求错误')breakcase 401:httpLogError(error, '未授权,请登录')breakcase 403:httpLogError(error, '拒绝访问')breakcase 404:httpLogError(error, `请求地址出错: ${error.response.config.url}`)breakcase 408:httpLogError(error, '请求超时')breakcase 500:httpLogError(error, '服务器内部错误')breakcase 501:httpLogError(error, '服务未实现')breakcase 502:httpLogError(error, '网关错误')breakcase 503:httpLogError(error, '服务不可用')breakcase 504:httpLogError(error, '网关超时')breakcase 505:httpLogError(error, 'HTTP版本不受支持')breakdefault:httpLogError(error, '请求错误')break}return Promise.reject(error)})return request
    }export const service = createService()
    
  4. src》api》request.js

    import { service } from './service'
    function createRequest(service) {function request(config) {// config 自定义配置// axios默认配置const configDefault = {baseURL: import.meta.env.VITE_APP_API_BASEURL, // 所有通过此配置的基础地址 在.env文件配置timeout: 15000, // 请求超时时间responseType: 'json', // 响应类型headers: {// 请求头配置...}}const requestConfig = Object.assign(configDefault, config)return service(requestConfig)}return request
    }export const request = createRequest(service)
    
  5. src》modules》demo.js

    /*** 命名=》API_xxx_methodName*/import { request } from '@/api/request.js'
    export default {API_DEMO_POST(data = {}) {return request({url: 'demo/mock',method: 'post',data})},API_DEMO_GET(params = {}) {return request({url: '/demo/get',method: 'get',params})}
    }

在vite.config.js中配置自动化导入

在原有的配置中添加

import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
// ...
// https://vitejs.dev/config/
export default defineConfig({plugins: [//...AutoImport({imports: [//...{'@/api': ['useRequest']}],//...}),//...],//...
})

检测

<template><view class="content"><view><button type="primary" @click="getList">点击请求数据</button></view></view><view class="p-2"><viewclass="my-15rpx b-b-solid b-b-1rpx b-b-color-[#cccccc]"v-for="item in list":key="item.id"><text class="text-18rpx font-bold">{{ item.title }}</text><view class="mt-4 text-12rpx color-[#9999]">{{ item.body }}</view></view></view>
</template><script setup>const { API_DEMO_GET } = useRequest()const list = ref([])const getList = () => {uni.showLoading({title: '加载中...'})API_DEMO_GET().then((res) => {console.log(res)list.value = resuni.hideLoading()}).catch(() => {uni.hideLoading()})}
</script>

api

图标库

  1. 前往图标库查找相关图标iconify.design

  2. 安装图标所在的图标库

    # 格式:pnpm add @iconify-json/[the-collection-you-want] -D# 例如
    pnpm add @iconify-json/ep -D
    

    安装完后可以使用当前库下的所有图标
    https://icon-sets.iconify.design/ep/

  3. 项目中使用
    使用unocss的方式https://iconify.design/docs/usage/css/unocss/#icons-with-unocss

    <text class="i-ep-apple w-40rpx h-40rpx color-red"></text>
    

UI 方案

自行使用相关ui接入项目
uni-ui
https://www.uvui.cn/
https://uviewui.com/

模板

拉取后 开箱即用
模板地址👉 https://github.com/gitboyzcf/uni-preset-vue3-vite

敬请期待

后续还会有新功能接入当前模板,敬请期待…






到这里就结束了,后续还会更新 前端 系列相关,还请持续关注!
感谢阅读,若有错误可以在下方评论区留言哦!!!

111


推荐文章👇


https://dhexx.cn/news/show-5426448.html

相关文章

OJ在线评测系统 思考主流OJ的实现方案 常用概念 自己的思考

OJ判题系统常用概念 OJ系统 在线判题系统 AC all accpeted 测试样例全部通过 题目介绍 题目输入 题目输出 题目输出用例 题目输入用例 不能让用户随便引入包 随便遍历 暴力破解 需要使用正确的算法 提交后不会立刻出结果 而是异步处理 提交后会生成一个提交记录 有运…

[linux 驱动]misc设备驱动详解与实战

目录 1 描述 2 结构体 2.1 miscdevice 2.2 file_operations 3 注册和注销 3.1 misc_register 3.2 misc_deregister 4 解析 misc 内核源码 4.1 核心代码 4.2 函数解析 4.2.1 class_create_file 4.2.2 class_destroy 4.2.3 register_chrdev 5 示例 5.1 简单示例 5…

UE5安卓项目打包安装

Android studio安装 参考&#xff1a;https://docs.unrealengine.com/5.2/zh-CN/how-to-set-up-android-sdk-and-ndk-for-your-unreal-engine-development-environment/ 打开android studio的官网&#xff1a;Download Android Studio & App Tools - Android Developers …

基于51单片机的自动清洗系统(自动洗衣机)

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于AT89C52单片机&#xff0c;采用DS18B20温度传感器检测温度&#xff0c;通过LCD1602显示屏显示&#xff0c;并且按键 可以加减温度的上限&#xff1b; 点击清洗按键后&#xff0c;倒计时1分钟&…

AIGC论文查重是什么?

AIGC&#xff0c;即人工智能生成内容&#xff08;Artificial Intelligence Generated Content&#xff09;&#xff0c;是指利用人工智能技术&#xff0c;如自然语言处理、机器学习等&#xff0c;自动生成文本、图像、音频等多种形式的内容。AIGC论文查重&#xff0c;顾名思义&…

深入理解 JWT、OAuth2 和 Spring Security 的特性及其相互关系

在现代应用程序中&#xff0c;安全性是至关重要的。随着微服务架构的兴起和对无状态认证的需求增加&#xff0c;JSON Web Token (JWT)、OAuth2 和 Spring Security 已成为实现安全认证和授权的关键技术。本文将详细探讨这三者的特性及其相互关系&#xff0c;帮助你理解如何利用…

2024.9.19

[ABC266F] Well-defined Path Queries on a Namori 题面翻译 题目描述 给定一张有 N N N 个点、 N N N 条边的简单连通无向图和 Q Q Q 次询问&#xff0c;对于每次询问&#xff0c;给定 x i , y i x_i,y_i xi​,yi​&#xff0c;表示两点的编号&#xff0c;请你回答第 x i …

模拟视频推到WVP推流列表

效果 1. wvp创建RTMP 2. 使用ffmpeg将本地的视频转为rtmp ffmpeg -re -i F:rtsp\123.mp4 -c copy -f flv rtmp://192.168.1.237:1935/cd/10001?sign=Z4Y3eYeSg

golang学习笔记21——golang协程管理及sync.WaitGroup的使用

推荐学习文档 golang应用级os框架&#xff0c;欢迎stargolang应用级os框架使用案例&#xff0c;欢迎star案例&#xff1a;基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识&#xff0c;这里有免费的golang学习笔…

【电路笔记】-运算放大器比较器

运算放大器比较器 文章目录 运算放大器比较器1、概述2、表示2.1 同相比较器2.2 反相比较器3、临界点转换4、施密特触发器4.1 同相触发器4.2 反相触发器4.3 应用5、总结1、概述 在前面的大多数运算放大器文章中,电路都有一个到反相输入的反馈环路。 这种设计是最常见的,因为它…