動態

詳情 返回 返回

flutter3-winseek客户端AI實例|Flutter3.32+DeepSeek流式ai對話模板Exe - 動態 詳情

原創首發flutter3+deepseek+window_manager客户端Ai流式打字Flutter-WinSeek

flutter3-winseek-chat:基於flutter3.32+dart3.8+deepseek+dio+getx+markdown+highlight等技術搭建桌面客户端AI流式打字效果聊天對話Exe項目。支持側邊欄收縮、stream流輸出、代碼高亮/複製、對話本地存儲等功能。

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

flutter3-deepseek流式AI模板|Flutter3.27+Dio+DeepSeeek聊天ai助手

vue3-webseek網頁版AI問答|Vite6+DeepSeek+Arco流式ai聊天打字效果

Vue3-DeepSeek-Chat流式AI對話|vite6+vant4+deepseek智能ai聊天助手

Electron35-DeepSeek桌面端AI系統|vue3.5+electron+arco客户端ai模板

Tauri2.0-DeepSeek電腦端Ai對話|tauri2+vite6+deepseek流式ai聊天系統

使用技術

  • 編輯器:vscode
  • 技術框架:flutter3.32.0+dart3.8.0
  • 對話大模型:deepseek-v3
  • 流請求:dio^5.8.0+1
  • 窗口管理:window_manager^0.5.0
  • 托盤管理:system_tray^2.0.3
  • 路由/狀態管理:get^4.7.2
  • 存儲服務:get_storage^2.1.1
  • markdown解析:flutter_markdown^0.7.7
  • 高亮組件:flutter_highlight^0.7.0
  • 環境變量配置:flutter_dotenv^5.2.1

功能特色

  1. 最新跨平台Flutter3.32構建,接入DeepSeek-V3,絲滑般流式輸出
  2. 支持側邊欄收縮/展開
  3. 支持上下文多輪對話、代碼高亮、本地存儲會話
  4. 支持代碼塊橫向滾動、複製代碼功能
  5. 支持圖片100%寬度渲染、在線圖片預覽
  6. 支持網絡鏈接跳轉、表格功能
  7. 採用自定義無邊框窗口、托盤圖標

項目結構目錄

Flutter3-WinSeek客户端ai項目已經更新到我的原創作品集。

flutter3.32+deepseek+dio客户端ai流式對話Exe

通過 flutter create flutter_winseek 命令即可快速創建一個flutter空項目模板。

通過 flutter run -d windows 命令即可運行到windows桌面。

.env環境變量配置

在flutter中使用 flutter_dotenv 插件來配置環境變量。

# 項目名稱
APP_NAME = 'Flutter3-WinSeek'

# DeepSeek API配置
DEEPSEEK_API_KEY = apikey
DEEPSEEK_BASE_URL = https://api.deepseek.com

在頁面獲取環境變量

// 獲取.env環境變量baseUrl和apiKey
String baseURL = dotenv.get('DEEPSEEK_BASE_URL');
String apiKEY = dotenv.get('DEEPSEEK_API_KEY');

項目佈局模板

項目整體分為側邊欄+自定義頂部導航+AI聊天對話區三個模塊。

return Scaffold(
  backgroundColor: Colors.grey[50],
  body: DragToResizeArea(
    child: Row(
      children: [
        // 側邊欄
        AnimatedSize(
          duration: const Duration(milliseconds: 300),
          curve: Curves.easeInOut,
          child: Container(
            width: collapsed ? 0 : 260,
            decoration: BoxDecoration(
              border: Border(right: BorderSide(color: Colors.grey.withAlpha(50)))
            ),
            child: Material(
              color: Color(0xFFF3F3F3),
              child: Sidebar(),
            ),
          ),
        ),
        // 主體容器
        Expanded(
          child: Column(
            children: [
              // 自定義導航欄
              SizedBox(
                height: 30.0,
                child: Row(
                  children: [
                    IconButton(
                      onPressed: () {
                        setState(() {
                          collapsed = !collapsed;
                        });
                      },
                      icon: Icon(collapsed ? Icons.format_indent_increase : Icons.format_indent_decrease, size: 16.0,),
                      tooltip: collapsed ? '展開' : '收縮',
                    ),
                    Expanded(
                      child: DragToMoveArea(
                        child: SizedBox(
                          height: double.infinity,
                        ),
                      ),
                    ),
                    // 右上角操作按鈕
                    WinBtns(
                      leading: Row(
                        children: [
                          ...
                        ],
                      ),
                    ),
                  ],
                ),
              ),
              // 右側主面板
              Expanded(
                child: Container(
                  child: widget.child,
                ),
              ),
            ],
          ),
        ),
      ],
    ),
  ),
);

   

