全新研发flutter3+dart3+photo_view跨多端仿微信App界面聊天Flutter3-Chat

flutter3-chat基于最新跨全平台技术flutter3+dart3+material-design+shared_preferences+easy_refresh构建的仿微信APP界面聊天实例项目。实现发送图文表情消息/gif大图、长按仿微信语音操作面板、图片预览、红包及朋友圈等功能。

技术架构

  • 编辑器:Vscode
  • 框架技术:Flutter3.16.5+Dart3.2.3
  • UI组件库:material-design3
  • 弹窗组件:showDialog/SimpleDialog/showModalBottomSheet/AlertDialog
  • 图片预览:photo_view^0.14.0
  • 本地缓存:shared_preferences^2.2.2
  • 下拉刷新:easy_refresh^3.3.4
  • toast提示:toast^0.3.0
  • 网址预览组件:url_launcher^6.2.4

Flutter3.x开发跨平台App项目,性能有了大幅度提升,官方支持编译到android/ios/macos/windows/linux/web等多平台,未来可期!

项目构建目录

通过 flutter create app_project 命令即可快速创建一个跨平台初始化项目。

通过命令创建项目后,项目结构就如上图所示。

需要注意的是,flutter项目是基于dart语音开发,需要首先配置Dart SDK和Flutter SDK开发环境,大家可以去官网查看详细配置文档。

https://flutter.dev/

https://flutter.cn/

https://pub.flutter-io.cn/

https://www.dartcn.com/

另外使用VScode编辑器开发项目,可自行安装Flutter / Dart扩展插件。

由于flutter3支持编译到windows,大家可以开发初期在windows上面调试,后期release apk到手机上。

通过如下命令即可运行到windows平台

flutter run -d windows

运行后默认窗口大小为1280x720,可以修改windows/runner/main.cpp文件里面的窗口尺寸。

同样,可以通过 flutter run -d chrome 命令运行到web上预览。

假如在没有真机的情况下,我们可以选择模拟器调试。目前市面上有很多类型模拟器,他们使用adb连接时都会有不同的默认端口,下面列出了一些常用的模拟器及端口号。通过adb connect连接上指定模拟器之后,执行flutter run命令即可运行项目到模拟器上面。

flutter3实现圆角文本框及渐变按钮

Container(
height: 40.0,
margin: const EdgeInsets.symmetric(vertical: 5.0, horizontal: 30.0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: const Color(0xffdddddd)),
borderRadius: BorderRadius.circular(15.0),
),
child: Row(
children: [
Expanded(
child: TextField(
keyboardType: TextInputType.phone,
controller: fieldController,
decoration: InputDecoration(
hintText: '输入手机号',
suffixIcon: Visibility(
visible: authObj['tel'].isNotEmpty,
child: InkWell(
hoverColor: Colors.transparent,
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
onTap: handleClear,
child: const Icon(Icons.clear, size: 16.0,),
)
),
contentPadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 12.0),
border: const OutlineInputBorder(borderSide: BorderSide.none),
),
onChanged: (value) {
setState(() {
authObj['tel'] = value;
});
},
),
)
],
),
),

按钮渐变则是通过Container组件的decotaion里面的gradient属性设置渐变效果。

Container(
margin: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 30.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
// 自定义按钮渐变色
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF0091EA), Color(0xFF07C160)
],
)
),
child: SizedBox(
width: double.infinity,
height: 45.0,
child: FilledButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.transparent),
shadowColor: MaterialStateProperty.all(Colors.transparent),
shape: MaterialStatePropertyAll(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0))
)
),
onPressed: handleSubmit,
child: const Text('登录', style: TextStyle(fontSize: 18.0),),
),
)
),

flutter实现60s倒计时发送验证码功能。

Timer? timer;
String vcodeText = '获取验证码';
bool disabled = false;
int time = 60; // 60s倒计时
void handleVcode() {
if(authObj['tel'] == '') {
snackbar('手机号不能为空');
}else if(!Utils.checkTel(authObj['tel'])) {
snackbar('手机号格式不正确');
}else {
setState(() {
disabled = true;
});
startTimer();
}
}
startTimer() {
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
setState(() {
if(time > 0) {
vcodeText = '获取验证码(${time--})';
}else {
vcodeText = '获取验证码';
time = 60;
disabled = false;
timer.cancel();
}
});
});
snackbar('短信验证码已发送,请注意查收', color: Colors.green);
}

