Vue3入门 - 登录功能开发(Vue3+ts+Pinia+Element Plus)

news2024/11/16 19:46:21

        Vue3中实现登录功能,通常涉及到创建一个表单,用户输入用户名和密码,然后将信息发送到后端进行验证,得到响应结果后作出相应操作。

一、创建项目

        这里他用pnpm进行项目的创建的,所以需要事先全局安装pnpm(在安装pnpm前,先确认本地电脑上是否已安装nodejs),命令如下:

npm install -g pnpm

1.1 创建vue

        使用pnpm创建vue项目命令如下:

pnpm create vue

        执行后作出相应选择,选择你项目中需要的选项即可。示例如下:

D:\workspace\vscode>pnpm create vue

Vue.js - The Progressive JavaScript Framework

√ 请输入项目名称: ... vue-project
√ 是否使用 TypeScript 语法? ... 否 / 是
√ 是否启用 JSX 支持? ... 否 / 是
√ 是否引入 Vue Router 进行单页面应用开发? ... 否 / 是
√ 是否引入 Pinia 用于状态管理? ... 否 / 是
√ 是否引入 Vitest 用于单元测试? ... 否 / 是
√ 是否要引入一款端到端(End to End)测试工具? » 不需要
√ 是否引入 ESLint 用于代码质量检测? ... 否 / 是
√ 是否引入 Prettier 用于代码格式化? ... 否 / 是
√ 是否引入 Vue DevTools 7 扩展用于调试? (试验阶段) ... 否 / 是

正在初始化项目 D:\workspace\vscode\vue-project...

项目初始化完成,可执行以下命令:

  cd vue-project
  pnpm install
  pnpm format
  pnpm dev

1.2 初始化项目

        当项目创建完成后,根据提示命令对项目进行初始化,先输入命令进入项目目录:

cd vue-project

        然后执行install命令,初始化项目:

D:\workspace\vscode\vue-project>pnpm install

   ╭──────────────────────────────────────────────────────────────────╮
   │                                                                  │
   │                Update available! 9.7.0 → 9.10.0.                 │
   │   Changelog: https://github.com/pnpm/pnpm/releases/tag/v9.10.0   │
   │                Run "pnpm add -g pnpm" to update.                 │
   │                                                                  │
   │         Follow @pnpmjs for updates: https://x.com/pnpmjs         │
   │                                                                  │
   ╰──────────────────────────────────────────────────────────────────╯

 WARN  5 deprecated subdependencies found: @humanwhocodes/config-array@0.11.14, 
@humanwhocodes/object-schema@2.0.3, glob@7.2.3, inflight@1.0.6, rimraf@3.0.2
Packages: +425
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++
Progress: resolved 463, reused 272, downloaded 153, added 425, done
node_modules/.pnpm/esbuild@0.21.5/node_modules/esbuild: Running postinstall script...
node_modules/.pnpm/esbuild@0.21.5/node_modules/esbuild: Running postinstall script, 
done in 341msstinstall script, done
in 209ms

dependencies:
+ pinia 2.2.2
+ vue 3.5.3
+ vue-router 4.4.3

devDependencies:
+ @rushstack/eslint-patch 1.10.4
+ @tsconfig/node20 20.1.4
+ @types/jsdom 21.1.7
+ @types/node 20.16.5 (22.5.4 is available)
+ @vitejs/plugin-vue 5.1.3
+ @vitejs/plugin-vue-jsx 4.0.1
+ @vue/eslint-config-prettier 9.0.0
+ @vue/eslint-config-typescript 13.0.0
+ @vue/test-utils 2.4.6
+ @vue/tsconfig 0.5.1
+ eslint 8.57.0 (9.10.0 is available)
+ eslint-plugin-vue 9.28.0
+ jsdom 24.1.3 (25.0.0 is available)
+ npm-run-all2 6.2.2
+ prettier 3.3.3
+ typescript 5.4.5 (5.6.2 is available)
+ vite 5.4.3
+ vite-plugin-vue-devtools 7.4.4
+ vitest 1.6.0 (2.0.5 is available)
+ vue-tsc 2.1.6