return ScrollConfiguration(
  behavior: CustomScrollBehavior(),
  child: Column(
    children: [
      Container(
        padding: EdgeInsets.all(10.0),
        child: Column(
          spacing: 10.0,
          children: [
            ...
          ],
        ),
      ),
      Container(
        margin: EdgeInsets.only(bottom: 10.0),
        padding: EdgeInsets.symmetric(horizontal: 20.0),
        child: Row(
          spacing: 5.0,
          children: [
            Icon(Icons.history, size: 18.0,),
            Text('歷史對話'),
            Spacer(),
            SizedBox(
              height: 25.0, width: 25.0,
              child: Transform.translate(
                offset: Offset(3.0, 0),
                child: IconButton(
                  onPressed: () => handleClear(),
                  tooltip: '清空會話',
                  icon: Icon(Icons.delete_sweep_outlined, size: 14.0),
                  padding: EdgeInsets.zero,
                  style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.grey[50])),
                ),
              )
            )
          ],
        ),
      ),
      Expanded(
        child: Obx(() {
          if(chatStore.sessions.isEmpty) {
            return Column(
              spacing: 5.0,
              children: [
                SizedBox(height: 20.0,),
                Image.asset('assets/images/empty.png', height: 40.0, width: 40.0,),
                Text('暫無對話', style: TextStyle(color: Colors.black38), overflow: TextOverflow.ellipsis,),
              ],
            );
          }
          return ListView.separated(
            padding: EdgeInsets.symmetric(horizontal: 10.0),
            separatorBuilder: (context, index) => SizedBox(height: 2.0),
            itemCount: chatStore.sessions.length,
            itemBuilder: (context, index) {
              // ...
            },
          );
        }),
      ),
      Container(
        margin: EdgeInsets.symmetric(vertical: 10.0),
        padding: EdgeInsets.symmetric(horizontal: 10.0),
        child: InkWell(
          borderRadius: BorderRadius.circular(10.0),
          child: Container(
            padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
            child: Row(
              spacing: 5.0,
              children: [
                Image.asset('assets/images/avatar.png',height: 30.0,width: 30.0,fit: BoxFit.cover),
                Text('Andy'),
                Spacer(),
                Icon(Icons.arrow_forward_ios_rounded, color: Colors.grey, size: 10.0,)
              ],
            ),
          ),
          onTap: () {
            Get.toNamed('/setting');
          },
        ),
      ),
    ],
  ),
);

flutter3 ai對話編輯框

當窗口最大化,編輯框最大寬度限制在750px

編輯框組件封裝在components目錄下。