Flutter3沉浸式渐变状态导航栏

要实现如上图渐变AppBar也非常简单,只需要配置AppBar提供的可伸缩灵活区域属性 flexibleSpace 配合gradient即可快速实现渐变导航栏。

AppBar(
title: Text('Flutter3-Chat'),
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF0091EA), Color(0xFF07C160)
],
)
),
)
),

Flutter3字体图标/自定义badge

flutter内置了丰富的字体图标,通过图标组件 Icon(Icons.add) 引入即可使用。

https://api.flutter-io.cn/flutter/material/Icons-class.html

另外还支持通过自定义IconData方式自定义图标,如使用阿里iconfont图表库图标。

Icon(IconData(0xe666, fontFamily: 'iconfont'), size: 18.0)

把下载的字体文件放到assets目录,

pubspec.yaml中引入字体文件。

class FStyle {
// 自定义iconfont图标
static iconfont(int codePoint, {double size = 16.0, Color? color}) {
return Icon(
IconData(codePoint, fontFamily: 'iconfont', matchTextDirection: true),
size: size,
color: color,
);
} // 自定义Badge红点
static badge(int count, {
Color color = Colors.redAccent,
bool isdot = false,
double height = 18.0,
double width = 18.0
}) {
final num = count > 99 ? '99+' : count;
return Container(
alignment: Alignment.center,
height: isdot ? height / 2 : height,
width: isdot ? width / 2 : width,
decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(100.00)),
child: isdot ? null : Text('$num', style: const TextStyle(color: Colors.white, fontSize: 12.0)),
);
}
}

FStyle.badge(23)
FStyle.badge(2, color: Colors.pink, height: 10.0, width: 10.0)
FStyle.badge(0, isdot: true)

Flutter仿微信PopupMenu下拉菜单/下拉刷新

通过flutter提供的PopupMenuButton组件实现下拉菜单功能。

PopupMenuButton(
icon: FStyle.iconfont(0xe62d, size: 17.0),
offset: const Offset(0, 50.0),
tooltip: '',
color: const Color(0xFF353535),
itemBuilder: (BuildContext context) {
return <PopupMenuItem>[
popupMenuItem(0xe666, '发起群聊', 0),
popupMenuItem(0xe75c, '添加朋友', 1),
popupMenuItem(0xe603, '扫一扫', 2),
popupMenuItem(0xe6ab, '收付款', 3),
];
},
onSelected: (value) {
switch(value) {
case 0:
print('发起群聊');
break;
case 1:
Navigator.pushNamed(context, '/addfriends');
break;
case 2:
print('扫一扫');
break;
case 3:
print('收付款');
break;
}
},
)
// 下拉菜单项
static popupMenuItem(int codePoint, String title, value) {
return PopupMenuItem(
value: value,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(width: 10.0,),
FStyle.iconfont(codePoint, size: 21.0, color: Colors.white),
const SizedBox(width: 10.0,),
Text(title, style: const TextStyle(fontSize: 16.0, color: Colors.white),),
],
),
);
}

如上图:下拉刷新、上拉加载更多是通过 easy_refresh 组件实现功能。

EasyRefresh(
// 下拉加载提示
header: const ClassicHeader(
// showMessage: false,
),
// 加载更多提示
footer: ClassicFooter(),
// 下拉刷新逻辑
onRefresh: () async {
// ...下拉逻辑
await Future.delayed(const Duration(seconds: 2));
},
// 上拉加载逻辑
onLoad: () async {
// ...
},
child: ListView.builder(
itemCount: chatList.length,
itemBuilder: (context, index) {
return Ink(
// ...
);
},
),
)

如上图:弹窗功能均是自定义AlertDialog实现效果。通过无限制容器UnconstrainedBox配合SizedBox组件实现自定义窗口大小。

