<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      flutter3-dylive仿抖音App實例|Flutter3+Getx實戰短視頻直播應用

      原創研發flutter3+getX+mediaKit仿抖音app短視頻直播實戰Flutter-DouYin

      flutter3_dylive使用最新跨平臺技術flutter3.x+dart3+getx+get_storage+media_kit開發手機端仿抖音app小視頻直播實戰項目。實現了抖音全屏式上下滑動視頻、左右滑動切換頁面模塊,直播間進場/禮物動畫,聊天等模塊。

      技術棧

      • 編輯器:Vscode
      • 技術框架:Flutter3.19.2+Dart3.3.0
      • 路由/狀態管理:get: ^4.6.6
      • 本地緩存:get_storage: ^2.1.1
      • 圖片預覽插件:photo_view: ^0.14.0
      • 刷新加載:easy_refresh^3.3.4
      • toast輕提示:toast^0.3.0
      • 視頻套件:media_kit: ^1.1.10+1

      flutter_douyin實現了類似抖音全屏沉浸式滑動效果(上下滑動視頻、左右切換頁面模塊)。

      如下圖:實現了左右滑動的同時,頂部狀態欄+Tab菜單+底部bottomNavigationBar導航欄三者聯動效果。

      項目結構目錄

      在項目創建前期,需要配置好Flutter SDK和Dart SDK開發環境。

      https://flutter.dev/

      https://www.dartcn.com/

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

      如果是使用Vscode編輯器開發flutter項目,大家需自行配置flutter/dart擴展語法插件。

      目前最新版Flutter3.27仿抖音app商城項目已經同步到我的原創作品集。

      原創flutter3.27仿抖音短視頻+直播+聊天app商城系統

      項目中的一些技術知識點,有些是在之前的項目flutter3聊天實例中有介紹過,感興趣的話可以去看看。

      http://www.rzrgm.cn/xiaoyan2017/p/18008370

      http://www.rzrgm.cn/xiaoyan2017/p/18048244

      Flutter入口配置main.dart

      import 'dart:io';
      import 'package:flutter/material.dart';
      import 'package:get/get.dart';
      import 'package:get_storage/get_storage.dart';
      import 'package:media_kit/media_kit.dart';
      
      import 'utils/index.dart';
      
      // 引入布局模板
      import 'layouts/index.dart';
      
      import 'binding/binding.dart';
      
      // 引入路由管理
      import 'router/index.dart';
      
      void main() async {
        // 初始化get_storage
        await GetStorage.init();
      
        // 初始化media_kit
        WidgetsFlutterBinding.ensureInitialized();
        MediaKit.ensureInitialized();
      
        runApp(const MyApp());
      }
      
      class MyApp extends StatelessWidget {
        const MyApp({super.key});
      
        @override
        Widget build(BuildContext context) {
          return GetMaterialApp(
            title: 'FLUTTER3 DYLIVE',
            debugShowCheckedModeBanner: false,
            theme: ThemeData(
              colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFFFE2C55)),
              useMaterial3: true,
              // 修正windows端字體粗細不一致
              fontFamily: Platform.isWindows ? 'Microsoft YaHei' : null,
            ),
            home: const Layout(),
            // 全局綁定GetXController
            initialBinding: GlobalBindingController(),
            // 初始路由
            initialRoute: Utils.isLogin() ? '/' : '/login',
            // 路由頁面
            getPages: routePages,
            // 錯誤路由
            // unknownRoute: GetPage(name: '/404', page: Error),
          );
        }
      }

      Flutter3底部導航欄

      底部導航欄使用 bottomNavigationBar 組件實現頁面模塊切換。通過getx全局狀態來聯動控制底部導航欄背景顏色。

      導航欄中間圖標/圖片按鈕,使用了 Positioned 組件定位實現功能。

      return Scaffold(
        backgroundColor: Colors.grey[50],
        body: pageList[pageCurrent],
        // 底部導航欄
        bottomNavigationBar: Theme(
          // Flutter去掉BottomNavigationBar底部導航欄的水波紋
          data: ThemeData(
            splashColor: Colors.transparent,
            highlightColor: Colors.transparent,
            hoverColor: Colors.transparent,
          ),
          child: Obx(() {
            return Stack(
              children: [
                Container(
                  decoration: const BoxDecoration(
                    border: Border(top: BorderSide(color: Colors.black54, width: .1)),
                  ),
                  child: BottomNavigationBar(
                    backgroundColor: bottomNavigationBgcolor(),
                    fixedColor: FStyle.primaryColor,
                    unselectedItemColor: bottomNavigationItemcolor(),
                    type: BottomNavigationBarType.fixed,
                    elevation: 1.0,
                    unselectedFontSize: 12.0,
                    selectedFontSize: 12.0,
                    currentIndex: pageCurrent,
                    items: [
                      ...pageItems
                    ],
                    onTap: (index) {
                      setState(() {
                        pageCurrent = index;
                      });
                    },
                  ),
                ),
                // 自定義底部導航欄中間按鈕
                Positioned(
                  left: MediaQuery.of(context).size.width / 2 - 15,
                  top: 0,
                  bottom: 0,
                  child: InkWell(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        // Icon(Icons.tiktok, color: bottomNavigationItemcolor(centerDocked: true), size: 32.0,),
                        Image.asset('assets/images/applogo.png', width: 32.0, fit: BoxFit.contain,)
                        // Text('直播', style: TextStyle(color: bottomNavigationItemcolor(centerDocked: true), fontSize: 12.0),)
                      ],
                    ),
                    onTap: () {
                      setState(() {
                        pageCurrent = 2;
                      });
                    },
                  ),
                ),
              ],
            );
          }),
        ),
      );
      import 'package:flutter/material.dart';
      import 'package:get/get.dart';
      
      import '../styles/index.dart';
      import '../../controllers/page_video_controller.dart';
      
      // 引入pages頁面
      import '../pages/index/index.dart';
      import '../pages/video/index.dart';
      import '../pages/live/index.dart';
      import '../pages/message/index.dart';
      import '../pages/my/index.dart';
      
      class Layout extends StatefulWidget {
        const Layout({super.key});
      
        @override
        State<Layout> createState() => _LayoutState();
      }
      
      class _LayoutState extends State<Layout> {
        PageVideoController pageVideoController = Get.put(PageVideoController());
      
        // page索引
        int pageCurrent = 0;
        // page頁面
        List pageList = [const Index(), const FVideo(), const FLiveList(), const Message(), const My()];
        // tabs選項
        List pageItems = [
          const BottomNavigationBarItem(
            icon: Icon(Icons.home_outlined),
            label: '首頁'
          ),
          const BottomNavigationBarItem(
            icon: Icon(Icons.play_arrow_outlined),
            label: '短視頻'
          ),
          const BottomNavigationBarItem(
            icon: Icon(Icons.live_tv_rounded, color: Colors.transparent,),
            label: ''
          ),
          BottomNavigationBarItem(
            icon: Stack(
              alignment: const Alignment(4, -2),
              children: [
                const Icon(Icons.messenger_outline),
                FStyle.badge(1)
              ],
            ),
            label: '消息'
          ),
          BottomNavigationBarItem(
            icon: Stack(
              alignment: const Alignment(1.5, -1),
              children: [
                const Icon(Icons.person_outline),
                FStyle.badge(0, isdot: true)
              ],
            ),
            label: '我'
          )
        ];
      
        // 底部導航欄背景色
        Color bottomNavigationBgcolor() {
          int index = pageCurrent;
          int pageVideoTabIndex = pageVideoController.pageVideoTabIndex.value;
          Color color = Colors.white;
          if(index == 1) {
            if([1, 2, 3].contains(pageVideoTabIndex)) {
              color = Colors.white;
            }else {
              color = Colors.black;
            }
          }
          return color;
        }
        // 底部導航欄顏色
        Color bottomNavigationItemcolor({centerDocked = false}) {
          int index = pageCurrent;
          int pageVideoTabIndex = pageVideoController.pageVideoTabIndex.value;
          Color color = Colors.black54;
          if(index == 1) {
            if([1, 2, 3].contains(pageVideoTabIndex)) {
              color = Colors.black54;
            }else {
              color = Colors.white60;
            }
          }else if(index == 2 && centerDocked) {
            color = FStyle.primaryColor;
          }
          return color;
        }
      
        // ...
      }

      Flutter實現抖音全屏式滑動

      如下圖:實現類似抖音左右滑動全屏切換頁面模塊、上下滑動絲滑切換短視頻。

      采用 TabBar 和 PageView 聯動頁面滑動。

      return Scaffold(
        extendBodyBehindAppBar: true,
        appBar: AppBar(
          forceMaterialTransparency: true,
          backgroundColor: [1, 2, 3].contains(pageVideoController.pageVideoTabIndex.value) ? null : Colors.transparent,
          foregroundColor: [1, 2, 3].contains(pageVideoController.pageVideoTabIndex.value) ? Colors.black : Colors.white,
          titleSpacing: 1.0,
          leading: Obx(() => IconButton(icon: Icon(Icons.menu, color: tabColor(),), onPressed: () {},),),
          title: Obx(() {
            return TabBar(
              controller: tabController,
              tabs: pageTabs.map((v) => Tab(text: v)).toList(),
              isScrollable: true,
              tabAlignment: TabAlignment.center,
              overlayColor: MaterialStateProperty.all(Colors.transparent),
              unselectedLabelColor: unselectedTabColor(),
              labelColor: tabColor(),
              indicatorColor: tabColor(),
              indicatorSize: TabBarIndicatorSize.label,
              unselectedLabelStyle: const TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei'),
              labelStyle: const TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.w600),
              dividerHeight: 0,
              labelPadding: const EdgeInsets.symmetric(horizontal: 10.0),
              indicatorPadding: const EdgeInsets.symmetric(horizontal: 5.0),
              onTap: (index) {
                pageVideoController.updatePageVideoTabIndex(index); // 更新索引
                pageController.jumpToPage(index);
              },
            );
          }),
          actions: [
            Obx(() => IconButton(icon: Icon(Icons.search, color: tabColor(),), onPressed: () {},),),
          ],
        ),
        body: Column(
          children: [
            Expanded(
              child: Stack(
                children: [
                  /// 水平滾動模塊
                  PageView(
                    // 自定義滾動行為(支持桌面端滑動、去掉滾動條槽)
                    scrollBehavior: PageScrollBehavior().copyWith(scrollbars: false),
                    scrollDirection: Axis.horizontal,
                    controller: pageController,
                    onPageChanged: (index) {
                      pageVideoController.updatePageVideoTabIndex(index); // 更新索引
                      setState(() {
                        tabController.animateTo(index);
                      });
                    },
                    children: [
                      ...pageModules
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      );
      PageVideoController pageVideoController = Get.put(PageVideoController());
      
      List<String> pageTabs = ['熱點', '長視頻', '文旅', '商城', '關注', '同城服務', '推薦'];
      final pageModules = [
        const HotModule(),
        const LongVideoModule(),
        const TripModule(),
        const MallModule(),
        const FavorModule(),
        const NearModule(),
        const RecommendModule()
      ];
      late final TabController tabController = TabController(initialIndex: pageVideoController.pageVideoTabIndex.value, length: pageTabs.length, vsync: this);
      // 頁面controller
      late final PageController pageController = PageController(initialPage: pageVideoController.pageVideoTabIndex.value, viewportFraction: 1.0);
      
      @override
      void dispose() {
        tabController.dispose();
        pageController.dispose();
        super.dispose();
      }

      flutter短視頻mini進度條

      底部mini播放進度條一開始是采用自定義組件實現效果,不過不能拖動滾動條進度,后來就采用了Slider組件來實現。

      // flutter滑動短視頻模塊  Q:282310962
      
      return Container(
        color: Colors.black,
        child: Column(
          children: [
            Expanded(
              child: Stack(
                children: [
                  /// 垂直滾動模塊
                  PageView.builder(
                    // 自定義滾動行為(支持桌面端滑動、去掉滾動條槽)
                    scrollBehavior: PageScrollBehavior().copyWith(scrollbars: false),
                    scrollDirection: Axis.vertical,
                    controller: pageController,
                    onPageChanged: (index) async {
                      ...
                    },
                    itemCount: videoList.length,
                    itemBuilder: (context, index) {
                      return Stack(
                        children: [
                          // 視頻區域
                          Positioned(
                            top: 0,
                            left: 0,
                            right: 0,
                            bottom: 0,
                            child: GestureDetector(
                              child: Stack(
                                children: [
                                  // 短視頻插件
                                  Visibility(
                                    visible: videoIndex == index,
                                    child: Video(
                                      controller: videoController,
                                      fit: BoxFit.cover,
                                      // 無控制條
                                      controls: NoVideoControls,
                                    ),
                                  ),
                                  // 播放/暫停按鈕
                                  StreamBuilder(
                                    stream: player.stream.playing,
                                    builder: (context, playing) {
                                      return Visibility(
                                        visible: playing.data == false,
                                        child: Center(
                                          child: IconButton(
                                            padding: EdgeInsets.zero,
                                            onPressed: () {
                                              player.playOrPause();
                                            },
                                            icon: Icon(
                                              playing.data == true ? Icons.pause : Icons.play_arrow_rounded,
                                              color: Colors.white70,
                                              size: 70,
                                            ),
                                          ),
                                        ),
                                      );
                                    },
                                  ),
                                ],
                              ),
                              onTap: () {
                                player.playOrPause();
                              },
                            ),
                          ),
                          // 右側操作欄
                          Positioned(
                            bottom: 15.0,
                            right: 10.0,
                            child: Column(
                              ...
                            ),
                          ),
                          // 底部信息區域
                          Positioned(
                            bottom: 15.0,
                            left: 10.0,
                            right: 80.0,
                            child: Column(
                              ...
                            ),
                          ),
                          // 播放mini進度條
                          Positioned(
                            bottom: 0.0,
                            left: 10.0,
                            right: 10.0,
                            child: Visibility(
                              visible: videoIndex == index && position > Duration.zero,
                              child: Listener(
                                child: SliderTheme(
                                  data: const SliderThemeData(
                                    trackHeight: 2.0,
                                    thumbShape: RoundSliderThumbShape(enabledThumbRadius: 4.0), // 調整滑塊的大小
                                    // trackShape: RectangularSliderTrackShape(), // 使用矩形軌道形狀
                                    overlayShape: RoundSliderOverlayShape(overlayRadius: 0), // 去掉Slider默認上下邊距間隙
                                    inactiveTrackColor: Colors.white24, // 設置非活動進度條的顏色
                                    activeTrackColor: Colors.white, // 設置活動進度條的顏色
                                    thumbColor: Colors.pinkAccent, // 設置滑塊的顏色
                                    overlayColor: Colors.transparent, // 設置滑塊覆蓋層的顏色
                                  ),
                                  child: Slider(
                                    value: sliderValue,
                                    onChanged: (value) async {
                                      // debugPrint('當前視頻播放時間$value');
                                      setState(() {
                                        sliderValue = value;
                                      });
                                      // 跳轉播放時間
                                      await player.seek(duration * value.clamp(0.0, 1.0));
                                    },
                                    onChangeEnd: (value) async {
                                      setState(() {
                                        sliderDraging = false;
                                      });
                                      // 繼續播放
                                      if(!player.state.playing) {
                                        await player.play();
                                      }
                                    },
                                  ),
                                ),
                                onPointerMove: (e) {
                                  setState(() {
                                    sliderDraging = true;
                                  });
                                },
                              ),
                            ),
                          ),
                          // 視頻播放時間
                          Positioned(
                            bottom: 90.0,
                            left: 10.0,
                            right: 10.0,
                            child: Visibility(
                              visible: sliderDraging,
                              child: Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Text(position.label(reference: duration), style: const TextStyle(color: Colors.white, fontSize: 16.0, fontWeight: FontWeight.w600),),
                                  Container(
                                    margin: const EdgeInsets.symmetric(horizontal: 7.0),
                                    child: const Text('/', style: TextStyle(color: Colors.white54, fontSize: 10.0,),),
                                  ),
                                  Text(duration.label(reference: duration), style: const TextStyle(color: Colors.white54, fontSize: 16.0, fontWeight: FontWeight.w600),),
                                ],
                              ),
                            ),
                          ),
                        ],
                      );
                    },
                  ),
                  /// 固定層
                  // 紅包
                  Positioned(
                    left: 15.0,
                    top: MediaQuery.of(context).padding.top + 20,
                    child: Container(
                      height: 40.0,
                      width: 40.0,
                      decoration: BoxDecoration(
                        color: Colors.black12,
                        borderRadius: BorderRadius.circular(100.0),
                      ),
                      child: UnconstrainedBox(
                        child: Image.asset('assets/images/time-hb.png', width: 30.0, fit: BoxFit.contain,),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      );

      flutter3直播模塊

      flutter直播模塊包含了頂部信息、底部進場提示+商品層+彈幕層+操作欄等幾個模塊。

      // 商品購買動效
      Container(
        ...
      ),
      
      // 加入直播間動效
      const AnimationLiveJoin(
        joinQueryList: [
          {'avatar': 'assets/images/logo.png', 'name': 'andy'},
          {'avatar': 'assets/images/logo.png', 'name': 'jack'},
          {'avatar': 'assets/images/logo.png', 'name': '一條咸魚'},
          {'avatar': 'assets/images/logo.png', 'name': '四季平安'},
          {'avatar': 'assets/images/logo.png', 'name': '葉子'},
        ],
      ),
      
      // 送禮物動效
      const AnimationLiveGift(
        giftQueryList: [
          {'label': '小心心', 'gift': 'assets/images/gift/gift1.png', 'user': 'Jack', 'avatar': 'assets/images/avatar/uimg2.jpg', 'num': 12},
          {'label': '棒棒糖', 'gift': 'assets/images/gift/gift2.png', 'user': 'Andy', 'avatar': 'assets/images/avatar/uimg6.jpg', 'num': 36},
          {'label': '大啤酒', 'gift': 'assets/images/gift/gift3.png', 'user': '一條咸魚', 'avatar': 'assets/images/avatar/uimg1.jpg', 'num': 162},
          {'label': '人氣票', 'gift': 'assets/images/gift/gift4.png', 'user': 'Flower', 'avatar': 'assets/images/avatar/uimg5.jpg', 'num': 57},
          {'label': '鮮花', 'gift': 'assets/images/gift/gift5.png', 'user': '四季平安', 'avatar': 'assets/images/avatar/uimg3.jpg', 'num': 6},
          {'label': '捏捏小臉', 'gift': 'assets/images/gift/gift6.png', 'user': 'Alice', 'avatar': 'assets/images/avatar/uimg4.jpg', 'num': 28},
          {'label': '你真好看', 'gift': 'assets/images/gift/gift7.png', 'user': '葉子', 'avatar': 'assets/images/avatar/uimg7.jpg', 'num': 95},
          {'label': '親吻', 'gift': 'assets/images/gift/gift8.png', 'user': 'YOYO', 'avatar': 'assets/images/avatar/uimg8.jpg', 'num': 11},
          {'label': '玫瑰', 'gift': 'assets/images/gift/gift12.png', 'user': '宇輝', 'avatar': 'assets/images/avatar/uimg9.jpg', 'num': 3},
          {'label': '私人飛機', 'gift': 'assets/images/gift/gift16.png', 'user': 'Hison', 'avatar': 'assets/images/avatar/uimg10.jpg', 'num': 273},
        ],
      ),
      
      // 直播彈幕+商品講解
      Container(
        margin: const EdgeInsets.only(top: 7.0),
        height: 200.0,
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Expanded(
              child: ListView.builder(
                padding: EdgeInsets.zero,
                itemCount: liveJson[index]['message']?.length,
                itemBuilder: (context, i) => danmuList(liveJson[index]['message'])[i],
              ),
            ),
            SizedBox(
              width: isVisibleGoodsTalk ? 7 : 35,
            ),
            // 商品講解
            Visibility(
              visible: isVisibleGoodsTalk,
              child: Column(
                ...
              ),
            ),
          ],
        ),
      ),
      
      // 底部工具欄
      Container(
        margin: const EdgeInsets.only(top: 7.0),
        child: Row(
          ...
        ),
      ),

      直播聊天彈幕通過Flexible配合Text.rich / TextSpan實現消息自適應布局界面。

      通過 SlideTransition 組件實現直播進場動畫。

      return SlideTransition(
        position: animationFirst ? animation : animationMix,
        child: Container(
          alignment: Alignment.centerLeft,
          margin: const EdgeInsets.only(top: 7.0),
          padding: const EdgeInsets.symmetric(horizontal: 7.0,),
          height: 23.0,
          width: 250,
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.centerLeft,
              end: Alignment.centerRight,
              colors: [
                Color(0xFF6301FF), Colors.transparent
              ],
            ),
            borderRadius: BorderRadius.horizontal(left: Radius.circular(10.0)),
          ),
          child: joinList!.isNotEmpty ? 
            Text('歡迎 ${joinList![0]['name']} 加入直播間', style: const TextStyle(color: Colors.white, fontSize: 14.0,),)
            :
            Container()
          ,
        ),
      );
      class _AnimationLiveJoinState extends State<AnimationLiveJoin> with TickerProviderStateMixin {
        // 動畫控制器
        late AnimationController controller = AnimationController(
          vsync: this,
          duration: const Duration(milliseconds: 500), // 第一個動畫持續時間
        );
        late AnimationController controllerMix = AnimationController(
          vsync: this,
          duration: const Duration(milliseconds: 1000), // 第二個動畫持續時間
        );
        // 動畫
        late Animation<Offset> animation = Tween(begin: const Offset(2.5, 0), end: const Offset(0, 0)).animate(controller);
        late Animation<Offset> animationMix = Tween(begin: const Offset(0, 0), end: const Offset(-2.5, 0)).animate(controllerMix);
      
        Timer? timer;
        // 是否第一個動畫
        bool animationFirst = true;
        // 是否空閑
        bool idle = true;
        // 加入直播間數據列表
        List? joinList;
      
        @override
        void initState() {
          super.initState();
      
          joinList = widget.joinQueryList!.toList();
      
          runAnimation();
          animation.addListener(() {
            if(animation.status == AnimationStatus.forward) {
              debugPrint('第一個動畫進行中');
              idle = false;
              setState(() {});
            }else if(animation.status == AnimationStatus.completed) {
              debugPrint('第一個動畫結束');
              animationFirst = false;
              if(controllerMix.isCompleted || controllerMix.isDismissed) {
                timer = Timer(const Duration(seconds: 2), () {
                  controllerMix.forward();
                  debugPrint('第二個動畫開始');
                });
              }
              setState(() {});
            }
          });
          animationMix.addListener(() {
            if(animationMix.status == AnimationStatus.forward) {
              setState(() {});
            }else if(animationMix.status == AnimationStatus.completed) {
              animationFirst = true;
              controller.reset();
              controllerMix.reset();
              if(joinList!.isNotEmpty) {
                joinList!.removeAt(0);
              }
              idle = true;
              // 執行下一個數據
              runAnimation();
              setState(() {});
            }
          });
        }
      
        void runAnimation() {
          if(joinList!.isNotEmpty) {
            // 空閑狀態才能執行,防止添加數據播放狀態混淆
            if(idle == true) {
              if(controller.isCompleted || controller.isDismissed) {
                setState(() {});
                timer = Timer(Duration.zero, () {
                  controller.forward();
                });
              }
            }
          }
        }
      
        @override
        void dispose() {
          controller.dispose();
          controllerMix.dispose();
          timer?.cancel();
          super.dispose();
        }
      
      }

      綜上就是flutter3實戰開發仿抖音的一些知識分享,由于涉及的技術點還是蠻多的,就沒有非常詳細的展開介紹了。希望以上的一些分享能給大家有些幫助~

      Uniapp-DeepSeek跨三端AI助手|uniapp+vue3+deepseek-v3流式ai聊天模板

      flutter3-trip仿攜程酒店預訂|Flutter3.27+Getx預約旅游酒店App程序

      flutter3+dart3聊天室|Flutter3跨平臺仿微信App語音聊天/朋友圈

      flutter3-winchat桌面端聊天實例|Flutter3+Dart3+Getx仿微信Exe程序

      最新版Flutter3.27仿抖音App直播商城實例

      http://www.rzrgm.cn/xiaoyan2017/p/18700875

      最后附上兩個跨端項目

      uniapp+vue3短視頻直播商城:http://www.rzrgm.cn/xiaoyan2017/p/17938517

      tauri2+vite5中后臺管理系統:http://www.rzrgm.cn/xiaoyan2017/p/18467237

       

      posted @ 2024-03-24 11:40  xiaoyan2017  閱讀(2409)  評論(0)    收藏  舉報
      友情鏈接: UP主小店B站
      主站蜘蛛池模板: 四虎成人精品永久网站| 久久婷婷大香萑太香蕉AV人| 成人激情视频一区二区三区| 男女性杂交内射女bbwxz| 欧美性插b在线视频网站| 久久日产一线二线三线| 精品无码av无码专区| 亚洲精品国产精品乱码不卡| 国产三级国产精品久久成人| 国产一区二区午夜福利久久| 久久精品夜夜夜夜夜久久| 久久精品一本到99热免费| 国产伦一区二区三区视频| 疯狂做受XXXX高潮国产| 亚洲美免无码中文字幕在线| www插插插无码免费视频网站| 国产精品国产精品一区精品| 成人无码午夜在线观看| 中文字幕av国产精品| 三上悠亚精品一区二区久久| 污污网站18禁在线永久免费观看| 亚洲一区二区精品偷拍| 妓女妓女一区二区三区在线观看| 把腿张开ji巴cao死你h| 无码国内精品人妻少妇| 亚洲一区二区约美女探花| 国产极品粉嫩尤物一区二区| 亚洲理论在线A中文字幕| 2019亚洲午夜无码天堂| 国产成人拍国产亚洲精品| 青草青草久热国产精品| 成年午夜免费韩国做受视频| 国产精品亚洲二区在线看| 亚洲熟女综合色一区二区三区 | 免费高清特级毛片A片| 亚洲国产精品自产在线播放 | 97久久精品人人澡人人爽| 亚洲 制服 丝袜 无码| 亚洲国产av区一区二| 久久久国产成人一区二区| 老妇女性较大毛片|