Done in 9.8s

        初始化项目后,则可以运行项目了,当执行pnpm dev后您会发现,瞬间项目就运行起来了,比vue2+webpack时快了很多。

D:\workspace\vscode\vue-project>pnpm dev

> vue-project@0.0.0 dev D:\workspace\vscode\vue-project
> vite


  VITE v5.4.3  ready in 1285 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  Vue DevTools: Open http://localhost:5173/__devtools__/ as a separate window
  ➜  Vue DevTools: Press Alt(⌥)+Shift(⇧)+D in App to toggle the Vue DevTools

  ➜  press h + enter to show help

二、Pinia

        在创建项目时,我们就已经选择安装了Pinia,这里就不重复安装了。

        pinia是Vue的存储库,它允许您跨组件/页面共享状态。它Vuex的替代品,其功能和性能更优于vuex,在后期使用中会逐渐被大家发现。

        这里我们先使用pinia全局存储用户信息、接口访问令牌、菜单列表等数据,当然这些只是作为一个项目的基础部分,其他共享信息可根据你们的项目需求进行添加。

        关于这部分,就不细讲了,之前一篇已详细讲解过,地址:Vue3入门 - Pinia使用(替代Vuex)-CSDN博客

        Pinia官方文档:Pinia 中文文档

三、路由创建

        在创建Vue项目里,如果你已在选项中选择安装了vue-router,则此时您的目录中肯定已有router/index.ts文件,代码如下:

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView
    },
    {
      path: '/about',
      name: 'about',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('../views/AboutView.vue')
    }
  ]
})

export default router

        此时,我们将目录中多余的文件删除,创建首页、登录页面、404页面、layout文件等,如下图:

  • components/LayoutIndex.vue:主界面公共框架页面
  • views/NotFound.vue:404页面
  • views/HomeIndex.vue:首页
  • views/LoginIndex.vue:登录界面

3.1 App.vue

        首页清理App.vue中代码,将多余代码全部清除,保留RouterView视图组件,代码如下:

<script setup lang="ts">
import { RouterView } from 'vue-router'
</script>

<template>
  <RouterView />
</template>

<style>
*{ margin: 0; padding: 0; }

#app{
  width: 100%;
  min-height: 100%;
  font-size: 12px;
  font-family: 'Segoe UI', Tahoma, Verdana, sans-serif;
}
</style>

3.2 LayoutIndex.vue

        在components目录中创建LayoutIndex.vue组件,用于编写主界面框,及主界面头部、左侧导航后期都将在此组件中引用并展示。由于该篇只讲登录界面,还未涉及主界面,所以先添加视图组件留位占坑,代码如下:

<script setup lang="ts">
import { RouterView } from 'vue-router'
</script>
<template>
  <RouterView></RouterView>
</template>

3.3 NotFound.vue

        当路由错误,找不到对应页面时,通过路由匹配跳转到404页面,显示页面不存在等错误提示。由于是演示界面,样式就随便写了,大家可自行优化。代码如下:

<template>
<div class="error-wrap">
    <h3>错误:页面不存在~</h3>
    <p class="intro">404</p>
</div>
</template>
<style scoped>
.error-wrap{ 
    width: 100%; 
    min-height: 100vh; 
    text-align: center; 
    display: flex; 
    justify-content: center; 
    align-items: center; 
    flex-direction: column; 
}
.error-wrap h3{ font-size: 30px; margin-bottom: 20px; }
.error-wrap p.intro{ font-size: 62px; font-weight: bold; }
</style>

3.4 HomeIndex.vue

        首页也先留坑占位,等后续讲了主界面时,再详细说明。代码如下:

<template>
  <div>
    首页
  </div>
</template>

3.5 LoginIndex.vue

        登录界面也先留坑,待下面讲到“登录界面开发”时再细讲,代码如下:

<template>
<div>
    <h3>登录页面</h3>
</div>
</template>

