flutter聊天界面-TextField输入框实现@功能等匹配正则表达式展示高亮功能
flutter聊天界面-TextField输入框实现@功能等匹配正则表达式展示高亮功能
一、简要描述
描述:
最近有位朋友讨论的时候,提到了输入框的高亮展示。在flutter TextField中需要插入特殊样式的标签,比如:“请 @张三 回答一下”,这一串字符在TextField中输入,当输入@时 弹出好友列表选择,然后将 “@张三”高亮显示在TextField中。
效果图如下
视频效果
flutter聊天界面-TextField输入框实现@功能
昨天整理的文中,简单实用TextEditingController的buildTextSpan时候,直接修改代码
List<InlineSpan> textSpans = RichTextHelper.getRichText(value.text);if (composingRegionOutOfRange) {return TextSpan(style: style, children: textSpans);}
会出现光标输入的问题,这里修改了一下,完善了一下。
大家可以使用rich_text_controller
来实现,查看rich_text_controller源码可以看到,RichTextController继承TextEditingController,重写了buildTextSpan。经过我在iPhone上测试,当输入@汉字的时候,对中文兼容会有问题,这里做一下修改完善修改。
二、TextEditingController的buildTextSpan方法
在TextEditingController中buildTextSpan方法中,我们可以看到,该方法中的代码
composingRegionOutOfRange:仅有输入完成的字
在最后一部分的代码中含有未输入完成的字
final TextStyle composingStyle = style?.merge(const TextStyle(decoration: TextDecoration.underline))?? const TextStyle(decoration: TextDecoration.underline);return TextSpan(style: style,children: <TextSpan>[TextSpan(text: value.composing.textBefore(value.text)),TextSpan(style: composingStyle,text: value.composing.textInside(value.text),),TextSpan(text: value.composing.textAfter(value.text)),],);
-
composingStyle未输入完成的字的样式,可以自己做下修改。
-
value.composing.textBefore:当前输入前面的字。
-
value.composing.textAfter:当前输入后面的字。
当输入过程中,我们将value.composing.textBefore,value.composing.textAfter匹配高亮即可
代码如下
value.composing.textBefore
TextSpan(style: style, children: buildRegExpSpan(context: context, text: value.composing.textBefore(value.text))),
value.composing.textAfter
TextSpan(style: style, children: buildRegExpSpan(context: context, text: value.composing.textAfter(value.text))),
匹配正则表达式
List<TextSpan> buildRegExpSpan({required BuildContext context,TextStyle? style,required String? text}) {List<TextSpan> children = [];if (!(text != null && text.isNotEmpty)) {return children;}final matches = <String>{};List<Map<String, List<int>>> matchIndex = [];// Validating with REGEXRegExp? allRegex;allRegex = patternMatchMap != null? RegExp(patternMatchMap?.keys.map((e) => e.pattern).join('|') ?? "",caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;// Validating with StringsRegExp? stringRegex;stringRegex = stringMatchMap != null? RegExp(r'\b' + stringMatchMap!.keys.join('|').toString() + r'+\$',caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;text.splitMapJoin(stringMatchMap == null ? allRegex! : stringRegex!,onNonMatch: (String span) {if (stringMatchMap != null &&children.isNotEmpty &&stringMatchMap!.keys.contains("${children.last.text}$span")) {final String? ks =stringMatchMap!["${children.last.text}$span"] != null? stringMatchMap?.entries.lastWhere((element) {return element.key.allMatches("${children.last.text}$span").isNotEmpty;}).key: '';children.add(TextSpan(text: span, style: stringMatchMap![ks!]));return span.toString();} else {children.add(TextSpan(text: span, style: style));return span.toString();}},onMatch: (Match m) {matches.add(m[0]!);final RegExp? k = patternMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key;final String? ks = stringMatchMap?[m[0]] != null? stringMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key: '';if (deleteOnBack!) {if ((isBack(text!, _lastValue) && m.end == selection.baseOffset)) {WidgetsBinding.instance.addPostFrameCallback((_) {children.removeWhere((element) => element.text! == text);text = text!.replaceRange(m.start, m.end, "");selection = selection.copyWith(baseOffset: m.end - (m.end - m.start),extentOffset: m.end - (m.end - m.start),);});} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}final resultMatchIndex = matchValueIndex(m);if (resultMatchIndex != null && onMatchIndex != null) {matchIndex.add(resultMatchIndex);onMatchIndex!(matchIndex);}return (onMatch(List<String>.unmodifiable(matches)) ?? '');},);return children;}
这里使用的是rich_text_controller中的代码,做了相应的修改,输入@张三正则表达式正常高亮显示了。
整个text_field_controller代码如下
import 'package:flutter/material.dart';class TextFieldController extends TextEditingController {final Map<RegExp, TextStyle>? patternMatchMap;final Map<String, TextStyle>? stringMatchMap;final Function(List<String> match) onMatch;final Function(List<Map<String, List<int>>>)? onMatchIndex;final bool? deleteOnBack;String _lastValue = "";/// controls the caseSensitive property of the full [RegExp] used to pattern matchfinal bool regExpCaseSensitive;/// controls the dotAll property of the full [RegExp] used to pattern matchfinal bool regExpDotAll;/// controls the multiLine property of the full [RegExp] used to pattern matchfinal bool regExpMultiLine;/// controls the unicode property of the full [RegExp] used to pattern matchfinal bool regExpUnicode;bool isBack(String current, String last) {return current.length < last.length;}TextFieldController({String? text,this.patternMatchMap,this.stringMatchMap,required this.onMatch,this.onMatchIndex,this.deleteOnBack = false,this.regExpCaseSensitive = true,this.regExpDotAll = false,this.regExpMultiLine = false,this.regExpUnicode = false}): assert((patternMatchMap != null && stringMatchMap == null) ||(patternMatchMap == null && stringMatchMap != null)),super(text: text);/// Setting this will notify all the listeners of this [TextEditingController]/// that they need to update (it calls [notifyListeners]).set text(String newText) {value = value.copyWith(text: newText,selection: const TextSelection.collapsed(offset: -1),composing: TextRange.empty,);}/// Builds [TextSpan] from current editing value.TextSpan buildTextSpan({required BuildContext context,TextStyle? style,required bool withComposing}) {assert(!value.composing.isValid || !withComposing || value.isComposingRangeValid);// If the composing range is out of range for the current text, ignore it to// preserve the tree integrity, otherwise in release mode a RangeError will// be thrown and this EditableText will be built with a broken subtree.final bool composingRegionOutOfRange = !value.isComposingRangeValid || !withComposing;if (composingRegionOutOfRange) {List<TextSpan> children = [];final matches = <String>{};List<Map<String, List<int>>> matchIndex = [];// Validating with REGEXRegExp? allRegex;allRegex = patternMatchMap != null? RegExp(patternMatchMap?.keys.map((e) => e.pattern).join('|') ?? "",caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;// Validating with StringsRegExp? stringRegex;stringRegex = stringMatchMap != null? RegExp(r'\b' + stringMatchMap!.keys.join('|').toString() + r'+\$',caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;text.splitMapJoin(stringMatchMap == null ? allRegex! : stringRegex!,onNonMatch: (String span) {if (stringMatchMap != null &&children.isNotEmpty &&stringMatchMap!.keys.contains("${children.last.text}$span")) {final String? ks =stringMatchMap!["${children.last.text}$span"] != null? stringMatchMap?.entries.lastWhere((element) {return element.key.allMatches("${children.last.text}$span").isNotEmpty;}).key: '';children.add(TextSpan(text: span, style: stringMatchMap![ks!]));return span.toString();} else {children.add(TextSpan(text: span, style: style));return span.toString();}},onMatch: (Match m) {matches.add(m[0]!);final RegExp? k = patternMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key;final String? ks = stringMatchMap?[m[0]] != null? stringMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key: '';if (deleteOnBack!) {if ((isBack(text, _lastValue) && m.end == selection.baseOffset)) {WidgetsBinding.instance.addPostFrameCallback((_) {children.removeWhere((element) => element.text! == text);text = text.replaceRange(m.start, m.end, "");selection = selection.copyWith(baseOffset: m.end - (m.end - m.start),extentOffset: m.end - (m.end - m.start),);});} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}final resultMatchIndex = matchValueIndex(m);if (resultMatchIndex != null && onMatchIndex != null) {matchIndex.add(resultMatchIndex);onMatchIndex!(matchIndex);}return (onMatch(List<String>.unmodifiable(matches)) ?? '');},);_lastValue = text;return TextSpan(style: style, children: children);}final TextStyle composingStyle = style?.merge(const TextStyle(decoration: TextDecoration.underline))?? const TextStyle(decoration: TextDecoration.underline);return TextSpan(children: <TextSpan>[TextSpan(style: style, children: buildRegExpSpan(context: context, text: value.composing.textBefore(value.text))),TextSpan(style: composingStyle,text: value.composing.textInside(value.text),),TextSpan(style: style, children: buildRegExpSpan(context: context, text: value.composing.textAfter(value.text))),],);}Map<String, List<int>>? matchValueIndex(Match match) {final matchValue = match[0]?.replaceFirstMapped('#', (match) => '');if (matchValue != null) {final firstMatchChar = match.start + 1;final lastMatchChar = match.end - 1;final compactMatch = {matchValue: [firstMatchChar, lastMatchChar]};return compactMatch;}return null;}List<TextSpan> buildRegExpSpan({required BuildContext context,TextStyle? style,required String? text}) {List<TextSpan> children = [];if (!(text != null && text.isNotEmpty)) {return children;}final matches = <String>{};List<Map<String, List<int>>> matchIndex = [];// Validating with REGEXRegExp? allRegex;allRegex = patternMatchMap != null? RegExp(patternMatchMap?.keys.map((e) => e.pattern).join('|') ?? "",caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;// Validating with StringsRegExp? stringRegex;stringRegex = stringMatchMap != null? RegExp(r'\b' + stringMatchMap!.keys.join('|').toString() + r'+\$',caseSensitive: regExpCaseSensitive,dotAll: regExpDotAll,multiLine: regExpMultiLine,unicode: regExpUnicode): null;text.splitMapJoin(stringMatchMap == null ? allRegex! : stringRegex!,onNonMatch: (String span) {if (stringMatchMap != null &&children.isNotEmpty &&stringMatchMap!.keys.contains("${children.last.text}$span")) {final String? ks =stringMatchMap!["${children.last.text}$span"] != null? stringMatchMap?.entries.lastWhere((element) {return element.key.allMatches("${children.last.text}$span").isNotEmpty;}).key: '';children.add(TextSpan(text: span, style: stringMatchMap![ks!]));return span.toString();} else {children.add(TextSpan(text: span, style: style));return span.toString();}},onMatch: (Match m) {matches.add(m[0]!);final RegExp? k = patternMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key;final String? ks = stringMatchMap?[m[0]] != null? stringMatchMap?.entries.firstWhere((element) {return element.key.allMatches(m[0]!).isNotEmpty;}).key: '';if (deleteOnBack!) {if ((isBack(text!, _lastValue) && m.end == selection.baseOffset)) {WidgetsBinding.instance.addPostFrameCallback((_) {children.removeWhere((element) => element.text! == text);text = text!.replaceRange(m.start, m.end, "");selection = selection.copyWith(baseOffset: m.end - (m.end - m.start),extentOffset: m.end - (m.end - m.start),);});} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}} else {children.add(TextSpan(text: m[0],style: stringMatchMap == null? patternMatchMap![k]: stringMatchMap![ks],),);}final resultMatchIndex = matchValueIndex(m);if (resultMatchIndex != null && onMatchIndex != null) {matchIndex.add(resultMatchIndex);onMatchIndex!(matchIndex);}return (onMatch(List<String>.unmodifiable(matches)) ?? '');},);return children;}
}
至此可以看到效果图中@张三 高亮显示了。
三、使用TextFieldController测试@张三 高亮
调整好TextFieldController后,我这里测试@张三 高亮
我们进行初始化TextFieldController
// Add a controllerlate TextFieldController _controller;void initState() {// TODO: implement initState_controller = TextFieldController(patternMatchMap: {////* Returns every Hashtag with red color//RegExp(r"@[^\s]+\s?"):TextStyle(color:Colors.green),////* Returns every Hashtag with red color//RegExp(r"\B#[a-zA-Z0-9]+\b"):TextStyle(color:Colors.red),////* Returns every Mention with blue color and bold style.//RegExp(r"\B@[a-zA-Z0-9]+\b"):TextStyle(fontWeight: FontWeight.w800 ,color:Colors.blue,),////* Returns every word after '!' with yellow color and italic style.//RegExp(r"\B![a-zA-Z0-9]+\b"):TextStyle(color:Colors.yellow, fontStyle:FontStyle.italic),// add as many expressions as you need!},//* starting v1.2.0// Now you have the option to add string Matching!// stringMatchMap: {// "String1":TextStyle(color: Colors.red),// "String2":TextStyle(color: Colors.yellow),// },//! Assertion: Only one of the two matching options can be given at a time!//* starting v1.1.0//* Now you have an onMatch callback that gives you access to a List<String>//* which contains all matched stringsonMatch: (List<String> matches){// Do something with matches.//! P.S// as long as you're typing, the controller will keep updating the list.},deleteOnBack: true,// You can control the [RegExp] options used:regExpUnicode: true,);super.initState();}
在TextField中使用TextFieldController。具体代码如下
TextField(minLines: 1,maxLines: null,keyboardType: TextInputType.multiline,textAlignVertical: TextAlignVertical.center,autofocus: true,focusNode: editFocusNode,controller: _controller,textInputAction: TextInputAction.send,decoration: InputDecoration(contentPadding: EdgeInsets.symmetric(vertical: 10, horizontal: 8.0),filled: true,isCollapsed: true,floatingLabelBehavior: FloatingLabelBehavior.never,hintText: "说点什么吧~",hintStyle: TextStyle(fontSize: 14,fontWeight: FontWeight.w400,fontStyle: FontStyle.normal,color: ColorUtil.hexColor(0xACACAC),decoration: TextDecoration.none,),enabledBorder: OutlineInputBorder(/*边角*/borderRadius: const BorderRadius.all(Radius.circular(5.0), //边角为30),borderSide: BorderSide(color: ColorUtil.hexColor(0xf7f7f7), //边框颜色为绿色width: 1, //边线宽度为1),),focusedBorder: OutlineInputBorder(borderRadius: const BorderRadius.all(Radius.circular(5.0), //边角为30),borderSide: BorderSide(color: ColorUtil.hexColor(0xECECEC), //边框颜色为绿色width: 1, //宽度为1),),),)
经过输入删除测试,输入的“@张三”高亮显示在TextField中正常了。
使用TextEditingController的buildTextSpan,可以查看:https://blog.csdn.net/gloryFlow/article/details/132889374
完善TextField输入框匹配正则表达式高亮显示,可以查看:https://blog.csdn.net/gloryFlow/article/details/132899084
四、小结
flutter聊天界面-TextField输入框buildTextSpan实现@功能展示高亮功能。自定义修改TextEditingController。
内容较多,描述可能不准确,请见谅。
本文地址:https://blog.csdn.net/gloryFlow/article/details/132899084
学习记录,每天不停进步。
相关文章:
flutter聊天界面-TextField输入框实现@功能等匹配正则表达式展示高亮功能
flutter聊天界面-TextField输入框实现功能等匹配正则表达式展示高亮功能 一、简要描述 描述: 最近有位朋友讨论的时候,提到了输入框的高亮展示。在flutter TextField中需要插入特殊样式的标签,比如:“请 张三 回答一下”&#x…...
【C语言】指针的进阶(二)—— 回调函数的讲解以及qsort函数的使用方式
目录 1、函数指针数组 1.1、函数指针数组是什么? 1.2、函数指针数组的用途:转移表 2、扩展:指向函数指针的数组的指针 3、回调函数 3.1、回调函数介绍 3.2、回调函数的案例:qsort函数 3.2.1、回顾冒泡排序 3.2.1、什么是qso…...
Java集合之HashSet接口
Set Set接口、HashSet类、TreeSet类 Set(组、集):表示无序,元素不能重复的集合,组中的元素必须唯一 Set接口 Set接口定义了组/集/集合(Set)。他扩展了Collection接口,并声明了不允…...
uniapp----微信小程序 日历组件(周日历 月日历)【Vue3+ts+uView】
uniapp----微信小程序 日历组件(周日历&& 月日历)【Vue3tsuView】 用Vue3tsuView来编写日历组件;存在周日历和月日历两种显示方式;高亮显示当天日期,红点渲染有数据的日期,点击显示数据 1. calenda…...
【记录】深度学习环境配置(pytorch版)
1080面对Transformer连勉强也算不上了,还是要去用小组的卡 完整记一个环境配置,方便后面自用✍️ 目前要简单许多,因为显卡驱动已经装好,后安装的库版本与其对应即可。 nvidia-smi查看GPU信息 ** CUDA版本12.2 conda -V查询conda…...
如何将项目推送到GitHub中
将项目推送到 GitHub 仓库并管理相关操作,遵循以下步骤: 创建 GitHub 账户:如果您没有 GitHub 账户,首先需要在 GitHub 官网 上创建一个账户。 创建新仓库:在 GitHub 页面上,点击右上角的加号图标…...
数据库直连提示 No suitable driver found for jdbc:postgresql
背景:我在代码里使用直连的方式在数据库中创建数据库等,由于需要适配各个数据库服务所以我分别兼容了mysql、postgresql、oracal等。但是在使用过程中会出现错误: No suitable driver found for jdbc:postgresql 但是我再使用mysql的直连方式…...
Stability AI推出Stable Audio;ChatGPT:推荐系统的颠覆者
🦉 AI新闻 🚀 Stability AI推出Stable Audio,用户可以生成个性化音乐片段 摘要:Stability AI公司发布了一款名为Stable Audio的工具,用户可以根据自己的文本内容自动生成音乐或音频。免费版可生成最长20秒音乐片段&a…...
HTML中的<canvas>元素
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ canvas元素⭐ 用途⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们…...
【论文阅读】MARS:用于自动驾驶的实例感知、模块化和现实模拟器
【论文阅读】MARS:用于自动驾驶的实例感知、模块化和现实模拟器 Abstract1 Introduction2 Method2.1 Scene Representation2.3 Towards Realistic Rendering2.4 Optimization3.1 Photorealistic Rendering3.2 Instance-wise Editing3.3 The blessing of moduler des…...
Leetcode 2856. Minimum Array Length After Pair Removals
Leetcode 2856. Minimum Array Length After Pair Removals 1. 解题思路2. 代码实现 题目链接:2856. Minimum Array Length After Pair Removals 1. 解题思路 这一题思路而言个人觉得还是挺有意思的,因为显然这道题没法直接用greedy的方法进行处理&am…...
深入了解Vue.js框架:构建现代化的用户界面
目录 一.Vue前言介绍 二.Vue.js框架的核心功能与特性 三.MVVM的介绍 四.Vue的生命周期 五.库与框架的区别 1.库(Library): 2.框架(Framework): 六.Vue常用指令演示 1.v-model 2.v-on:click&…...
力扣 -- 673. 最长递增子序列的个数
小算法: 通过一次遍历找到数组中最大值出现的次数: 利用这个小算法求解这道题就会非常简单了。 参考代码: class Solution { public:int findNumberOfLIS(vector<int>& nums) {int nnums.size();vector<int> len(n,1);auto…...
43.248.189.X网站提示风险,存在黑客攻击页面被篡改,改如何解决呢?
当用户百度搜索我们的网站,准备打开该网站时,访问页面提示风险,告知被黑客攻击并有被篡改的情况,有哪些方案可以查看解决问题? 当遇到网站提示风险到时候,可以考虑采用下面几个步骤来解决问题:…...
Java8中判断一个对象不为空存在一个类对象是哪个
Java8中判断一个对象不为空存在一个类对象是哪个? 在Java 8中,你可以使用java.util.Optional类来处理可能为空的对象。Optional类可以帮助你优雅地处理空值情况,而不需要显式地进行空值检查。 这是一个简单的Optional示例: imp…...
项目:点餐系统
项目扩展: 1.订单操作 2.用户管理(临时用户生成用户注册与登录) 项目有可能涉及到的面试: 说说你的项目 为什么要做这个项目 服务器怎么搭建的 最初我自己写了一个简单的服务器,但是不太稳定,比较粗…...
ElasticSearch 5.6.3 自定义封装API接口
在实际业务中,查询 elasticsearch 时会遇到很多特殊查询,官方接口包有时不便利,特殊情况需要自定义接口,所以为了灵活使用、维护更新 编写了一套API接口,仅供学习使用 当前自定义API接口依赖 elasticsearch 5.6.3 版本…...
企业架构LNMP学习笔记51
企业案例使用: 主从模式: 缓存集群结构示意图: 去实现Redis的业务分离: 读的请求分配到从服务器上,写的请求分配到主服务器上。 Redis是没有中间件来进行分离的。 是通过业务代码直接来进行读写分离。 准备两台虚…...
rom修改----安卓系列机型如何内置app 如何选择so文件内置
系统内置app的需求 在与各工作室对接中操作单中,很多需要内置客户特定的有些app到系统里,这样方便客户刷入固件后直接调用。例如内置apk 去开机引导 去usb调试 默认开启usb安全设置等等。那么很多app内置有不同的反应。有的可以直接内置。有的需要加so…...
SpringMvc中的请求转发和重定向
之前的案例,我们发现request域中的值可以传到jsp页面中,也就是通过视图解析器跳转到视图的底层是请求转发。 如果我们跳转时不想使用视图解析器,可以使用原生HttpServletRequest进行请求转发或HttpServletResponse进行重定向: Req…...
Oracle,高斯创建自增序列
某些时候,需要获取到一个自增值 然后点击左下 Apply 也可以通过SQL语句执行 dual在Oracle中是张虚拟表,通常用于执行这样的查询 Oracle中查询语句: select 序列名.nextval from dual 在高斯数据库中:查询是 select my_sequence.nextval 不需要加form xxx …...
操作系统学习笔记-精简复习版
文章目录 操作系统概述1、操作系统2、主要功能3、用户态和内核态4、系统调用 进程管理1、进程和线程2、引入线程的好处3、线程间同步4、进程控制块 PCB5、进程的状态6、进程的通信方式7、进程的调度算法8、僵尸进程&孤儿进程9、死锁 内存管理1、内存碎片2、内存管理3、虚拟…...
系统架构:软件工程速成
文章目录 参考概述软件工程概述软件过程 可行性分析可行性分析概述数据流图数据字典 需求分析需求分析概述ER图状态转换图 参考 软件工程速成(期末考研复试软考)均适用. 支持4K 概述 软件工程概述 定义:采用工程的概念、原理、技术和方法来开发与维护软件。 三…...
VUE之proxy配置实现跨域
什么是跨域 要了解跨域,首先得知道浏览器的同源策略。 同源策略:是由Netscape提出的一个安全策略,能够阻挡恶意文档,保护本地数据。它能限制一个源的文档或脚本对另一个源的交互,使得其它源的文档或脚本,…...
AI与医疗保健:革命性技术如何拯救生命
文章目录 引言AI的应用领域1. 影像识别2. 疾病诊断3. 药物研发4. 个性化治疗 AI技术1. 机器学习2. 深度学习3. 自然语言处理4. 基因组学 实际案例1. Google Health的深度学习模型2. IBM Watson for Oncology3. PathAI的病理学分析 道德和隐私考虑结论 🎉欢迎来到AIG…...
Spring Boot + Vue3前后端分离实战wiki知识库系统<十三>--单点登录开发二
接着Spring Boot Vue3前后端分离实战wiki知识库系统<十二>--用户管理&单点登录开发一继续往下。 登录功能开发: 接下来则来开发用户的登录功能,先准备后端的接口。 后端增加登录接口: 1、UserLoginReq: 先来准备…...
基于Java的高校科研信息管理系统设计与实现(亮点:完整严谨的科研项目审批流程、多文件上传、多角色)
高校科研信息管理系统 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序(小蔡coding)2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 主要功能描述 五、系统实现5.1…...
【uniapp】Dcloud的uni手机号一键登录,具体实现及踩过的坑,调用uniCloud.getPhoneNumber(),uni.login()等
一键登录Dcloud官网请戳这里,感兴趣的可以看看官网,有很详细的示例,选择App一键登录,可以看到一些常用的概述 比如: 1、调用uni.login就能弹出一键登录的页面 2、一键登录的流程,可以选择先预登录uni.prelo…...
Qt Quick Layouts Overview
Qt快速布局概述 #【中秋征文】程序人生,中秋共享# Qt快速布局是用于在用户界面中排列项目的项目。由于Qt快速布局还可以调整其项目的大小,因此它们非常适合可调整大小的用户界面。 开始 可以使用文件中的以下导入语句将 QML 类型导入到应用程序中。.qml…...
星臾计划 | 第六期优秀实习生访谈合集
此处划重点:优秀实习生评比活动将每三个月进行一次,获评同学可获得优秀实习生证书和丰厚的奖励 —— 是心动的感觉! 作为实习生培养计划,星臾计划不但能帮助在校生提前了解企业、熟悉工作环境,还能提前锁定正式 Offer…...
wordpress 照片展示/数据分析软件工具有哪些
上一篇博客中我们使用了四元数法计算ICP。本篇我们使用SVD计算ICP。下面是《视觉slam十四讲》中的计算方法:计算步骤如下:我们看到,只要求出了两组点之间的旋转,平移是非常容易得到的,所以我们重点关注R的计算。展开关…...
做静态网站d/北京网站seo招聘
6大设置优化你的IE(转)临时文件: IE在上网的过程中会在系统盘内自动的把浏览过的图片,动画,Cookies文本等数据信息保留在C: Documents and Settingswork hardLocal SettingsTemporary Internet Files(Win98 系统为C&am…...
在哪里做马可波罗网站/seo排名优化教程
文末获取资料CDH是Cloudera的100%开放源代码平台发行版,集成了多个大数据组件,可进行页面化管理和操作,市面上大多是公司使用的都是CDH平台。而今天这份资料是一份比较完整和细致的安装和运维教程,图文并茂。文末可以进…...
建设银行大学华东学院网站/seo数据是什么
经过一年的积淀,感觉自己A题目的能力下降了,没别的,就是挑战一下自己,看看自己能够做出多少题目。当我第一眼看到题目的时候感觉傻眼了,一个也没有产生思路,但是静下心来时候就会慢慢会点了。第一个是字符串…...
建设工程网站168/谷歌seo优化公司
本次学习主要以Red Hat为例展开学习 首先通过VMware虚拟机安装RHEL8系统,安装系统后,进入系统界面,选择root用户进行登录。迎来欢迎界面。 接下来开启Linux系统学习之旅! 软件安装 在系统中,安装软件有两种方法&…...
5x兴趣社区app怎么开发/seo推广优化方案
也就是一堆方程,每个方程都形如xixjP 模拟代入消元即可,并且求出取值范围 遇到环就可以直接解出来,判断是否可行 由于这题比较坑爹,读入太大会RE,要cheat,就不放代码了转载于:https://www.cnblogs.com/phil…...