一文带你轻松入门Flutter开发

农民  金牌会员 | 2025-2-19 10:28:21 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 871|帖子 871|积分 2613

一、Flutter 简介


Flutter 是谷歌推出的一款开源 UI 框架,旨在帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web、桌面和嵌入式平台等多种平台的开发。其核心上风在于跨平台特性和高性能表现。
Flutter 的跨平台本领使其可以或许在 iOS 和 Android 等主流平台上运行,乃至通过第三方扩展还可支持 MacOS、Windows 以及谷歌的 Fuchsia 操作系统等,这极大地减少了开发本钱,让开发者无需为差别平台编写大量重复代码,而是专注于业务逻辑和用户体验的优化。
在性能方面,Flutter 使用 Skia 图形引擎进行渲染,结合硬件加速,可以或许实现流畅的动画结果和快速的响应速率,其性能表现与原生应用相差无几,乃至在某些场景下超越原生应用,为用户带来平滑而自然的滑动结果和出色的平台感知体验。比方,在一些复杂的 UI 结构和动画展示场景中,Flutter 可以或许保持稳定的帧率,确保应用的流畅性。
别的,Flutter 的热重载功能也是其一大亮点。在开发过程中,应用代码更改可以实时反映到运行的应用步伐中,无需重启应用,这使得开发者可以或许敏捷查看代码更改后的结果,极大地进步了开发服从,降低了调试本钱,让开发流程更加高效便捷。
越来越多的企业和开发者选择 Flutter 进行开发,如腾讯的微信、QQ、QQ 邮箱,阿里的闲鱼、淘宝等。这得益于其丰富的 UI 组件库,开发者可以轻松构建出各种精美的界面,满意差别的设计需求;同时,Flutter 还支持与现有代码集成,方便开发者在已有项目底子上进行扩展和升级,这对于追求高效开发和优质用户体验的项目来说,无疑是一个极具吸引力的选择,使得 Flutter 在众多跨平台开发框架中脱颖而出,成为当下热门的开发工具之一。
二、开发环境搭建


2.1 安装 Flutter SDK