// 关于弹窗
void aboutAlertDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return UnconstrainedBox(
constrainedAxis: Axis.vertical,
child: SizedBox(
width: 320.0,
child: AlertDialog(
contentPadding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
backgroundColor: Colors.white,
surfaceTintColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
content: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset('assets/images/logo.png', width: 90.0, height: 90.0, fit: BoxFit.cover,),
const SizedBox(height: 10.0),
const Text('Flutter3-WChat', style: TextStyle(color: Color(0xFF0091EA), fontSize: 22.0),),
const SizedBox(height: 5.0),
const Text('基于flutter3+dart3开发跨平台仿微信App聊天实例。', style: TextStyle(color: Colors.black45),),
const SizedBox(height: 20.0),
Text('2024/01 Andy Q: 282310962', style: TextStyle(color: Colors.grey[400], fontSize: 12.0),),
],
),
),
),
),
);
}
);
} // 二维码名片弹窗
void qrcodeAlertDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return UnconstrainedBox(
constrainedAxis: Axis.vertical,
child: SizedBox(
width: 320.0,
child: AlertDialog(
contentPadding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
backgroundColor: const Color(0xFF07C160),
surfaceTintColor: const Color(0xFF07C160),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(3.0)),
content: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset('assets/images/qrcode.png', width: 250.0, fit: BoxFit.cover,),
const SizedBox(height: 15.0),
const Text('扫一扫,加我公众号', style: TextStyle(color: Colors.white60, fontSize: 14.0,),),
],
),
),
),
),
);
}
);
} // 退出登录弹窗
void logoutAlertDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: const Text('确定要退出登录吗?', style: TextStyle(fontSize: 16.0),),
backgroundColor: Colors.white,
surfaceTintColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
elevation: 2.0,
actionsPadding: const EdgeInsets.all(15.0),
actions: [
TextButton(
onPressed: () {Navigator.of(context).pop();},
child: const Text('取消', style: TextStyle(color: Colors.black54),)
),
TextButton(
onPressed: handleLogout,
child: const Text('退出登录', style: TextStyle(color: Colors.red),)
),
],
);
}
);
}

flutter实现微信朋友圈九宫格

GroupZone(images: item['images']),

GroupZone(
images: uploadList,
album: true,
onChoose: () async {
Toast.show('选择手机相册图片', duration: 2, gravity: 1);
},
),

// 创建可点击预览图片
createImage(BuildContext context, String img, int key) {
return GestureDetector(
child: Hero(
tag: img, // 放大缩小动画效果标识
child: img == '+' ?
Container(color: Colors.transparent, child: const Icon(Icons.add, size: 30.0, color: Colors.black45),)
:
Image.asset(
img,
width: width,
fit: BoxFit.contain,
),
),
onTap: () {
// 选择图片
if(img == '+') {
onChoose!();
}else {
Navigator.of(context).push(FadeRoute(route: ImageViewer(
images: album ? imgList!.sublist(0, imgList!.length - 1) : imgList,
index: key,
)));
}
},
);
}

使用photo_view插件实现预览大图功能,支持预览单张及多张大图。

import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart'; class ImageViewer extends StatefulWidget {
const ImageViewer({
super.key,
this.images,
this.index = 0,
}); final List? images; // 预览图列表
final int index; // 当前预览图索引 @override
State<ImageViewer> createState() => _ImageViewerState();
} class _ImageViewerState extends State<ImageViewer> {
int currentIndex = 0; @override
void initState() {
super.initState();
currentIndex = widget.index;
} @override
Widget build(BuildContext context) {
var imgCount = widget.images?.length; return Scaffold(
body: Stack(
children: [
Positioned(
top: 0,
left: 0,
bottom: 0,
right: 0,
child: GestureDetector(
child: imgCount == 1 ? PhotoView(
imageProvider: AssetImage(widget.images![0]),
backgroundDecoration: const BoxDecoration(
color: Colors.black,
),
minScale: PhotoViewComputedScale.contained,
maxScale: PhotoViewComputedScale.covered * 2,
heroAttributes: PhotoViewHeroAttributes(tag: widget.images![0]),
enableRotation: true,
)
:
PhotoViewGallery.builder(
itemCount: widget.images?.length,
builder: (context, index) {
return PhotoViewGalleryPageOptions(
imageProvider: AssetImage(widget.images![index]),
minScale: PhotoViewComputedScale.contained,
maxScale: PhotoViewComputedScale.covered * 2,
heroAttributes: PhotoViewHeroAttributes(tag: widget.images![index]),
);
},
scrollPhysics: const BouncingScrollPhysics(),
backgroundDecoration: const BoxDecoration(
color: Colors.black,
),
pageController: PageController(initialPage: widget.index),
enableRotation: true,
onPageChanged: (index) {
setState(() {
currentIndex = index;
});
},
),
onTap: () {
Navigator.of(context).pop();
},
),
),
// 图片索引index
Positioned(
top: MediaQuery.of(context).padding.top + 15,
width: MediaQuery.of(context).size.width,
child: Center(
child: Visibility(
visible: imgCount! > 1 ? true : false,
child: Text('${currentIndex+1} / ${widget.images?.length}', style: const TextStyle(color: Colors.white)),
)
),
),
],
),
);
}
}

