springboot + Vue前后端项目(第十七记)

项目实战第十七记

  • 写在前面
  • 1. 个人信息
    • 1.1 Person.vue
    • 1.2 设置路由并改动Header.vue
    • 1.3 动态刷新头像
      • 1.3.1 在保存个人信息时,触发方法
      • 1.3.2 父组件Manage.vue
      • 1.3.3 再将user以prop方式传递给子组件Header.vue
      • 1.3.4 Header.vue使用user
    • 1.4 效果图
  • 2. 修改密码
    • 2.1 前端页面编写(Password.vue)
    • 2.2 修改密码后退出系统
    • 2.3 路由设置并改动Header.vue
    • 2.4 后端接口编写
      • 2.4.1 UserController
      • 2.4.2 UserServiceImpl
      • 2.4.3 UserMapper
    • 2.5 页面效果
  • 总结
  • 写在最后

写在前面

  • 本篇主要讲解个人信息和修改密码页面,补充篇

1. 个人信息

1.1 Person.vue

<template><el-card style="width: 500px;"><el-form label-width="80px" size="small"><el-uploadclass="avatar-uploader"action="http://localhost:9000/file/upload":show-file-list="false":on-success="handleAvatarSuccess"><img v-if="form.avatarUrl" :src="form.avatarUrl" class="avatar"><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload><el-form-item label="用户名"><el-input v-model="form.username" autocomplete="off"></el-input></el-form-item><el-form-item label="昵称"><el-input v-model="form.nickname" autocomplete="off"></el-input></el-form-item><el-form-item label="邮箱"><el-input v-model="form.email" autocomplete="off"></el-input></el-form-item><el-form-item label="电话"><el-input v-model="form.phone" autocomplete="off"></el-input></el-form-item><el-form-item label="地址"><el-input v-model="form.address" autocomplete="off"></el-input></el-form-item><el-form-item><el-button type="primary" @click="save">确 定</el-button></el-form-item></el-form></el-card></template><script>export default {name: "Person",data() {return {form: {},user: localStorage.getItem("loginUser") ? JSON.parse(localStorage.getItem("loginUser")) : {}}},created() {this.load();},methods: {load(){const username = this.user.usernameif(!username){this.$message.error("当前无法获取用户信息!");return false}// 数据库做了唯一性处理this.request.get("/user/username/"+username).then(res => {this.form = res.data})},save() {this.request.post("/user", this.form).then(res => {if (res.code === '200') {this.$message.success("保存成功")//this.dialogFormVisible("保存成功")this.load()//向父组件传递值   触发方法this.$emit('refreshUser')} else {this.$message.error("保存失败")}})},handleAvatarSuccess(res) {console.log('===',res)//res就是文件的路径this.form.avatarUrl = res}}}</script><style>.avatar-uploader {text-align: center;padding-bottom: 10px;}.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;}.avatar-uploader .el-upload:hover {border-color: #409EFF;}.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 138px;height: 138px;line-height: 138px;text-align: center;}.avatar {width: 138px;height: 138px;display: block;}</style>

1.2 设置路由并改动Header.vue

// 拼装动态路由const manageRoute = { path: '/', name: 'Manage', component: () => import('../views/Manage.vue'), redirect: "/home", children: [{ path: 'person', name: '个人信息', component: () => import('../views/Person.vue'),meta: { title: '个人信息' }},{ path: 'password', name: '修改密码', component: () => import('../views/Password.vue'),meta: { title: '修改密码' }}] }

在Header.vue中添加

<el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/person">个人信息</router-link>
</el-dropdown-item>

1.3 动态刷新头像

当更换头像时,点击确定时,实现头像的同步更新

1.3.1 在保存个人信息时,触发方法

save() {this.request.post("/user", this.form).then(res => {if (res.code === '200') {this.$message.success("保存成功")this.load()/*这段Vue模板代码定义了一个方法,当调用这个方法时,会触发名为refreshUser的自定义事件。这个事件可以被父组件监听到,从而在父组件中执行相应的逻辑操作。**/this.$emit('refreshUser')} else {this.$message.error("保存失败")}})},

1.3.2 父组件Manage.vue

// 触发@refreshUser自定义事件
<el-main><!--  表示当前页面的子路由会在 <router-view/> 里面显示     --><router-view @refreshUser="getUser"/>
</el-main>// 获取用户的最新数据
getUser(){const username = localStorage.getItem('loginUser') ?         			 JSON.parse(localStorage.getItem('loginUser')).username : '';this.request.get('/user/username/' + username).then(res => {if(res.code == '200'){// 重新赋值后台的最新User数据this.user = res.data;}})}

1.3.3 再将user以prop方式传递给子组件Header.vue

<el-header style="border-bottom: 1px solid #ccc;"><Header :collapse-btn-class="collapseBtnClass" :collapse="isCollapse" :user="user"/>
</el-header>

完整的Manage.vue代码

<template><el-container style="min-height: 100vh"><el-aside :width="sideWidth + 'px'" style="box-shadow: 2px 0 6px rgb(0 21 41 / 0.35);"><Aside :is-collapse="isCollapse" :logo-text-show="logoTextShow"/></el-aside><el-container><el-header style="border-bottom: 1px solid #ccc;"><Header :collapse-btn-class="collapseBtnClass" :collapse="isCollapse" :user="user"/></el-header><el-main><!--  表示当前页面的子路由会在 <router-view/> 里面显示     --><router-view @refreshUser="getUser"/></el-main></el-container></el-container>
</template><script>import Aside from "@/components/Aside";
import Header from "@/components/Header";export default {name: 'HomeView',components: {Aside,Header},data() {return {collapseBtnClass: 'el-icon-s-fold',isCollapse: false,sideWidth: 200,logoTextShow: true,headerBg: 'headerBg',user: {}}},created() {this.getUser()},methods: {collapse() {  // 点击收缩按钮触发this.isCollapse = !this.isCollapseif (this.isCollapse) {  // 收缩this.sideWidth = 64this.collapseBtnClass = 'el-icon-s-unfold'this.logoTextShow = false} else {   // 展开this.sideWidth = 200this.collapseBtnClass = 'el-icon-s-fold'this.logoTextShow = true}},// 获取用户的最新数据getUser(){const username = localStorage.getItem('loginUser') ? JSON.parse(localStorage.getItem('loginUser')).username : '';this.request.get('/user/username/' + username).then(res => {if(res.code == '200'){// 重新赋值后台的最新User数据this.user = res.data;}})}}
}
</script><style>
.headerBg {background: #eee!important;
}
</style>

1.3.4 Header.vue使用user

// 接收数据
props: {collapseBtnClass: String,collapse: Boolean,// 定义一个user属性接受从Manage.vue传进来的user对象user: Object},// 使用数据
<div style="display: inline-block"><img :src="user.avatarUrl" alt=""style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px;overflow: hidden;"><span>{{ user.nickname }}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
</div>

完整的Header.vue代码

<template><div style="line-height: 60px; display: flex"><div style="flex: 1;"><span :class="collapseBtnClass" style="cursor: pointer; font-size: 18px" @click="collapse"></span><el-breadcrumb separator=">" style="display: inline-block; margin-left: 10px"><el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
<!--        <el-breadcrumb-item>{{ currentPathName }}</el-breadcrumb-item>--><el-breadcrumb-item v-for="(item, index) in breadCrumbs" :key="item.path"><router-link :to="item.path">{{ item.meta.title }}</router-link></el-breadcrumb-item></el-breadcrumb></div><el-dropdown style="width: 100px; cursor: pointer"><div style="display: inline-block"><img :src="user.avatarUrl" alt=""style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px;overflow: hidden;"><span>{{ user.nickname }}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i></div><el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center"><el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/person">个人信息</router-link></el-dropdown-item><el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/password">修改密码</router-link></el-dropdown-item><el-dropdown-item style="font-size: 14px; padding: 5px 0"><span style="text-decoration: none" @click="logout">退出</span></el-dropdown-item></el-dropdown-menu></el-dropdown></div>
</template><script>
export default {name: "Header",props: {collapseBtnClass: String,collapse: Boolean,// 定义一个user属性接受从Manage.vue传进来的user对象user: Object},// 当当前路由发生变化时,调用getBreadcrumb方法来更新面包屑导航的数据watch: {$route() {this.getBreadcrumb();}},data(){return {breadCrumbs: [],//user: localStorage.getItem("loginUser") ? JSON.parse(localStorage.getItem("loginUser")) : ""}},created() {this.getBreadcrumb()},methods: {getBreadcrumb(){// 从当前路由的匹配记录中过滤出具有meta属性且包含title属性的路由记录this.breadCrumbs = this.$route.matched.filter(item => item.meta && item.meta.title);},// 退出登录logout(){this.$router.push("/login");localStorage.removeItem("loginUser")this.$message.success("退出成功")}}// computed: {//   currentPathName () {//     return this.$store.state.currentPathName;  //需要监听的数据//   }// },}
</script><style scoped></style>

1.4 效果图

在这里插入图片描述
在这里插入图片描述
注意:上传的头像最好是正方形的大小,形成的头像才会是规整的

2. 修改密码

2.1 前端页面编写(Password.vue)

<template><el-card style="width: 500px;"><el-form label-width="120px" size="small" :model="form" :rules="rules" ref="pass"><el-form-item label="原密码" prop="password"><el-input v-model="form.password" autocomplete="off" show-password></el-input></el-form-item><el-form-item label="新密码" prop="newPassword"><el-input v-model="form.newPassword" autocomplete="off" show-password></el-input></el-form-item><el-form-item label="确认新密码" prop="confirmPassword"><el-input v-model="form.confirmPassword" autocomplete="off" show-password></el-input></el-form-item><el-form-item><el-button type="primary" @click="save">确 定</el-button></el-form-item></el-form></el-card>
</template><script>
export default {name: "Password",data() {return {form: {},user: localStorage.getItem("loginUser") ? JSON.parse(localStorage.getItem("loginUser")) : {},rules: {password: [{ required: true, message: '请输入原密码', trigger: 'blur' },{ min: 3, message: '长度不少于3位', trigger: 'blur' }],newPassword: [{ required: true, message: '请输入新密码', trigger: 'blur' },{ min: 3, message: '长度不少于3位', trigger: 'blur' }],confirmPassword: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 3, message: '长度不少于3位', trigger: 'blur' }],}}},created() {// 通过用户名和旧密码来唯一标识用户,然后再修改密码this.form.username = this.user.username},methods: {save() {this.$refs.pass.validate((valid) => {if (valid) {if (this.form.newPassword !== this.form.confirmPassword) {this.$message.error("2次输入的新密码不相同")return false}this.request.post("/user/password", this.form).then(res => {if (res.code === '200') {this.$message.success("修改成功")this.$store.commit("logout")} else {this.$message.error(res.msg)}})}})},}
}
</script><style>
.avatar-uploader {text-align: center;padding-bottom: 10px;
}
.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;
}
.avatar-uploader .el-upload:hover {border-color: #409EFF;
}
.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 138px;height: 138px;line-height: 138px;text-align: center;
}
.avatar {width: 138px;height: 138px;display: block;
}
</style>

2.2 修改密码后退出系统

// 退出系统
this.$store.commit("logout")

store文件下index.js

import Vue from 'vue'
import Vuex from 'vuex'
import router from "@/router";Vue.use(Vuex)export default new Vuex.Store({state: {currentPathName: ''},getters: {},mutations: {// setPath(state){//   state.currentPathName = localStorage.getItem('currentPathName')// },logout() {// 清空缓存localStorage.removeItem("loginUser")localStorage.removeItem("menus")router.push("/login")// 重置路由//resetRouter()}},actions: {},modules: {}
})

2.3 路由设置并改动Header.vue

// 拼装动态路由
const manageRoute = { path: '/', name: 'Manage', component: () => import('../views/Manage.vue'), redirect: "/home", children: [{ path: 'person', name: '个人信息', component: () => import('../views/Person.vue'),meta: { title: '个人信息' }},{ path: 'password', name: '修改密码', component: () => import('../views/Password.vue'),meta: { title: '修改密码' }}] }

完整的index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Manage from '../views/Manage.vue'
import store from "@/store";Vue.use(VueRouter)
//定义一个路由对象数组
const routes = [{path: '/login',name: '登录',component: () => import('../views/Login.vue')},{path: '/register',name: '注册',component: () => import('../views/Register.vue')},{path: '/404',name: '404',component: () => import('../views/404.vue')}]//使用路由对象数组创建路由实例,供main.js引用
const router = new VueRouter({mode: 'history',base: process.env.BASE_URL,routes
})// 注意:刷新页面会导致页面路由重置
export const setRoutes = () => {const storeMenus = localStorage.getItem("menus");if (storeMenus) {// 获取当前的路由对象名称数组const currentRouteNames = router.getRoutes().map(v => v.name)if (!currentRouteNames.includes('Manage')) {// 拼装动态路由const manageRoute = { path: '/', name: 'Manage', component: () => import('../views/Manage.vue'), redirect: "/home", children: [{ path: 'person', name: '个人信息', component: () => import('../views/Person.vue'),meta: { title: '个人信息' }},{ path: 'password', name: '修改密码', component: () => import('../views/Password.vue'),meta: { title: '修改密码' }}] }const menus = JSON.parse(storeMenus)menus.forEach(item => {if (item.path) {  // 当且仅当path不为空的时候才去设置路由let itemMenu = { path: item.path.replace("/", ""), name: item.name, component: () => import('../views/' + item.pagePath + '.vue'),meta: { title: item.name }}manageRoute.children.push(itemMenu)} else if(item.children.length) {item.children.forEach(item => {if (item.path) {let itemMenu = { path: item.path.replace("/", ""), name: item.name, component: () => import('../views/' + item.pagePath + '.vue'),meta: { title: item.name }}manageRoute.children.push(itemMenu)}})}})// 动态添加到现在的路由对象中去router.addRoute(manageRoute)}}
}// 重置我就再set一次路由
setRoutes()// 路由守卫
router.beforeEach((to, from, next) => {// localStorage.setItem('currentPathName',to.name);   // 设置当前的路由名称,为了在Header组件中去使用// store.commit('setPath')    // 触发store的数据更新// 未找到路由情况if(!to.matched.length){const storeMenus = localStorage.getItem("menus");if(storeMenus){   // 有菜单没有找到路由,跳转至 404页面next("/404")}else {    // // 没有菜单,直接跳转至登录页next("/login")}}next()   // 放行路由
})export default router

Header.vue改动

<el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/password">修改密码</router-link>
</el-dropdown-item>

完整的Header.vue

<template><div style="line-height: 60px; display: flex"><div style="flex: 1;"><span :class="collapseBtnClass" style="cursor: pointer; font-size: 18px" @click="collapse"></span><el-breadcrumb separator=">" style="display: inline-block; margin-left: 10px"><el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
<!--        <el-breadcrumb-item>{{ currentPathName }}</el-breadcrumb-item>--><el-breadcrumb-item v-for="(item, index) in breadCrumbs" :key="item.path"><router-link :to="item.path">{{ item.meta.title }}</router-link></el-breadcrumb-item></el-breadcrumb></div><el-dropdown style="width: 100px; cursor: pointer"><div style="display: inline-block"><img :src="user.avatarUrl" alt=""style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px;overflow: hidden;"><span>{{ user.nickname }}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i></div><el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center"><el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/person">个人信息</router-link></el-dropdown-item><el-dropdown-item style="font-size: 14px; padding: 5px 0;"><router-link to="/password">修改密码</router-link></el-dropdown-item><el-dropdown-item style="font-size: 14px; padding: 5px 0"><span style="text-decoration: none" @click="logout">退出</span></el-dropdown-item></el-dropdown-menu></el-dropdown></div>
</template><script>
export default {name: "Header",props: {collapseBtnClass: String,collapse: Boolean,// 定义一个user属性接受从Manage.vue传进来的user对象user: Object},// 当当前路由发生变化时,调用getBreadcrumb方法来更新面包屑导航的数据watch: {$route() {this.getBreadcrumb();}},data(){return {breadCrumbs: [],//user: localStorage.getItem("loginUser") ? JSON.parse(localStorage.getItem("loginUser")) : ""}},created() {this.getBreadcrumb()},methods: {getBreadcrumb(){// 从当前路由的匹配记录中过滤出具有meta属性且包含title属性的路由记录this.breadCrumbs = this.$route.matched.filter(item => item.meta && item.meta.title);},// 退出登录logout(){this.$router.push("/login");localStorage.removeItem("loginUser")this.$message.success("退出成功")}}// computed: {//   currentPathName () {//     return this.$store.state.currentPathName;  //需要监听的数据//   }// },}
</script><style scoped></style>

2.4 后端接口编写

2.4.1 UserController

@PostMapping("/password")
public Result updatePassword(@RequestBody UserPasswordDTO userPasswordDTO){if(StrUtil.isBlank(userPasswordDTO.getUsername()) || StrUtil.isBlank(userPasswordDTO.getPassword())){return Result.error(Constants.CODE_400,"参数错误");}userService.updatePassword(userPasswordDTO);return Result.success();}

用UserPasswordDTO接收前端传过来的表单参数

package com.ppj.entity.dto;import lombok.Data;@Data
public class UserPasswordDTO {private String username;private String password;private String newPassword;
}

2.4.2 UserServiceImpl

@Override
public void updatePassword(UserPasswordDTO userPasswordDTO) {int res = userMapper.updatePassword(userPasswordDTO);if(res<1){throw new ServiceException(Constants.CODE_600,"密码修改失败");}
}

2.4.3 UserMapper

package com.ppj.mapper;import com.ppj.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ppj.entity.dto.UserPasswordDTO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Update;/*** <p>*  Mapper 接口* </p>** @author ppj* @since 2024-04-20*/
@Mapper
public interface UserMapper extends BaseMapper<User> {int updatePassword(UserPasswordDTO userPasswordDTO);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ppj.mapper.UserMapper"><update id="updatePassword" parameterType="com.ppj.entity.dto.UserPasswordDTO">update sys_userset password = #{newPassword}where username = #{username} and password = #{password}</update></mapper>

2.5 页面效果

在这里插入图片描述

总结

  1. 这篇主要的难点是头像上传后的同步刷新;
  2. 修改密码其实是更新用户,通过用户名和旧密码确定唯一用户,然后才进行密码更改。

写在最后

如果此文对您有所帮助,请帅戈靓女们务必不要吝啬你们的Zan,感谢!!不懂的可以在评论区评论,有空会及时回复。
文章会一直更新

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

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

相关文章

[RK-Linux] RK3562 I2C驱动TP芯片GSL3680

TP芯片GSL3680 1、简介 GSL3680是一款电容屏多点触摸控制单芯片,其芯片内部框架图如下所示: GSL3680采用了独特的互电容感应技术,可以在1ms内测量多达192个节点,支持广泛的传感器选择,包括单层或双层ITO,玻璃或薄膜,采用了先进的抗电磁干扰信号处理技术,使其对各种干…

C++初学者指南第一步---12.引用

C初学者指南第一步—12.引用 文章目录 C初学者指南第一步---12.引用1. 功能&#xff08;和限制&#xff09;1.1 非常量引用1.2 常量引用1.3 auto引用 2.用法2.1 范围for循环中的引用2.2 常量引用的函数形参2.3 非常量引用的函数形参2.4 函数参数的选择&#xff1a;copy / const…

git拉取gitee项目到本地

git安装等不做赘述。 根据需要选择不同操作 1.只是单纯拉取个项目&#xff0c;没有后续的追踪等操作 不需要使用git init初始化本地文件夹 新建一个文件夹用于存储项目&#xff0c;右键选择 git bash here 会出现命令行窗口 如果像我一样&#xff0c;只是拉取个项目作业&…

若以框架学习(3),echarts结合后端数据展示,暂时完结。

前三天&#xff0c;参加毕业典礼&#xff0c;领毕业证&#xff0c;顿时感到空落落的失去感&#xff0c;没有工作&#xff0c;啥也没有&#xff0c;总感觉一辈子白活了。晚上ktv了一晚上&#xff0c;由于我不咋个唱歌&#xff0c;没心情&#xff0c;听哥几个唱了一晚上周杰伦&am…

Redis实战—Redis分布式锁

本博客为个人学习笔记&#xff0c;学习网站与详细见&#xff1a;黑马程序员Redis入门到实战 P56 - P63 目录 分布式锁介绍 基于Redis的分布式锁 Redis锁代码实现 修改业务代码 分布式锁误删问题 分布式锁原子性问题 Lua脚本 编写脚本 代码优化 总结 分布式锁介绍…

闲鱼商品详情API:深入解析与应用指南

在二手交易市场中&#xff0c;阿里巴巴集团旗下的闲鱼平台以其社区氛围和交易模式&#xff0c;吸引了大量用户。为了进一步丰富用户体验和提升交易透明度&#xff0c;开放了一系列API接口&#xff0c;其中包括商品详情API 闲鱼商品详情API接口概述 闲鱼商品详情API接口允许用…

自然语言处理(NLP)技术。

自然语言处理&#xff08;NLP&#xff09;技术可以应用于各种不同的场景和应用程序。以下是一些例子&#xff1a; 1. 机器翻译&#xff1a;NLP技术可以帮助将一种语言翻译成另一种语言。例如&#xff0c;Google Translate使用NLP技术来实现在不同语言之间进行翻译。 2. 文本分…

express+vue在线im实现【三】

往期内容 expressvue在线im实现【一】 expressvue在线im实现【二】 本期示例 本期总结 支持各种类型的文件上传&#xff0c;常见文件类型图片&#xff0c;音频&#xff0c;视频等&#xff0c;上传时同步获取音频与视频的时长&#xff0c;以及使用上传文件的缓存路径来作为vi…

WDF驱动开发-DMA(一)

在 Windows 7 及更早版本上&#xff0c;Kernel-Mode Driver Framework (KMDF) 仅支持 (DMA) 设备的总线-主直接内存访问。 此类设备包含其自己的 DMA 控制器。 在片上系统 (SoC) 上运行Windows 8及更高版本的平台上&#xff0c;该框架还支持系统模式 DMA&#xff0c;其中多个设…

视频讲解|基于模型预测算法的含储能微网双层能量管理模型【mpc】

1 主要内容 该讲解视频对应的免费程序链接为【防骗贴】基于模型预测算法的含储能微网双层能量管理模型&#xff0c;主要做的是一个微网双层优化调度模型&#xff0c;微网聚合单元包括风电、光伏、储能以及超级电容器&#xff0c;在微网的运行成本层面考虑了电池的退化成本&…

快捷方式(lnk)--加载HTA-CS上线

免责声明:本文仅做技术交流与学习... 目录 CS: HTA文档 文件托管 借助mshta.exe突破 本地生成lnk快捷方式: 非系统图标路径不同问题: 关于lnk的上线问题: CS: HTA文档 配置监听器 有效载荷---->HTA文档--->选择监听器--->选择powershell模式----> 默认生成一…

政务大厅引导系统:AR、VR技术革新引领政务服务体验升级

一、传统政务大厅面临的普遍痛点 随着城市的发展和政务服务需求的增长&#xff0c;传统的政务大厅面临着诸多挑战和痛点&#xff1a; 信息不对称&#xff1a;政务大厅内各部门信息分散&#xff0c;群众难以快速获取全面准确的服务信息&#xff0c;导致办事效率低下。 办事流…

ES6 新增Set 和 Map 两种数据结构

ES6 新增了 Set 和 Map 这两种数据结构&#xff0c;它们为 JavaScript 提供了更强大和灵活的数据处理能力。下面详细介绍一下 Set 和 Map 的特性和用法&#xff1a; Set Set 是一种类似于数组的数据结构&#xff0c;但是成员的值都是唯一的&#xff0c;没有重复的值。 特性&…

4字节十进制数 转为 IPV4点分十进制 -- C++语言实现

4字节十进制数 转为 IPV4点分十进制 – C语言实现 //IPv4表示&#xff0c;通过4字节整数&#xff0c;比如1 6777 2418(0x0A 00 01 02)&#xff0c;表示10.0.1.2 // 4字节 4 * 1字节 4 * 8bit 32 bit // 2 ^32 1024 * 1024 *1024 * 4 42 9496 7296 0xff ff ff ff 1 //写…

计算机视觉 | 基于图像处理和边缘检测算法的黄豆计数实验

目录 一、实验原理二、实验步骤1. 图像读取与预处理2. 边缘检测3. 轮廓检测4. 标记轮廓序号 三、实验结果 Hi&#xff0c;大家好&#xff0c;我是半亩花海。 本实验旨在利用 Python 和 OpenCV 库&#xff0c;通过图像处理和边缘检测算法实现黄豆图像的自动识别和计数&#xff0…

ICMPV6协议

ICMPV6&#xff1a;intermet 控制管理协议--- 存在大量的子协议 1、PMTU---路径 MTU 发现协议 通过ICMPV6error包来获取整段路径上最小 MTU 值 2、NDP------邻居发现协议---用于取代IPV4下的 ARP协议 假设PC1和PC2 通讯 1无2的MAC地址 …

JetBrains GoLand 2024 mac/win版:高效开发,Go无止境

JetBrains GoLand 2024是一款专为Go语言开发者设计的集成开发环境(IDE)&#xff0c;为开发者带来了更加高效、智能和便捷的编程体验。 GoLand 2024 mac/win版获取 在代码编辑方面&#xff0c;GoLand 2024提供了全行代码补全功能&#xff0c;通过利用先进的深度学习模型&#x…

C#面:C#中的析构函数是什么?

在C#中&#xff0c;析构函数是一种特殊的方法&#xff0c;用于在对象被销毁之前执行一些清理操作。它的名称与类名相同&#xff0c;但在名称前面加上一个波浪线&#xff08;~&#xff09;。析构函数没有参数&#xff0c;也没有返回类型。 当对象不再被使用时&#xff0c;垃圾回…

力扣85.最大矩形

力扣85.最大矩形 遍历所有行作为底边 做求矩形面积&#xff08;84. class Solution {public:int maximalRectangle(vector<vector<char>>& matrix) {if (matrix.empty()) return 0;int n matrix.size(),m matrix[0].size();int res0;vector<int> li…

grub引导LinuxMint

注意事项&#xff1a;文件系统必须是FAT32 安装 sudo apt install gparted -y 分区管理软件 使用gparted分区和查看设备路径 sudo apt-get install grub-efi-amd64 #/dev/sdd1 是需要制作分区引导的设备路径 sudo mount /dev/sdd1 /mnt/123 #bios sudo grub-install --targe…