flutter3+dart3聊天室|Flutter3跨平臺(tái)仿微信App語音聊天/朋友圈
全新研發(fā)flutter3+dart3+photo_view跨多端仿微信App界面聊天Flutter3-Chat。
flutter3-chat基于最新跨全平臺(tái)技術(shù)flutter3+dart3+material-design+shared_preferences+easy_refresh構(gòu)建的仿微信APP界面聊天實(shí)例項(xiàng)目。實(shí)現(xiàn)發(fā)送圖文表情消息/gif大圖、長按仿微信語音操作面板、圖片預(yù)覽、紅包及朋友圈等功能。
flutter3-winseek客戶端AI實(shí)例|Flutter3.32+DeepSeek流式ai對(duì)話模板Exe
flutter3-deepseek流式AI模板|Flutter3.27+Dio+DeepSeeek聊天ai助手
技術(shù)架構(gòu)
- 編輯器:Vscode
- 框架技術(shù):Flutter3.16.5+Dart3.2.3
- UI組件庫:material-design3
- 彈窗組件:showDialog/SimpleDialog/showModalBottomSheet/AlertDialog
- 圖片預(yù)覽:photo_view^0.14.0
- 本地緩存:shared_preferences^2.2.2
- 下拉刷新:easy_refresh^3.3.4
- toast提示:toast^0.3.0
- 網(wǎng)址預(yù)覽組件:url_launcher^6.2.4


Flutter3.x開發(fā)跨平臺(tái)項(xiàng)目,性能有了大幅度提升,官方支持編譯到android/ios/macos/windows/linux/web等多平臺(tái),未來可期!
項(xiàng)目構(gòu)建目錄
通過 flutter create app_project 命令即可快速創(chuàng)建一個(gè)跨平臺(tái)初始化項(xiàng)目。

通過命令創(chuàng)建項(xiàng)目后,項(xiàng)目結(jié)構(gòu)就如上圖所示。

需要注意:flutter項(xiàng)目基于dart語音開發(fā),需要首先配置Dart SDK和Flutter SDK開發(fā)環(huán)境,大家可以去官網(wǎng)查看配置文檔。
另外使用VScode編輯器開發(fā)項(xiàng)目,可自行安裝Flutter / Dart擴(kuò)展插件。

























目前flutter3-chat聊天app已經(jīng)正式同步到我的原創(chuàng)作品集。
由于flutter3支持編譯到windows,大家可以開發(fā)初期在windows上面調(diào)試,后期release apk到手機(jī)上。
通過如下命令即可運(yùn)行到windows平臺(tái)
flutter run -d windows

運(yùn)行后默認(rèn)窗口大小為1280x720,可以修改windows/runner/main.cpp文件里面的窗口尺寸。

同樣,可以通過 flutter run -d chrome 命令運(yùn)行到web上預(yù)覽。
假如在沒有真機(jī)的情況下,我們可以選擇模擬器調(diào)試。目前市面上有很多類型模擬器,他們使用adb連接時(shí)都會(huì)有不同的默認(rèn)端口,下面列出了一些常用的模擬器及端口號(hào)。通過adb connect連接上指定模擬器之后,執(zhí)行flutter run命令即可運(yùn)行項(xiàng)目到模擬器上面。

flutter3實(shí)現(xiàn)圓角文本框及漸變按鈕

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: '輸入手機(jī)號(hào)', 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屬性設(shè)置漸變效果。
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實(shí)現(xiàn)60s倒計(jì)時(shí)發(fā)送驗(yàn)證碼功能。

Timer? timer; String vcodeText = '獲取驗(yàn)證碼'; bool disabled = false; int time = 60; // 60s倒計(jì)時(shí) void handleVcode() { if(authObj['tel'] == '') { snackbar('手機(jī)號(hào)不能為空'); }else if(!Utils.checkTel(authObj['tel'])) { snackbar('手機(jī)號(hào)格式不正確'); }else { setState(() { disabled = true; }); startTimer(); } } startTimer() { timer = Timer.periodic(const Duration(seconds: 1), (timer) { setState(() { if(time > 0) { vcodeText = '獲取驗(yàn)證碼(${time--})'; }else { vcodeText = '獲取驗(yàn)證碼'; time = 60; disabled = false; timer.cancel(); } }); }); snackbar('短信驗(yàn)證碼已發(fā)送,請(qǐng)注意查收', color: Colors.green); }
Flutter3沉浸式漸變狀態(tài)導(dǎo)航欄



要實(shí)現(xiàn)如上圖漸變AppBar也非常簡(jiǎn)單,只需要配置AppBar提供的可伸縮靈活區(qū)域?qū)傩?nbsp;flexibleSpace 配合gradient即可快速實(shí)現(xiàn)漸變導(dǎo)航欄。
AppBar( title: Text('Flutter3-Chat'), flexibleSpace: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFF0091EA), Color(0xFF07C160) ], ) ), ) ),
Flutter3字體圖標(biāo)/自定義badge
flutter內(nèi)置了豐富的字體圖標(biāo),通過圖標(biāo)組件 Icon(Icons.add) 引入即可使用。
https://api.flutter-io.cn/flutter/material/Icons-class.html
另外還支持通過自定義IconData方式自定義圖標(biāo),如使用阿里iconfont圖表庫圖標(biāo)。
Icon(IconData(0xe666, fontFamily: 'iconfont'), size: 18.0)
把下載的字體文件放到assets目錄,

在pubspec.yaml中引入字體文件。