3.6 路由配置

        当基本页面创建完成后,我们就可以进入router/index.ts文件中,对路由进行配置了。代码如下:

import { createRouter, createWebHistory } from 'vue-router'
import LayoutIndex from '@/components/LayoutIndex.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'index',
      component: LayoutIndex,
      redirect: "/home",
      children: [
        { 
          path: '/home', 
          name: 'home', 
          meta: {
            requiresAuth: true,        // 标识该路由需要校验用户是否登录
            title: "首页"
          },
          component: () => import('@/views/HomeIndex.vue') 
        }
      ]
    },
    {
      path: '/login',
      name: 'login',
      meta: {
        title: "登录界面"
      },
      component: () => import('@/views/LoginIndex.vue')
    }, 
    {
      path: '/:catchAll(.*)',
      name: "NotFound",
      component: () => import('@/views/NotFound.vue')
    }
  ]
})

export default router

        当上述代码配置完成后,则可以通过浏览器地址栏,进行路由跳转了。

注意:Vue3中是使用 :pathMach(.*) 或者 :catchAll(.*) 匹配所有路径,Vue2中是使用"*"号。如果在Vue3中使用星号,则会报错:Error: Catch all routes ("*") must now be defined using a param with a custom regexp.

3.7 导航守卫

        正如其名,vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的、单个路由独享的、或者组件级的。

        这里使用是全局前置守卫,可以使用router.beforeEach注册,示例如下:

const router = createRouter({ ... })

router.beforeEach((to, from) => {
  // ...
  // 返回 false 以取消导航
  return false
})

        守卫方法参数:

序号字段说明
1to即将要进入的目标
2from当前导航正要离开的路由
3next可选参数。建议使用Vue3新写法,通过返回值进行跳转。

        返回的值如下:

序号返回值说明
1false取消当前的导航。如果浏览器URL改变了(可能是用户手动或者浏览器后退按钮),那么URL地址会重置到from路由对应的址址。
2路由地址通过一个路由地址重写向到一个不同的地址,如果调用router.push(),且可以传入诸如replace: true或name: 'home' 之类的选项。它会中断当前的导航,同时用相同的from创建一个新导航。

3.7.1 新增是否登录校验

        这里我们在stores/modules/login.ts文件中,新增校验用户是否登录的计算属性,代码如下:

import { defineStore } from 'pinia'
import type { UserInfoType } from '@/types/global'
import { useUserInfoStore, useAccessTokenStore } from '../global'
import { computed } from 'vue'

// 登录统一处理用户信息和访问令牌
export const useLoginStore = defineStore('login', () => {
  const { userInfoChange, user_info } = useUserInfoStore()
  const { accessTokenChange, access_token } = useAccessTokenStore()
  // 定义getters,判断用户是否登录(当用户id不等于undefined存在时,并且访问令牌不为空时,表示用户已登录)
  const is_login = computed(() => 'undefined' !== typeof user_info.value['id'] && access_token.value != '')
  // 定义actions修改用户信息和访问令牌令牌
  const loginChange = (_userInfo: UserInfoType, _token: string) => {
    userInfoChange(_userInfo)
    accessTokenChange(_token)
  }
  return { is_login, loginChange }
})

3.7.2 守卫校验登录状态

        在router/index.ts文件中,引入useLoginStore,并在导航卫士执行时,判断该用户是否登录并作出相应操作,代码如下:

import { createRouter, createWebHistory } from 'vue-router'
import LayoutIndex from '@/components/LayoutIndex.vue'
import { useLoginStore } from '@/stores'

const router = createRouter({
  // 略...
})

// 登录路由地址
const loginPath = '/login'
// 路由卫士
router.beforeEach((to) => {
  const stores = useLoginStore() // 获取用户状态库
  if(to.meta){
    // 修改界面标题
    if('undefined' !== typeof to.meta.title) document.title = to.meta.title
    // 该路由需要校验登录状态,并且用户未登录,则跳转到登录界面
    if (to.meta.requiresAuth && !stores.is_login && to.path != loginPath) return loginPath
  }
})

