人类行为验证处理方案 —— 脱离UI组件库实现登录、注册+表单校验

目录

01: 构建登录模块基础UI结构

02: 表单校验实现原理与方案分析

表单校验的实现原理 

自定义表单校验方案分析 

文章中的方案实现

03: 基于 vee-validate 实现普适的表单校验         

04: 什么是人类行为验证?它的目的、实现原理、构建方案分别是什么? 

什么是人类行为验证 

目的 

它的实现原理是什么? 

我们如何在项目中使用它

05: 构建人类行为验证模块

06: 用户登录行为处理 

07: 用户信息获取行为

08: 退出登录操作 

09: token 超时处理 

10: 注册页面基本样式处理 

11: 处理注册行为 

12: 总结


 

01: 构建登录模块基础UI结构

- src/views
- - login-register
- - - components
- - - - header.vue
- - - login
- - - - index.vue
// src/views/login-register/components/header.vue<template><!-- 头部图标:PC端 --><div class="hidden pt-5 h-8 xl:block"><imgv-lazyclass="m-auto"src="https://res.lgdsunday.club/signlogo.png"alt=""/></div><!-- 头部图标:移动端 --><div class="h-[111px] xl:hidden"><imgv-lazyclass="dark:hidden"src="https://res.lgdsunday.club/login-bg.png"alt=""/><imgv-lazyclass="h-5 absolute top-[5%] left-[50%] translate-x-[-50%]"src="https://m.imooc.com/static/wap/static/common/img/logo-small@2x.png"alt=""srcset=""/></div>
</template>
// src/views/login-register/login/index.vue<template><divclass="relative h-screen bg-white dark:bg-zinc-800 text-center xl:bg-zinc-200"><!-- 头部图标:PC端 --><header-vue></header-vue><!-- 表单区 --><divclass="block px-3 mt-4 dark:bg-zinc-800 xl:bg-white xl:w-[388px] xl:dark:bg-zinc-900 xl:m-auto xl:mt-8 xl:py-4 xl:rounded-sm xl:shadow-lg"><h3class="mb-2 font-semibold text-base text-main dark:text-zinc-300 hidden xl:block">账号登录</h3><!-- 表单 --><vee-form @submit="onLoginHandler"><vee-fieldclass="dark:bg-zinc-800 dark:text-zinc-400 border-b-zinc-400 border-b-[1px] w-full outline-0 pb-1 px-1 text-base focus:border-b-main dark:focus:border-b-zinc-200 xl:dark:bg-zinc-900"name="username":rules="validateUsername"type="text"placeholder="用户名"autocomplete="on"v-model="loginForm.username"/><vee-error-messageclass="text-sm text-red-600 block mt-0.5 text-left"name="username"></vee-error-message><vee-fieldclass="dark:bg-zinc-800 dark:text-zinc-400 border-b-zinc-400 border-b-[1px] w-full outline-0 pb-1 px-1 text-base focus:border-b-main dark:focus:border-b-zinc-200 xl:dark:bg-zinc-900"name="password":rules="validatePassword"type="password"placeholder="密码"autocomplete="on"v-model="loginForm.password"/><vee-error-messageclass="text-sm text-red-600 block mt-0.5 text-left"name="password"></vee-error-message><div class="pt-1 pb-3 leading-[0px] text-right"><aclass="inline-block p-1 text-zinc-400 text-right dark:text-zinc-600 hover:text-zinc-600 dark:hover:text-zinc-400 text-sm duration-400 cursor-pointer"@click="onToRegister">去注册</a></div><m-buttonclass="w-full dark:bg-zinc-900 xl:dark:bg-zinc-800":loading="loading":isActiveAnim="false">登录</m-button></vee-form><div class="flex justify-around mt-4"><!-- QQ --><qq-login-vue></qq-login-vue><!-- 微信 --><wx-login-vue></wx-login-vue></div></div><!-- 人类行为验证模块 --><slider-captcha-vuev-if="isSliderCaptchaVisible"@close="isSliderCaptchaVisible = false"@success="onCaptchaSuccess"></slider-captcha-vue></div>
</template><script>
export default {name: 'login'
}
</script><script setup>
import headerVue from '../components/header.vue'
import sliderCaptchaVue from './slider-captcha.vue'
import {Form as VeeForm,Field as VeeField,ErrorMessage as VeeErrorMessage
} from 'vee-validate'
import { validateUsername, validatePassword } from '../validate'
import { ref } from 'vue'
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'
import { LOGIN_TYPE_USERNAME } from '@/constants'
import qqLoginVue from './qq-login.vue'
import wxLoginVue from './weixin-login.vue'const store = useStore()
const router = useRouter()// 控制 sliderCaptcha 展示
const isSliderCaptchaVisible = ref(false)/*** 登录触发*/
const onLoginHandler = () => {isSliderCaptchaVisible.value = true
}/*** 人类行为验证通过*/
const onCaptchaSuccess = async () => {isSliderCaptchaVisible.value = false// 登录操作onLogin()
}// 登录时的 loading
const loading = ref(false)
// 用户输入的用户名和密码
const loginForm = ref({username: '',password: ''
})
/*** 用户登录行为*/
const onLogin = async () => {loading.value = true// 执行登录操作try {await store.dispatch('user/login', {...loginForm.value,loginType: LOGIN_TYPE_USERNAME})} finally {loading.value = false}router.push('/')
}/*** 进入注册页面*/
const onToRegister = () => {// 配置跳转方式store.commit('app/changeRouterType', 'push')router.push('/register')
}
</script><style lang="scss" scoped></style>

