当前位置: 首页 > news >正文

Flutter富文本实现学习

Flutter 代码如何实现一个带有富文本显示和交互的页面。

前置知识点学习

RealRichText

`RealRichText` 和 `ImageSpan` 不是 Flutter 框架中内置的组件,而是自定义的组件或来自第三方库。这些组件的实现可以提供比标准 `RichText` 更丰富的功能,比如在富文本中插入图片、处理点击事件等。由于这些组件在标准 Flutter 中不存在,我将解释如何可能实现类似的功能。

TextSpan

`TextSpan` 是 Flutter 中用于构建富文本的基本组件之一。它允许你在同一个文本组件中混合和匹配不同的文本样式和手势识别功能。`TextSpan` 通常与 `RichText` 组件一起使用,以显示复杂的文本布局。

`TextSpan` 的基本结构

`TextSpan` 是一个不可变的、递归的数据结构,可以包含其他 `TextSpan`,从而允许嵌套不同的文本样式。

TextSpan({TextStyle? style,String? text,List<InlineSpan>? children,GestureRecognizer? recognizer,String? semanticsLabel,
})

关键属性

`style`:

  • 指定文本的样式,例如字体大小、颜色、粗细等。
  • 类型为 `TextStyle`。

`text`:

  • 要显示的文本字符串。
  • `text` 和 `children` 之间是互斥的,如果需要在一个 `TextSpan` 中显示多个文本片段,通常使用 `children`。

`children`:

  • 一个 `InlineSpan`(通常为 `TextSpan`)的列表,用于嵌套子文本。
  • 允许创建复杂的文本结构,如不同样式的文本段落。

`recognizer`:

  • 用于处理文本的手势识别,例如点击事件。
  • 通常使用 `TapGestureRecognizer` 来处理点击事件。

`semanticsLabel`:

  • 为文本提供一个可供屏幕阅读器使用的标签,帮助无障碍访问。

使用示例

下面是一个简单的例子,展示如何使用 `TextSpan` 来创建一个包含多种样式和交互的文本。

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';class RichTextExample extends StatelessWidget {const RichTextExample({super.key});@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Rich Text Example")),body: Center(child: RichText(text: TextSpan(text: 'Hello ',style: const TextStyle(color: Colors.black, fontSize: 18),children: <TextSpan>[const TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)),const TextSpan(text: ' and ',),const TextSpan(text: 'italic',style: TextStyle(fontStyle: FontStyle.italic),),TextSpan(text: ' clickable ',style: const TextStyle(color: Colors.blue),recognizer: TapGestureRecognizer()..onTap = () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Clickable text clicked!')),);},),const TextSpan(text: 'text.',),],),),),);}
}

ImageSpan

`ImageSpan` 是一种在富文本中嵌入图片的技术。在 Flutter 中,虽然没有直接提供一个名为 `ImageSpan` 的组件,但你可以通过使用 `WidgetSpan` 来实现类似的功能。`WidgetSpan` 允许你在 `RichText` 中插入任意的 Flutter 小部件,包括图片。

使用 `WidgetSpan` 实现 `ImageSpan` 的功能

`WidgetSpan` 是 `InlineSpan` 的子类,可以在 `TextSpan` 列表中使用来嵌入小部件。通过这种方式,你可以在文本段落中插入图片或者其他小部件。

示例代码

import 'package:flutter/material.dart';class RichTextWithImageExample extends StatelessWidget {const RichTextWithImageExample({super.key});@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Rich Text with Image Example")),body: Center(child: RichText(text: TextSpan(style: const TextStyle(color: Colors.black, fontSize: 18),children: <InlineSpan>[const TextSpan(text: 'This is an example of '),WidgetSpan(child: Image.asset("static/demo.png",width: 24,height: 24,)),const TextSpan(text: ' in a rich text widget.'),]),),),);}
}

解释

`RichText` 和 `TextSpan`:

  • `RichText` 用于显示复杂的文本布局,`TextSpan` 用于定义文本的样式和内容。

