2.IHRM人力资源 - 登录

一、登录页结构与表单开发

我们要实现的登录界面

image-20240109112142005

目前的登录界面

image-20240109112337473

1.1 登录页结构

复制下面的代码到views/login/index.vue页面下

image-20240109113326105

<template><div class="login-container"><div class="logo"/><div class="form"><h1>登录</h1><el-card shadow="never" class="login-card"><!--登录表单--></el-card></div></div>
</template>
<script>
export default {name: 'Login'
}
</script>
<style lang="scss">
.login-container {display: flex;align-items: stretch;height: 100vh;.logo {flex: 3;background: rgba(38, 72, 176) url(../../assets/common/login_back.png) no-repeat center / cover;border-top-right-radius: 60px;display: flex;flex-direction: column;align-items: flex-end;justify-content: center;padding: 0 100px;.icon {background: url(../../assets/common/logo.png) no-repeat 70px center /contain;width: 300px;height: 50px;margin-bottom: 50px;}p {color: #fff;font-size: 18px;margin-top: 20px;width: 300px;text-align: center;}}.form {flex: 2;display: flex;flex-direction: column;justify-content: center;padding-left: 176px;.el-card {border: none;padding: 0;}h1 {padding-left: 20px;font-size: 24px;}.el-input {width: 350px;height: 44px;.el-input__inner {background: #f4f5fb;}}.el-checkbox {color: #606266;}}
}
</style>

保存并看一下页面结构,并没有登录表单,然后下面写一下登录表单

image-20240109113238985

1.2 登录表单结构

<template><div class="login-container"><div class="logo"/><div class="form"><h1>登录</h1><el-card shadow="never" class="login-card"><!--登录表单--><!--el-form element-ui的表单--><!--el-form-item 表单中的一项--><!--el-input 输入框--><el-form><el-form-item><el-input placeholder="请输入手机号"></el-input></el-form-item><el-form-item><el-input placeholder="请输入密码"></el-input></el-form-item><!--勾选框--><el-form-item><el-checkbox>用户平台使用协议</el-checkbox></el-form-item><!--登录按钮设置一下宽度 style="width: 350px"--><el-form-item><el-button type="primary" style="width: 350px">登录</el-button></el-form-item></el-form></el-card></div></div>
</template>
<script>
export default {name: 'Login'
}
</script>
<style lang="scss">
.login-container {display: flex;align-items: stretch;height: 100vh;.logo {flex: 3;background: rgba(38, 72, 176) url(../../assets/common/login_back.png) no-repeat center / cover;border-top-right-radius: 60px;display: flex;flex-direction: column;align-items: flex-end;justify-content: center;padding: 0 100px;.icon {background: url(../../assets/common/logo.png) no-repeat 70px center /contain;width: 300px;height: 50px;margin-bottom: 50px;}p {color: #fff;font-size: 18px;margin-top: 20px;width: 300px;text-align: center;}}.form {flex: 2;display: flex;flex-direction: column;justify-content: center;padding-left: 176px;.el-card {border: none;padding: 0;}h1 {padding-left: 20px;font-size: 24px;}.el-input {width: 350px;height: 44px;.el-input__inner {background: #f4f5fb;}}.el-checkbox {color: #606266;}}
}
</style>

二、登录

我们使用了很多Element-ui的组件

官网:Element-ui组件官网

接下来我们的登录流程将会按照下图进行设计

2.1 登录表单校验

比如校验手机号的格式是否正确,密码是否符合位数

13.Vue - ref属性、props配置、mixin混入、插件、scoped样式

在element-ui中其实就是如下所示的组件,进行表单验证

我们可以通过el-form标签的ref属性获取form表单的整体实例,进而进行整体的校验

el-form标签中的:rules="rulesFrom"属性其实就是我们的校验规则,并且校验规则都会写在rulesFrom里

el-form标签中的:model="ruleForm"属性其实就是我们所绑定的数据从ruleForm数据结构中来

el-form-item标签汇总的prop="test1"属性,并且test1字段是ruleForm数据结构中的一个属性

el-input标签做一个v-model双向绑定,这样的话就能做回显了

image-20240112112319251

<template><div class="login-container"><div class="logo"/><div class="form"><h1>登录</h1><el-card shadow="never" class="login-card"><!--登录表单--><!--el-form element-ui的表单--><!--el-form-item 表单中的一项--><!--el-input 输入框--><el-form ref="loginFormRef" :model="loginFromModel" :rules="loginFromRules"><el-form-item prop="mobile"><el-input placeholder="请输入手机号" v-model="loginFromModel.mobile"></el-input></el-form-item><el-form-item prop="password"><!-- show-password是el-input属性,表示不展示input框中信息--><el-input show-password placeholder="请输入密码" v-model="loginFromModel.password"></el-input></el-form-item><!--勾选框--><el-form-item prop="isAgree"><el-checkbox v-model="loginFromModel.isAgree">用户平台使用协议</el-checkbox></el-form-item><!--登录按钮设置一下宽度 style="width: 350px"--><el-form-item prop="isAgree"><el-button @click="login" type="primary" style="width: 350px">登录</el-button></el-form-item></el-form></el-card></div></div>
</template>
export default {name: 'Login',data() {return {// 登录表单数据结构loginFromModel: {mobile: '',password: '',isAgree: false},// 登录表单规则,数据字段和loginFromModel一样,只不过值是数组的模式// 数组中的每一个对象值就是一个校验规则loginFromRules: {// 手机号校验规则mobile: [/***  required: true 必填*  trigger触发模式*    change表示只要我们不断的写就会触发校验*    blur 失去焦点才会触发校验*/{ required: true, message: '请输入手机号信息', trigger: 'blur' },// 正则表达式检验规则{ pattern: /^1[3-9]\d{9}$/, message: '手机号输入格式不合规范', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' },// 密码长度校验规则{ min: 6, max: 16, message: '密码长度在 6 到 16 个字符', trigger: 'blur' }],/*** 说明:required命令检测不了false,只能检测null/undefine/空字符串*  所以我们要自定义校验方式,其实是自定义校验方式是一个函数*    需要三个参数rule,value,callback*    rule:校验规则*    value:要校验的值*    callback: 一个必须要执行的函数(无论校验成功还是失败都要执行)*              如果校验成功的话直接执行callback()函数,如果失败的话执行callback(new Error(错误信息))*/isAgree: [{validator: (rule, value, callback) => {value ? callback() : callback(new Error('您必须勾选用户平台使用协议'))}}]}}},methods: {login() {/*** 通过表单的ref属性获取表单实例对象,并且执行此表单实例对象的validate方法校验一下* validate方法可以传入一个回调函数,并且会传入一个参数,我们可以命名为isOK*/this.$refs.loginFormRef.validate((isOK) => {if (!isOK) {// 此时isOK为false,表示校验没有通过alert('校验没有通过,请检查您的登录信息')return}// 此时isOK为true,表示校验通过了})}}
}
</script>

效果展示

image-20240113133756705

2.2 Vuex 用户模块

我们在登录表单校验之后并不是直接调用请求到后台验证用户名和密码是否正确

而是前端又调用了VuexAction,之后会再去调用登录接口并返回一个token,我们要把此token进行缓存并使用vuex进行共享,共享之后相当于我们的登录成功了,然后跳转到主页

image-20240113134425480

使用了vuex表示一定有数据要去做共享,在这里我们要共享用户的token,之后在每个页面我们都能拿到用户的token了

Vuex基础知识

vuex中的用户模块如下图所示:

image-20240113134628710

// State理解为数据源,像极了我们之前学的data,用来存放数据
const state = {token: null
}// Mutations类似java中的数据层,只对数据进行操作,不对业务操作(比如数据加减乘除)
const mutations = {// 修改tokensetToken(state, token) {state.token = token// console.log(state.token)}
}/*** actions似java中的业务逻辑层,对逻辑操作,然后向mutations发送数据,在这个业务逻辑中也可以互相调用* actions可以做异步操作*/
const actions = {/*** 参数1: context上下文对象,有commit和dispatch方法* 参数2:我们要传入的参数*/login(context, data) {console.log(context)console.log(data)// TODO 调用登录接口(代办)// 假设登录成功之后就会返回一个token,我们要将此token实现共享就要存储在state中// vuex中想修改state中数据必须通过mutations,不能直接修改state中属性context.commit('setToken', '123456')}
}// 对三个变量进行一个默认的导出
export default {// 开启命名空间。表示之后调用state/mutations/actions时必须带上模块名称namespaced: true,state,mutations,actions
}

但是现在有一个问题,当我们刷新页面之后,state.token的值会消失,所以我们要实现vuex持久化

2.3 vuex 数据持久化

这样就算我们给state.token赋值之后,但刷新页面后仍然是null,所以此时永远不能取到我们缓存的token值

// State理解为数据源,像极了我们之前学的data,用来存放数据
const state = {token: null
}

所以我们要实现vuex的数据持久化,我们要从缓存中读取state.token的初始值

编写一个工具类

image-20240113145501980

// 我们使用了一个cookie的包,其实和localStorage都可以实现前端缓存数据
import Cookies from 'js-cookie'const TokenKey = 'vue_admin_template_token'// 按需导出了三个函数    // 获取token
export function getToken() {return Cookies.get(TokenKey)
}// 设置token
export function setToken(token) {return Cookies.set(TokenKey, token)
}// 移除token
export function removeToken() {return Cookies.remove(TokenKey)
}

在vuex用户模块user.js中进行引用

// @符号表示根路径
import { getToken, setToken, removeToken } from '@/utils/auth'const state = {// 这样就算我们给state.token赋值之后,但刷新页面后仍然是null,所以此时永远不能取到我们缓存的token值// token: null// 从缓存中读取初始值token: getToken()
}const mutations = {// 修改tokensetToken(state, token) {state.token = token// console.log(state.token)// 将token值同步到缓存setToken(token)},removeToken() {// 删除vuex的tokenstate.token = null// 删除缓存中的tokenremoveToken()}
}

我们要在登录组件中进行调用vuex

methods: {login() {/*** 通过表单的ref属性获取表单实例对象,并且执行此表单实例对象的validate方法校验一下* validate方法可以传入一个回调函数,并且会传入一个参数,我们可以命名为isOK*/this.$refs.loginFormRef.validate((isOK) => {if (!isOK) {// 此时isOK为false,表示校验没有通过alert('校验没有通过,请检查您的登录信息')return}/*** 此时isOK为true,表示校验通过了,调用vuex中的用户模块* 此时因为我们开启了命名空间,传参时要带上模块名,即模块名/actions中方法名* dispatch方法是调用vuex中的actions*/this.$store.dispatch('user/login', this.loginFromModel)})}
}

效果如下图所示

image-20240113150404419

2.4 登录联调

image-20240113200709958

2.4.1 请求模块封装

编写登录接口

image-20240113200838635

// 引入封装的axios工具
import request from '@/utils/request'// 按需暴露一个登录方法
export function login(Data) {// request发送登录请求,会得到一个promise结果并将其返回return request({// 请求地址url: '/sys/login',// 请求方式method: 'POST',// 请求参数data: Data// 在ES6中上面data: Data可以简写为 data})
}

2.4.2 登录表单 调用vuex

image-20240113201636001

methods: {login() {/*** 通过表单的ref属性获取表单实例对象,并且执行此表单实例对象的validate方法校验一下* validate方法可以传入一个回调函数,并且会传入一个参数,我们可以命名为isOK*/this.$refs.loginFormRef.validate((isOK) => {if (!isOK) {// 此时isOK为false,表示校验没有通过alert('校验没有通过,请检查您的登录信息')return}/*** 此时isOK为true,表示校验通过了,调用vuex中的用户模块* 此时因为我们开启了命名空间,传参时要带上模块名,即模块名/actions中方法名* dispatch方法是调用vuex中的actions*/this.$store.dispatch('user/login', this.loginFromModel)})}
}

2.4.3 vux模块 调用登录接口

image-20240113201858115

2.4.4 登录测试

超级管理员电话号:138 0000 0002

超级管理员密码:hm#qd@23!

登录密码:网络安全需要,密码以由原来的123456 变更为hm#qd@23! , 管理员不可修改密码,新建用户的密码仍为123456

image-20240113202917035

点击登录接口

image-20240113205216951

请求信息

image-20240113205231956

响应信息

image-20240113205552222

成功存储了浏览器缓存:cookie

image-20240113205300039

image-20240113205459505

刷新之后进入了主页面

image-20240113205515377

补充:为了方便,登录表单的数据我们可以做出如下所示的修改

data() {return {// 登录表单数据结构loginFromModel: {mobile: process.env.NODE_ENV === 'development' ? '13800000002' : '',password: process.env.NODE_ENV === 'development' ? 'hm#qd@23!' : '',isAgree: isAgree: process.env.NODE_ENV === 'development'},}   

2.5 跳转主页面

当用户登录成功后直接跳转到主页面,而不是等到用户手动刷新之后才跳转到主页面

此功能是登录的最后一个功能

修改登录页面的代码

image-20240113211212413

methods: {login() {/*** 通过表单的ref属性获取表单实例对象,并且执行此表单实例对象的validate方法校验一下* validate方法可以传入一个回调函数,并且会传入一个参数,我们可以命名为isOK*/this.$refs.loginFormRef.validate(async(isOK) => {if (!isOK) {// 此时isOK为false,表示校验没有通过alert('校验没有通过,请检查您的登录信息')return}/*** 此时isOK为true,表示校验通过了,调用vuex中的用户模块* 此时因为我们开启了命名空间,传参时要带上模块名,即模块名/actions中方法名* dispatch方法是调用vuex中的actions* Vuex中的action返回的是一个promise,说明是一个异步,我们必须等到promise执行成功才能继续跳转到主页* 只要是用了await表示下方的代码一定是promise执行成功了* await 一定要写,因为我们要等待登录成功,如果失败的话就走axios中的reject*/await this.$store.dispatch('user/login', this.loginFromModel)// 登录成功后跳转到主页面//  this.$router获取到路由的实例对象,push表示我们要跳转到哪里,'/'表示我们的主页this.$router.push('/')})}
}

我们可以看一下路由的配置

image-20240113212644831

image-20240113212723553

import Vue from 'vue'
import Router from 'vue-router'Vue.use(Router)/***  Layout @/在vue中代表路径别名*  @ 符号表示当前目录的src*  @/ 表示src下的layout,而layout又是一个目录,所以会拉取index.vue文件*  即index.vue组件就是我们的路由组件,会实现二级路由
* */
import Layout from '@/layout'export const constantRoutes = [{path: '/login',component: () => import('@/views/login/index'),hidden: true},{path: '/404',component: () => import('@/views/404'),hidden: true},{path: '/',component: Layout,redirect: '/dashboard',children: [{path: 'dashboard',name: 'Dashboard',component: () => import('@/views/dashboard/index'),meta: { title: 'Dashboard', icon: 'dashboard' }}]},{path: '/example',component: Layout,redirect: '/example/table',name: 'Example',meta: { title: 'Example', icon: 'el-icon-s-help' },children: [{path: 'table',name: 'Table',component: () => import('@/views/table/index'),meta: { title: 'Table', icon: 'table' }},{path: 'tree',name: 'Tree',component: () => import('@/views/tree/index'),meta: { title: 'Tree', icon: 'tree' }}]},{path: '/form',component: Layout,children: [{path: 'index',name: 'Form',component: () => import('@/views/form/index'),meta: { title: 'Form', icon: 'form' }}]},{path: '/nested',component: Layout,redirect: '/nested/menu1',name: 'Nested',meta: {title: 'Nested',icon: 'nested'},children: [{path: 'menu1',component: () => import('@/views/nested/menu1/index'), // Parent router-viewname: 'Menu1',meta: { title: 'Menu1' },children: [{path: 'menu1-1',component: () => import('@/views/nested/menu1/menu1-1'),name: 'Menu1-1',meta: { title: 'Menu1-1' }},{path: 'menu1-2',component: () => import('@/views/nested/menu1/menu1-2'),name: 'Menu1-2',meta: { title: 'Menu1-2' },children: [{path: 'menu1-2-1',component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),name: 'Menu1-2-1',meta: { title: 'Menu1-2-1' }},{path: 'menu1-2-2',component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),name: 'Menu1-2-2',meta: { title: 'Menu1-2-2' }}]},{path: 'menu1-3',component: () => import('@/views/nested/menu1/menu1-3'),name: 'Menu1-3',meta: { title: 'Menu1-3' }}]},{path: 'menu2',component: () => import('@/views/nested/menu2/index'),name: 'Menu2',meta: { title: 'menu2' }}]},{path: 'external-link',component: Layout,children: [{path: 'https://panjiachen.github.io/vue-element-admin-site/#/',meta: { title: 'External Link', icon: 'link' }}]},// 404 page must be placed at the end !!!{ path: '*', redirect: '/404', hidden: true }
]const createRouter = () => new Router({// mode: 'history', // require service supportscrollBehavior: () => ({ y: 0 }),routes: constantRoutes
})const router = createRouter()// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {const newRouter = createRouter()router.matcher = newRouter.matcher // reset router
}export default router

跳转后如下如图所示

image-20240113213017032

三、vue-cli 代理解决跨域

下面仅仅是解决开发环境中的跨域问题,生产环境的跨域问题后面会详细解析

image-20240113151249028

如果跨域问题不解决的话,我们的请求是发送不过去的

Vue - 前端代理服务器解决跨域问题

image-20240113152849778

image-20240113152925711

我们前端页面的地址是http://localhost:9528,后端项目的地址是https://heimahr.itheima.net/,一眼可以看出前后端地址不同源

浏览器同源策略:协议、主机、端口三者一致。目前来说都不一致,如果后端不开启cors的话,前端是请求不到后端去的

解决方案:配置vue-cli代理服务器

如果是node向后端接口服务发送请求的话不会发生跨域问题,因为同源策略是浏览器的策略,并不是node的策略

相当于前端向后端请求的中间新加了一个vue-cli(node)

image-20240113153125683

修改vue.config.js文件,并且修改后记得重启项目

module.exports = {.....// 此属性中存放项目的一些配置,可以在这个位置写代理的一些属性devServer: {port: port,open: true,overlay: {warnings: false,errors: true},// before: require('./mock/mock-server.js'), 基础模板做的模拟数据// 代理属性proxy: {// path:目标服务器,想要代理到哪里'/api': {// 要代理到的目标服务器target: 'https://heimahr.itheima.net/'}}},     ....    }

四、axios 封装

image-20240113194132188

image-20240113154412346

基地址:axios中有一个baseurl的属性,表示我痛序偶axios设置了一个基础的地址,剩下的所有请求都不要再拼接这个地址了

超时时间:请求超时时间,比如设置为10s,但是我们前端发起请求而服务器10s内没有做出响应,则表示请求失败

axios中还有两个比较重要的拦截器:请求拦截器与响应拦截器

一般来说我们的请求拦截器是往请求中注入一个token,后面的请求就不用一个一个的往请求数据中添加token数据了

响应拦截器一般是负责解析一些数据结构及处理异常

拦截器的基础知识

axios——难点语法使用、拦截器的使用、取消请求功能演示

image-20240113154949071

4.1 配置axios基础信息

配置一下axios的基地址和超时时间

image-20240113170125447

我们补充一下其他文件的内容

vuex中的index.js文件

image-20240113171642993

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'Vue.use(Vuex)const store = new Vuex.Store({// 模块modules: {app,settings,user},// Vuex中的计算属性getters
})export default store

vuex中的getters.js文件

image-20240113171719736

const getters = {sidebar: state => state.app.sidebar,device: state => state.app.device,token: state => state.user.token,avatar: state => state.user.avatar,name: state => state.user.name
}
export default getters

4.2 请求拦截器

如下所示的代码我们配置了基地址、超时时间、请求拦截器

// 引入axios
import axios from 'axios'
// 引入vuex可以获取vuex实例对象,
// 我们在vuex实例对象找那个又添加了一个getters.js,其实是为了获取token数据
import store from '@/store/index.js'// 创建一个axios实例
// 根据指定配置创建一个新的axios,也就是每个新的axios都有自己的配置
var service = axios.create({// 基地址。因为后端的所有地址都有一个共同路径/apibaseURL: '/api',// 超时时间,单位为毫秒,10000毫秒为10秒timeout: 10000
})// 创建请求拦截器,并且两个参数都是回调函数
// 请求成功的时候执行第一个成功回调函数
// 请求失败的时候执行第二个失败回调函数,error就是错误对象
service.interceptors.request.use(// 成功时执行(config) => {// 将vuex中的token值放入到请求头里面if (store.getters.token) {// 存在token,才放入请求头中config.headers.Authorization = `Bearer ${store.getters.token}`}return config},// 失败时执行(error) => {// 默认支持promise的,下面语句相当于终止了当前promise的执行return Promise.reject(error)})// 默认导出axios实例对象
export default service

4.3 响应拦截器

仍然是修改如下所示文件

image-20240113193909930

image-20240113192714709

// 创建响应拦截器,并且两个参数都是回调函数
service.interceptors.response.use(// 请求成功时响应,此时的响应默认包裹了一层data,即response.data才是后台服务返回的内容(response) => {// 一次性解析出response.data中的三个属性const { data, message, success } = response.dataif (success) {// 此时响应正常return data} else {Message({ type: 'error', message: message })return Promise.reject(new Error(message))}},// 请求失败时响应(error) => {// this.$message.warning 不能这么使用,因为此时的this不是组件实例对象Message({ type: 'error', message: error.message })// 默认支持promise的,下面语句相当于终止了当前promise的执行return Promise.reject(error)}
)

4.4 axios 区分不同环境

4.4.1 介绍

开发环境:开发人员开发代码、测试的代码环境。此环境对代码的要求不是很高,可以随意更改,因为还不是面向真正的用户

生产环境:也叫做正式环境,面向真实的用户

image-20240113194614759

下面我们就要实现下图流程中的“区分环境”模块

image-20240113194259285

怎么区分不同的环境

使用环境变量,有如下两个位置

  • .env.development中设置开发环境变量 默认 NODE_ENV 值为 development

  • .env.production中设置生产环境变量默认 NODE_ENV 值为 production

image-20240113200035069

执行不同的命令,NODE_ENV的值是不同的,我们需要node命令来取出NODE_ENV的值

process.env.属性的方式获取

process.env是我们node.js的全局变量,可以通过它来取到环境变量的名称

测试一下

开发环境下:在登录界面写一个created钩子函数

created(){alert(process.env.NODE_ENV)
}

image-20240113195347418

生产环境下:

image-20240113195433408

4.4.2 区分不同环境

所以为什么要区分环境

开发环境下我们的数据随意更改,但是生产环境下数据是不能随意更改的,并且开发环境下和生产环境下的请求路径也是有所差别的

比如开发环境下请求/api路径,生产环境下走/prod-api路径

image-20240113195841574

vue-cli给我们做了一个变量规范

Vue代码中NODE_ENV之外,所有的变量必须以VUE_APP_开头

image-20240113200155923

所以接下来我们要在axios中区分不同的环境,将VUE_APP_BASE_API的值赋值给axios的基地址

image-20240113200427220

// 创建一个axios实例
// 根据指定配置创建一个新的axios,也就是每个新的axios都有自己的配置
var service = axios.create({// 基地址。因为后端的所有地址都有一个共同路径/api// 并且这个地方不能写死,否则生产环境和开发环境都走的一个地址baseURL: process.env.VUE_APP_BASE_API,// 超时时间,单位为毫秒,10000毫秒为10秒timeout: 10000
})

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

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

相关文章

CANFD数据记录仪在新能源汽车复杂路测下的应用

CANFD数据记录仪在新能源汽车复杂路测下的应用 汽车制造商在生产预批量阶段的耐久性测试中,为了检测潜在故障,必须让车辆在严酷的路况和环境下接受测试。为确保能回溯故障发生的现场情况,我们需要对测试数据精准记录与储存。这些数据是新车型优化迭代的关键,也是确保产品质量的…

【2023我的编程之旅】系统学习C语言easyx图形库心得体会

目录 引言 C语言基础知识回顾 easyx图形库介绍 如何快速学习easyx图形库 学习笔记积累 学习成果展示 学习拓展 总结 引言 首先说一下我为什么要学习C语言easyx图形库。我接触C语言easyx图形库是在我今年一月份的时候&#xff0c;也是机缘巧合之下偶然在B站上看到了鸣人…

C++力扣题目669--修剪二叉搜索树

给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&#xff0c;原有的父代子代关系都应当保留)。…

Win10不用U盘重装系统教程

在Win10电脑中&#xff0c;用户想重装电脑系统&#xff0c;但是自己没有U盘&#xff0c;想知道不用U盘要怎么完成Win10系统的重装&#xff1f;接下来小编给大家介绍Win10系统不用U盘重装的步骤&#xff0c;帮助大家轻轻松松完成系统Win10的重新安装&#xff0c;体验Win10系统的…

CF1446C Xor Tree 题解 DP Trie树

Xor Tree 传送门 题面翻译 给定你一个非负整数序列 a a a&#xff0c;保证其中每个数两两不同。 对于每个 a i a _ i ai​&#xff0c;它会向 j ≠ i j \ne i ji 且 a i ⊕ a j a_i\oplus a_j ai​⊕aj​&#xff08; ⊕ \oplus ⊕ 代表异或&#xff09;最小的 a j a…

React18-树形菜单-递归

文章目录 案例分析技巧通信展示效果实现代码技巧点技巧点 Refer to 案例分析 https://github.com/dL-hx/manager-fe/commit/85faf3b1ae9a925513583feb02b9a1c87fb462f7 从接口获取城市数据,渲染出一个树形菜单 要求: 可以展开和收起 技巧 学会递归渲染出一个树形菜单, 并点击后…

gramine运行nodejs例程

首先&#xff0c; 修改js例程代码&#xff1a; const { Web3 } require(web3); const rpcURL "https://sepolia.infura.io/v3/40b89bc0f5584056b19626b521ee5874"; const web3 new Web3(rpcURL); const address "0xde51E698b4585Af1C8322cc084ABbdbDcfe533…

C++力扣题目450--删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤&#xff1a; 首先…

Generalized Focal Loss论文个人理解

论文地址&#xff1a;Generalized Focal Loss: Towards Efficient Representation Learning for Dense Object Detection 论文解决问题 研究人员最近更加关注边界框的表示(representation)及其定位质量估计&#xff08;LQE&#xff0c;本论文中指的是IoU score&#xff09;&a…

MtimeMtimecmp

Mtime: 实时time计数器&#xff0c;可读可写&#xff1b;mtime必须按照一个固定的频率递增&#xff1b;如果count overflow了&#xff0c;则mtime的值需要卷绕&#xff1b;对于32/64的系统来说&#xff0c;mtime的值都是64bits的&#xff1b; 与mtime对应的&#xff0c;还有一…

项目中使用iframe引入html 解决路由错乱问题以及父子组件传值调用方法

iframe与外部之间传值 父组件 <iframeid"iframe"src"luckysheet/index.html"frameborder"0"scrolling"no"style"width: 100%; height: 60vh; border: 0"/>const frame document.getElementById(iframe);frame.onloa…

Python综合练习之图表

文章目录 文件目录如下图标效果timeline_bar_with_graphic.htmltable_base.html articles.jsonarticlesData.pyarticlesEchartsEntity.pyarticlesEntity.py Python学习了约一个月的时间&#xff0c;这是一篇综合练习的文章。主要做的内容是通过封装对象、实现抽象方法生成统计图…

不可预测的市场中,为何有人持续胜出?

为什么经济学家和证券分析师难以预测经济或股价走势&#xff0c;而少数投资大师却能几十年持续复利&#xff1f;这两个问题看似矛盾&#xff0c;既然无法预测&#xff0c;为何又能产生确定性的赚钱结果呢&#xff1f; 有人认为这是因为幸存者偏差。然而&#xff0c;三十年以上连…

优优嗨聚集团:债务逾期,如何应对与解决?

在现代社会&#xff0c;债务问题已成为越来越多人面临的难题。债务逾期不仅会给个人带来巨大的经济压力&#xff0c;还会影响个人信用记录&#xff0c;甚至可能引发法律纠纷。那么&#xff0c;当债务逾期时&#xff0c;我们应该如何应对与解决呢&#xff1f; 一、了解债务情况 …

C# ObjectArx 绘制表格并设置单元格合并

第一行默认是标题&#xff0c;可设置行【RowType】进行设置类型 Document doc Application.DocumentManager.MdiActiveDocument;using (Transaction tr doc.TransactionManager.StartOpenCloseTransaction()){BlockTable bt tr.GetObject(doc.Database.BlockTableId, OpenMo…

GZ075 云计算应用赛题第9套

2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷9 某企业根据自身业务需求&#xff0c;实施数字化转型&#xff0c;规划和建设数字化平台&#xff0c;平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”&#xff0c;拟采用开源OpenSt…

导轨式信号隔离变送器比例阀门线性驱动器4-20mA/0-5V/0-10V转0-165mA/0-80mA/0-1A/0-2A/0-4A

主要特性 精度、线性度误差等级&#xff1a; 0.1、0.2、0.5 级4-20mA/0-5V/0-10V 等标准信号输入0~100mA/0~500mA/0~1A/0-5A 等电流信号输出0~1V(max 2A)/0~10V/0-24V(max 5A) 等电压信号输出信号输入/信号输出 3000VDC 隔离辅助电源&#xff1a;12V、15V 或 24V 直流单电源供…

【微服务】日志搜集elasticsearch+kibana+filebeat(单机)

日志搜集eskibanafilebeat&#xff08;单机&#xff09; 日志直接输出到es中&#xff0c;适用于日志量小的项目 基于7.17.16版本 主要配置在于filebeat&#xff0c; es kibana配置改动不大 环境部署 es kibana单机环境部署 略 解压即可 常见报错&#xff0c;百度即可。 记录…

修改csdn的字体大小颜色

修改csdn的字体大小颜色 修改csdn的字体大小颜色 修改csdn的字体大小颜色一、设置字体与颜色格式二、修改字体格式三、修改字体颜色 一、设置字体与颜色格式 <font face"华文行楷" colorred size5>本字体是华文行楷&#xff0c;红色&#xff0c;5号大小</fo…

怎样获取power shell 的全部可用命令?2/5(篇幅有点长,分成5份)

在power shell 窗口中&#xff0c;有一个获取全部可用命令的命令&#xff1a;get-command&#xff0c;获取到的命令有1640多个&#xff0c;够学习了吧&#xff1f;那么&#xff0c;power shell 命令有哪些类别呢&#xff1f; PowerShell命令可以分为以下几类&#xff1a; Cmdl…