return Container(
  width: double.infinity,
  padding: EdgeInsets.symmetric(vertical: 10.0),
  child: Column(
    spacing: 6.0,
    children: [
      // 技能欄
      if (widget.skillbar)
      ScrollConfiguration(
        behavior: CustomScrollBehavior(),
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          padding: EdgeInsets.symmetric(horizontal: 15.0),
          child: Row(
            spacing: 4.0,
            children: [
              ...
            ]
          ),
        ),
      ),
      // 編輯框
      Container(
        margin: EdgeInsets.symmetric(horizontal: 15.0),
        padding: EdgeInsets.all(10.0),
        decoration: BoxDecoration(
          color: Colors.white,
          border: Border.all(color: Colors.grey.withAlpha(100), width: .5),
          borderRadius: BorderRadius.circular(15.0),
          boxShadow: [
            BoxShadow(
              color: Colors.black.withAlpha(20),
              offset: Offset(0.0, 3.0),
              blurRadius: 6.0,
              spreadRadius: 0.0,
            ),
          ]
        ),
        child: Column(
          spacing: 10.0,
          children: [
            // 輸入框
            ConstrainedBox(
              constraints: BoxConstraints(minHeight: 48.0, maxHeight: 150.0),
              child: TextField(
                ...
              ),
            ),
            // 操作欄
            Row(
              spacing: 10.0,
              children: [
                SizedBox(
                  height: 30.0,
                  child: TextButton(
                    onPressed: () {
                      setState(() {
                        isDeep =! isDeep;
                      });
                    },
                    style: ButtonStyle(
                      backgroundColor: WidgetStateProperty.all(isDeep ? Color(0xFF4F6BFE).withAlpha(30) : Colors.grey[200]),
                      padding: WidgetStateProperty.all(EdgeInsets.symmetric(horizontal: 10.0)),
                    ),
                    child: Row(
                      spacing: 4.0,
                      children: [
                        Icon(Icons.stream, color: isDeep ? Color(0xFF4F6BFE) : Colors.black, size: 18.0,),
                        Text('深度思考(R1)', style: TextStyle(color: isDeep ? Color(0xFF4F6BFE) : Colors.black, fontSize: 13.0),),
                      ],
                    ),
                  ),
                ),
                SizedBox(
                  height: 30.0,
                  child: TextButton(
                    onPressed: () {
                      setState(() {
                        isNetwork =! isNetwork;
                      });
                    },
                    style: ButtonStyle(
                      backgroundColor: WidgetStateProperty.all(isNetwork ? Color(0xFF4F6BFE).withAlpha(30) : Colors.grey[200]),
                      padding: WidgetStateProperty.all(EdgeInsets.symmetric(horizontal: 10.0)),
                    ),
                    child: Row(
                      spacing: 4.0,
                      children: [
                        Icon(Icons.travel_explore, color: isNetwork ? Color(0xFF4F6BFE) : Colors.black, size: 18.0,),
                        Text('聯網', style: TextStyle(color: isNetwork ? Color(0xFF4F6BFE) : Colors.black, fontSize: 13.0),),
                      ],
                    ),
                  ),
                ),
                Spacer(),
                SizedBox(
                  height: 30.0,
                  width: 30.0,
                  child: PopupMenuButton(
                    icon: Icon(Icons.add),
                    padding: EdgeInsets.zero,
                    tooltip: '',
                    offset: Offset(-35.0, 0),
                    constraints: BoxConstraints(maxWidth: 160),
                    color: Colors.white,
                    itemBuilder: (BuildContext context) {
                      return [
                        PopupMenuItem(value: 'camera', height: 40.0, child: Row(spacing: 5.0, children: [Icon(Icons.camera_alt_outlined), Text('拍照識文字')],)),
                        PopupMenuItem(value: 'image', height: 40.0, child: Row(spacing: 5.0, children: [Icon(Icons.image_outlined), Text('圖片識文字')],)),
                        PopupMenuItem(value: 'file', height: 40.0, child: Row(spacing: 5.0, children: [Icon(Icons.file_present_outlined), Text('文件')],)),
                      ];
                    },
                    onSelected: (value) {
                      debugPrint(value);
                    },
                  ),
                ),
                SizedBox(
                  height: 30.0,
                  width: 30.0,
                  child: IconButton(
                    onPressed: disabled ? null : () => handleSubmit(),
                    icon: loading ?
                      SizedBox(height: 16.0, width: 16.0, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2.0,))
                      :
                      Icon(Icons.send, color: Colors.white, size: 18.0)
                    ,
                    style: ButtonStyle(
                      backgroundColor: WidgetStateProperty.all(disabled ? Color(0xFF4F6BFE).withAlpha(100) : Color(0xFF4F6BFE)),
                      padding: WidgetStateProperty.all(EdgeInsets.zero)
                    ),
                    disabledColor: Colors.red,
                  ),
                )
              ],
            ),
          ],
        ),
      ),
    ],
  )
);