02: 表单校验实现原理与方案分析

        在绝大多数的情况下,我们进行登录时,都会通过 UI 组件库 实现表单校验功能。但是在没有 UI 组件库 的情况下,我们应该如何进行表单校验呢?

想要搞明白这一点,我们首先就需要搞明白表单校验的 实现原理。 

表单校验的实现原理 

我们知道,所谓表单校验,指的是:

        1. 在某一个时机下(失去焦点、内容变化)

        2. 检查表单元素中的 value 是否符合某个条件(校验条件)

        3. 如果不符合,则给出对应的提示

根据以上描述,我们所需要关注的,其实就是三点内容:

        1. 监听表单元素的对应时机

        2. 检查内容是否匹配校验条件

        3. 根据检查结果,展示对应提示

自定义表单校验方案分析 

根据以上原理描述,如果我们想要自定义一套表单校验的功能逻辑,是不是就比较简单了:

        1. 创建对应的 field 输入框组件

        2. 该组件中,包含两个元素:

                1. input 输入框

                2. span 表示错误提示

3. 监听 input 输入框的 blur 失去焦点 事件

4. 根据 input 的 value 判断是否满足一个或多个指定的条件(比如:是否为空)

5. 如果不满足,则展示 span 标签,表示错误提示消息

文章中的方案实现

        根据以上描述,我们确实可以实现一个基础的表单校验。但是这样的表单校验组件,很难具有 普适 性,因为实际开发中,表单校验的场景多种多样。比如:国际化处理。 

        把它抽离成一个 通用组件 意义并不大。咱们在文章中,就不会专门去实现这样的一个组件。而是会采用一种更加普适的方式。

        这种方式就是:vee-validate

        vee-validate 是一个 vue 中专门做表单校验的库,该库更加具有 普适 性,也更加适合大家在实际开发中的使用。

03: 基于 vee-validate 实现普适的表单校验         

- src/views/login-register
- - validate.js
// 关键代码import {Form as VeeForm,Field as VeeField,ErrorMessage as VeeErrorMessage
} from 'vee-validate'// 三个组件的使用
// src/views/login-register/validate.js/*** 用户名的表单校验*/
export const validateUsername = (value) => {if (!value) {return '用户名为必填的'}if (value.length < 3 || value.length > 12) {return '用户名应该在 3-12 位之间'}return true
}/*** 密码的表单校验*/
export const validatePassword = (value) => {if (!value) {return '密码为必填的'}if (value.length < 6 || value.length > 12) {return '密码应该在 6-12 位之间'}return true
}/*** 确认密码的表单校验*/
export const validateConfirmPassword = (value, password) => {if (value !== password[0]) {return '两次密码输入必须一致'}return true
}