export default router

        此时上述代码在 document.title = to.meta.title处会报错:Type "{} | null" cannot be assigned to type "string".Cannot assign type "null" to type "string"。意思这里可能会给document.title赋值一个{}或null值,将其作以下修改:

document.title = to.meta.title || ''

        此时则会报错:Cannot assign type '{}' to type 'string'。意思不能将类型"{}"分配给类型“string”。官方给出的解决方式是扩展RouteMeta接口来输入meta字段。代码如下:

// 在 src/types目录下, 新建 vue-router.d.ts类型声明文件
import "vue-router"
declare module 'vue-router' {
  interface RouteMeta {
    title?: string        // 可选
  }
}

         上述问题都解决后,输入不存在路由则会跳转到404页面;当输入“/home”主页路径则会直接跳转到登录界面,这是因为首页路由在meta中添加requiresAuth为true,当进入该页面前,导航守卫中判断用户是否登录,未登录则会跳转到登录界面。

四、Element Plus

        在讲axios请求前,我们先讲下Element Plus的安装;写过vue2的朋友肯定知道,在Vue2中一般是使用Element-UI组件库,在Vue3中开始使用Element Plus。

4.1 安装

pnpm add element-plus

4.2 引用

        打开main.ts文件,在内部添加Element Plus的样式引入,以及组件安装。代码如下:

import { createApp } from 'vue'
import pinia from '@/stores'
import App from './App.vue'
import router from './router'
// 引入Element Plus样式
import 'element-plus/dist/index.css'
// 引入Element Plus
import ElementPlus from 'element-plus'

const app = createApp(App)
app.use(pinia)
app.use(router)
app.use(ElementPlus)

app.mount('#app')

4.3 自动导入

        按需导入需要使用额外的插件来导入要使用的组件,首先需要安装unplugin-vue-components 和 unplugin-auto-import这两款插件,代码如下:

pnpm add -D unplugin-vue-components unplugin-auto-import

        本次演示项目使用的是vite,配置如下:

// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  // ...
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

        如果使用webpack可去官方查看,地址:https://element-plus.org/zh-CN/guide/quickstart.html

        当上述配置完成后,我们在components目录中按驼峰模式命名的组件,则会按需直接在页面使用(注意:页面使用时,将驼峰模式修改为 - 分隔使用),代码如下:

<header-compt></header-compt>

五、axios封装

        对于一个项目,与后台交互,进行Http请求是基本需求。在Vue3中使用axios普遍,所以要进行后续开发,需要先安装Axios。

5.1 安装axios

pnpm add axios

5.2 封装axios

        在项目中,可以在组件中直接引用axios发送请求,但通常将axios作为底层库,再将其封装一个axios实例对象导出。代码如下:

import axios from 'axios'
import { ElMessage } from 'element-plus'
import { useAccessTokenStore } from '@/stores'

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

const instance = axios.create({
  baseURL: 'API请求地址',
  timeout: 1000 * 60
})

// 添加请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 获取访问令牌
    const { access_token } = useAccessTokenStore()
    // 如果令牌存在,则追加到header中
    if (access_token) config.headers['accesstoken'] = access_token
    return config
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)

// 添加响应拦截器
instance.interceptors.response.use(
  (response) => {
    if (response.data.code == 200) {
      return response.data
    }
    ElMessage.error(response.data.message) // 错误提示
    return Promise.reject(response.data)
  },
  (error) => {
    // 对响应错误做点什么
    return Promise.reject(error)
  }
)
export default instance

5.2 创建API

        当axios封装好后,在src目录下创建api文件夹,用于定义项目中所有api请求函数。示例如下:

import Request from '@/utils/request'

/**
 * 登录接口
 * @param {*} params 
 * @returns 
 */
export const loginService = (params) => {
  return Request.post("/login", params)
}

六、SASS安装

        接下来就要编写登录界面了,这里我们将要使用到CSS的预编译工具,例如有Styus、Less、Sass等,这里将使用Sass进行样式编写。安装命令如下:

