• [问题求助] 预约会议后的回调函数缺少对应的返回参数
    返回的对象里,对应param属性里缺少confBaseInfo属性,这个属性里会有对应的会议号等信息
  • [技术干货] 基于Java+SpringBoot+vue+element驾校管理系统设计和实现-转载
     一、前言介绍:         随着社会的发展和科学技术的进步,互联网技术越来越受欢迎。网络传播的生活方式逐渐受到广大人民群众的喜爱。越来越多的互联网爱好者开始在互联网上满足他们的基本需求,同时逐渐进入各个用户的生活起居。互联网具有许多优点,例如便利性,速度,高效率和低成本。因此,类似于驾校管理,满足用户工作繁忙的需求,不仅是方便用户随时查看信息的途径,而且还能提高管理效率。本文首先以驾校管理过程的基本问题作为研究对象。在开发系统之前,我们对现有状况进行了详细的调查和分析。最后,我们利用计算机技术开发了一套完整合适的驾校管理。该系统的实现主要优势是:该系统主要采用计算机技术开发,它方便快捷;系统可以通过管理员界面查看系统所涉及的驾校管理所有信息管理。          驾校管理软件是一款方便、快捷、实用的信息服务查询软件。随着智能网络在全球市场的不断普及以及各种智能平台的使用,作为中国主流智能的技术开发系统,自然需要这样的软件来满足更多用户的需求和体验。系统的开发与人们的日常需求相关,如通过管理系统获取到个人中心、学员管理、驾校教练管理、预约教练管理、预约教练管理、评价教练管理、考试成绩管理、考试通知管理、报考信息管理、练车通知管理、预约练车管理、驾考套餐管理、报名信息管理、车辆信息管理等信息详细情况,了解最新资讯信息等。  二、主要技术:  2.1  Spring Boot框架介绍:         Spring框架是Java平台上的一种开源应用框架,提供具有控制反转特性的容器。尽管Spring框架自身对编程模型没有限制,但其在Java应用中的频繁使用让它备受青睐,以至于后来让它作为EJB(EnterpriseJavaBeans)模型的补充,甚至是替补。Spring框架为开发提供了一系列的解决方案,比如利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等等。Spring框架具有控制反转(IOC)特性,IOC旨在方便项目维护和测试,它提供了一种通过Java的反射机制对Java对象进行统一的配置和管理的方法。Spring框架利用容器管理对象的生命周期,容器可以通过扫描XML文件或类上特定Java注解来配置对象,开发者可以通过依赖查找或依赖注入来获得对象。Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。Spring框架的AOP框架仅提供基本的AOP特性,虽无法与AspectJ框架相比,但通过与AspectJ的集成,也可以满足基本需求。Spring框架下的事务管理、远程访问等功能均可以通过使用SpringAOP技术实现。Spring的事务管理框架为Java平台带来了一种抽象机制,使本地和全局事务以及嵌套事务能够与保存点一起工作,并且几乎可以在Java平台的任何环境中工作。  2.2 MYSQL数据库:                 数据库是系统开发过程中不可或缺的一部分。 在WEB应用方面,MySQL AB开发了一个具有很大优势的MySQL关系数据库管理系统。 MySQL可以将数据存储在不同的表中,这非常灵活,并且还可以提高系统在实际应用中的速度。 数据库访问最常用于标准SQL语言,MySQL用于SQL语言,因此它具有高度兼容性。数据库的操作是必不可少的,包括对数据库表的增加、删除、修改、查询等功能。现如今,数据库可以分为关系型数据库和非关系型数据库,Mysql属于关系性数据库,Mysql数据库是一款小型的关系型数据库,它以其自身特点:体积小、速度快、成本低等,Mysql数据库是目前最受欢迎的开源数据库。          在WEB应用技术中, Mysql数据库支持不同的操作系统平台,虽然在不同平台下的安装和配置都不相同,但是差别也不是很大,Mysql在Windows平台下两种安装方式,二进制版和免安装版。安装完Mysql数据库之后,需要启动服务进程,相应的客户端就可以连接数据库,客户端可通过命令行或者图形界面工具登录数据库。  三、系统设计: 3.1 系统架构设计: ​  3.2 登录时序图设计: ​  四、功能截图:  4.1 登录注册:  4.2 前端页面: 4.2.1 系统首页:   4.2.2 教练模块:   4.2.3 考试须知:   4.2.4 预约练车:   4.2.5 车辆信息:  4.2.6 系统公告信息:  4.2.7 个人中心模块:   4.2.8 用户后台模块:  4.3 后端管理:  4.3.1 教练管理:  4.3.2 考试通知:  4.3.3 报名管理:  4.3.4 车辆信息:  4.3.5 系统公告等  五、代码实现:     /**  * 登录相关  */ @RequestMapping("users") @RestController public class UserController{          @Autowired     private UserService userService;          @Autowired     private TokenService tokenService;       /**      * 登录      */     @IgnoreAuth     @PostMapping(value = "/login")     public R login(String username, String password, String captcha, HttpServletRequest request) {         UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));         if(user==null || !user.getPassword().equals(password)) {             return R.error("账号或密码不正确");         }         String token = tokenService.generateToken(user.getId(),username, "users", user.getRole());         return R.ok().put("token", token);     }          /**      * 注册      */     @IgnoreAuth     @PostMapping(value = "/register")     public R register(@RequestBody UserEntity user){ //        ValidatorUtils.validateEntity(user);         if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {             return R.error("用户已存在");         }         userService.insert(user);         return R.ok();     }       /**      * 退出      */     @GetMapping(value = "logout")     public R logout(HttpServletRequest request) {         request.getSession().invalidate();         return R.ok("退出成功");     }          /**      * 密码重置      */     @IgnoreAuth     @RequestMapping(value = "/resetPass")     public R resetPass(String username, HttpServletRequest request){         UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));         if(user==null) {             return R.error("账号不存在");         }         user.setPassword("123456");         userService.update(user,null);         return R.ok("密码已重置为:123456");     }          /**      * 列表      */     @RequestMapping("/page")     public R page(@RequestParam Map<String, Object> params,UserEntity user){         EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();         PageUtils page = userService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params));         return R.ok().put("data", page);     }       /**      * 列表      */     @RequestMapping("/list")     public R list( UserEntity user){            EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();           ew.allEq(MPUtil.allEQMapPre( user, "user"));          return R.ok().put("data", userService.selectListView(ew));     }       /**      * 信息      */     @RequestMapping("/info/{id}")     public R info(@PathVariable("id") String id){         UserEntity user = userService.selectById(id);         return R.ok().put("data", user);     }          /**      * 获取用户的session用户信息      */     @RequestMapping("/session")     public R getCurrUser(HttpServletRequest request){         Long id = (Long)request.getSession().getAttribute("userId");         UserEntity user = userService.selectById(id);         return R.ok().put("data", user);     }       /**      * 保存      */     @PostMapping("/save")     public R save(@RequestBody UserEntity user){ //        ValidatorUtils.validateEntity(user);         if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {             return R.error("用户已存在");         }         userService.insert(user);         return R.ok();     }       /**      * 修改      */     @RequestMapping("/update")     public R update(@RequestBody UserEntity user){ //        ValidatorUtils.validateEntity(user);         UserEntity u = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername()));         if(u!=null && u.getId()!=user.getId() && u.getUsername().equals(user.getUsername())) {             return R.error("用户名已存在。");         }         userService.updateById(user);//全部更新         return R.ok();     }       /**      * 删除      */     @RequestMapping("/delete")     public R delete(@RequestBody Long[] ids){         userService.deleteBatchIds(Arrays.asList(ids));         return R.ok();     } }      @Configuration public class InterceptorConfig extends WebMvcConfigurationSupport{          @Bean     public AuthorizationInterceptor getAuthorizationInterceptor() {         return new AuthorizationInterceptor();     }          @Override     public void addInterceptors(InterceptorRegistry registry) {         registry.addInterceptor(getAuthorizationInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**");         super.addInterceptors(registry);     }          /**      * springboot 2.0配置WebMvcConfigurationSupport之后,会导致默认配置被覆盖,要访问静态资源需要重写addResourceHandlers方法      */     @Override     public void addResourceHandlers(ResourceHandlerRegistry registry) {         registry.addResourceHandler("/**")         .addResourceLocations("classpath:/resources/")         .addResourceLocations("classpath:/static/")         .addResourceLocations("classpath:/admin/")         .addResourceLocations("classpath:/front/")           .addResourceLocations("classpath:/public/");         registry.addResourceHandler("/upload/**").addResourceLocations("file:D:/work/");           super.addResourceHandlers(registry);     } }  ———————————————— 版权声明:本文为CSDN博主「java李杨勇」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_39709134/article/details/128781905 
  • [技术干货] Object.assign详解
    一、Object.assign是什么?       首先了解下Object.assign()是什么。我们先看看ES6官方文档是怎么介绍的?       Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。       简单来说,就是Object.assign()是对象的静态方法,可以用来复制对象的可枚举属性到目标对象,利用这个特性可以实现对象属性的合并。 二、用法:       Object.assign(target, ...sources)   参数:target--->目标对象       source--->源对象   返回值:target,即目标对象 三、使用示例: 1、目标对象和源对象无重名属性 var target={name:'guxin',age:18}; var source={state:'single'} var result=Object.assign(target,source); console.log(target,target==result); 我们可以看到source上的state属性合并到了target对象上。如果只是想将两个或多个对象的属性合并到一起,不改变原有对象的属性,可以用一个空的对象作为target对象。像下面这样: var result=Object.assign({},target,source); 2、目标对象和源对象有重名属性 上面的示例目标对象和源对象是没有重名属性的,那么如果他们有重名属性又会怎样呢?是后面的属性覆盖前面的还是前面的属性覆盖后面的呢?我们接下来看下一个例子: var target={name:'guxin',age:18} var source={state:'signle',age:22} var result=Object.assign(target,source) console.log(target)  可以看到如果有同名属性的话,后面的属性值会覆盖前面的属性值。 3、有多个源对象 前面的示例都是只有一个源对象,那么如果有多个源对象情况会不会不同呢?我们继续看下面的例子:         var target={name:'guxin',age:18}         var source1={state:'signle',age:22}         var source2={mood:'happy',age:25}         var result=Object.assign(target,source1,source2)         console.log(target) 可以看到有多个源对象情况也是和一个源对象一样的。没有同名的属性会直接复制到目标对象上,同名的属性后面的属性值会覆盖前面的同名属性值。  四、注意事项: 1、Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象,继承属性和不可枚举属性是不能拷贝的。 2、针对深拷贝,需要使用其他办法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。 3、目标对象自身也会改变 4、异常会打断后续拷贝任务  五、兼容性 目前IE浏览器不兼容Object.assign(),如果需要兼容IE的话最好不要直接使用这个方法。  六、与$.extend()的比较 我们通过一个简单的示例来比较两者有什么不同,          var target={name:'guxin',age:18}         var source1={state:'signle',age:22}         var source2={mood:'happy',age:25}         var result=Object.assign(target,source1,source2)         console.log(target,'assign')         var targetObj={name:'guxin',age:18}         var sourceObj1={state:'signle',age:22}         var sourceObj2={mood:'happy',age:25}         var result=$.extend(targetObj,sourceObj1,sourceObj2)         console.log(targetObj,'extend') 可以看到两者得到的结果是一样的。所以,我认为这两个方法,除了兼容性应该是一样的。 ———————————————— 原文链接:https://blog.csdn.net/guxin_duyin/article/details/88916106 
  • [技术干货] javascript中将xml转为json的方法
    这篇文章将为大家详细讲解有关javascript中将xml转为json的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。javascript中将xml转换为json字符串的方法:首先通过XML字符串或请求XML文件来获取XML的DOM对象;然后通过遍历和递归来获取子元素的nodeValue值;最后拼接出JSON字符串即可。利用JavaScript将XML转换为JSON首先通过XML字符串来生成XML的DOM对象:/**  * 通过传入xml的内容字符串来解析xml  * @param xmlString xml字符串  * @returns xml的Document对象  */ function getXmlDocumentByXmlString(xmlString) {     var xmlDoc = null;     if (window.DOMParser) {         var parser = new DOMParser();         xmlDoc = parser.parseFromString(xmlString, "text/xml");     } else {         //IE         xmlDoc = new ActiveXObject("Microsoft.XMLDOM");         xmlDoc.async = "false";         xmlDoc.loadXML(xmlString);     }     return xmlDoc; }或者通过请求XML文件来获取XML的DOM对象:/**  * 通过传入xml文件路径来解析xml文档  * @param xmlFilePath xml文档路径,如:files/test.xml  * @returns xml的Document对象  */ function getXmlDocumentByFilePath(xmlFilePath) {     //xmlDocument对象     var xmlDoc = null;     //xmlhttp对象     var xmlhttp = null;     if (window.XMLHttpRequest) {         //IE7+, FireFox, Chrome, Opera, Safari         xmlhttp = new XMLHttpRequest();     } else {         //IE6, IE5         xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");     }     xmlhttp.open("GET", xmlFilePath, false);     xmlhttp.send();     xmlDoc = xmlhttp.responseXML;     return xmlDoc; }接下来就是重点的部分了,通过遍历和递归获取子元素的nodeValue,来拼接出JSON字符串,实现将XML转换成JSON字符串:/**  * 将XML的Document对象转换为JSON字符串  * @param xmlDoc xml的Document对象  * @return string  */ function convertToJSON(xmlDoc) {     //准备JSON字符串和缓存(提升性能)     var jsonStr = "";     var buffer = new Array();     buffer.push("{");     //获取xml文档的所有子节点     var nodeList = xmlDoc.childNodes;     generate(nodeList);     /**      * 中间函数,用于递归解析xml文档对象,并附加到json字符串中      * @param node_list xml文档的的nodeList      */     function generate(node_list) {         for (var i = 0; i < node_list.length; i++) {             var curr_node = node_list[i];             //忽略子节点中的换行和空格             if (curr_node.nodeType == 3) {                 continue;             }             //如果子节点还包括子节点,则继续进行遍历             if (curr_node.childNodes.length > 1) {                 buffer.push("\"" + curr_node.nodeName + "\": {");                 generate(curr_node.childNodes);             } else {                 var firstChild = curr_node.childNodes[0];                 if (firstChild != null) {                     //nodeValue不为null                     buffer.push("\"" + curr_node.nodeName + "\":\"" + firstChild.nodeValue + "\"");                 } else {                     //nodeValue为null                     buffer.push("\"" + curr_node.nodeName + "\":\"\"");                 }             }             if (i < (node_list.length - 2)) {                 buffer.push(",");             } else {                 break;             }         }         //添加末尾的"}"         buffer.push("}");     }     jsonStr = buffer.join("");     return jsonStr; }使用方式:通过getXmLDocumentByFilePath(xmlFilePath)或者getXmlDocumentByXmlString(xmlString)获取XML的Document对象,然后通过调用convertToJSON(xmlDocument)传入xml的Ducument对象即可得到转换后的JSON字符串。适用范围:不含有attribute的任意XML文档。关于“javascript中将xml转为json的方法”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。原文链接:https://m.yisu.com/zixun/446969.html
  • [技术干货] vue中async和await异步编程
    async&await是Promise的语法糖,使用他的目的就是用同步的写法,写异步的操作。async 是“异步”的简写, async 用于申明一个异步的 function,await 可以认为是 async wait 的简写,await 用于等待一个异步方法执行完成。当我们函数中需要返回值是promise对象时通常用async和await简化。          async作为一个关键字放到函数之前,表示函数是异步的函数,异步函数也就意味着该函数的执行不会阻塞后面代码的执行,等async 函数返回一个promise 对象。  1.async async可以作用在任何方法前, 返回值是一个Promise对象  async function a(){  } console.log(a());   var b = (async () => {       }) console.log(b()); async函数内部return的返回值, 会成为then回调函数的参数  async function a() {     return 123 } a().then(res=>{     console.log(res); }) async作用的方法,如果内部出现报错,可以被promise的catch方法捕获  async function a() {     console.log(a);     let a = 123; } a().catch(err=>{     console.log(err); }) 2. await await只能作用在async修饰的方法中,不能单独使用,如果使用报错、  function a(){     await //报错:await is not defined     console.log(123); } a() 正常情况 await后面跟着一个Promise对象,返回的是Promise对象的成功后结果  async function a(){     var b = await new Promise((resolve,reject)=>{         resolve('123')     })     return b } a().then(res=>{     console.log(res); }) ———————————————— 原文链接:https://blog.csdn.net/qq_44858608/article/details/124332167 
  • [技术干货] async和await用法介绍
     一;async 1.函数前面加上 async 关键字,则该函数会返回一个结果为 promise 的对象。 2. async 函数返回 promise 对象的状态。 2.1:如果返回的是一个非 Promise 类型的数据, 则async 函数返回 promise 的状态 为 fulfilled 成功。 2.2:如果返回的是一个 Promise对象,则 async 函数返回 promise 的状态由返回的Promise对象的状态决定。 2.3:如果 throw Errow 抛出异常,则 async 函数返回 promise 的状态为 rejected 失败。 二;await 1.await 右侧的表达式一般为 promise 对象。 2.await 是在等一个表达式的结果,等一个返回值(回调成功的内容) 3.如果 await 右侧是一个 promise 对象,则 await 返回的是 promise 成功的值。 注意: 1.await 必须写在 async 函数中,但 async 函数中可以没有 await。 2.如果 await 的 promise 失败了,就会抛出异常,该异常需要通过 try catch 捕获处理。 3.如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。  三;async 和 await 结合发送 ajax   1.封装一个 发送GET请求的 promise  function sendAjax(url) {             return new Promise((resolve, reject) => {                 const xhr = new XMLHttpRequest()                 xhr.open('GET', url)                 xhr.send()                 // 处理返回结果                 xhr.onreadystatechange = function () {                     if (xhr.readyState == 4) {                         // 判断状态码                         if (xhr.readyState >= 200 && xhr.readyState < 300) {                             resolve(xhr.response)                         }else {                             reject(xhr.status)                         }                     }                 }             })         } 2.async和await结合发送ajax请求  // 触发点击事件发送ajax请求         let btn = document.querySelector('#btn')         btn.addEventListener('click', async function () {             try {                 let res = await sendAjax('get请求地址')                 console.log(res);             } catch (error) {                 console.log(error);             }         }) ———————————————— 原文链接:https://blog.csdn.net/Allurewuhui/article/details/123434870 
  • [技术干货] JavaScript开发小技巧
    1、使用var声明变量如果给一个没有声明的变量赋值,默认会作为一个全局变量(即使在函数内赋值)。要尽量避免不必要的全局变量。2、行尾使用分号虽然JavaScript允许省略行尾的分号,但是有时不注意的省略,会导致不必要的错误。建议在可用可不用行尾分号的地方加上分号。3、获取指定范围内的随机数var getRandom = function(max, min) {min = arguments[1] || 0;return Math.floor(Math.random() * (max - min + 1) + min);};上面的函数接受一个你希望的随机最大数和一个你希望的随机最小数。4、打乱数字数组的顺序var sortArray = array.sort(function(){ return Math.random() - 0.5;});5、取出数组中的随机项var ran = array[Math.floor(Math.random() * array.length)];6、去除字符串的首尾空格var s = string.trim();7、类数组对象转为数组比如:类数组对象遍历:Array.prototype.forEach.call(argumens,function(value){})DOM的NodeList和HTMLCollection也是类数组对象8、获取数组中的最大值和最小值var max = Math.max.apply(Math, array);var min = Math.min.apply(Math, array);9、清空数组array.length = 0;array = [];10、保留指定小数位var num = num.toFixed(2);返回字符串,保留两位小数11、使用for-in循环来遍历对象的属性for(var key in object) { // object[key]}不要用for-in来遍历数据12、获取某月天数function getMonthDay(date){ date = date || new Date(); if(typeof date === 'string') { date = new Date(date); }; date.setDate(32); return 32 - date.getDate();}传入date参数,可以是字符串、日期对象实例;为空表示当月天数13、浮点数问题0.1 + 0.2 = 0.30000000000000004 != 0.3JavaScript的数字都遵循IEEE 754标准构建,在内部都是64位浮点小数表示14、JSON序列化和反序列化使用JSON.stringify()来将JavaScript对象序列化为有效的字符串。使用JSON.parse()来将有效的字符串转换为JavaScript对象。在AJAX传输数据时很有用15、使用“===”替换“==”相等运算符(==)在比较时会将操作数进行相应的类型转换,而全等运算符(===)不会进行类型转换。16、避免使用with()使用with()可以把变量加入到全局作用域中,因此,如果有其它的同名变量,一来容易混淆,二来值也会被覆盖。17、不要使用eval()或函数构造器eval()和函数构造器(Function consturctor)的开销较大,每次调用,JavaScript引擎都要将源代码转换为可执行的代码。18、简化if语句if (condition) { fn();}可替换成:condition && fn();19、给可能省略的参数赋默认值function test(a, b){ a = a || '1';}20、给数组循环中缓存length的值如果你确定循环中数组的长度不会变化,那么你可以这样:var length = array.length;for(var i = 0; i < length; i++) {}可以避免在每次迭代都将会重新计算数组的大小,提高效率21、合并数组对于小数组,我们可以这样:var arr1 = [1,2,3];var arr2 = [4,5,6];var arr3 = arr1.concat(arr2); // [1,2,3,4,5,6]不过,concat()这个函数并不适合用来合并两个大型的数组,因为其将消耗大量的内存来存储新创建的数组。在这种情况之个,可以使用Array.prototype.push.apply(arr1,arr2)来替代创建一个新数组。这种方法不是用来创建一个新的数组,其只是将第一个第二个数组合并在一起,同时减少内存的使用:Array.prototype.push.apply(arr1, arr2); console.log(arr1); // [1,2,3,4,5,6]22 枚举对象“自身”的属性for...in除了枚举对象“自身”的属性外,还会枚举出继承过来的属性。var hasOwn = Object.prototype.hasOwnProperty;var obj = {name: 'tg', age: 24};for(var name in obj) { if (hasOwn.call(obj, name)) { console.log(name + ':' + obj[name]); }}// name:tg// age:24转载自http://bbs.jeecms.com/java/83762.jhtml
  • [技术干货] 基于Java+SpringBoot+vue等疫情期间在线网课管理系统详细设计实现-转载
     一、前言介绍: 1.1 背景及意义         疫情网课也都将通过计算机进行整体智能化操作,对于疫情网课管理系统所牵扯的管理及数据保存都是非常多的,例如管理员;首页、个人中心、学生管理、教师管理、班级管理、课程分类管理、课程表管理、课程信息管理、作业信息管理、请假信息管理、上课签到管理、论坛交流、系统管理,学生;首页、个人中心、课程表管理、课程信息管理、作业信息管理、请假信息管理、上课签到管理,教师;首页、个人中心、学生管理、班级管理、课程分类管理、课程表管理、课程信息管理、作业信息管理、请假信息管理、上课签到管理、系统管理,前台首页;首页、课程表、论坛交流、学校公告、个人中心、后台管理、师生聊天等功能,这给管理者的工作带来了巨大的挑战,面对大量的信息,传统的管理系统,都是通过笔记的方式进行详细信息的统计,后来出现电脑,通过电脑输入软件将纸质的信息统计到电脑上,这种方式比较传统,而且想要统计数据信息比较麻烦,还受时间和空间的影响,所以为此开发了疫情网课管理系统;为学生提供了方便管理平台,方便管理员查看及维护,并且可以通过需求进行内容的编辑及维护等;对于学生和教师而言,可以随时进行查询所需信息,管理员可以足不出户就可以获取到系统的数据信息等,而且还能节省学生和教师很多时间,所以开发疫情网课管理系统给管理者带来了很大的方便,同时也方便管理员对学生及教师信息进行处理。          本论文疫情网课管理系统主要牵扯到的程序,数据库与计算机技术等。覆盖知识面大,可以大大的提高系统人员工作效率。  1.2 系统运行环境  开发系统:Windows10  架构模式:MVC/前后端分离  JDK版本:Java JDK1.8  开发工具:IDEA  数据库版本: mysql5.7  数据库可视化工具: navicat for mysql  服务器:SpringBoot自带 apache tomcat  主要技术:Java,Springboot,mybatis,mysql,jquery,html,vue,elementui等  二、系统设计: 2.1 系统架构设计 ​  2.2 角色功能图 ​  2.3 登录时序图设计 ​  三、功能截图:  3.1 登录注册: 管理员通过用户名和密码、验证码、角色填写完成后进行登录  ​  学生注册,在学生注册页面可以填写学号、密码、学生、年龄、手机、邮箱等信息进行注册   ​  3.2 前台首页: 学生点击进入到系统操作界面可以查看首页、个人中心、课程表管理、课程信息管理、作业信息管理、请假信息管理、上课签到管理等功能模块,个人信息:通过列表可以获取学号、学生、性别、年龄、手机、邮箱、班级、照片等信息并进行修改操作。  ​   ​   课程表信息:  ​  可以下载和收藏操作   ​ 论讨交流,可以发布论讨文章和进行评论交流等  ​  学校公告:  ​  个人中心:  ​ 师生聊天:  ​   用户后端:  ​  3.3 后台管理:  管理员登录成功后进入到系统操作界面,可以对首页、个人中心、学生管理、教师管理、班级管理、课程分类管理、课程表管理、课程信息管理、作业信息管理、请假信息管理、上课签到管理、论坛交流、系统管理等功能模块进行相对应操作。  学生管理:  ​   课程表管理:  ​  作业信息管理:  ​ 学校公告:  ​  四、数据设计: 每个数据库的应用它们都是和区分开的,当运行到一定的程序当中,它就会与自己相关的协议与客户端进行通讯。那么这个系统就会对使这些数据进行连接。当我们选择哪个桥段的时候,接下来就会简单的叙述这个数据库是如何来创建的。当点击完成按钮的时候就会自动在对话框内弹出数据源的名称,在进行点击下一步即可,直接在输入相对应的身份验证和登录密码。   ​  五、代码实现: /**  * 登录相关  */ @RequestMapping("users") @RestController public class UserController{          @Autowired     private UserService userService;          @Autowired     private TokenService tokenService;       /**      * 登录      */     @IgnoreAuth     @PostMapping(value = "/login")     public R login(String username, String password, String captcha, HttpServletRequest request) {         UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));         if(user==null || !user.getPassword().equals(password)) {             return R.error("账号或密码不正确");         }         String token = tokenService.generateToken(user.getId(),username, "users", user.getRole());         return R.ok().put("token", token);     }          /**      * 注册      */     @IgnoreAuth     @PostMapping(value = "/register")     public R register(@RequestBody UserEntity user){ //        ValidatorUtils.validateEntity(user);         if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {             return R.error("用户已存在");         }         userService.insert(user);         return R.ok();     }       /**      * 退出      */     @GetMapping(value = "logout")     public R logout(HttpServletRequest request) {         request.getSession().invalidate();         return R.ok("退出成功");     }          /**      * 密码重置      */     @IgnoreAuth     @RequestMapping(value = "/resetPass")     public R resetPass(String username, HttpServletRequest request){         UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));         if(user==null) {             return R.error("账号不存在");         }         user.setPassword("123456");         userService.update(user,null);         return R.ok("密码已重置为:123456");     }          /**      * 列表      */     @RequestMapping("/page")     public R page(@RequestParam Map<String, Object> params,UserEntity user){         EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();         PageUtils page = userService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params));         return R.ok().put("data", page);     }       /**      * 列表      */     @RequestMapping("/list")     public R list( UserEntity user){            EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();           ew.allEq(MPUtil.allEQMapPre( user, "user"));          return R.ok().put("data", userService.selectListView(ew));     }     /**      * 信息      */     @RequestMapping("/info/{id}")     public R info(@PathVariable("id") String id){         UserEntity user = userService.selectById(id);         return R.ok().put("data", user);     }          /**      * 获取用户的session用户信息      */     @RequestMapping("/session")     public R getCurrUser(HttpServletRequest request){         Long id = (Long)request.getSession().getAttribute("userId");         UserEntity user = userService.selectById(id);         return R.ok().put("data", user);     }     /**      * 保存      */     @PostMapping("/save")     public R save(@RequestBody UserEntity user){         if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {             return R.error("用户已存在");         }         userService.insert(user);         return R.ok();     }       /**      * 修改      */     @RequestMapping("/update")     public R update(@RequestBody UserEntity user){         UserEntity u = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername()));         if(u!=null && u.getId()!=user.getId() && u.getUsername().equals(user.getUsername())) {             return R.error("用户名已存在。");         }         userService.updateById(user);//全部更新         return R.ok();     }       /**      * 删除      */     @RequestMapping("/delete")     public R delete(@RequestBody Long[] ids){         userService.deleteBatchIds(Arrays.asList(ids));         return R.ok();     } }  ———————————————— 版权声明:本文为CSDN博主「java李杨勇」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_39709134/article/details/128438852 
  • [技术干货] 基于Java+Springboot+Vue+elememt社区疫情返乡管控系统设计实现-转载
    前言介绍:          随着国内经济形势的不断发展,中国互联网进入了一个难得的高峰发展时期,这使得中外资本家纷纷转向互联网市场。然而,许多管理领域的不合理结构,人员不足以及市场管理需求的增加使得更多的人具备了互联网管理的意识。在当今高度发达的信息中,信息管理改革已成为一种更加广泛和全面的趋势。“社区疫情返乡人员防控管理平台系统”是基于Mysql5.7版本数据库,在Springboot程序设计的基础上实现的。                  该系统具有首页、个人中心、用户管理、物资捐赠管理。物资申请管理、物资捐赠审核、反人员管理、外出报备管理、投诉信息管理、体温上报管理、商品代买管理、商品配送管理、社区论坛、系统管理等功能。通过用户模块来管理自己的信息。用户注册登陆本社区疫情后,可以进入个人后台来管理首页、个人中心、返乡报备管理、外出报备管理、投诉信息管理、体温上报管理、商品代买管理、商品配送管理等功能。最后在主页页面,增加了推送功能,使用户可以直接快速接触到最丰富的内容、通过对此项目的练习、设计、学习、代码编写、让自己熟练的运用Java主流相关的一系列技术、比如、系统前期的调研、数据库的反复设计和修改、字段长度的控制、类型的掌控、编码的设计、以及代码规范、接口调试、前端页面样式代码编写、前端后端对接、以及跨域问题和其他权限问题的解决。为以为从事Java开发或相关工作打下巩固基础。  此社区疫情基本上实现了整个社区疫情返乡人员防控管理平台信息管理的过程,向大众提供了一个安全、动态、高效的社区疫情防控管理平台系统。  二、系统设计: 系统整体架构: ​​  主要研究方法: 本系统采用基于Java语言B/S架构模式实现的,即Java启动运行的客户端与服务器的结构,基于 J2EE的基本标准,Tomcat7.0及以上作为运行服务器支持,基于、java、springboot、vue等主要技术设计,idea作为开发环境,数据库采用Mysql 5.0以上。  (1)项目调查法:参考基于java社区疫情返乡人员防控管理平台系统相关的系统设计和实现、结合这次毕业设计的自己的系统需求调研,设计出本系统的主要功能设计和架构。  (2)文献参考法:通过查阅阅读最近三年基于java社区疫情返乡人员防控管理平台有关的优质文献参考和相关书籍、了解基于java社区疫情返乡人员防控管理平台的现状和涉及的技术情况  (3)经验总结法:经过网络搜索查看、老师的指导、自己的学习开发经验结合、对系统开发整理、具体情况,进行归纳、分析总结,满足系统的各项可行性分析,使系统设计和实现的合理化、标准化。  (4)实证测试法:通过自己对前面资料的查询、阅读、以及利用自己所学习的计算机相关技术来完成编码实现、进行系统功能测试、代码编写、完成功能模块开发。最后进行测试  登录模块设计: ​  三、功能截图:  登录注册: 用户后台登录:  ​  系统首页: 社区疫情防控管理平台系统,用户输入进入到系统首页可以查看首页、社区论坛、社区公告、个人中心、后台管理等内容进行操作。    物资申请: 物资申请列表,这里的物资是用户捐赠的一些疫情防疫物资等、点击查看详情和申请操作。   申请详情: 比如常用的口罩信息等。  ​​  公告列表 点击可以查看公告详情,这里的数据是后台管理员编辑上传就行。    公告详情  社区论坛: 点击查看社区论坛列表和详情,用户登录后可以添加社区论坛信息,可以进行论坛信息进行评论等操作。   点击查看详情,用户登录后可以进行评论操作。    后台管理: 管理员登录进入社区疫情防控管理平台系统可以查看首页、个人中心、用户管理、物资捐赠管理,物资申请管理,返乡报备管理、外出报备管理、投诉信息管理、体温上报管理、商品代买管理、商品配送管理、社区论坛、系统管理等内容进行详细操作   捐赠物资管理:  返乡报备管理 : 在返乡报备管理页面可以对出发地点、返乡时间、体温、身体状态、近15天轨迹、核酸报告、经过疫区、报备时间、用户姓名、姓名、用户手机、详细住址、审核回复、审核状态、审核等信息进行详情,修改或删除等操作。   外出申请管理: 在外出报备管理页面可以对外出事由、外出地点、经过疫区、外出时间、返回时间、外出报备出行方式、随行人员、用户姓名、姓名、用户手机、详细住址、审核回复、审核状态、审核等信息进行详情,修改或删除等操作。   投诉信息管理:  核酸检测管理: 在核酸检测管理页面可以对用户姓名、姓名、性别、年龄、体温、健康码、是否咳嗽、是否腹泻、是否乏力、是否就医、其他情况、上报时间等信息进行详情,修改或删除等操作   商品代买管理: 在商品代买管理页面可以对用户姓名、姓名、用户手机、详细住址、申请时间、备注、审核回复、审核状态、审核等信息进行详情,修改或删除等操作。   商品配送管理:  社区论坛管理:  返乡公告管理:  四、数据设计: 主要数据库表字段设计: 用户信息:主键id、用户id、用户姓名、表名、角色、密码、新增时间、过期时间  物资捐赠:物资名称,物资介绍,物资图片,捐赠地址,捐赠数量,捐赠对象,发布时间,捐赠内容。审核状态,审核回复,备注等。  物资申请:物资名称,物资信息,申请人,申请时间,申请数量,用户账号,审核状态,审核回复  疫情社区论坛信息:主键id、创建日期、帖子标题名称、帖子内容、父节点id、用户id、用户姓名、状态  返乡报备:主键id、创建日期、出发地点、返乡时间、体温、身体状态、近15天轨迹、核酸报告、经过疫区、报备时间、用户姓名、姓名、用户手机、详细住址、是否审核、审核回复  用户信息:主键id、创建日期、用户姓名、密码、姓名、头像、性别、年龄、详细住址、用户手机、邮箱、身份证  外出报备:主键id、创建日期、外出事由、外出地点、经过疫区、外出时间、返回时间、外出报备出行方式、随行人员、用户姓名、姓名、用户手机、详细住址、是否审核、审核回复  投诉信息:(主键id、创建日期、标题名称、名称、类型、图片信息、投诉内容、投诉日期、用户姓名、姓名、用户手机、详细住址、是否审核、审核回复  体温上报信息:主键id、创建日期、用户姓名、姓名、性别、年龄、体温、健康码、是否咳嗽、是否腹泻、是否乏力、是否就医、其他情况、上报时间  商品配送信息:主键id、创建日期、用户姓名、姓名、用户手机、详细住址、商品金额、配送状态、更新时间、是否支付  社区疫情公告信息:主键id、创建日期、标题名称、简介、图片信息内容  数据库实体设计: 用户管理结构图: ​  投诉信息管理实体: ​体温上报管理实体: ​  五、代码实现: 用户登录: <div id="app" class="login">         <form id="loginForm" class="layui-form login-form" :style='{"padding":"20px","boxShadow":"0 0 0px rgba(255,0,0,.8)","borderColor":"rgba(0, 112, 126, 1)","backgroundColor":"rgba(255, 255, 255, 1)","borderRadius":"20px","borderWidth":"2px","width":"400px","borderStyle":"solid","justifyContent":"center","height":"auto"}'>             <h1 class="logo" v-if="false" :style='{"padding":"5px 0","boxShadow":"0 0 6px rgba(255,0,0,.8)","borderColor":"rgba(0,0,0,.3)","backgroundColor":"#fff","borderRadius":"6px","borderWidth":"0","borderStyle":"solid"}'><img :style='{"boxShadow":"0 0 6px rgba(255,0,0,.8)","margin":"0 auto","borderColor":"rgba(0,0,0,.3)","borderRadius":"100%","borderWidth":"1px","width":"44px","borderStyle":"solid","height":"44px"}' src="$template2.front.login.logo.backgroundImage"></h1>                          <div class="msg-warn hide title" v-if="true" :style='{"padding":"0 10px","boxShadow":"0 0 6px rgba(255,0,0,.8)","margin":"10px auto","borderColor":"rgba(0,0,0,1)","backgroundColor":"#f7f7f7","color":"red","isshow":true,"borderRadius":"8px","borderWidth":"0","width":"auto","lineHeight":"32px","fontSize":"12px","borderStyle":"solid"}'>公共场所不建议自动登录,以防账号丢失</div>             <div :style='{"padding":"0","boxShadow":"0 0 6px rgba(255,0,0,0)","margin":"0 auto","borderColor":"rgba(0, 112, 126, 1)","backgroundColor":"rgba(213, 195, 195, 0.49)","borderRadius":"20px","borderWidth":"0 0 0px 0","width":"80%","borderStyle":"solid","height":"64px"}' class="form-item">                 <label v-if="false" :style='{"padding":"0 10px","boxShadow":"0 0 6px rgba(255,0,0,0)","borderColor":"rgba(0,0,0,0)","backgroundColor":"transparent","color":"#333","borderRadius":"0","textAlign":"right","borderWidth":"0","width":"84px","fontSize":"16px","borderStyle":"solid"}' class="form-label">账号</label>                 <input :style='{"padding":"0 10px","boxShadow":"0 0 6px rgba(0,0,0,.5)","borderColor":"rgba(0, 112, 126, 1)","backgroundColor":"#fff","color":"#333","borderRadius":"8px","textAlign":"left","borderWidth":"1px","width":"100%","fontSize":"14px","borderStyle":"solid","height":"44px"}' type="text" name="username" required lay-verify="required" placeholder="请输入账号" autocomplete="off" class="layui-input">             </div>             <div :style='{"padding":"0","boxShadow":"0 0 6px rgba(255,0,0,0)","margin":"0 auto","borderColor":"rgba(0, 112, 126, 1)","backgroundColor":"rgba(213, 195, 195, 0.49)","borderRadius":"20px","borderWidth":"0 0 0px 0","width":"80%","borderStyle":"solid","height":"64px"}' class="form-item">                 <label v-if="false" :style='{"padding":"0 10px","boxShadow":"0 0 6px rgba(255,0,0,0)","borderColor":"rgba(0,0,0,0)","backgroundColor":"transparent","color":"#333","borderRadius":"0","textAlign":"right","borderWidth":"0","width":"84px","fontSize":"16px","borderStyle":"solid"}' class="form-label">密码</label>                 <input :style='{"padding":"0 10px","boxShadow":"0 0 6px rgba(0,0,0,.5)","borderColor":"rgba(0, 112, 126, 1)","backgroundColor":"#fff","color":"#333","borderRadius":"8px","textAlign":"left","borderWidth":"1px","width":"100%","fontSize":"14px","borderStyle":"solid","height":"44px"}' type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">             </div>                 <div class="form-item codes" :style='{"padding":"0","boxShadow":"0 0 6px rgba(255,0,0,0)","margin":"0 auto","borderColor":"rgba(0, 112, 126, 1)","backgroundColor":"rgba(213, 195, 195, 0.49)","borderRadius":"20px","borderWidth":"0 0 0px 0","width":"80%","borderStyle":"solid","height":"64px"}'>                   <input style="flex: 1;" type="text" id="code" placeholder="请输入验证码">                   <div class="nums" id="nums" style="display: flex;justify-content: center;align-items: center;">                                        </div>                 </div>               <div :style='{"padding":"0","boxShadow":"0 0 6px rgba(255,0,0,0)","margin":"0 auto","borderColor":"rgba(0, 112, 126, 1)","backgroundColor":"#fff","borderRadius":"0","borderWidth":"0 0 1px 0","width":"80%","borderStyle":"solid","height":"44px"}' class="form-item l-redio">                 <input v-if="item.hasFrontLogin=='是'" v-for="(item,index) in menu" v-bind:key="index" type="radio" name="role" id="role" :value="item.tableName" :title="item.roleName">             </div>             <button :style='{"padding":"0 10px","boxShadow":"0 0px 0px rgba(255, 0, 0, 1)","margin":"10px auto","borderColor":"rgba(0, 112, 126, 1)","backgroundColor":"rgba(38, 155, 158, 1)","color":"#fff","borderRadius":"8px","borderWidth":"0","width":"60%","fontSize":"14px","borderStyle":"solid","height":"44px"}' class="layui-btn layui-btn-fluid layui-btn-danger btn-submit" lay-submit lay-filter="login">登录</button>             <p :style='{"color":"rgba(255, 0, 0, 1)","textAlign":"left","fontSize":"12px"}' class="txt"><a style="color: inherit;font-size: inherit;" v-if="item.hasFrontRegister=='是'" v-for="(item,index) in menu" v-bind:key="index" :href="'javascript:registerClick(\''+item.tableName+'\')'">注册{{item.roleName.replace('注册','')}}</a></p>         </form>     </div>  物资申请:     /**  * 申请物资  * 后端接口  * @author   * @email   * @date 2021210-11 19:15:03  */ @RestController @RequestMapping("/juanzengdingdan") public class JuanzengdingdanController {     @Autowired     private JuanzengdingdanService juanzengdingdanService;          /**      * 后端列表      */     @RequestMapping("/page")     public R page(@RequestParam Map<String, Object> params,JuanzengdingdanEntity juanzengdingdan,         HttpServletRequest request){         String tableName = request.getSession().getAttribute("tableName").toString();         String username = (String)request.getSession().getAttribute("username");         EntityWrapper<JuanzengdingdanEntity> ew = new EntityWrapper<JuanzengdingdanEntity>();         if(tableName.equals("jigou")) {             juanzengdingdan.setJigouzhanghao((String)request.getSession().getAttribute("username"));         }         if(tableName.equals("yonghu")) {             juanzengdingdan.setYonghuzhanghao((String)request.getSession().getAttribute("username"));         }         PageUtils page = juanzengdingdanService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, juanzengdingdan), params), params));           return R.ok().put("data", page);     }             /**      * 列表      */     @RequestMapping("/lists")     public R list( JuanzengdingdanEntity juanzengdingdan){            EntityWrapper<JuanzengdingdanEntity> ew = new EntityWrapper<JuanzengdingdanEntity>();           ew.allEq(MPUtil.allEQMapPre( juanzengdingdan, "juanzengdingdan"));          return R.ok().put("data", juanzengdingdanService.selectListView(ew));     }        /**      * 查询      */     @RequestMapping("/query")     public R query(JuanzengdingdanEntity juanzengdingdan){         EntityWrapper< JuanzengdingdanEntity> ew = new EntityWrapper< JuanzengdingdanEntity>();          ew.allEq(MPUtil.allEQMapPre( juanzengdingdan, "juanzengdingdan"));          JuanzengdingdanView juanzengdingdanView =  juanzengdingdanService.selectView(ew);         return R.ok("查询申请物资成功").put("data", juanzengdingdanView);     }             /**      * 前端详情      */     @RequestMapping("/detail/{id}")     public R detail(@PathVariable("id") Long id){         JuanzengdingdanEntity juanzengdingdan = juanzengdingdanService.selectById(id);         return R.ok().put("data", juanzengdingdan);     }              /**      * 前端保存      */     @RequestMapping("/add")     public R add(@RequestBody JuanzengdingdanEntity juanzengdingdan, HttpServletRequest request){         juanzengdingdan.setId(new Date().getTime()+new Double(Math.floor(Math.random()*1000)).longValue());         juanzengdingdan.setJuanzengshijian(new Date());         juanzengdingdanService.insert(juanzengdingdan);         return R.ok();     }       /**      * 修改      */     @RequestMapping("/update")     public R update(@RequestBody JuanzengdingdanEntity juanzengdingdan, HttpServletRequest request){         //ValidatorUtils.validateEntity(juanzengdingdan);         juanzengdingdanService.updateById(juanzengdingdan);//全部更新         return R.ok();     }          /**      * 删除      */     @RequestMapping("/delete")     public R delete(@RequestBody Long[] ids){         juanzengdingdanService.deleteBatchIds(Arrays.asList(ids));         return R.ok();     }         }  配置拦截:    @Configuration public class InterceptorConfig extends WebMvcConfigurationSupport{          @Bean     public AuthorizationInterceptor getAuthorizationInterceptor() {         return new AuthorizationInterceptor();     }          @Override     public void addInterceptors(InterceptorRegistry registry) {         registry.addInterceptor(getAuthorizationInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**");         super.addInterceptors(registry);     }          /**      * springboot 2.0配置WebMvcConfigurationSupport之后,会导致默认配置被覆盖,要访问静态资源需要重写addResourceHandlers方法      */     @Override     public void addResourceHandlers(ResourceHandlerRegistry registry) {         registry.addResourceHandler("/**")         .addResourceLocations("classpath:/resources/")         .addResourceLocations("classpath:/static/")         .addResourceLocations("classpath:/admin/")         .addResourceLocations("classpath:/front/")         .addResourceLocations("classpath:/public/");         registry.addResourceHandler("/upload/**").addResourceLocations("file:D:/work/");         super.addResourceHandlers(registry);     } }  ———————————————— 版权声明:本文为CSDN博主「java李杨勇」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_39709134/article/details/128124580 
  • [技术干货] Spring注解开发-转载
     1、Spring注解开发 1 注解开发定义Bean对象【重点】 目的:xml配置Bean对象有些繁琐,使用注解简化Bean对象的定义  问题导入 问题1:使用什么标签进行Spring注解包扫描?  问题2:@Component注解和@Controller、@Service、@Repository三个衍生注解有什么区别?  1.1 基本使用 【第一步】在applicationContext.xml中开启Spring注解包扫描  <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:context="http://www.springframework.org/schema/context"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">      <!--扫描com.itheima包及其子包下的类中注解-->     <context:component-scan base-package="com.lfs"/> </beans> 【第二步】在类上使用@Component注解定义Bean。  //@Component定义bean @Component("bookDao") public class BookDaoImpl implements BookDao {     public void save() {         System.out.println("book dao save ...");     } } @Component public class BookServiceImpl implements BookService {     private BookDao bookDao;      public void setBookDao(BookDao bookDao) {         this.bookDao = bookDao;     }      public void save() {         System.out.println("book service save ...");         bookDao.save();     } } 补充说明:如果@Component注解没有使用参数指定Bean的名称,那么类名首字母小写就是Bean在IOC容器中的默认名称。例如:BookServiceImpl对象在IOC容器中的名称是bookServiceImpl。  【第三步】在测试类中获取Bean对象  public class AppForAnnotation {     public static void main(String[] args) {         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");         BookDao bookDao = (BookDao) ctx.getBean("bookDao");         System.out.println(bookDao);         //按类型获取bean         BookService bookService = ctx.getBean(BookService.class);         System.out.println(bookService);     } } 注意:在测试类中不要调用bookService的save方法,因为还没有给BookServiceImpl中的bookDao赋值,调用bookService的save方法会出现空指针异常。  1.2 @Component三个衍生注解 说明:加粗的注解为常用注解  Spring提供**@Component**注解的三个衍生注解 @Controller:用于表现层bean定义 @Service:用于业务层bean定义 @Repository:用于数据层bean定义 @Repository("bookDao") public class BookDaoImpl implements BookDao { }  @Service public class BookServiceImpl implements BookService { } 2 纯注解开发模式【重点】 问题导入 问题1:配置类上使用什么注解表示该类是一个配置类?  问题2:配置类上使用什么注解进行Spring注解包扫描?  2.1 纯注解开发模式介绍 Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道 Java类代替Spring核心配置文件 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cGOu29Re-1670647827838)(assets/image-20210803192052811.png)]  @Configuration注解用于设定当前类为配置类 @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式 @ComponentScan({com.itheima.service","com.lfs.dao"}) 1 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象 //加载配置文件初始化容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //加载配置类初始化容器 ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); 2.2 代码演示 【第一步】定义配置类代替配置文件  //声明当前类为Spring配置类 @Configuration //Spring注解扫描,相当于<context:component-scan base-package="com.itheima"/> @ComponentScan("com.itheima") //设置bean扫描路径,多个路径书写为字符串数组格式 //@ComponentScan({"com.itheima.service","com.lfs.dao"}) public class SpringConfig { } 【第二步】在测试类中加载配置类,获取Bean对象并使用  public class AppForAnnotation {     public static void main(String[] args) {         //AnnotationConfigApplicationContext加载Spring配置类初始化Spring容器         ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);         BookDao bookDao = (BookDao) ctx.getBean("bookDao");         System.out.println(bookDao);         //按类型获取bean         BookService bookService = ctx.getBean(BookService.class);         System.out.println(bookService);     } } 3 注解开发Bean作用范围和生命周期管理 问题导入 在类上使用什么注解定义Bean的作用范围?  3.1 bean作用范围注解配置 使用@Scope定义bean作用范围 @Repository @Scope("singleton") public class BookDaoImpl implements BookDao { } 3.2 bean生命周期注解配置 使用@PostConstruct、@PreDestroy定义bean生命周期 @Repository @Scope("singleton") public class BookDaoImpl implements BookDao {     public BookDaoImpl() {         System.out.println("book dao constructor ...");     }     @PostConstruct     public void init(){         System.out.println("book init ...");     }     @PreDestroy     public void destroy(){         System.out.println("book destory ...");     } } 注意:@PostConstruct和@PreDestroy注解是jdk中提供的注解,从jdk9开始,jdk中的javax.annotation包被移除了,也就是说这两个注解就用不了了,可以额外导入一下依赖解决这个问题。  <dependency>   <groupId>javax.annotation</groupId>   <artifactId>javax.annotation-api</artifactId>   <version>1.3.2</version> </dependency> 4 注解开发依赖注入【重点】 问题导入 问题1:请描述@Autowired注解是如何进行自动装配的?  问题2:请描述@Qualifier注解的作用  4.1 使用@Autowired注解开启自动装配模式(按类型) @Service public class BookServiceImpl implements BookService {     //@Autowired:注入引用类型,自动装配模式,默认按类型装配     @Autowired     private BookDao bookDao;      public void save() {         System.out.println("book service save ...");         bookDao.save();     } } 说明:不管是使用配置文件还是配置类,都必须进行对应的Spring注解包扫描才可以使用。@Autowired默认按照类型自动装配,如果IOC容器中同类的Bean有多个,那么默认按照变量名和Bean的名称匹配,建议使用@Qualifier注解指定要装配的bean名称  注意:自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法。  4.2 使用@Qualifier注解指定要装配的bean名称 目的:解决IOC容器中同类型Bean有多个装配哪一个的问题  @Service public class BookServiceImpl implements BookService {     //@Autowired:注入引用类型,自动装配模式,默认按类型装配     @Autowired     //@Qualifier:自动装配bean时按bean名称装配     @Qualifier("bookDao")     private BookDao bookDao;      public void save() {         System.out.println("book service save ...");         bookDao.save();     } } 注意:@Qualifier注解无法单独使用,必须配合@Autowired注解使用  4.3 使用@Value实现简单类型注入 @Repository("bookDao") public class BookDaoImpl implements BookDao {     //@Value:注入简单类型(无需提供set方法)     @Value("${name}")     private String name;      public void save() {         System.out.println("book dao save ..." + name);     } } 以上@Value注解中使用${name}从属性文件中读取name值,那么就需要在配置类或者配置文件中加载属性文件。  @Configuration @ComponentScan("com.itheima") //@PropertySource加载properties配置文件 @PropertySource({"classpath:jdbc.properties"}) //{}可以省略不写 public class SpringConfig { } 注意:@PropertySource()中加载多文件请使用数组格式配置,不允许使用通配符*  5 注解开发管理第三方Bean【重点】 问题导入 导入自己定义的配置类有几种方式?  【第一步】单独定义配置类 public class JdbcConfig {     //@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中     @Bean     public DataSource dataSource(){         DruidDataSource ds = new DruidDataSource();         ds.setDriverClassName("com.mysql.jdbc.Driver");         ds.setUrl("jdbc:mysql://localhost:3306/spring_db");         ds.setUsername("root");         ds.setPassword("root");         return ds;     } } 【第二步】将独立的配置类加入核心配置 方式1:@Import注解导入式 @Configuration @ComponentScan("com.itheima") //@Import:导入配置信息 @Import({JdbcConfig.class}) public class SpringConfig { } 方式2:@ComponentScan扫描式 @Configuration @ComponentScan({"com.itheima.config","com.itheima.service","com.itheima.dao"})  //只要com.itheima.config包扫到了就行,三个包可以合并写成com.itheima public class SpringConfig { } 6 注解开发为第三方Bean注入资源【重点】 问题导入 配置类中如何注入简单类型数据,如何注入引用类型数据?  6.1 简单类型依赖注入 public class JdbcConfig {     //1.定义一个方法获得要管理的对象     @Value("com.mysql.jdbc.Driver")     private String driver;     @Value("jdbc:mysql://localhost:3306/spring_db")     private String url;     @Value("root")     private String userName;     @Value("root")     private String password;     //2.@Bean:表示当前方法的返回值是一个bean对象,添加到IOC容器中     @Bean     public DataSource dataSource(){         DruidDataSource ds = new DruidDataSource();         ds.setDriverClassName(driver);         ds.setUrl(url);         ds.setUsername(userName);         ds.setPassword(password);         return ds;     } } 说明:如果@Value()中使用了EL表达式读取properties属性文件中的内容,那么就需要加载properties属性文件。  6.2 引用类型依赖注入 //Spring会自动从IOC容器中找到BookDao对象赋值给参数bookDao变量,如果没有就会报错。 @Bean  public DataSource dataSource(BookDao bookDao){     System.out.println(bookDao);     DruidDataSource ds = new DruidDataSource();     ds.setDriverClassName(driver);     ds.setUrl(url);     ds.setUsername(userName);     ds.setPassword(password);     return ds; } 说明:引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象 ———————————————— 版权声明:本文为CSDN博主「楠慧」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_64071654/article/details/128263980 
  • [技术干货] 执行js代码(executeScript)命令使用技巧
    Js中定位操作元素1.使用控制台定位1.右击需要定位的元素,选择Copy选项,再选择Copy JS path的子选项复制上元素定位路径。 2.切换到Console面板,粘贴上前面复制的信息,即可在第二行预览定位元素的情况。 3.这里使用的是CSS的定位方式,如果觉得控制台生成的定位路径不好用,那么可以修改上图中红色字体的定位信息 2.使用XPATH方式定位xpath的通常格式是:document.evaluate('......', document).iterateNext()其中的......表示的是xpath语句xpath语句可以右击操作元素,选择Copy选项,再选择Copy XPath的子选项复制上元素定位路径。 也可以手动书写相关xpath语句,不过最好在Elements面板中通过Ctrl+f组合键唤出搜索栏(下图中红色部分),然后写上自己的xpath语句进行验证,确保定位的元素是唯一的(下图中绿色部分)。使用场景1.执行点击动作先定位操作元素,再执行click方法上图中使用了JS path2.获取元素数量1.通过querySelectorAll方法获取元素数量......使用的是CSS语法return document.querySelectorAll(".......").length在Studio中获取js的返回值需要使用return关键词 2.通过evaluate方法获取元素数量......使用的是XPATH语法return document.evaluate('......', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE).snapshotLength同理在Studio中获取js的返回值需要使用return关键词3.获取元素文本先定位操作元素,再执行获取方法,相关的方法较多,可以逐一尝试// 方法1 document.querySelector("span#content").value // 方法2 document.querySelector("span#content").innerHTML // 方法3 document.querySelector("span#content").innerText // 方法4 document.querySelector("span#content").textContent // 方法5 document.querySelector("span#content").nodeValue对于一个元素,不一定每种方法都可以获取到文本值,选择一个可用的就行 同理在Studio中获取js的返回值需要使用return关键词 更多使用场景欢迎在下面补充注意事项1.iframe框架的选取在拾取的时候,如果js操作的目标元素不在iframe中,那么可以拾取整个页面,但是如果目标元素位于某层iframe中,那么就需要具体拾取到那一层iframe元素上。
  • [技术干货] top.location.href和localtion.href有什么不同
    window.location.href、location.href是本页面跳转 parent.location.href是上一层页面跳转 top.location.href是最外层的页面跳转 top.location.href=”url” 在顶层页面打开url(跳出框架)   self.location.href=”url” 仅在本页面打开url地址   parent.location.href=”url”   在父窗口打开Url地址    this.location.href=”url”    用法和self的用法一致 if (top.location == self.location) 判断当前location 是否为顶层来 禁止frame引用  如果页面当中有自定义的frame的话, 也可以将parent self top换为自定义frame的名称 效果就是在自定义frame窗口打开url地址实际中可能这样使用        if(top !== self){             top.location.href = location.href;         }   禁止frame引用 以下是从网上找到的一个例子,不是很直观, 我加了上面那三行代码, 可以先去掉, 再加上, 看一下效果,就很清楚了 以下是top.htm 代码
  • [问题求助] GDE中js脚本里怎么设置disabled属性啊
    disabled在脚本里怎么写才规范啊,无论怎么写都是报错呢,试了几种方法需求是点击提交按钮后,将该按钮设为禁用状态,待请求发送成功后,再解除按钮限制
  • 剑指 Offer 49. 丑数 && 264. 丑数 II ●●-转载
     描述 只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。  通常 1 为第一个丑数,求按从小到大的顺序的第 n 个丑数。  示例 输入:n = 10 输出:12 解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。  题解 1. 小顶堆 要得到从小到大的第 n 个丑数,可以使用最小堆实现。  初始时堆为空。首先将最小的丑数 1 加入堆。  每次取出堆顶元素 x,即堆中最小的丑数,由于 2x, 3x, 5x 也是丑数,因此将 2x, 3x, 5x 加入堆。  上述做法会导致堆中出现重复元素的情况。为了避免重复元素,可以使用哈希集合去重,避免相同元素多次加入堆。  在排除重复元素的情况下,第 n 次从最小堆中取出的元素即为第 n 个丑数。  时间复杂度:O ( n log ⁡ n ) O(n \log n)O(nlogn)。得到第 n 个丑数需要进行 n 次循环,每次循环都要从最小堆中取出 1 个元素以及向最小堆中加入最多 3 个元素,因此每次循环的时间复杂度是 O ( log ⁡ ( 3 n ) + 3 log ⁡ ( 3 n ) ) O(\log (3n) + 3 \log (3n))O(log(3n)+3log(3n)),总时间复杂度是 O ( n log ⁡ n ) O(n \log n)O(nlogn)。 空间复杂度:O ( n ) O(n)O(n)。空间复杂度主要取决于最小堆和哈希集合的大小,最小堆和哈希集合的大小都不会超过 3n。 class Solution { public:     int nthUglyNumber(int n) {         vector factors = {2, 3, 5};        // 因子         unordered_set hash;                // 哈希         priority_queue, greater> heap;    // 小顶堆         hash.insert(1L);         heap.push(1L);         int uglyn = 1;                                     for(int i = 1; i <= n; ++i){             long top = heap.top();             heap.pop();             uglyn = (int)top;                    // 第n个丑数             for(int factor : factors){            // 堆中最小的丑数 * 因子2/3/5                 long next = top * factor;                 if(hash.count(next) == 0){                     hash.insert(next);                     heap.push(next);                 }             }         }         return uglyn;     } }; 2. 动态规划 方法一使用最小堆,会预先存储较多的丑数,维护最小堆的过程也导致时间复杂度较高。 可以使用动态规划的方法进行优化。  定义数组 uglys,其中 uglys[i-1] 表示第 i 个丑数。 uglys[0] = 1;  如何得到其余的丑数呢? 每个丑数都有一次与 2/3/5 相乘的机会,定义三个指针 p2、p3、p5,表示下一个丑数是三个指针指向的丑数乘以对应的质因数得到的最小值。初始时,三个指针的值都是 0,每轮将对应指针执行 +1 即可。  uglys[i] = min(min(num2, num3), num5); 在进行指针判断移动操作时,对每个指针得到的结果都进行一次对比,去除重复操作,比如 5*2 与 2*5,那么 p2 和 p5 都右移。  时间复杂度:O(n)。需要计算数组中的 n 个元素,每个元素的计算都可以在 O(1) 的时间内完成。 空间复杂度:O(n) class Solution { public:     int nthUglyNumber(int n) {         vector uglys(n, 1);         int p2 = 0, p3 = 0, p5 = 0;         for(int i = 1; i < n; ++i){             int num2 = uglys[p2]*2, num3 = uglys[p3]*3, num5 = uglys[p5]*5;             uglys[i] = min(min(num2, num3), num5);             if(uglys[i] == num2) ++p2;             if(uglys[i] == num3) ++p3;             if(uglys[i] == num5) ++p5;      // 不用else,去重,2*5 跟 5*2的情况,p2与p5++         }         return uglys[n-1];     } }; ———————————————— 版权声明:本文为CSDN博主「keep_fan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_19887221/article/details/126689247 
  • [技术干货] js中数组reduce方法的使用和实现【转载】
    reduce方法定义reduce() 方法对数组中的每个元素执行一个传入的callback回调函数(升序执行,空值和已删除的除外),将其结果汇总为单个返回值。reduce方法语法arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])reduce方法参数callback自己传入的为数组中每个值 (如果没有传入 initialValue则第一个值除外)执行的函数,包含四个参数:(1)accumulator累计器累计回调的返回值; 它是上一次调用callback回调时返回的值,或初始化时initialValue的值(见于下方)。(2)currentValue数组中当前正在处理的元素。(3)index 可选数组中当前正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则从索引1起始。(4)selfArray可选调用reduce()的源数组自身。initialValue可选作为第一次调用 callback函数时的第一个参数的值。 如果没有传入初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。reduce方法返回值函数累计处理的结果(可以是任意值,取决于自己需要什么)。reduce方法详细描述reduce为数组中的每一个元素依次执行callback函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:1、accumulator 累计器2、currentValue 当前值3、currentIndex 当前值的索引4、selfArray数组本身回调函数第一次执行时,accumulator 和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。特别注意:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。如果调用reduce函数的数组为空且没有提供initialValue,会抛出TypeError 。如果数组仅有一个元素(无论位置如何)并且没有提供initialValue, 或者有提供initialValue但是数组为空,那么此唯一值将被返回并且callback不会被执行。reduce方法使用示例参数累加 // 不传入initialValue参数 let arr1 = [1,3, , ,5] let newArr = arr1.reduce((acc, cur, index, selfArr) => { console.log({acc, cur, index}) return acc + cur }) console.log(newArr) // {acc: 1, cur: 3, index: 1} // {acc: 4, cur: 5, index: 4} // 9 // 传入initialValue参数 let newArr1 = arr1.reduce((acc, cur, index) => { console.log({acc, cur, index}) return acc + cur }, 0) console.log(newArr1) // {acc: 0, cur: 1, index: 0} // {acc: 1, cur: 3, index: 1} // {acc: 4, cur: 5, index: 4} // 9上述代码的最终结果都是返回数组中每个元素相加的和,区别就是第一组代码没有传入initialValue 参数,第二组传入了initialValue 参数。根据打印结果可以看出,第一组没有传入initialValue参数的代码从arr1数组中索引为1的元素开始执行callback函数,一共执行了两次,并且acc初始值为数组的第一个元素。第二组传入initialValue 参数的代码,从arr1原数组中索引值为0的元素开始执行并且acc初始值为传入的initialValue的值。两组代码都没有为arr1原数组中的空值执行callback函数。数组对象结构的参数累加 let arr2 = [ { num: 1, }, { num: 5, }, { num: 7, } ] const newArr2 = arr2.reduce((acc, cur, index) => { return acc + cur.num }, 0) console.log(newArr2) // 13上述代码是循环原数组arr2中每一项,并将每一项里面num的值进行相加,并且返回最后相加的结果。数组去重 let arr3 = [1,2,1,1,3,5,2] const newArr3 = arr3.reduce((acc, cur) => { if (!acc.includes(cur)) acc.push(cur) return acc }, []) console.log(newArr3) // [1, 2, 3, 5]上述代码 执行时初始参数传入一个空数组,然后开始从原数组arr3的第一个元素开始执行callback函数,每次都会利用数组的includes方法判断当前元素是否已经存在传入的数组里面,最后返回传入的数组赋值给acc参数。最后的结果就是已经去重好的新数组newArr3。对象分类 let arr4 = [ { name: '小红', age: 21 }, { name: '小绿', age: 20 }, { name: '小蓝', age: 20 }, { name: '大白', age: 19 } ]; const newArr4 = arr4.reduce((acc, cur, index) => { if (!acc[cur.age]) acc[cur.age] = [] acc[cur.age].push(cur) return acc }, {}) console.log(newArr4) // { // 19: [{ name: '大白', age: 19 }], // 20: [{name: "小绿", age: 20}, {name: "小蓝", age: 20}], // 21: [{name: "小红", age: 21}] // }上述代码将数据列表根据age进行分类,同样age的数据合并组成key:value形式展示出来。计算数组中元素出现的次数 let arr5 = [1,2,3,1,2,1] const newArr5 = arr5.reduce((acc, cur) => { acc[cur]? acc[cur] ++: acc[cur] = 1 return acc }, {}) console.log(newArr5) // {1: 3, 2: 2, 3: 1}上述代码利用对象中key – value数据形式来计算得出数组中每个元素出现的次数。最后在来看下空数组和数组只有一个参数时的值: // 数组为空,传入initialValue初始值时和只有一个参数没有传入初始值时 console.log([].reduce((acc, cur) => { console.log(acc, cur) return cur }, 0)) // 0 console.log([1].reduce((acc, cur) => { console.log(acc, cur) return 10 })) // 1下面根据上述描述和使用来模拟实现我们自己的reduce方法。步骤思路1、 将方法添加到Array的原型上2、 传入回调函数形参和初始值形参3、 判断initialValue 初始值是否传入4、 判断原数组的元素是不是空值,来调用callback函数5、 将每次执行的callback函数的返回值赋值给accumulator6、 返回accumulator实现代码 Array.prototype.myReduce = function(callback, initialValue) { let accumulator,initIndex, length = this.length // 判断initialValue初始参数有没有传入 if (initialValue || initialValue === 0) { // 空数组时直接返回传入的初始参数 if (length === 0) return initialValue initIndex = 0 accumulator = initialValue } else { // 空数组时报错 if (length === 0) throw new TypeError('xxxxxxxxx') // 原数组只有一个元素时,返回此元素 if (length === 1) return this[0] initIndex = 1 accumulator = this[0] } for (let index = initIndex; index < length; index++) { // 通过hasOwnProperty方法剔除空值,然后将传入的callback函数的值赋值给accumulator累计参数 if(this.hasOwnProperty(index)) accumulator = callback(accumulator, this[index], index, this) } return accumulator }测试验证 Array.prototype.myReduce = function(callback, initialValue) { let accumulator,initIndex, length = this.length // 判断initialValue初始参数有没有传入 if (initialValue || initialValue === 0) { // 空数组时直接返回传入的初始参数 if (length === 0) return initialValue initIndex = 0 accumulator = initialValue } else { // 空数组时报错 if (length === 0) throw new TypeError('xxxxxxxxx') // 原数组只有一个元素时,返回此元素 if (length === 1) return this[0] initIndex = 1 accumulator = this[0] } for (let index = initIndex; index < length; index++) { // 通过hasOwnProperty方法剔除空值,然后将传入的callback函数的值赋值给accumulator累计参数 if(this.hasOwnProperty(index)) accumulator = callback(accumulator, this[index], index, this) } return accumulator } // 不传入initialValue参数 let arr1 = [1,3, , ,5] let newArr = arr1.myReduce((acc, cur, index, selfArr) => { console.log({acc, cur, index}) return acc + cur }) console.log(newArr) // {acc: 1, cur: 3, index: 1} // {acc: 4, cur: 5, index: 4} // 9 // 传入initialValue参数 let newArr1 = arr1.myReduce((acc, cur, index) => { console.log({acc, cur, index}) return acc + cur }, 0) console.log(newArr1) // {acc: 0, cur: 1, index: 0} // {acc: 1, cur: 3, index: 1} // {acc: 4, cur: 5, index: 4} // 9 let arr2 = [ { num: 1, }, { num: 5, }, { num: 7, } ] const newArr2 = arr2.myReduce((acc, cur, index) => { return acc + cur.num }, 0) console.log(newArr2) // 13 let arr3 = [1,2,1,1,3,5,2] const newArr3 = arr3.myReduce((acc, cur) => { if (!acc.includes(cur)) acc.push(cur) return acc }, []) console.log(newArr3) // [1, 2, 3, 5] let arr4 = [ { name: '小红', age: 21 }, { name: '小绿', age: 20 }, { name: '小蓝', age: 20 }, { name: '大白', age: 19 } ]; const newArr4 = arr4.myReduce((acc, cur, index) => { if (!acc[cur.age]) acc[cur.age] = [] acc[cur.age].push(cur) return acc }, {}) console.log(newArr4) // { // 19: [{ name: '大白', age: 19 }], // 20: [{name: "小绿", age: 20}, {name: "小蓝", age: 20}], // 21: [{name: "小红", age: 21}] // } let arr5 = [1,2,3,1,2,1] const newArr5 = arr5.myReduce((acc, cur) => { acc[cur]? acc[cur] ++: acc[cur] = 1 return acc }, {}) console.log(newArr5) // {1: 3, 2: 2, 3: 1} // 数组为空,传入initialValue初始值时和只有一个参数没有传入初始值时 console.log([].myReduce((acc, cur) => { console.log(acc, cur) return cur }, 0)) // 0 console.log([1].myReduce((acc, cur) => { console.log(acc, cur) return 10 })) // 1使用自己模拟实现的方法打印结果和原方法一致。作者:绿芽链接:https://www.jianshu.com/p/a31f43462007
总条数:53 到第
上滑加载中