flutter3集成deepseek api流輸出

flutter通過dio請求deepseek對話大模型,實現stream流式輸出打字。

final response = await dio.post(
  '$baseURL/v1/chat/completions',
  options: Options(
    // 響應超時
    receiveTimeout: const Duration(seconds: 60),
    headers: {
      "Content-Type": "application/json",
      "Authorization": "Bearer $apiKEY",
    },
    // 設置響應類型為流式響應
    responseType: ResponseType.stream,
  ),
  data: {
    // 多輪會話
    'messages': widget.multiConversation ? chatStore.historySession : [{'role': 'user', 'content': editorValue}],
    'model': 'deepseek-chat', // deepseek-chat對話模型 deepseek-reasoner推理模型
    'stream': true, // 流式輸出
    'max_tokens': 8192, // 限制一次請求中模型生成 completion 的最大 token 數(默認使用 4096)
    'temperature': 0.4, // 嚴謹採樣 越低越嚴謹(默認1)
  }
);

flutter3自定義托盤管理

項目中採用 system_tray 組件來自定義系統托盤圖標。

// 創建系統托盤圖標
Future<void> initSystemTray() async {
  String trayIco = 'assets/images/tray.ico';
  SystemTray systemTray = SystemTray();

  // 初始化系統托盤
  await systemTray.initSystemTray(
    title: 'system-tray',
    iconPath: trayIco,
  );

  // 右鍵菜單
  final Menu menu = Menu();
  await menu.buildFrom([
    MenuItemLabel(label: '打開主界面', image: 'assets/images/tray.ico', onClicked: (menuItem) async => await windowManager.show()),
    MenuItemLabel(label: '隱藏窗口', image: 'assets/images/tray.ico', onClicked: (menuItem) async => await windowManager.hide()),
    MenuItemLabel(label: '設置中心', image: 'assets/images/tray.ico', onClicked: (menuItem) => Get.toNamed('/setting')),
    MenuItemLabel(label: '鎖屏', image: 'assets/images/tray.ico', onClicked: (menuItem) => {}),
    MenuItemLabel(label: '關閉程序並退出', image: 'assets/images/tray.ico', onClicked: (menuItem) async => await windowManager.destroy()),
  ]);
  await systemTray.setContextMenu(menu);

  // 右鍵事件
  systemTray.registerSystemTrayEventHandler((eventName) async {
    debugPrint('eventName: $eventName');
    if (eventName == kSystemTrayEventClick) {
      Platform.isWindows ? await windowManager.show() : systemTray.popUpContextMenu();
    } else if (eventName == kSystemTrayEventRightClick) {
      Platform.isWindows ? systemTray.popUpContextMenu() : await windowManager.show();
    }
  });
}

好了,以上就是Flutter3.32接入DeepSeek搭建客户端ai流式對話項目的一些分享,希望對大家有所幫助~💪

Tauri2.0-DeepSeek電腦端Ai對話|tauri2+vite6+deepseek流式ai聊天系統

附上幾個最新實戰項目案例

flutter3-deepseek流式AI模板|Flutter3.27+Dio+DeepSeeek聊天ai助手

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

vue3-webseek網頁版AI問答|Vite6+DeepSeek+Arco流式ai聊天打字效果

Electron35-DeepSeek桌面端AI系統|vue3.5+electron+arco客户端ai模板

Vue3-DeepSeek-Chat流式AI對話|vite6+vant4+deepseek智能ai聊天助手

flutter3-dymall仿抖音直播商城|Flutter3.27短視頻+直播+聊天App實例

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

Tauri2.0-Vue3OS桌面端os平台|tauri2+vite6+arco電腦版OS管理系統

tauri2.0-admin桌面端後台系統|Tauri2+Vite5+ElementPlus管理後台EXE程序

Vite5+Electron聊天室|electron31跨平台仿微信EXE客户端|vue3聊天程序

uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天語音/朋友圈

user avatar xiangzhihong 頭像 youbeiputao 頭像 flutterdev 頭像
點贊 3 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.