flutter3聊天模块

文本框TextField设置maxLines: null即可实现多行文本输入,支持图文emoj混排,网址连接识别等功能。

// 输入框
Offstage(
offstage: voiceBtnEnable,
child: TextField(
decoration: const InputDecoration(
isDense: true,
hoverColor: Colors.transparent,
contentPadding: EdgeInsets.all(8.0),
border: OutlineInputBorder(borderSide: BorderSide.none),
),
style: const TextStyle(fontSize: 16.0,),
maxLines: null,
controller: editorController,
focusNode: editorFocusNode,
cursorColor: const Color(0xFF07C160),
onChanged: (value) {},
),
),

支持仿微信语音按住说话,左滑取消发送、右滑转换语音功能。

// 语音
Offstage(
offstage: !voiceBtnEnable,
child: GestureDetector(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
alignment: Alignment.center,
height: 40.0,
width: double.infinity,
child: Text(voiceTypeMap[voiceType], style: const TextStyle(fontSize: 15.0),),
),
onPanStart: (details) {
setState(() {
voiceType = 1;
voicePanelEnable = true;
});
},
onPanUpdate: (details) {
Offset pos = details.globalPosition;
double swipeY = MediaQuery.of(context).size.height - 120;
double swipeX = MediaQuery.of(context).size.width / 2 + 50;
setState(() {
if(pos.dy >= swipeY) {
voiceType = 1; // 松开发送
}else if (pos.dy < swipeY && pos.dx < swipeX) {
voiceType = 2; // 左滑松开取消
}else if (pos.dy < swipeY && pos.dx >= swipeX) {
voiceType = 3; // 右滑语音转文字
}
});
},
onPanEnd: (details) {
// print('停止录音');
setState(() {
switch(voiceType) {
case 1:
Toast.show('发送录音文件', duration: 1, gravity: 1);
voicePanelEnable = false;
break;
case 2:
Toast.show('取消发送', duration: 1, gravity: 1);
voicePanelEnable = false;
break;
case 3:
Toast.show('语音转文字', duration: 1, gravity: 1);
voicePanelEnable = true;
voiceToTransfer = true;
break;
}
voiceType = 0;
});
},
),
),

按住录音显示面板