访问 Flutter 官方网站(https://flutter.dev/docs/get-started/install),根据操作系统选择相应的 Flutter SDK 下载链接进行下载。由于网络原因,大概下载速率较慢,国内开发者也可使用清华大学的镜像源(https://mirrors.tuna.tsinghua.edu.cn/flutter/)进行下载,以进步下载服从。下载完成后,将压缩包解压到指定目录,比方在 Windows 系统下,可解压到 “C:\flutter” 目录;在 macOS 系统下,可解压到 “~/development/flutter” 目录。
解压完成后,需要将 Flutter SDK 的路径添加到系统环境变量中,以便在任何位置都能使用 Flutter 下令。以 Windows 系统为例,右键点击 “此电脑”,选择 “属性”,在弹出的窗口中点击 “高级系统设置”,然后在 “系统属性” 窗口的 “高级” 选项卡下,点击 “环境变量” 按钮。在 “系统变量” 列表中找到 “Path” 变量,点击 “编辑” 按钮,在弹出的编辑窗口中点击 “新建”,将 Flutter SDK 的 “bin” 目录路径(如 “C:\flutter\bin”)添加进去,然后依次点击 “确定” 生存设置。在 macOS 系统下,打开终端,使用文本编辑器(如 vim 或 nano)打开 “~/.bash_profile” 或 “~/.zshrc” 文件(取决于你使用的默认 Shell),添加以下内容:
  1. export PATH="$PATH:/Users/your_username/development/flutter/bin"
复制代码
将 “your_username” 替换为你的实际用户名,生存文件后,在终端中实验 “source ~/.bash_profile” 或 “source ~/.zshrc” 使环境变量见效。
2.2 安装 Dart SDK

Flutter 基于 Dart 语言开发,在安装 Flutter SDK 时,通常会主动安装 Dart SDK。但假如需要手动安装 Dart SDK,可以访问 Dart 官方网站(https://dart.dev/get-dart),根据操作系统选择合适的下载链接进行下载和安装。安装完成后,同样需要将 Dart SDK 的 “bin” 目录路径添加到系统环境变量中,以便可以或许在下令行中使用 Dart 相关下令。
2.3 设置 Android SDK

Flutter 开发需要使用 Android SDK 来构建和运行 Android 应用。确保安装了最新版本的 Android SDK,可以通过 Android Studio 进行安装。打开 Android Studio,在接待界面中选择 “Configure”,然后点击 “SDK Manager”,在弹出的 “SDK Platforms” 选项卡中,确保选中了最新的 Android 版本(如 Android 13.0)以及 “Android SDK Platform-Tools” 和 “Android SDK Build-Tools” 等须要的组件,点击 “Apply” 按钮进行安装。安装完成后,还需要配置 Android SDK 的环境变量。在 Windows 系统下,右键点击 “此电脑”,选择 “属性”,进入 “高级系统设置”,点击 “环境变量”,在 “系统变量” 中新建一个名为 “ANDROID_HOME” 的变量,变量值为 Android SDK 的安装目录(如 “C:\Users\your_username\AppData\Local\Android\Sdk”),然后在 “Path” 变量中添加 “% ANDROID_HOME%\tools” 和 “% ANDROID_HOME%\platform-tools”。在 macOS 系统下,打开终端,使用文本编辑器打开 “~/.bash_profile” 或 “~/.zshrc” 文件,添加以下内容:
  1. export ANDROID_HOME=$HOME/Library/Android/sdk
  2. export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
复制代码
生存文件后,在终端中实验 “source ~/.bash_profile” 或 “source ~/.zshrc” 使环境变量见效。
2.4 配置 IDE



  • 使用 VS Code 进行开发:起首,确保已经安装了 VS Code(https://code.visualstudio.com/)。打开 VS Code,在左侧的扩展栏中搜刮 “Flutter” 插件并安装,安装完成后,VS Code 会主动提示安装相关的 Dart 插件。安装完成后,按下 “Ctrl + Shift + P”(Windows/Linux)或 “Command + Shift + P”(macOS)组合键,打开下令面板,输入 “Flutter: Select SDK”,选择之前安装的 Flutter SDK 路径,即可完成配置。
  • 使用 Android Studio 进行开发:打开 Android Studio,在接待界面中选择 “Configure”,然后点击 “Plugins”,在插件市场中搜刮 “Flutter” 插件并安装,安装完成后,Android Studio 会主动配置 Flutter SDK 路径。假如主动配置失败,可以手动配置,在 “Settings”(Windows/Linux)或 “Preferences”(macOS)中,找到 “Languages & Frameworks” 下的 “Flutter” 选项,将 Flutter SDK 的路径设置为之前解压的 Flutter SDK 目录。
2.5 配置模仿器

为了在开发过程中方便测试应用,需要安装 Android 或 iOS 模仿器环境。对于 Android 模仿器,可以使用 Android Studio 自带的 AVD Manager 来创建和管理假造设备。在 Android Studio 中,点击 “Tools” 菜单,选择 “AVD Manager”,在弹出的窗口中点击 “Create Virtual Device” 按钮,选择所需的设备类型(如 Pixel 系列)和系统版本(如 Android 13.0),然后按照提示完成假造设备的创建。创建完成后,在 AVD Manager 中选择要启动的假造设备,点击 “Play” 按钮即可启动模仿器。
对于 iOS 模仿器,需要在安装了 Xcode 的 macOS 系统上进行操作。打开 Xcode,点击 “Xcode” 菜单,选择 “Open Developer Tool”,然后选择 “Simulator”,在模仿器中可以选择差别的 iOS 设备类型(如 iPhone 14 Pro)和系统版本(如 iOS 16.0)进行测试。
三、第一个 Flutter 应用


3.1 创建项目

我们可以通过下令行或 IDE(如 Android Studio、VS Code)来创建 Flutter 项目。使用下令行创建时,在终端中实验以下下令:
  1. flutter create my_flutter_app
复制代码
此中 “my_flutter_app” 为项目名称,你可以根据实际需求进行修改。实验该下令后,Flutter 会主动创建一个包罗基本结构和文件的项目目录。
若使用 Android Studio 创建项目,起首打开 Android Studio,在接待界面中选择 “New Project”,然后在弹出的窗口中选择 “Flutter” 项目类型,接着按照向导填写项目名称、项目路径等信息,最后点击 “Finish” 按钮,Android Studio 将主动创建并配置好 Flutter 项目。
3.2 运行项目

项目创建完成后,进入项目目录,在终端中实验以下下令来运行项目:
  1. cd my_flutter_app
  2. flutter run
复制代码
“cd my_flutter_app” 用于切换到项目目录,“flutter run” 则启动项目并在默认的模仿器或毗连的设备上运行。假如你的电脑毗连了多个设备或模仿器,大概需要指定运行的目标设备,可以使用 “-d” 参数来指定设备 ID,比方:
  1. flutter run -d emulator-5554
复制代码
这里 “emulator-5554” 是设备的 ID,你可以通过 “flutter devices” 下令查看已毗连的设备及其 ID。
在运行项目时,有时大概会遇到项目卡在 “Initializing gradle…” 的环境,这通常是由于网络题目导致 Gradle 下载依赖包痴钝或失败。解决方法可以是更换 Gradle 的下载源,在项目标 “android/build.gradle” 文件中,将 “google ()” 和 “mavenCentral ()” 等源替换为国内的镜像源,比方:
  1. maven { url 'https://maven.aliyun.com/repository/google' }
  2. maven { url 'https://maven.aliyun.com/repository/jcenter' }
复制代码
然后重新运行项目。
3.3 分析代码结构

Flutter 项目创建后,会生成一些特定的目录和文件。此中,“android” 目录存放与 Android 平台相关的代码,如 AndroidManifest.xml、build.gradle 等文件,用于构建和配置 Android 版本的应用;“ios” 目录则存放与 iOS 平台相关的代码,包括 Xcode 项目文件和相关配置,用于构建 iOS 应用;“lib” 目录是我们重要编写 Flutter 代码的地方,通常会有一个 “main.dart” 文件,它是整个 Flutter 应用的入口文件;“test” 目录用于存放测试代码,方便我们对应用的功能进行单元测试和集成测试;“pubspec.yaml” 是项目标配置文件,类似于其他项目中的 package.json 文件,用于管理项目标依赖库和资源文件等。
下面重点分析 “main.dart” 文件中的代码结构和功能。起首,代码会导入 “package:flutter/material.dart” 库,这是 Flutter 的核心 UI 组件库,提供了丰富的预定义组件,如 Text、Button、ListView 等,用于构建应用的界面。
接着,定义了一个 “main” 函数,它是 Dart 语言的步伐入口点,在 Flutter 应用中,“main” 函数通常会调用 “runApp” 函数,并传入一个根组件作为参数,比方:
  1. void main() {
  2.   runApp(const MyApp());
  3. }
复制代码
这里的 “MyApp” 类是我们自定义的根组件,它继承自 “StatelessWidget” 或 “StatefulWidget”。“StatelessWidget” 实用于无状态的组件,即组件的 UI 在其生命周期内不会发生变化;而 “StatefulWidget” 实用于有状态的组件,其 UI 会根据内部状态的改变而更新。
以 “StatelessWidget” 为例,通常会重写 “build” 方法,该方法返回一个代表 UI 结构的 Widget 树,比方:
  1. class MyApp extends StatelessWidget {
  2.   const MyApp({Key? key}) : super(key: key);
  3.   @override
  4.   Widget build(BuildContext context) {
  5.     return MaterialApp(
  6.       title: 'My Flutter App',
  7.       home: Scaffold(
  8.         appBar: AppBar(
  9.           title: const Text('My First Flutter App'),
  10.         ),
  11.         body: const Center(
  12.           child: Text('Hello, World!'),
  13.         ),
  14.       ),
  15.     );
  16.   }
  17. }
复制代码
在上述代码中,“MaterialApp” 是一个常用的根组件,它提供了应用的基本结构和主题配置等功能;“Scaffold” 是一种结构组件,用于搭建页面的基本框架,包括顶部的 “AppBar”(应用栏)和主体的 “body” 部分;“Center” 是一个结构组件,用于将其子组件居中显示;“Text” 是用于显示文本的组件,这里显示了 “Hello, World!”。
通过如许的代码结构,我们可以构建出一个简朴的 Flutter 应用界面,展示一个带有标题栏和居中文本的页面,这是 Flutter 应用开发的底子结构,后续我们可以在此底子上进一步扩展和优化应用的功能和界面。
四、底子组件与结构


4.1 常用组件先容



  • Text:用于显示文本内容,通过 “text” 属性设置要显示的文本,“style” 属性可以设置文本的样式,如字体大小、颜色、粗细等。比方:
  1. Text(
  2.   'Hello, Flutter!',
  3.   style: TextStyle(
  4.     fontSize: 20,
  5.     color: Colors.blue,
  6.     fontWeight: FontWeight.bold
  7.   )
  8. )
复制代码


  • Container:一个多功能的容器组件,可设置子组件的大小、配景颜色、边距、内边距、边框等属性,用于包裹和装饰其他组件。比方:
  1. Container(
  2.   width: 100,
  3.   height: 100,
  4.   color: Colors.grey,
  5.   child: Text('Container Widget'),
  6.   margin: EdgeInsets.all(10),
  7.   padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
  8.   decoration: BoxDecoration(
  9.     border: Border.all(color: Colors.black, width: 2)
  10.   )
  11. )
复制代码


  • Button:Flutter 提供了多种按钮组件,如 “RaisedButton”(凸起按钮)、“FlatButton”(扁平按钮)、“IconButton”(图标按钮)等。以 “RaisedButton” 为例,通过 “onPressed” 属性设置按钮的点击变乱,“child” 属性设置按钮显示的内容。比方:
  1. RaisedButton(
  2.   onPressed: () {
  3.     // 按钮点击后的操作
  4.     print('Button Clicked');
  5.   },
  6.   child: Text('Click Me')
  7. )
复制代码


  • TextField:用于文本输入,可设置输入框的提示文本、键盘类型、输入限制等属性,通过 “controller” 属性获取输入框的文本内容。比方:
  1. TextField(
  2.   controller: _textController,
  3.   decoration: InputDecoration(
  4.     hintText: 'Enter text here',
  5.     border: OutlineInputBorder()
  6.   ),
  7.   keyboardType: TextInputType.text,
  8.   maxLength: 20
  9. )
复制代码
此中,“_textController” 是 “TextEditingController” 的实例,用于获取和控制输入框的文本。
4.2 结构技巧与实践



  • Row 和 Column:“Row” 用于水平排列子组件,“Column” 用于垂直排列子组件。在 “Row” 和 “Column” 中,可以使用 “mainAxisAlignment” 属性设置子组件在主轴上的对齐方式(如 “start”、“center”、“end”、“spaceBetween”、“spaceAround” 等),“crossAxisAlignment” 属性设置子组件在交叉轴上的对齐方式(如 “start”、“center”、“end”、“stretch” 等)。比方:
  1. Row(
  2.   mainAxisAlignment: MainAxisAlignment.spaceAround,
  3.   children: [
  4.     Container(width: 50, height: 50, color: Colors.red),
  5.     Container(width: 50, height: 50, color: Colors.green),
  6.     Container(width: 50, height: 50, color: Colors.blue)
  7.   ]
  8. )
  9. Column(
  10.   crossAxisAlignment: CrossAxisAlignment.center,
  11.   children: [
  12.     Container(width: 50, height: 50, color: Colors.yellow),
  13.     Container(width: 50, height: 50, color: Colors.purple),
  14.     Container(width: 50, height: 50, color: Colors.orange)
  15.   ]
  16. )
复制代码


  • Stack 和 Positioned:“Stack” 答应子组件堆叠在一起,“Positioned” 用于在 “Stack” 中准确控制子组件的位置。比方:
  1. Stack(
  2.   children: [
  3.     Container(width: 100, height: 100, color: Colors.grey),
  4.     Positioned(
  5.       left: 20,
  6.       top: 20,
  7.       child: Container(width: 50, height: 50, color: Colors.blue)
  8.     )
  9.   ]
  10. )
复制代码


  • Expanded 和 Flexible:“Expanded” 和 “Flexible” 用于在 “Row” 或 “Column” 中分配子组件的空间,使子组件可以或许根据剩余空间进行弹性扩展或收缩。“Expanded” 会尽大概占满剩余空间,而 “Flexible” 则根据 “flex” 属性的值来分配空间比例。比方:
  1. Row(
  2.   children: [
  3.     Expanded(
  4.       child: Container(color: Colors.red)
  5.     ),
  6.     Flexible(
  7.       flex: 2,
  8.       child: Container(color: Colors.green)
  9.     )
  10.   ]
  11. )
复制代码


  • ListView 和 GridView:“ListView” 用于创建垂直或水平的滚动列表,“GridView” 用于创建网格结构。可以使用 “ListView.builder” 和 “GridView.builder” 来高效地构建列表和网格,通过 “itemBuilder” 回调函数创建每个子项的组件,“itemCount” 属性设置子项的数量。比方:
  1. ListView.builder(
  2.   itemCount: 10,
  3.   itemBuilder: (context, index) {
  4.     return ListTile(
  5.       title: Text('Item $index')
  6.     );
  7.   }
  8. )
  9. GridView.builder(
  10.   gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  11.     crossAxisCount: 3
  12.   ),
  13.   itemCount: 9,
  14.   itemBuilder: (context, index) {
  15.     return Container(
  16.       color: Colors.grey[200],
  17.       child: Center(
  18.         child: Text('Grid Item $index')
  19.       )
  20.     );
  21.   }
  22. )
复制代码


  • SizedBox:用于在结构中添加空缺地区或指定固定大小的空间,通过 “width” 和 “height” 属性设置宽度和高度。比方:
  1. SizedBox(
  2.   width: 20,
  3.   height: 20
  4. )
复制代码
这些结构组件可以相互嵌套和组合,根据差别的设计需求构建出复杂而机动的用户界面结构,满意各种应用场景的要求,是 Flutter 结构设计的底子和关键。
五、状态管理底子


5.1 状态管理的重要性

状态管理在 Flutter 应用开发中占据着核心地位,对于构建复杂且高效的应用步伐至关重要。在 Flutter 的声明式 UI 编程范式下,UI 的呈现完全依赖于应用的状态,这意味着当应用状态发生变化时,UI 需要相应地进行更新以反映这些变化,从而确保用户界面与应用数据的一致性和同步性。
比方,在一个简朴的计数器应用中,计数器的值就是应用的一个状态。当用户点击 “增加” 按钮时,计数器的值会发生变化,这个状态的改变必须及时通报给 UI,使得界面上显示的计数器数字可以或许随之更新,否则用户将无法直观地看到操作的结果,应用的交互性和可用性将大打折扣。
良好的状态管理不仅可以或许保证 UI 与数据的实时同步,还对代码的可维护性和复用性有着显著的提升作用。它可以或许将业务逻辑与 UI 的更新逻辑分离开来,使得代码结构更加清晰,易于明确和修改。当应用规模徐徐扩大,功能日益复杂时,合理的状态管理机制可以避免状态与 UI 之间的精密耦合,降低代码的复杂度,进步开发服从,减少因状态处理不妥而引发的错误和调试难度,同时也方便其他开发者对代码进行维护和扩展,为项目标长期发展奠基坚固的底子。
5.2 简易状态管理方法

在 Flutter 中,有一种轻量且易于上手的状态管理方法,纵然用InheritedWidget。InheritedWidget是 Flutter 框架提供的一个底子类,它答应在 Widget 树中高效地共享数据,并在数据发生变化时关照依赖它的子 Widget 进行更新,从而实现简朴的状态管理功能。
以下是一个使用InheritedWidget进行状态管理的简朴示例:
  1. // 定义一个继承自InheritedWidget的类,用于存储和共享数据
  2. class AppData extends InheritedWidget {
  3.   final int counter;
  4.   AppData({required this.counter, required Widget child}) : super(child: child);
  5.   // 提供一个静态方法,方便子Widget获取AppData的实例
  6.   static AppData of(BuildContext context) {
  7.     return context.dependOnInheritedWidgetOfExactType<AppData>()!;
  8.   }
  9.   // 重写updateShouldNotify方法,用于判断是否需要通知子Widget更新
  10.   @override
  11.   bool updateShouldNotify(AppData oldWidget) {
  12.     return oldWidget.counter!= counter;
  13.   }
  14. }
  15. // 在Widget树的上层使用AppData来提供数据
  16. class MyApp extends StatelessWidget {
  17.   @override
  18.   Widget build(BuildContext context) {
  19.     return AppData(
  20.       counter: 0,
  21.       child: MaterialApp(
  22.         title: 'Flutter Demo',
  23.         home: MyHomePage(),
  24.       ),
  25.     );
  26.   }
  27. }
  28. // 在子Widget中获取并使用AppData中的数据
  29. class MyHomePage extends StatelessWidget {
  30.   @override
  31.   Widget build(BuildContext context) {
  32.     // 通过AppData.of方法获取AppData实例,进而获取计数器的值
  33.     int counter = AppData.of(context).counter;
  34.     return Scaffold(
  35.       appBar: AppBar(
  36.         title: Text('Flutter State Management'),
  37.       ),
  38.       body: Center(
  39.         child: Text('Counter: $counter'),
  40.       ),
  41.       floatingActionButton: FloatingActionButton(
  42.         onPressed: () {
  43.           // 模拟计数器增加的操作,这里可以根据实际需求修改AppData中的数据
  44.           // 为了简单起见,我们直接创建一个新的AppData实例,实际应用中可能需要更复杂的状态更新逻辑
  45.           Navigator.push(
  46.             context,
  47.             MaterialPageRoute(
  48.               builder: (context) => MyApp(
  49.                 counter: counter + 1,
  50.               ),
  51.             ),
  52.           );
  53.         },
  54.         tooltip: 'Increment',
  55.         child: Icon(Icons.add),
  56.       ),
  57.     );
  58.   }
  59. }
复制代码
在上述示例中,AppData类继承自InheritedWidget,用于存储一个计数器的值。在MyApp类中,我们将AppData作为根 Widget 的一部分,将计数器的初始值设置为0,并将其通报给MaterialApp和后续的 Widget 树。在MyHomePage类中,通过AppData.of(context)方法获取AppData的实例,从而获取计数器的值并显示在界面上。当点击FloatingActionButton时,我们通过Navigator.push方法创建一个新的页面,并将计数器的值增加1后通报给新的MyApp实例,从而实现了状态的更新和 UI 的相应变化。
这种基于InheritedWidget的状态管理方法固然简朴,但在一些简朴的应用场景中可以或许有用地实现数据的共享和状态的管理,帮助开发者初步明确和掌握 Flutter 中的状态管理概念和机制,为进一步学习和使用更复杂的状态管理方案(如 Provider、Bloc、Riverpod 等)奠基底子。
六、总结与展望


通过本文,我们对 Flutter 的入门知识有了较为全面的相识,从开发环境的搭建,到创建第一个应用,再到学习底子组件与结构以及状态管理的底子知识,每一步都是构建复杂 Flutter 应用的基石。
然而,这仅仅是 Flutter 开发的起点。在后续的学习和实践中,还有很多丰富而强大的功能等待我们去探索。比方,深入学习更多的组件和结构方式,以构建更加复杂和精美的用户界面;进一步掌握状态管理方案,如 Provider、Bloc、Riverpod 等,以便更好地处理应用中的数据和状态变化,提升应用的性能和可维护性;探索动画和网络哀求等高级功能,为应用增加更多的交互性和实时性。
为了继续深入学习 Flutter 开发,建议读者参考以下资源:


  • 官方文档:Flutter 官方网站提供了细致的文档,涵盖了从底子概念到高级特性的所有内容,是学习 Flutter 的权威资料。
  • 社区论坛:如 Stack Overflow、Flutter 社区等,开发者可以在这些论坛上提问、分享履历和获取解决方案,与其他开发者交流学习心得。
  • 相关书籍:比方《Flutter 实战》《Flutter 技能入门与实战》等,这些书籍对 Flutter 的知识进行了系统的整理和讲授,有助于读者深入明确和掌握 Flutter 开发技巧。
总之,Flutter 作为一款强大的跨平台开发框架,具有广阔的应用远景和发展潜力。希望本文可以或许引发读者对 Flutter 开发的兴趣,鼓励大家在这个范畴不绝探索和实践,开发出更加优秀的跨平台应用步伐。
   最后,本人页开源了一些基本的使用示例,可以看我往期文章:Flutter仿微信,高度还原、开源,内里有基本的组件用法、封装方法等……

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农民

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表