pnpm add sass

        安装成功后,我们将3.3 NotFound.vue中的样式重新书写,在标签style的属性lang中赋值scss即可。代码如下:

<template>
<div class="error-wrap">
    <h3>错误:页面不存在~</h3>
    <p class="intro">404</p>
</div>
</template>
<style lang="scss" scoped>
.error-wrap{ 
    width: 100%; 
    min-height: 100vh; 
    text-align: center; 
    display: flex; 
    justify-content: center; 
    align-items: center; 
    flex-direction: column; 
    h3{ 
        font-size: 30px; 
        margin-bottom: 20px; 
    }
    p.intro{ 
        font-size: 62px; 
        font-weight: bold; 
    }
}
</style>

七、登录界面开发

7.1 页面编写

        这里css单独定义scss文件,通过@import引入到登录界面,代码如下:

.login-wrap{ width: 100%; 
    .right-large-thumb, .login-box{ 
        height: 100vh; display: flex; justify-content: center; align-items: center; 
    }
    .right-large-thumb{  background-color: aqua;
        h3{ font-size: 36px; }
    }

    .login-box{ padding: 30px; box-sizing: border-box;
        .ruleForm-box{ width: 50%; }
    }
}

vue页面,代码如下:

<script setup lang="ts">
import { reactive, ref } from 'vue'
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
import type { RuleForm } from '@/interface/user'
import { loginService } from '@/api/index'

defineOptions({
  name: 'LoginIndex'
})

const formSize = ref<ComponentSize>('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({
  name: '',
  password: ''
})

const rules = reactive<FormRules<RuleForm>>({
  name: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
  password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
})

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      // do something...
    } else {
      console.log('error submit!', fields)
    }
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}
</script>
<template>
  <div class="login-wrap">
    <el-row>
      <el-col :span="12">
        <div class="right-large-thumb">
          <h3>DEMO系统</h3>
        </div>
      </el-col>
      <el-col :span="12">
        <div class="login-box">
          <el-form
            ref="ruleFormRef"
            :model="ruleForm"
            :rules="rules"
            label-width="auto"
            class="ruleForm-box"
            :size="formSize"
            status-icon
          >
            <el-form-item label="用户" prop="name">
              <el-input v-model="ruleForm.name" />
            </el-form-item>
            <el-form-item label="密码" prop="password">
              <el-input type="password" v-model="ruleForm.password" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="submitForm(ruleFormRef)"> 登录 </el-button>
              <el-button @click="resetForm(ruleFormRef)">重置</el-button>
            </el-form-item>
          </el-form>
        </div>
      </el-col>
    </el-row>
  </div>
</template>
<style lang="scss" scoped>
@import './index.scss';
</style>

        页面样式效果如下:

7.2 API请求

        上述代码中,完成登录界面框架搭建、输入框校验等操作,当用户输入符合要求的登录信息后,将输入信息提交到后台校验,待接口响应最终结果。如果登录失败则提示用户, 要是登录成功将接口返回的用户信息和访问令牌存储到useStore中,完成登录操作步骤。

        上篇中已详细讲解过用户信息和访问令牌的useStore定义和数据持久化(地址:Vue3入门 - Pinia使用(替代Vuex)-CSDN博客),并且定义的userLoginStore统一存储用户信息和访问令牌,这里不再阐述。

代码如下:

import { reactive, ref } from 'vue'
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
import type { RuleForm } from '@/interface/user'
import { loginService } from '@/api/index'
import { useLoginStore } from '@/stores/index'
import { useRouter } from 'vue-router'

// 略...

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log('submit!')
      loginService(ruleForm)
        .then((res) => {
          console.log('success', res)
          if(res.code == 200){
            useLoginStore(res.data.userInfo, res.data.accesstoken)
            setTimeout(() => {
              const router = useRouter()
              // 返回首页
              router.push('/')
            }, 1200)
          }
        })
        .catch((e) => {
          console.error('e', e)
        })
    } else {
      console.log('error submit!', fields)
    }
  })
}