04: 什么是人类行为验证?它的目的、实现原理、构建方案分别是什么? 

当表单校验完成之后,接下来我们就来处理 人类行为验证 模块。

想要搞清楚 人类行为验证,就需要搞明白三点内容:

        1. 什么是人类行为验证。

        2. 它的目的是什么。

        3. 它的实现原理是什么。

        4. 我们应该如何在项目中使用它。

什么是人类行为验证 

在我们日常使用的应用中,人类行为验证其实已经无处不在了。

比如大家应该都见过如下场景:

以上场景,均属于人类行为验证模块。

目的 

为什么需要有这样的一个东西呢?这样的一个东西对用户而言是非常讨厌的一个操作。

想要搞明白这个问题,大家就需要先搞清楚现在的应用面临的一个问题。

        假如在一个博客系统中,它会根据博客的访问量进行首页排名。假设有一个人,写了一段脚本代码,构建出巨量的 IP 来不断地访问一个指定的博客。这个博客就会被顶到非常靠前的访问位置中。 

        又假如:在某些投票或者砍价的应用中,也有人利用一段脚本代码,伪造出巨量的用户去进行投票或者砍价的行为,这样的投票或者砍价是不是也就失去了原本的意义。

        针对以上这种场景,我们应该如何防止呢?如何能够判断出,当前进行“投票”的操作是 进行的,而不是 机器 进行的呢?

        想要解决这个问题,就需要使用到 人类行为验证 了。

        简单来说,人类行为验证的目的就是:明确当前的操作是人完成的,而非机器。 

它的实现原理是什么? 

想要完成这样的判断,并且让判断准确,其实是非常复杂的:

        人机验证通过对用户的行为数据、设备特征与网络数据构建多维度数据分析,采用完整的可信前端安全方案,保证数据采集的真实性、有效性。 比如以下几个方面(包括但不仅限于):

        1. 浏览器特征检查:所有浏览器都有差异,可以通过各种前端相关手段检查浏览器环境的真实性。

        2. 鼠标事件(click、move、hover、leave)。

        3. 页面窗口(size、scroll、坐标)。

        4. cookie。

通过收集到的多维度数据,分析并建立人类行为模型,以此来判断用户是否是一个机器人。

以这样的滚动为例:

        人进行的拖动拼图和机器进行的拖动拼图,两者的 鼠标行为轨迹 是不同的。这个不同就是区分人和机器的关键。 

我们如何在项目中使用它

目前人类行为验证的实现方案,主要分为两种:

1. 收费平台,年费在几万到几十万不等,有专门的技术人员帮助对接:

        极验

        网易易盾

2. 免费开源,验证的精准度需要看服务端的能力:

        gitee 开源的 SliderCaptcha

我们这里主要是使用这个开源的 SliderCaptcha 实现。

大家在实际项目中可以根据实际情况进行处理。 

05: 构建人类行为验证模块