`WidgetSpan`:

  • `WidgetSpan` 可以嵌入任何小部件。在这个例子中,它用于插入一个图片。
  • `child` 属性接受一个 `Widget`,这里使用 `Image.asset` 来加载本地图片。

图片资源:

  • 确保图片路径正确,并在 `pubspec.yaml` 中声明图片资源。
  • 例如:
flutter:assets:- assets/demo.png

 使用场景

  • 图文混排: 当需要在同一个文本段落中展示图片和文本,比如图标、表情符号或其他装饰性元素。
  • 动态内容: 在文章或聊天应用中以富文本形式展示内容,图片作为内嵌元素。
  • 自定义格式: 创建带有图片的复杂格式文本,比如新闻应用中的插图或注释。

通过 `WidgetSpan`,你可以在 Flutter 的文本组件中灵活地插入图片和其他小部件,实现更复杂的文本布局和丰富的用户界面体验。

TapGestureRecognizer

`TapGestureRecognizer` 是 Flutter 中用于检测点击手势的一个手势识别器。它通常用于处理文本中的点击事件,特别是在 `TextSpan` 中,使得文本中的某些部分可以响应用户的点击操作。

基本使用

`TapGestureRecognizer` 是 `GestureRecognizer` 的一个子类,它专门用于处理点击(tap)事件。通常情况下,它与 `RichText` 和 `TextSpan` 结合使用,以实现文本的可点击功能。

如何使用 `TapGestureRecognizer`

以下是一个简单示例,展示如何在 `TextSpan` 中使用 `TapGestureRecognizer`,使得文本的一部分可以被点击并响应事件:

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class TapGestureExample extends StatelessWidget {const TapGestureExample({super.key});@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Tap Gesture Recognizer Example")),body: Center(child: RichText(text: TextSpan(text: 'Click ',style: const TextStyle(color: Colors.black, fontSize: 18),children: <TextSpan>[TextSpan(text: 'here',style: const TextStyle(color: Colors.blue, decoration: TextDecoration.underline),recognizer: TapGestureRecognizer()..onTap = () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Text clicked!')),);},),const TextSpan(text: ' to see the effect.',),],),),),);}
}

 解释

`RichText` 和 `TextSpan`:

  • `RichText` 用于显示富文本。通过 `TextSpan`,你可以定义不同的文本样式和内容。

`TapGestureRecognizer`:

  • 创建一个 `TapGestureRecognizer` 实例并将其分配给 `TextSpan` 的 `recognizer` 属性。
  • 使用 `..onTap`(级联操作符)来定义 `onTap` 回调函数,当用户点击该文本时调用。

响应点击:

  • 在 `onTap` 回调中使用 `ScaffoldMessenger` 显示一个 `SnackBar`,以反馈用户的点击操作。

注意事项

释放资源:

  • 如果在有状态的小部件中使用 `TapGestureRecognizer`,请确保在 `dispose` 方法中调用 `dispose` 方法来释放手势识别器,以避免内存泄漏。

多手势识别:

  • `TapGestureRecognizer` 可以与其他类型的手势识别器一起使用。使用 `GestureDetector` 可以创建更复杂的手势识别场景。

用户体验:

  • 确保可点击的文本有视觉上的提示,如颜色变化或下划线,以便用户能够清楚地识别哪些文本是可交互的。

通过 `TapGestureRecognizer`,你可以为文本添加交互功能,使得应用的用户界面更加动态和响应用户操作。