// 录音主体(按住说话/松开取消/语音转文本)
Visibility(
visible: voicePanelEnable,
child: Material(
color: const Color(0xDD1B1B1B),
child: Stack(
children: [
// 取消发送+语音转文字
Positioned(
bottom: 120,
left: 30,
right: 30,
child: Visibility(
visible: !voiceToTransfer,
child: Column(
children: [
// 语音动画层
Stack(
children: [
Container(
height: 70.0,
margin: const EdgeInsets.symmetric(horizontal: 50.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/voice_record.gif', height: 30.0,)
],
),
),
Positioned(
right: (MediaQuery.of(context).size.width - 60) / 2,
bottom: 1,
child: RotatedBox(
quarterTurns: 0,
child: CustomPaint(painter: ArrowShape(arrowColor: Colors.white, arrowSize: 10.0)),
)
),
],
),
const SizedBox(height: 50.0,),
// 操作项
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 取消发送
Container(
height: 60.0,
width: 60.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.0),
color: voiceType == 2 ? Colors.red : Colors.black38,
),
child: const Icon(Icons.close, color: Colors.white54,),
),
// 语音转文字
Container(
height: 60.0,
width: 60.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.0),
color: voiceType == 3 ? Colors.green : Colors.black38,
),
child: const Icon(Icons.translate, color: Colors.white54,),
),
],
),
],
),
),
),
// 语音转文字(识别结果状态)
Positioned(
bottom: 120,
left: 30,
right: 30,
child: Visibility(
visible: voiceToTransfer,
child: Column(
children: [
// 提示结果
Stack(
children: [
Container(
height: 100.0,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(15.0),
),
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.info, color: Colors.white,),
Text('未识别到文字。', style: TextStyle(color: Colors.white),),
],
),
),
Positioned(
right: 35.0,
bottom: 1,
child: RotatedBox(
quarterTurns: 0,
child: CustomPaint(painter: ArrowShape(arrowColor: Colors.red, arrowSize: 10.0)),
)
),
],
),
const SizedBox(height: 50.0,),
// 操作项
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
child: Container(
height: 60.0,
width: 60.0,
decoration: const BoxDecoration(
color: Colors.transparent,
),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.undo, color: Colors.white54,),
Text('取消', style: TextStyle(color: Colors.white70),)
],
),
),
onTap: () {
setState(() {
voicePanelEnable = false;
voiceToTransfer = false;
});
},
),
GestureDetector(
child: Container(
height: 60.0,
width: 100.0,
decoration: const BoxDecoration(
color: Colors.transparent,
),
child: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.graphic_eq_rounded, color: Colors.white54,),
Text('发送原语音', style: TextStyle(color: Colors.white70),)
],
),
),
onTap: () {},
),
GestureDetector(
child: Container(
height: 60.0,
width: 60.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.0),
color: Colors.white12,
),
child: const Icon(Icons.check, color: Colors.white12,),
),
onTap: () {},
),
],
),
],
),
),
),
// 提示文字(操作状态)
Positioned(
bottom: 120,
left: 0,
width: MediaQuery.of(context).size.width,
child: Visibility(
visible: !voiceToTransfer,
child: Align(
child: Text(voiceTypeMap[voiceType], style: const TextStyle(color: Colors.white70),),
),
),
),
// 背景
Align(
alignment: Alignment.bottomCenter,
child: Visibility(
visible: !voiceToTransfer,
child: Image.asset('assets/images/voice_record_bg.webp', width: double.infinity, height: 100.0, fit: BoxFit.fill),
),
),
// 背景图标
Positioned(
bottom: 25,
left: 0,
width: MediaQuery.of(context).size.width,
child: Visibility(
visible: !voiceToTransfer,
child: const Align(
child: Icon(Icons.graphic_eq_rounded, color: Colors.black54,),
),
),
),
],
),
),
)

flutter3绘制箭头

聊天模块消息及各种箭头展示,通过flutter提供的画板功能绘制箭头。

// 绘制气泡箭头
class ArrowShape extends CustomPainter {
ArrowShape({
required this.arrowColor,
this.arrowSize = 7,
}); final Color arrowColor; // 箭头颜色
final double arrowSize; // 箭头大小 @override
void paint(Canvas canvas, Size size) {
var paint = Paint()..color = arrowColor; var path = Path();
path.lineTo(-arrowSize, 0);
path.lineTo(0, arrowSize);
path.lineTo(arrowSize, 0);
canvas.drawPath(path, paint);
} @override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}

Okay,以上就是Flutter3+Dart3开发全平台聊天App实例的一些知识分享,希望对大家有所帮助哈~~

最后附上两个最新实战项目

uni-app+vue3+pinia2仿抖音直播商城:https://www.cnblogs.com/xiaoyan2017/p/17938517

electron27+react18 hooks仿macos桌面系统:https://www.cnblogs.com/xiaoyan2017/p/17850653.html

flexibleSpace