class FStyle { // 自定義iconfont圖標(biāo) static iconfont(int codePoint, {double size = 16.0, Color? color}) { return Icon( IconData(codePoint, fontFamily: 'iconfont', matchTextDirection: true), size: size, color: color, ); } // 自定義Badge紅點(diǎn) 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組件實(shí)現(xiàn)下拉菜單功能。
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, '發(fā)起群聊', 0), popupMenuItem(0xe75c, '添加朋友', 1), popupMenuItem(0xe603, '掃一掃', 2), popupMenuItem(0xe6ab, '收付款', 3), ]; }, onSelected: (value) { switch(value) { case 0: print('發(fā)起群聊'); break; case 1: Navigator.pushNamed(context, '/addfriends'); break; case 2: print('掃一掃'); break; case 3: print('收付款'); break; } }, )
// 下拉菜單項(xiàng) 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 組件實(shí)現(xiàn)功能。
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實(shí)現(xiàn)效果。通過無限制容器UnconstrainedBox配合SizedBox組件實(shí)現(xiàn)自定義窗口大小。
// 關(guān)于彈窗 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開發(fā)跨平臺(tái)仿微信App聊天實(shí)例。', 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('掃一掃,加我公眾號(hào)', 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實(shí)現(xiàn)微信朋友圈九宮格


GroupZone(images: item['images']), GroupZone( images: uploadList, album: true, onChoose: () async { Toast.show('選擇手機(jī)相冊(cè)圖片', duration: 2, gravity: 1); }, ),

// 創(chuàng)建可點(diǎn)擊預(yù)覽圖片 createImage(BuildContext context, String img, int key) { return GestureDetector( child: Hero( tag: img, // 放大縮小動(dòng)畫效果標(biāo)識(shí) 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插件實(shí)現(xiàn)預(yù)覽大圖功能,支持預(yù)覽單張及多張大圖。
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; // 預(yù)覽圖列表 final int index; // 當(dāng)前預(yù)覽圖索引 @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設(shè)置maxLines: null即可實(shí)現(xiàn)多行文本輸入,支持圖文emoj混排,網(wǎng)址連接識(shí)別等功能。
// 輸入框 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) {}, ), ),

支持仿微信語音按住說話,左滑取消發(fā)送、右滑轉(zhuǎn)換語音功能。

// 語音 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; // 松開發(fā)送 }else if (pos.dy < swipeY && pos.dx < swipeX) { voiceType = 2; // 左滑松開取消 }else if (pos.dy < swipeY && pos.dx >= swipeX) { voiceType = 3; // 右滑語音轉(zhuǎn)文字 } }); }, onPanEnd: (details) { // print('停止錄音'); setState(() { switch(voiceType) { case 1: Toast.show('發(fā)送錄音文件', duration: 1, gravity: 1); voicePanelEnable = false; break; case 2: Toast.show('取消發(fā)送', duration: 1, gravity: 1); voicePanelEnable = false; break; case 3: Toast.show('語音轉(zhuǎn)文字', duration: 1, gravity: 1); voicePanelEnable = true; voiceToTransfer = true; break; } voiceType = 0; }); }, ), ),
按住錄音顯示面板
// 錄音主體(按住說話/松開取消/語音轉(zhuǎn)文本) Visibility( visible: voicePanelEnable, child: Material( color: const Color(0xDD1B1B1B), child: Stack( children: [ // 取消發(fā)送+語音轉(zhuǎn)文字 Positioned( bottom: 120, left: 30, right: 30, child: Visibility( visible: !voiceToTransfer, child: Column( children: [ // 語音動(dòng)畫層 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,), // 操作項(xiàng) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // 取消發(fā)送 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,), ), // 語音轉(zhuǎn)文字 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,), ), ], ), ], ), ), ), // 語音轉(zhuǎn)文字(識(shí)別結(jié)果狀態(tài)) Positioned( bottom: 120, left: 30, right: 30, child: Visibility( visible: voiceToTransfer, child: Column( children: [ // 提示結(jié)果 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('未識(shí)別到文字。', 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,), // 操作項(xiàng) 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('發(fā)送原語音', 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: () {}, ), ], ), ], ), ), ), // 提示文字(操作狀態(tài)) 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), ), ), // 背景圖標(biāo) 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開發(fā)全平臺(tái)聊天App實(shí)例的一些知識(shí)分享,希望對(duì)大家有所幫助哈~~??
Uniapp-DeepSeek跨三端AI助手|uniapp+vue3+deepseek-v3流式ai聊天模板
Electron35-DeepSeek桌面端AI系統(tǒng)|vue3.5+electron+arco客戶端ai模板
uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天語音/朋友圈
flutter3-dymall仿抖音直播商城|Flutter3.27短視頻+直播+聊天App實(shí)例
flutter3-trip仿攜程酒店預(yù)訂|Flutter3.27+Getx預(yù)約旅游酒店App程序
Tauri2.0-Vue3OS桌面端os平臺(tái)|tauri2+vite6+arco電腦版OS管理系統(tǒng)
Electron31-Vue3Admin管理系統(tǒng)|vite5+electron+pinia桌面端后臺(tái)Exe
最后附上兩個(gè)最新實(shí)戰(zhàn)項(xiàng)目
uni-app+vue3+pinia2仿抖音直播商城:http://www.rzrgm.cn/xiaoyan2017/p/17938517
flutter3+dart3桌面端仿微信Exe聊天:http://www.rzrgm.cn/xiaoyan2017/p/18048244


浙公網(wǎng)安備 33010602011771號(hào)