富文本代码实现学习

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:gsy_flutter_demo/widget/rich/real_rich_text.dart';class RichTextDemoPage extends StatefulWidget {const RichTextDemoPage({super.key});@override_RichTextDemoState createState() => _RichTextDemoState();
}class _RichTextDemoState extends State<RichTextDemoPage> {@overrideWidget build(BuildContext mainContext) {return Scaffold(appBar: AppBar(title: const Text("RichTextDemoPage"),),body: Container(margin: const EdgeInsets.all(10),child: Builder(builder: (context) {return Center(child: RealRichText([TextSpan(text: "A Text Link",style: const TextStyle(color: Colors.red, fontSize: 14),recognizer: TapGestureRecognizer()..onTap = () {show(context, "Link Clicked.");},),ImageSpan(const AssetImage("static/demo.png"),imageWidth: 24,imageHeight: 24,),ImageSpan(const AssetImage("static/demo.png"),imageWidth: 24,imageHeight: 24,margin: const EdgeInsets.symmetric(horizontal: 10)),const TextSpan(text: "哈哈哈",style: TextStyle(color: Colors.yellow, fontSize: 14),),TextSpan(text: "@Somebody",style: const TextStyle(color: Colors.black,fontSize: 14,fontWeight: FontWeight.bold),recognizer: TapGestureRecognizer()..onTap = () {show(context, "Link Clicked.");},),TextSpan(text: " #RealRichText# ",style: const TextStyle(color: Colors.blue, fontSize: 14),recognizer: TapGestureRecognizer()..onTap = () {show(context, "Link Clicked.");},),const TextSpan(text: "showing a bigger image",style: TextStyle(color: Colors.black, fontSize: 14),),ImageSpan(const AssetImage("static/demo.png"),imageWidth: 24,imageHeight: 24,margin: const EdgeInsets.symmetric(horizontal: 5)),const TextSpan(text: "and seems working perfect……",style: TextStyle(color: Colors.black, fontSize: 14),),]),);}),),);}show(context, text) {ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(text),action: SnackBarAction(label: 'ACTION',onPressed: () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('You pressed snackbar\'s action.'),));},),));}
}

三方flutter库中的富文本实现源码