flutter3+dart3聊天室|Flutter3跨平台仿微信App语音聊天/朋友圈的更多相关文章

  1. Taro聊天室|react+taro仿微信聊天App界面|taro聊天实例

    一.项目简述 taro-chatroom是基于Taro多端实例聊天项目,运用Taro+react+react-redux+taroPop+react-native等技术开发的仿微信App界面聊天室,实 ...

  2. Svelte3聊天室|svelte+svelteKit仿微信聊天实例|svelte.js开发App

    基于svelte3.x+svelteKit构建仿微信App聊天应用svelte-chatroom. svelte-chatroom 基于svelte.js+svelteKit+mescroll.js+ ...

  3. Svelte3.x网页聊天实例|svelte.js仿微信PC版聊天svelte-webchat

    基于Svelte3+SvelteKit+Sass仿微信Mac界面聊天实战项目SvelteWebChat. 基于svelte3+svelteKit+sass+mescroll.js+svelte-lay ...

  4. vue聊天室|h5+vue仿微信聊天界面|vue仿微信

    一.项目简介 基于Vue2.0+Vuex+vue-router+webpack2.0+es6+vuePhotoPreview+wcPop等技术架构开发的仿微信界面聊天室——vueChatRoom,实现 ...

  5. uni-app聊天室|vue+uniapp仿微信聊天实例|uniapp仿微信App界面

    一.介绍 运用UniApp+Vue+Vuex+swiper+uniPop等技术开发的仿微信原生App聊天室|仿微信聊天界面实例项目uniapp-chatroom,实现了发送图文消息.表情(gif图), ...

  6. react聊天室|react+redux仿微信聊天IM实例|react仿微信界面

    一.项目概况 基于react+react-dom+react-router-dom+redux+react-redux+webpack2.0+react-photoswipe+swiper等技术混合开 ...

  7. electron聊天室|vue+electron-vue仿微信客户端|electron桌面聊天

    一.项目概况 基于Electron+vue+electron-vue+vuex+Nodejs+vueVideoPlayer+electron-builder等技术仿制微信电脑端界面聊天室实例,实现消息 ...

  8. Vue3.0聊天室|vue3+vant3仿微信聊天实例|vue3.x仿微信app界面

    一.项目简介 基于Vue3.0+Vant3.x+Vuex4.x+Vue-router4+V3Popup等技术开发实现的仿微信手机App聊天实例项目Vue3-Chatroom.实现了发送图文表情消息/g ...

  9. Vue3.0+Electron聊天室|electron跨平台仿QQ客户端|vue3.x聊天应用

    基于vue3+electron11跨端仿制QQ桌面应用实战Vue3ElectronQchat. 使用vue3+electron+vuex4+ant-design-vue+v3scroll+v3laye ...

  10. Tauri-Vue3桌面端聊天室|tauri+vite3仿微信|tauri聊天程序EXE

    基于tauri+vue3.js+vite3跨桌面端仿微信聊天实例TauriVue3Chat. tauri-chat 运用最新tauri+vue3+vite3+element-plus+v3layer等 ...

随机推荐

  1. 开源:Taurus.DTS 微服务分布式任务框架,支持即时任务、延时任务、Cron表达式定时任务和广播任务。

    前言: 在发布完:开源:Taurus.DTC 微服务分布式事务框架,支持 .Net 和 .Net Core 双系列版本,之后想想,好像除了事务外,感觉里面多了一个任务发布订阅的基础功能. 本想既然都有 ...

  2. RSAC创新沙盒十强出炉,这家SCA公司火了

    引言 近日,全球网络安全行业创新风向标RSAC创新沙盒公布了本年度入围十强的名单,软件供应链安全企业Endor Labs凭借基于依赖关系建立应用开发生命周期的解决方案获得了广泛关注. Endor La ...

  3. vue动态组件使用

  4. python+appium使用方法

    一.python环境安装 确保需安装Appium-Python-Client包

  5. spring cloud 通过feign请求设置请求头

    本文为博主原创,转载请注明出处: spring cloud 服务组件之间通过feign 的方式请求,会携带很少的基础类型的消息头参数,比如Content-Type等,但不会携带自定义或指定的请求头参数 ...

  6. 物联网浏览器(IoTBrowser)-简单介绍

    物联网浏览器(IoTBrowser)是用于开发人机界面(HMI)或数据采集与监督控制系统(SCADA) 的工具,使用HTML或Vue前端技术开发物联网终端用户界面,支持串口.RFID.电子秤等硬件协议 ...

  7. 浏览器兼容 : IE 5 到 IE 9

    <!--[if IE]> <link href="ie.css" rel="stylesheet"> <![endif]--> ...

  8. Linux-进程动态监控-top

  9. [转帖]MySQL多版本并发控制机制(MVCC)-源码浅析

    https://zhuanlan.zhihu.com/p/144682180 MySQL多版本并发控制机制(MVCC)-源码浅析 前言 作为一个数据库爱好者,自己动手写过简单的SQL解析器以及存储引擎 ...

  10. [粘贴]github-redis-rdb-cli

    redis-rdb-cli A tool that can parse, filter, split, merge rdb and analyze memory usage offline. It c ...