- src/views/login-register/login
- - slider-captcha.vue
// src/views/login-register/login/slider-captcha.vue<template><divclass="fixed top-[20%] left-[50%] translate-x-[-50%] w-[340px] h-[270px] text-sm bg-white dark:bg-zinc-800 rounded border border-zinc-200 dark:border-zinc-900 shadow-3xl"><div class="flex items-center h-5 text-left px-1 mb-1"><span class="flex-grow dark:text-zinc-200">请完成安全验证</span><m-svg-iconname="refresh"fillClass="fill-zinc-900 dark:fill-zinc-200"class="w-3 h-3 p-0.5 rounded-sm duration-300 cursor-pointer hover:bg-zinc-200 dark:hover:bg-zinc-900"@click="onReset"></m-svg-icon><m-svg-iconname="close"fillClass="fill-zinc-900 dark:fill-zinc-200"class="ml-2 w-3 h-3 p-0.5 rounded-sm duration-300 cursor-pointer hover:bg-zinc-200 dark:hover:bg-zinc-900"@click="onClose"></m-svg-icon></div><div id="captcha"></div></div>
</template><script>
const EMITS_CLOSE = 'close'
const EMITS_SUCCESS = 'success'
</script><script setup>
import '@/vendor/SliderCaptcha/slidercaptcha.min.css'
import '@/vendor/SliderCaptcha/longbow.slidercaptcha.min.js'
import { getCaptcha } from '@/api/sys'
import { onMounted } from 'vue'const emits = defineEmits([EMITS_CLOSE, EMITS_SUCCESS])let captcha = null
onMounted(() => {captcha = sliderCaptcha({// 渲染位置id: 'captcha',// 用户拼图成功之后的回调async onSuccess(arr) {const res = await getCaptcha({behavior: arr})if (res) {emits(EMITS_SUCCESS)}},// 用户拼图失败之后的回调onFail() {console.log('onFail')},// 默认的验证方法,咱们不在此处进行验证,而是选择在用户拼图成功之后进行验证,所以此处永远返回为 trueverify() {return true}})
})/*** 重置*/
const onReset = () => {captcha.reset()
}/*** 关闭*/
const onClose = () => {emits(EMITS_CLOSE)
}
</script>
// index.html<!-- iconfont 在线图标,主要用于 sliderCaptcha --><link rel="stylesheet"href="https://at.alicdn.com/t/font_3042963_nv614canpao.css?spm=a313x.7781069.1998910419.47&file=font_3042963_nv614canpao.css" />

使用: 

// src/views/login-register/login/index.vue<template><!-- 人类行为验证模块 --><slider-captcha-vuev-if="isSliderCaptchaVisible"@close="isSliderCaptchaVisible = false"@success="onCaptchaSuccess"></slider-captcha-vue>
</template>
<script setup>
import sliderCaptchaVue from './slider-captcha.vue'// 控制 sliderCaptcha 展示
const isSliderCaptchaVisible = ref(false)/*** 登录触发*/
const onLoginHandler = () => {isSliderCaptchaVisible.value = true
}/*** 人类行为验证通过*/
const onCaptchaSuccess = async () => {isSliderCaptchaVisible.value = false// 登录操作onLogin()
}
</script>

06: 用户登录行为处理 

// src/views/login-register/login/index.vueconst store = useStore()
const router = useRouter()// 登录时的 loading
const loading = ref(false)
// 用户输入的用户名和密码
const loginForm = ref({username: '',password: ''
})
/*** 用户登录行为*/
const onLogin = async () => {loading.value = true// 执行登录操作try {await store.dispatch('user/login', {...loginForm.value,loginType: LOGIN_TYPE_USERNAME})} finally {loading.value = false}router.push('/')
}

        我们希望把所有登录逻辑都放入 vuex 中。这是一种比较常见的封装方式。token 的处理、用户信息的处理、退出登录的处理、刷新 token,都可以在一块完成。 

- src/store/modules
- - user.js
// src/store/modules/user.jsimport { loginUser, getProfile, registerUser } from '@/api/sys'
import md5 from 'md5'
import { message } from '@/libs'
import { LOGIN_TYPE_OAUTH_NO_REGISTER_CODE } from '@/constants'export default {namespaced: true,state: () => ({// 登录之后的 tokentoken: '',// 获取用户信息userInfo: {}}),mutations: {/*** 保存 token*/setToken(state, newToken) {state.token = newToken},/*** 保存用户信息*/setUserInfo(state, newInfo) {state.userInfo = newInfo}},actions: {/*** 注册*/async register(context, payload) {const { password } = payload// 注册return await registerUser({...payload,password: password ? md5(password) : ''})},/*** 登录*/async login(context, payload) {const { password } = payloadconst data = await loginUser({...payload,password: password ? md5(password) : ''})// QQ 扫码登录,用户未注册if (data.code === LOGIN_TYPE_OAUTH_NO_REGISTER_CODE) {return data.code}context.commit('setToken', data.token)context.dispatch('profile')},/*** 获取用户信息*/async profile(context) {const data = await getProfile()context.commit('setUserInfo', data)// 欢迎message('success',`欢迎您 ${data.vipLevel? '尊贵的 VIP' + data.vipLevel + ' 用户 ' + data.nickname: data.nickname} `,6000)},/*** 退出登录*/logout(context) {context.commit('setToken', '')context.commit('setUserInfo', {})// 退出登录之后,重新刷新下页面,// 因为对于前台项目而言,用户是否登录(是否为 VIP)看到的数据可能不同location.reload()}}
}
// 注意:在 src/store/index.js 中进行注册
npm i md5

07: 用户信息获取行为

企业级项目中常见的传递 token 方式:在 axios 请求头中

// src/utils/request.jsconst service = axios.create({baseURL: import.meta.env.VITE_BASE_API,timeout: 5000
})// 请求拦截器
service.interceptors.request.use((config) => {// config.headers.icode = '你需要在这里填入你的 icode'if (store.getters.token) {// 如果token存在 注入tokenconfig.headers.Authorization = `Bearer ${store.getters.token}`}return config // 必须返回配置},(error) => {return Promise.reject(error)}
)
// 代码在上一小节 src/store/modules/user.js 中。

08: 退出登录操作 

// 代码在上一小节 src/store/modules/user.js 中。
// src/views/layout/components/header/header-my.vue<script setup>
import { confirm } from '@/libs'/*** menu Item 点击事件,也可以根据其他的 key 作为判定,比如 name*/
const onItemClick = (path) => {// 有路径则进行路径跳转if (path) {// 配置跳转方式store.commit('app/changeRouterType', 'push')router.push(path)return}// 无路径则为退出登录confirm('您确定要退出登录吗?').then(() => {// 退出登录不存在跳转路径store.dispatch('user/logout')})
}
</script>

09: token 超时处理 

通常情况下 token 均具备时效性。在本文章中,token 失效后,服务端会返回 401.

当服务端返回 401 时,表示 token 超时,则需要重新登录。

对应的操作可以在 axios 的响应式拦截器中进行

// src/utils/request.jsimport axios from 'axios'
import store from '@/store'
import { message as $message } from '@/libs'const service = axios.create({baseURL: import.meta.env.VITE_BASE_API,timeout: 5000
})// 请求拦截器
service.interceptors.request.use((config) => {// config.headers.icode = '你需要在这里填入你的 icode'if (store.getters.token) {// 如果token存在 注入tokenconfig.headers.Authorization = `Bearer ${store.getters.token}`}return config // 必须返回配置},(error) => {return Promise.reject(error)}
)// 响应拦截器
service.interceptors.response.use((response) => {const { success, message, data } = response.data//   要根据success的成功与否决定下面的操作if (success) {return data} else {$message('warn', message)// TODO:业务错误return Promise.reject(new Error(message))}},// code 非 200 时,回调函数。(error) => {// 处理 token 超时问题if (error.response &&error.response.data &&error.response.data.code === 401) {// TODO: token超时store.dispatch('user/logout')}$message('error', error.response.data.message)// TODO: 提示错误消息return Promise.reject(error)}
)export default service

10: 注册页面基本样式处理 

- src/views/login-register
- - register
- - - index.vue
<template><divclass="relative h-screen bg-white dark:bg-zinc-800 text-center xl:bg-zinc-200"><!-- 头部图标 --><header-vue></header-vue><!-- 表单区 --><divclass="block px-3 mt-4 dark:bg-zinc-800 xl:bg-white xl:w-[388px] xl:dark:bg-zinc-900 xl:m-auto xl:mt-8 xl:py-4 xl:rounded-sm xl:shadow-lg"><h3class="mb-2 font-semibold text-base text-main dark:text-zinc-300 hidden xl:block">注册账号</h3><!-- 表单 --><vee-form @submit="onRegister"><!-- 用户名 --><vee-fieldclass="dark:bg-zinc-800 dark:text-zinc-400 border-b-zinc-400 border-b-[1px] w-full outline-0 pb-1 px-1 text-base focus:border-b-main dark:focus:border-b-zinc-200 xl:dark:bg-zinc-900"name="username"type="text"placeholder="用户名"autocomplete="on":rules="validateUsername"v-model="regForm.username"/><vee-error-messageclass="text-sm text-red-600 block mt-0.5 text-left"name="username"></vee-error-message><!-- 密码 --><vee-fieldclass="dark:bg-zinc-800 dark:text-zinc-400 border-b-zinc-400 border-b-[1px] w-full outline-0 pb-1 px-1 text-base focus:border-b-main dark:focus:border-b-zinc-200 xl:dark:bg-zinc-900"name="password"type="password"placeholder="密码"autocomplete="on":rules="validatePassword"v-model="regForm.password"/><vee-error-messageclass="text-sm text-red-600 block mt-0.5 text-left"name="password"></vee-error-message><!-- 确认密码 --><vee-fieldclass="dark:bg-zinc-800 dark:text-zinc-400 border-b-zinc-400 border-b-[1px] w-full outline-0 pb-1 px-1 text-base focus:border-b-main dark:focus:border-b-zinc-200 xl:dark:bg-zinc-900"name="confirmPassword"type="password"placeholder="确认密码"autocomplete="on"rules="validateConfirmPassword:@password"v-model="regForm.confirmPassword"/><vee-error-messageclass="text-sm text-red-600 block mt-0.5 text-left"name="confirmPassword"></vee-error-message><div class="pt-1 pb-3 leading-[0px] text-right"><div class="mb-2"><aclass="inline-block p-1 text-zinc-400 text-right dark:text-zinc-600 hover:text-zinc-600 dark:hover:text-zinc-400 text-sm duration-400 cursor-pointer"target="__black"@click="onToLogin">去登录</a></div><div class="text-center"><aclass="text-zinc-400 dark:text-zinc-600 hover:text-zinc-600 dark:hover:text-zinc-400 text-sm duration-400"href="https://m.imooc.com/newfaq?id=89"target="__black">注册即同意《慕课网注册协议》</a></div></div><m-buttonclass="w-full dark:bg-zinc-900 xl:dark:bg-zinc-800":isActiveAnim="false":loading="loading">立即注册</m-button></vee-form></div></div>
</template><script setup>
import headerVue from '../components/header.vue'
import {Form as VeeForm,Field as VeeField,ErrorMessage as VeeErrorMessage,defineRule
} from 'vee-validate'
import {validateUsername,validatePassword,validateConfirmPassword
} from '../validate'
import { LOGIN_TYPE_USERNAME } from '@/constants'
import { ref } from 'vue'
import { useStore } from 'vuex'
import { useRouter, useRoute } from 'vue-router'const store = useStore()
const router = useRouter()
const route = useRoute()/*** 插入规则*/
defineRule('validateConfirmPassword', validateConfirmPassword)/*** 进入登录页面*/
const onToLogin = () => {// 配置跳转方式store.commit('app/changeRouterType', 'push')router.push('/login')
}// 数据源
const regForm = ref({username: '',password: '',confirmPassword: ''
})
// loading
const loading = ref(false)
console.log(route)
/*** 触发注册*/
const onRegister = async () => {loading.value = truetry {const payload = {username: regForm.value.username,password: regForm.value.password}// 触发注册,携带第三方数据await store.dispatch('user/register', {...payload,...route.query})// 注册成功,触发登录await store.dispatch('user/login', {...payload,loginType: LOGIN_TYPE_USERNAME})} finally {loading.value = false}router.push('/')
}
</script><style lang="scss" scoped></style>

确认密码 要关联到 密码,这样的关联操作 需要进行一个单独的注册。

// src/views/login-register/validate.js/*** 确认密码的表单校验*/
export const validateConfirmPassword = (value, password) => {if (value !== password[0]) {return '两次密码输入必须一致'}return true
}// register/index.vue 中使用代码import { defineRule } from 'vee-validate'
import { validateConfirmPassword } from '../validate'/*** 插入规则*/
defineRule('validateConfirmPassword', validateConfirmPassword)<vee-field      placeholder="确认密码"autocomplete="on"rules="validateConfirmPassword:@password"
/>

11: 处理注册行为 

// src/store/modules/user.jsexport default {……actions: {……/*** 注册*/async register(context, payload) {const { password } = payload// 注册return await registerUser({...payload,password: password ? md5(password) : ''})},}
}
// src/views/login-register/register/index.vue
// 代码在上一小节中

12: 总结

在本篇文章中,我们主要处理了两块内容:

1. 人类行为验证

        1. 是什么

        2. 目的

        3. 实现原理

        4. 构建方案

2. 表单验证原理 以及在实际开发中 通过 vee-validate 实现表单验证功能

登录处理完成之后,接下来我们就需要处理用户的信息展示和修改了。

在用户信息展示和修改中,我们将接触到新的通用组件和图片裁剪、上传的概念。 

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

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

相关文章

UE_地编教程_创建地形洞材质

个人学习笔记&#xff0c;不喜勿喷。侵权立删&#xff01; 使用地形洞材质来遮罩地形上特定位置的可视性和碰撞。如要在山脉侧面创建进入洞穴的入口&#xff0c;此操作将非常有用。可使用地形材质和地形洞材质的相同材质&#xff0c;但注意&#xff1a;对比不使用不透明蒙版的…

AI大模型探索之路-实战篇4:深入DB-GPT数据应用开发框架调研

目录 前言一、DB-GPT总体概述二、DB-GPT关键特性1、私域问答&数据处理&RAG2、多数据源&GBI3、多模型管理4、自动化微调5、Data-Driven Multi-Agents&Plugins6、隐私安全 三、服务器资源准备1、创建实例2、打开jupyterLab 四、DB-GPT启动1、激活 conda 环境2、切…

docker安装etcd

1.查找etcd镜像 docker search etcdNAME: 镜像仓库源的名称 DESCRIPTION: 镜像的描述 STARS: 类似 Github 里面的 star&#xff0c;表示点赞、喜欢的意思。 OFFICIAL: 是否 docker 官方发布 2.拖取镜像并生成对应容器 docker run --name etcd -d -p 2379:2379 -p 2380:2380 …

校园一体式气象站功能特点与应用

TH-XQ4随着教育理念的更新和科技的发展&#xff0c;校园一体式气象站在现代校园中的应用越来越广泛。它不仅为学生提供了实时、准确的气象数据&#xff0c;还成为了推动科学教育、培养学生实践能力和环保意识的重要工具。本文将从功能、特点和应用三个方面对校园一体式气象站进…

Python学习---利用Python操作数据库

如何理解连接connection和游标 cursor&#xff1f; connection就像是连接出发地和目的地的高速公路cursor就像是在高速公路上的货车-拉货我们使用游标就可以完成对数据的操作当我们完成操作完成后就可以停下货车&#xff0c;然后公路再停止使用。 pysql实现查询 ""…

使用微信开发者工具真机调试的时候总是提示“tapShareButton WebviewId: xxxxx not foun ”

提示 机型 Android手机 调试型号 真机调试1.0 问题解决 由于真机调试1.0版本属于稳定版本&#xff0c;但是没想到会出现这个问题&#xff0c;所以想要解决真机调试的时候点击转发按钮调用 onShareAppMessage 方法的时候需要将真机调试切换至2.0版本。 onShareAppMessage 方…

JavaScript 新特性:新增声明命令与解构赋值的强大功能

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; ES5、ES6介绍 文章目录 &#x1f4af;声明命令 let、const&#x1f35f;1 let声明符&a…

【人工智能】数据分析与机器学习——泰坦尼克号(更新中)

1912年4月15日&#xff0c;泰坦尼克号在首次航行期间撞上冰山后沉没&#xff0c;船上共有2224名乘客和乘务人员&#xff0c;最终有1502人遇难。沉船导致大量伤亡的重要原因之一是&#xff0c;没有足够的救生艇给乘客和船员。虽然从这样的悲剧性事故中幸存下来有一定的运气因素&…

微信小程序进阶(1)--自定义组件

自定义组件 1.1 什么是自定义组件 开发文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/ 小程序中常常会有些通用的交互模块&#xff0c;比如&#xff1a;下拉选择列表、搜索框、日期选择器等&#xff1b;这些界面交互模块可…

数据挖掘案例-航空公司客户价值分析

文章目录 1. 案例背景2. 分析方法与过程2.1 分析流程步骤2.2 分析过程1. 数据探索分析2. 描述性统计分析3. 分布分析1.客户基本信息分布分析2. 客户乘机信息分布分析3. 客户积分信息分布分析 4. 相关性分析 3. 数据预处理3.1 数据清洗3.2 属性约束3. 3 数据转换 4. 模型构建4. …

超融合架构下,虚拟机高可用机制如何构建?

作者&#xff1a;SmartX 产品部 钟锦锌 虚拟机高可用&#xff08;High Availability&#xff0c;简称 HA&#xff09;是虚拟化/超融合平台最常用、关键的功能之一&#xff0c;可在服务器发生故障时通过重建业务虚拟机以降低故障对业务带来的影响。因此&#xff0c;为了充分保障…

ubuntu22.04下 easyconnect+输入法安装

先使用对应ubuntu版本的easyconnect安装 sudo dpkg -i EasyConnect_x64_7_6_7_3.deb 下载压缩包servicePack&#xff0c;并解压缩 cd 下载路径/servicePack sudo cp * /usr/share/sangfor/EasyConnect/ 打开easyConnect /usr/share/sangfor/EasyConnect/EasyConnect 此处…

pid中的d到底是什么意思?微分到底是用来做什么的,什么情况下用,避免入坑实际案例中的使用-----------PDI中的D阻尼调节

1,PID中表示的含义是什么? 比例&#xff08;proportional&#xff09;&#xff1a;放大比例-------表示现在 0.2 积分&#xff08;integral&#xff09;&#xff1a;误差积分------过去 0.04 微分 &#xff08;derivative&#xff09;&#xff1a;阻尼 ------未来 0.002 在调节…

IDEA设置运行内存

1.开启内存指示条​​​​​​​ 查看idea右下角​​​​​​​ 2.环境变量查看ideaVM地址&#xff0c;没有的话那就是默认的配置文件&#xff1a; idea 安装 bin 目录下 idea64.exe.vmoptions 3.去对应路径修改内存参数大小 4.重启IDEA&#xff0c;end

体育赛事直播系统源码开发:社区论坛模块如何实现引流与增收双赢

在当今数字化时代&#xff0c;体育直播平台不仅是赛事观看的窗口&#xff0c;更是一个互动和交流的社区&#xff0c;以及是一场关于用户体验、用户粘性以及商业模式创新的综合较量。为了在这片红海市场中脱颖而出&#xff0c;平台必须采取更加精细化和多元化的运营策略。其中&a…

前端命令行部署

最近接了一个项目&#xff0c;发版本需要把dist包给后端部署服务&#xff0c;再加上产品那边需求不稳定&#xff0c;改了又改&#xff0c;一天要发好几个&#xff0c;不仅跟我配合的后端不胜其烦&#xff0c;本人也是很烦。最近在网上看到一个npm自主部署的包–deploy cli工具&…

香橙派 AIpro开发板:开启AI视觉的无限可能

前言 在当今这个由数据和智能驱动的时代&#xff0c; 人工智能&#xff08;AI&#xff09; 已经成为推动技术创新和实现自动化的关键。 特别是在计算机视觉领域&#xff0c;AI的潜能被无限放大&#xff0c;它使得机器能够“看见”并理解视觉世界&#xff0c;从而执行复杂的任务…

LangChain 0.2 - 对话式RAG

文章目录 一、项目说明二、设置1、引入依赖2、LangSmith 三、Chains1、添加聊天记录Contextualizing the question聊天记录状态管理 2、合并 四、Agents1、检索工具2、代理建造者3、合并 五、下一步 本文翻译整理自&#xff1a;Conversational RAG https://python.langchain.co…

加宽全连接

一、Functional API 搭建神经网络模型 1.对宽深神经网络模型进行手写数字识别&#xff1a; 运行代码&#xff1a; inputs keras.layers.Input(shapeX_train.shape[1:]) hidden1 keras.layers.Dense(300,activation"relu")(inputs) hidden2 keras.layers.Dense(…