import 'dart:ui' as ui show Image;import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';/// According to the related Flutter Issues(#2022) ,
/// Inline-Image-In-Text is a long-time(2 years) missing feature since RichText(or the underlying Paragraph) does only support pure text.
/// But we can solve this problem in a simple/tricky way:
///
/// 1. Regarde the images as a particular blank TextSpan,
///   convert image's width and height to textspan's letterSpacing and fontSize.
///   the origin paragraph will do the layout operation and leave the desired image space for us.
/// 2. Override the paint function,
///   calculate the right offset via the getOffsetForCaret() api to draw the image over the space.
///
/// The only thing you have to do is converting your origin text to a TextSpan/ImageSpan List first.
///
/// {@tool sample}
///
/// ```dart
/// RealRichText([
///            TextSpan(
///              text: "showing a bigger image",
///              style: TextStyle(color: Colors.black, fontSize: 14),
///            ),
///            ImageSpan(
///              AssetImage("packages/real_rich_text/images/emoji_10.png"),
///              width: 40,
///              height: 40,
///            ),
///            TextSpan(
///              text: "and seems working perfect……",
///              style: TextStyle(color: Colors.black, fontSize: 14),
///            ),
///          ])
/// ```
/// {@end-tool}
///
class RealRichText extends Text {final List<TextSpan> textSpanList;const RealRichText(this.textSpanList, {super.key,TextStyle? style,TextAlign textAlign = TextAlign.start,TextDirection? textDirection,bool softWrap = true,TextOverflow overflow = TextOverflow.clip,TextScaler? textScaler,int? maxLines,Locale? locale,}) : super("",style: style,textAlign: textAlign,textDirection: textDirection,softWrap: softWrap,overflow: overflow,textScaler: textScaler,maxLines: maxLines,locale: locale);List<TextSpan> extractAllNestedChildren(TextSpan textSpan) {if (textSpan.children == null || textSpan.children!.isEmpty) {return [textSpan];}List<TextSpan> childrenSpan = [];for (var child in textSpan.children!) {childrenSpan.addAll(extractAllNestedChildren(child as TextSpan));}return childrenSpan;}@overrideWidget build(BuildContext context) {final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context);TextStyle? effectiveTextStyle = style;if (style == null || style!.inherit) {effectiveTextStyle = defaultTextStyle.style.merge(style);}if (MediaQuery.boldTextOf(context)) {effectiveTextStyle =effectiveTextStyle!.merge(const TextStyle(fontWeight: FontWeight.bold));}TextSpan textSpan = TextSpan(style: effectiveTextStyle,text: "",children: extractAllNestedChildren(TextSpan(style: effectiveTextStyle,text: "",children: textSpanList,)));// pass the context to ImageSpan to create a ImageConfigurationfor (var f in textSpan.children!) {if (f is ImageSpan) {f.updateImageConfiguration(context);}}Widget result = _RichTextWrapper(textAlign: textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start,textDirection: textDirection,// RichText uses Directionality.of to obtain a default if this is null.locale: locale,// RichText uses Localizations.localeOf to obtain a default if this is nullsoftWrap: softWrap ?? defaultTextStyle.softWrap,overflow: overflow ?? defaultTextStyle.overflow,textScaler: textScaler ?? MediaQuery.textScalerOf(context),maxLines: maxLines ?? defaultTextStyle.maxLines,text: textSpan);if (semanticsLabel != null) {result = Semantics(textDirection: textDirection,label: semanticsLabel,child: ExcludeSemantics(child: result,));}return result;}
}/// Since flutter engine does not support inline-image for now, we have to support this feature via a tricky solution:
/// convert image to a particular TextSpan whose text always be \u200B(a zero-width-space).
/// set letterSpacing by the required image width
/// set fontSize by the required image height
class ImageSpan extends TextSpan {final double imageWidth;final double imageHeight;final EdgeInsets? margin;final ImageProvider imageProvider;final ImageResolver imageResolver;ImageSpan(this.imageProvider, {this.imageWidth = 14.0,this.imageHeight = 14.0,this.margin,super.recognizer,})  : imageResolver = ImageResolver(imageProvider),super(style: TextStyle(color: Colors.transparent,letterSpacing:imageWidth + (margin == null ? 0 : margin.horizontal),height: 1,fontSize: (imageHeight / 1.15) +(margin == null ? 0 : margin.vertical)),text: "\u200B",children: []);void updateImageConfiguration(BuildContext context) {imageResolver.updateImageConfiguration(context, imageWidth, imageHeight);}double get width => imageWidth + (margin == null ? 0 : margin!.horizontal);double get height => imageHeight + (margin == null ? 0 : margin!.vertical);
}typedef ImageResolverListener = void Function(ImageInfo imageInfo, bool synchronousCall);class ImageResolver {final ImageProvider imageProvider;ImageStream? _imageStream;ImageConfiguration? _imageConfiguration;ui.Image? image;ImageResolverListener? _listener;ImageResolver(this.imageProvider);/// set the ImageConfiguration from outsidevoid updateImageConfiguration(BuildContext context, double width, double height) {_imageConfiguration = createLocalImageConfiguration(context,size: Size(width, height),);}ImageStreamListener? imageStreamListener;void resolve(ImageResolverListener listener) {assert(_imageConfiguration != null);final ImageStream? oldImageStream = _imageStream;_imageStream = imageProvider.resolve(_imageConfiguration!);assert(_imageStream != null);_listener = listener;if (_imageStream!.key != oldImageStream?.key) {if (imageStreamListener != null) {oldImageStream?.removeListener(imageStreamListener!);}imageStreamListener ??= ImageStreamListener(_handleImageChanged);_imageStream!.addListener(imageStreamListener!);}}void _handleImageChanged(ImageInfo imageInfo, bool synchronousCall) {image = imageInfo.image;_listener?.call(imageInfo, synchronousCall);}void addListening() {if (_listener != null) {imageStreamListener ??= ImageStreamListener(_handleImageChanged);_imageStream?.addListener(imageStreamListener!);}}void stopListening() {if (imageStreamListener != null) {_imageStream?.removeListener(imageStreamListener!);}}
}/// Just a subclass of RichText for overriding createRenderObject
/// to return a [_RealRichRenderParagraph] object
///
/// No more special purpose.
class _RichTextWrapper extends RichText {_RichTextWrapper({required TextSpan super.text,super.textAlign,super.textDirection,super.softWrap,super.overflow,super.textScaler,super.maxLines,super.locale,})  : assert(maxLines == null || maxLines > 0);@overrideRenderParagraph createRenderObject(BuildContext context) {assert(textDirection != null || debugCheckHasDirectionality(context));return _RealRichRenderParagraph(text as TextSpan,textAlign: textAlign,textDirection: textDirection ?? Directionality.of(context),softWrap: softWrap,overflow: overflow,textScaler: textScaler,maxLines: maxLines,locale: locale ?? Localizations.localeOf(context),);}
}/// paint the image on the top of those ImageSpan's blank space
class _RealRichRenderParagraph extends RenderParagraph {_RealRichRenderParagraph(TextSpan super.text,{required super.textAlign,required super.textDirection,required super.softWrap,required super.overflow,required super.textScaler,super.maxLines,super.locale});@overridevoid paint(PaintingContext context, Offset offset) {super.paint(context, offset);// Here it is!paintImageSpan(context, offset);}@overridevoid attach(covariant Object owner) {super.attach(owner as PipelineOwner);for (var textSpan in (text as TextSpan).children!) {if (textSpan is ImageSpan) {textSpan.imageResolver.addListening();}}}@overridevoid detach() {super.detach();for (var textSpan in (text as TextSpan).children!) {if (textSpan is ImageSpan) {textSpan.imageResolver.stopListening();}}}@overridevoid performLayout() {super.performLayout();debugPrint("size = $size");}/// this method draws inline-image over blank text space.void paintImageSpan(PaintingContext context, Offset offset) {final Canvas canvas = context.canvas;final Rect bounds = offset & size;debugPrint("_RealRichRenderParagraph offset=$offset bounds=$bounds");canvas.save();int textOffset = 0;for (TextSpan textSpanin (text as TextSpan).children as Iterable<TextSpan>) {if (textSpan is ImageSpan) {// this is the top-center point of the ImageSpanOffset offsetForCaret = getOffsetForCaret(TextPosition(offset: textOffset),bounds,);// found this is a overflowed image. ignore itif (textOffset != 0 &&offsetForCaret.dx == 0 &&offsetForCaret.dy == 0) {return;}// this is the top-left point of the ImageSpan.// Usually, offsetForCaret indicates the top-center offset// except the first text which is always (0, 0)Offset topLeftOffset = Offset(offset.dx +offsetForCaret.dx -(textOffset == 0 ? 0 : textSpan.width / 2),offset.dy + offsetForCaret.dy);debugPrint("_RealRichRenderParagraph ImageSpan, textOffset = $textOffset, offsetForCaret=$offsetForCaret, topLeftOffset=$topLeftOffset");// if image is not ready: wait for async ImageInfoif (textSpan.imageResolver.image == null) {textSpan.imageResolver.resolve((imageInfo, synchronousCall) {if (synchronousCall) {paintImage(canvas: canvas,rect: topLeftOffset & Size(textSpan.width, textSpan.height),image: textSpan.imageResolver.image!,fit: BoxFit.scaleDown,alignment: Alignment.center);} else {if (owner == null || !owner!.debugDoingPaint) {markNeedsPaint();}}});textOffset += textSpan.toPlainText().length;continue;}// else: just paint it. bottomCenter Alignment seems better...paintImage(canvas: canvas,rect: topLeftOffset & Size(textSpan.width, textSpan.height),image: textSpan.imageResolver.image!,fit: BoxFit.scaleDown,alignment: Alignment.center);}textOffset += textSpan.toPlainText().length;}canvas.restore();}
}

相关文章:

Flutter富文本实现学习

Flutter 代码如何实现一个带有富文本显示和交互的页面。 前置知识点学习 RealRichText RealRichText 和 ImageSpan 不是 Flutter 框架中内置的组件&#xff0c;而是自定义的组件或来自第三方库。这些组件的实现可以提供比标准 RichText 更丰富的功能&#xff0c;比如在富文本…...

如何解决 OpenAI API 连接问题:降级 urllib3 版本

如何解决 OpenAI API 连接问题&#xff1a;降级 urllib3 版本 在使用 OpenAI API 时&#xff0c;很多开发者可能会遇到连接问题&#xff0c;特别是在使用 Python 代码与 OpenAI 进行交互时。常见的错误包括 ProxyError、SSLError 和 MaxRetryError&#xff0c;它们通常表示在通…...

【C语言】库函数常见的陷阱与缺陷(三):内存分配函数[4]--free

C语言中的free函数用于释放之前通过malloc、calloc或realloc动态分配的内存。然而,在使用free函数时,开发者可能会遇到一些陷阱和缺陷。 一、功能与用法 free 函数是 C 语言中用于释放动态分配内存的关键函数。在程序使用 malloc、calloc 或 realloc 等函数在堆上分配了内存…...

论文分享 | PromptFuzz:用于模糊测试驱动程序生成的提示模糊测试

大语言模型拥有的强大能力可以用来辅助多种工作&#xff0c;但如何有效的辅助仍然需要人的精巧设计。分享一篇发表于2024年CCS会议的论文PromptFuzz&#xff0c;它利用模型提示生成模糊测试驱动代码&#xff0c;并将代码片段嵌入到LLVM框架中执行模糊测试。 论文摘要 制作高质…...

AWS K8s 部署架构

Amazon Web Services&#xff08;AWS&#xff09;提供了一种简化的Kubernetes&#xff08;K8s&#xff09;部署架构&#xff0c;使得在云环境中管理和扩展容器化应用变得更加容易。这个架构的核心是AWS EKS&#xff08;Elastic Kubernetes Service&#xff09;&#xff0c;它是…...

JavaSE笔记(四)

Java泛型与集合类 在前面我们学习了最重要的类和对象,了解了面向对象编程的思想,注意,非常重要,面向对象是必须要深入理解和掌握的内容,不能草草结束。在本章节,我们会继续深入了解,从我们的泛型开始,再到我们的数据结构,最后再开始我们的集合类学习。 走进泛型 为…...

C语言基础——指针(5)

一&#xff0e; 函数指针变量 1. 函数指针变量的定义&#xff1a; 类比数组指针变量&#xff0c;数组指针变量是存放数组地址的变量&#xff0c;那么同理&#xff0c;函数指针变量就是存放函数地址的变量。 2. 创建函数指针变量&#xff1a; 函数是有地址的&#xff0…...

curl+openssl 踩坑笔记

curl编译&#xff1a;点击跳转 踩坑一 * SSL certificate problem: unable to get local issuer certificate * closing connection #0 curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.se/docs/sslcerts.html …...

Unity 实现Canvas显示3D物体

新建一个UI相机&#xff0c;选择渲染层为UI 将主相机的渲染层去掉UI层 、 将Canvas的RenderMode设置为Screen Space - Camera,将RenderCamera设置为UI相机 新建3D物体的UI父物体&#xff0c;并将3D物体的层级设置为UI层 适当的放缩3DObjParent&#xff0c;让3D物体能显示出来…...

【Docker命令】如何使用`docker exec`在容器内执行命令

大家好&#xff0c;今天我们来聊聊Docker容器管理中的一个非常有用的命令&#xff1a;docker exec。在日常工作中&#xff0c;我们经常需要在运行中的Docker容器内执行各种命令&#xff0c;docker exec正是帮助我们实现这一需求的利器。下面我将通过一个简单的例子&#xff0c;…...

NetSuite Formula(HTML)超链打开Transaction

当Saved Search作为Sublist应用在Form时&#xff0c;如果Document Number是Group过的&#xff0c;则会出现如下超链失效的情况。 解决办法&#xff1a; 可以利用Saved Search中的Formula&#xff08;HTML&#xff09;功能来构建超链&#xff0c;用于打开Transaction。 以下图…...

【React】- 跨域PDF预览、下载(改文件名)、打印

我们经常会碰到跨域来方位PDF&#xff0c;同时需要下载、打印的需求&#xff0c;通常由于浏览器的安全策略&#xff0c;可以预览&#xff0c;但是下载和打印可能会受限&#xff0c;这时候怎么办呢&#xff1f; 1.创建一个隐藏的标签 要下载 iframe 中的 PDF 文件&#xff0c;…...

git clone ssh 设置代理

Linux配置方法 编辑 ~/.ssh/config 文件 Host github.com Hostname github.com ProxyCommand nc -v -x 127.0.0.1:1080 %h %pwindows配置方法 编辑 C:\Users\当前用户名.ssh\config 文件 Host github.com Hostname github.com ProxyCommand connect -S 127.0.0.1:1080 %h %…...

RK3568平台(USB篇)USB网络共享

使用RK的USB网络共享,在内核里面已经有了,这不需要自己写驱动程序,只需要把内核自带的USB网络共享的驱动添加上去即可。 一.RNDIS 协议简介 RNDIS 是微软定义的一种协议,它允许通过 USB 接口实现网络连接。通过 RNDIS,USB 设备可以充当网络适配器,允许主机通过 USB 与设…...

vite 打包时:JavaScript heap out of memory(内存溢出)

出错原因分析&#xff1a; 执行命令 npm run build 时出现以下错误提示&#xff1a; vite v3.2.7 building for production... 11:22:34 transforming (3) src\main.tsWARN Browserslist: caniuse…...

【服务器学习专栏 1.2 -- 带外管理】

请阅读 嵌入式学习必备专栏 文章目录 Overview服务器带外管理BMC 介绍BMC 特点BMC 工作原理 Overview 从技术的角度&#xff0c;网络管理可分为带外管理&#xff08;out-of-band&#xff09;和带内管理&#xff08;in-band&#xff09;两种管理模式。 带内管理&#xff0c;是指…...

微服务のGeteWay

目录 概念&#xff1a; 三大核心&#xff1a; 工作流程&#xff1a; 9527网关如何做路由映射&#xff1a; GetWay高级特性&#xff1a; 按服务名动态路由服务&#xff1a; 断言Route Predicate Factories &#xff1a; 获取当前时区时间&#xff1a; After Route &…...

html+css+js网页设计 美食 美食家6个页面

htmlcssjs网页设计 美食 美食家6个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xf…...

IntelliJ Idea常用快捷键详解

文章目录 IntelliJ Idea常用快捷键详解一、引言二、文本编辑与导航1、文本编辑2、代码折叠与展开 三、运行和调试四、代码编辑1、代码补全 五、重构与优化1、重构 六、使用示例代码注释示例代码补全示例 七、总结 IntelliJ Idea常用快捷键详解 一、引言 在Java开发中&#xff…...

服务器虚拟化:它是什么以及有什么好处?

运行虚拟服务器有助于创建更高效的 IT 基础架构。 随着业务每天收集的数据量逐年激增&#xff0c;传统的物理服务器已经无法单独满足业务需求。 相反&#xff0c;许多组织正在转向虚拟化的力量。 这是我们创建物理实体的虚拟版本的过程&#xff0c;在计算中&#xff0c;通常指…...

金融R用户慎入!这6行代码让VaR蒙特卡洛模拟提速11.8倍——某头部券商资管部刚下线的POC验证报告

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;金融R用户慎入&#xff01;这6行代码让VaR蒙特卡洛模拟提速11.8倍——某头部券商资管部刚下线的POC验证报告 性能瓶颈根源定位 该POC基于沪深300成分股日频收益率序列&#xff08;N300&#xff0c;T25…...

Rust OpenGL上下文创建库glutin:跨平台图形编程的终极指南

Rust OpenGL上下文创建库glutin&#xff1a;跨平台图形编程的终极指南 【免费下载链接】glutin A low-level library for OpenGL context creation 项目地址: https://gitcode.com/gh_mirrors/gl/glutin glutin是一个功能强大的Rust库&#xff0c;专门用于OpenGL上下文的…...

如何在 openclaw 中快速配置 taotoken 聚合大模型 api 端点

如何在 OpenClaw 中快速配置 Taotoken 聚合大模型 API 端点 1. 准备工作 在开始配置之前&#xff0c;请确保已安装 OpenClaw CLI 工具。可以通过以下命令检查是否已安装&#xff1a; openclaw --version如果未安装&#xff0c;请参考 OpenClaw 官方文档进行安装。同时&#…...

Python Web安全扫描工具|全自动漏洞检测与审计平台(支持多目标并发)

温馨提示&#xff1a;文末有联系方式产品概述 Python Web安全扫描工具是一款功能完备、开箱即用的自动化Web漏洞检测与安全审计平台。 它面向开发者与安全从业者&#xff0c;可对自建网站或测试环境进行系统性安全扫描、高危漏洞识别及结构化审计报告生成&#xff0c;助力快速定…...

open-interpreter:用自然语言操控电脑的本地AI助手实战指南

1. 项目概述&#xff1a;当你的电脑拥有了“自然语言”操作系统如果你用过ChatGPT&#xff0c;一定对那种用对话就能完成复杂任务的感觉印象深刻。但很多时候&#xff0c;这种对话被限制在了一个网页对话框里&#xff0c;它知道很多&#xff0c;却无法直接“动手”操作你的电脑…...

Perl脚本自动化日志分析与数据批量处理实操案例

Perl脚本自动化日志分析与数据批量处理实操案例 一、案例背景 在服务器运维、业务系统运行过程中&#xff0c;会产生海量日志文件&#xff0c;包含运行报错、接口请求、访问流量、异常告警等各类信息。人工逐条筛查日志效率极低&#xff0c;且容易遗漏关键故障信息。Perl语言具…...

hermes agent 框架接入 taotoken 多模型服务的配置要点

Hermes Agent 框架接入 Taotoken 多模型服务的配置要点 1. 准备工作 在开始配置 Hermes Agent 与 Taotoken 的对接前&#xff0c;请确保已完成以下准备工作。首先登录 Taotoken 控制台&#xff0c;在「API 密钥」页面创建一个新的 API Key。建议为 Hermes Agent 单独创建密钥…...

Revit族参数管理太乱?教你用Dynamo+Excel自动导出族库信息表(保姆级流程)

Revit族参数管理革命&#xff1a;DynamoExcel自动化解决方案全解析 在BIM项目交付过程中&#xff0c;族参数管理往往是设计师最头疼的环节之一。当项目进入收尾阶段&#xff0c;甲方要求提供所有门窗的规格参数表&#xff1b;当施工方询问墙面材料的防火等级分布&#xff1b;当…...

Halcon实战:用edges_sub_pix和fit_rectangle2搞定金属冲孔边缘缺陷检测(附完整代码)

Halcon工业视觉实战&#xff1a;金属冲孔边缘缺陷检测的工程化实现 金属冲压件的质量控制是工业自动化领域的关键环节。想象一下&#xff0c;当你站在生产线旁&#xff0c;数以千计的金属冲孔件正以每分钟数百件的速度通过检测工位——任何微小的边缘毛刺或凸起都可能导致后续组…...

电子制造企业设施升级与产能优化实践

1. 电子制造企业的设施升级战略解析当我在电子制造行业深耕十五年后&#xff0c;深刻认识到一个真理&#xff1a;生产线上的每一寸空间都是利润的战场。最近研究Epec公司的设施升级案例时&#xff0c;发现这个投资50万美元的改造项目完美诠释了现代电子制造企业的升级逻辑——不…...