// 略...

        当用户信息缓存后,则在3.7.1中讲到的is_login则为true,此时经过导航守卫则校验通过,会直接跳转到主界面。

        登录部分就讲到这,希望对大家有所帮助~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

神经网络的非线性激活

文章目录 一、神经网络的非线性激活是什么二、非线性激活常用函数三、非线性激活的实际演示 一、神经网络的非线性激活是什么 神经网络的非线性激活函数的主要作用是引入非线性变换&#xff0c;从而使网络能够学习和逼近复杂的函数关系。在神经网络中&#xff0c;线性变换&…

[产品管理-4]:NPDP新产品开发 - 2 - 战略 - 制定企业经营战略目标的结构化方法与工具

目录 一、SWOT分析工具 1、SWOT分析工具概述 2、SWOT分析与企业战略目标制定的关系 3、SWOT分析在企业战略目标制定中的应用实例 4、SWOT分析的改进与应用建议 二、P E S T L E 分 析&#xff1a;外部环境分析 2.1 概述 1. 政治因素&#xff08;Political&#xff09; …

COCOS:(飞机大战08)子弹和飞机添加碰撞器和刚体

做两个物体的碰撞有2种方式&#xff1a;碰撞检测和触发检测 这里子弹不能和飞机使用碰撞检测&#xff0c;因为会影响到敌机的运动&#xff0c;所有选择使用触发检测 从预制体Prefabs文件中&#xff0c;将子弹Bullet1和Bullet2拖到Canvas下 选中子弹&#xff0c;添加组件&#…

多线程:java中的实现

实现1&#xff1a; 通过java.util.concurrent.atomic中的原子性数据实现 static class Counter {// 通过加锁实现同步public static int count 0;public static final Object obj new Object(); // 通过原子性的整型来实现同步public static AtomicInteger c…

DesignPattern设计模式

1 前言 1.1 内容概要 理解使用设计模式的目的掌握软件设计的SOLID原则理解单例的思想&#xff0c;并且能够设计一个单例理解工厂设计模式的思想&#xff0c;能够设计简单工厂&#xff0c;理解工厂方法了解建造者模式的思想&#xff0c;掌握其代码风格理解代理设计模式的思想&a…

应用层自定义协议与序列化

一、理解应用层 上一篇文章http://t.csdnimg.cn/931k6简单介绍了如何写tcp / udp 网络服务&#xff0c;但是其实始终是在应用层。 一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应用层。 二、再谈协议 协议是一种 "约定"。socket api 的接口, 在读…

TiDB从0到1学习笔记(精华篇)

历时四个月&#xff0c;恭喜赵老师的《TiDB从0到1》 系列文章顺利完结&#xff0c;小编再次梳理一遍文稿&#xff0c;并附注解分享给大家。 整体架构 从 TiDB 1.0 到 8.0&#xff0c;TiDB 的体系结构一直在不断演进。接下来让我们一起看看整体架构的变化。 TiDB v1 TiDB v1&…

005——栈

目录 栈 栈的定义 栈的性质 栈的应用场景 存储结构&#xff1a; Ⅰ&#xff09;采用顺序存储结构实现——顺序栈 Ⅱ&#xff09;采用链式存储结构实现——链栈-->基于单链表&#xff08;带头结点&#xff09; 栈 栈的定义 之允许在一端进行插入和删除的线性表 栈的…

安卓获取apk的公钥,用于申请app备案等

要申请app的icp备案等场景&#xff0c;需要app的 证书MD5指纹和公钥&#xff0c;示例如下&#xff1a; 步骤1&#xff1a;使用keytool从APK中提取证书 1. 打开命令行&#xff0c;cd 到你的apk目录&#xff0c;如&#xff1a;app/release 2. 解压APK文件&#xff1a; unzip yo…

一维稳态与非稳态导热的详细分析

目录 引言 一维稳态导热 应用实例&#xff1a;单层平壁导热 数值求解&#xff1a; 一维非稳态导热 应用实例&#xff1a;单层平壁的非稳态导热 温度变化阶段 表格总结&#xff1a; 引言 热传导&#xff08;Heat Conduction&#xff09;是热量在物体内部通过微观粒子的相…

批量从word切割说话人!!对于转录后的文本进行纯数据清洗切割和区分说话人-批量从word切割说话人

battle AI的全过程 文章目录 初步切割同时基于文本中提取的动词变化类别做切割以及发言人变化路径设置 迁移模型到GPUbert输出空白debugCPU能运行的语义相似度代码GPU能用了但是没有加切分规则的代码 根据动词变化切分把发言人替换老师和学生的代码读取txt的代码先区分说话人&a…

Qt常用控件——QLCDNumber

文章目录 QLCDNumber核心属性倒计时小程序倒计时小程序相关问题 QLCDNumber核心属性 QLCDNumber是专门用来显示数字的控件&#xff0c;类似于这样&#xff1a; 属性说明intValue获取的数字值(int).value获取的数字值(double)和intValue是联动的例如value设为1.5&#xff0c;in…

黑马点评22——最佳实践-批处理优化

文章目录 pipeline和mset集群模式下的批处理问题 pipeline和mset pipeline就是大数据量的导入&#xff0c;pipeline是在单机模式下的。 redis的处理耗时相比较网络传输的耗时其实是比较低的。 所以我们最好采用批处理&#xff0c; 集群模式下的批处理问题 在集群环境…

生动灵活,MegActor重磅升级!旷视科技发布MegActor-Σ:首个基于DiT的人像动画方法!

文章链接&#xff1a;https://arxiv.org/pdf/2408.14975 项目链接&#xff1a;https://megactor-ops.github.io/ 亮点直击 一种新颖的混合模态扩散Transformer&#xff08;DiT&#xff09;&#xff0c;能够有效整合音频和视觉控制信号。相较于之前基于UNet的方法&#xff0c;这…

qsort的理解--加强对指针的理解

前言&#xff1a;前面我们学习指针变量&#xff0c;数组指针变量&#xff0c;函数指针变量&#xff1b;这些实际上都是变量&#xff0c;实质上是在内存中开辟一块空间&#xff1b;而这些变量存储的都是地址。还有指针数组&#xff0c;函数指针数组&#xff0c;这指的是把多个地…

AIGC大模型扩图:Sanster/IOPaint(4)

AIGC大模型扩图&#xff1a;Sanster/IOPaint&#xff08;4&#xff09; 用大模型实现AI扩大一张图的周边区域&#xff0c;变得更大&#xff0c;当然必须契合原图&#xff0c;和原图浑然一体。 1、这次模型换用 Sanster/PowerPaint-V1-stable-diffusion-inpainting 启动&#xf…

文件对比工具--BeyondCompare

&#x1f496;简介 Beyond Compare 是一款功能强大的文件和文件夹比较工具&#xff0c;由Scooter Software开发。它可以帮助用户轻松地比较文件和文件夹的差异&#xff0c;并且可以合并变化、同步文件以及备份重要数据 &#x1f4bb;环境 windows &#x1f4d6;版本 Beyon…

RocketMQ安装与使用

什么是消息中间件 消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流&#xff0c;并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型&#xff0c;它可以在分布式环境下扩展进程间的通信。对于消息中间件&#xff0c;常见的角色大致也就有Prod…

OpenCV高阶操作

在图像处理与计算机视觉领域&#xff0c;OpenCV&#xff08;Open Source Computer Vision Library&#xff09;无疑是最为强大且广泛使用的工具之一。从基础的图像读取、 1.图片的上下&#xff0c;采样 下采样&#xff08;Downsampling&#xff09; 下采样通常用于减小图像的…

日志相关知识

1.作用 a.为了代替System.out.println()&#xff0c;可以定义格式&#xff0c;重定向文件等。 b.可以存档&#xff0c;便于追踪问题。 c.可以按级别分类&#xff0c;便于打开或关闭某些级别。 d.可以根据配置文件调整日志&#xff0c;无需修改代码。 …