提交 02c8e358 authored 作者: songchuancai's avatar songchuancai

对接应用聊天接口

上级 94555935
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "chatGPT-chatbox-flutter-main",
"request": "launch",
"type": "dart"
},
{
"name": "chatGPT-chatbox-flutter-main (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "chatGPT-chatbox-flutter-main (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}
\ No newline at end of file
...@@ -192,7 +192,7 @@ class _HomePageState extends State<HomePage> { ...@@ -192,7 +192,7 @@ class _HomePageState extends State<HomePage> {
if (kIsWeb) { if (kIsWeb) {
// 设置语速 // 设置语速
await flutterTts.setSpeechRate(3); await flutterTts.setSpeechRate(1);
// 音调 // 音调
......
import 'package:allen/home_page.dart'; import 'package:allen/home_page.dart';
import 'package:allen/pallete.dart'; import 'package:allen/pallete.dart';
import 'package:allen/providers.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:allen/pages/login_page.dart'; import 'package:allen/pages/login_page.dart';
import 'package:allen/services/storage_service.dart'; import 'package:allen/services/storage_service.dart';
import 'package:allen/models/user.dart'; import 'package:allen/models/user.dart';
import 'package:allen/models/app_item.dart'; import 'package:allen/models/app_item.dart';
import 'package:allen/pages/chat_page.dart'; import 'package:allen/pages/chat_page.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp()); final prefs = await SharedPreferences.getInstance();
runApp(
ProviderScope(
overrides: [
sharedPreferencesProvider.overrideWithValue(prefs),
],
child: const MyApp(),
),
);
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
...@@ -33,6 +54,7 @@ class MyApp extends StatelessWidget { ...@@ -33,6 +54,7 @@ class MyApp extends StatelessWidget {
if (snapshot.connectionState == ConnectionState.waiting) { if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator(); return const CircularProgressIndicator();
} }
return snapshot.hasData ? const HomePage() : const LoginPage(); return snapshot.hasData ? const HomePage() : const LoginPage();
}, },
), ),
...@@ -40,21 +62,25 @@ class MyApp extends StatelessWidget { ...@@ -40,21 +62,25 @@ class MyApp extends StatelessWidget {
if (settings.name == '/home') { if (settings.name == '/home') {
return MaterialPageRoute(builder: (context) => const HomePage()); return MaterialPageRoute(builder: (context) => const HomePage());
} }
if (settings.name == '/login') { if (settings.name == '/login') {
return MaterialPageRoute(builder: (context) => const LoginPage()); return MaterialPageRoute(builder: (context) => const LoginPage());
} }
if (settings.name == '/chat') { if (settings.name == '/chat') {
final args = settings.arguments; final args = settings.arguments;
if (args is AppItem) { if (args is AppItem) {
return MaterialPageRoute( return MaterialPageRoute(
builder: (context) => ChatPage(app: args), builder: (context) => ChatPage(app: args),
); );
} }
return MaterialPageRoute(builder: (context) => const HomePage()); return MaterialPageRoute(builder: (context) => const HomePage());
} }
return MaterialPageRoute(builder: (context) => const HomePage()); return MaterialPageRoute(builder: (context) => const HomePage());
}, },
); );
} }
} }
\ No newline at end of file
class AppItem { class AppItem {
final String id;
final String name; final String name;
final String description; final String description;
final String iconUrl; final String iconUrl;
...@@ -8,6 +9,7 @@ class AppItem { ...@@ -8,6 +9,7 @@ class AppItem {
final bool isDefault; final bool isDefault;
AppItem({ AppItem({
required this.id,
required this.name, required this.name,
required this.description, required this.description,
required this.iconUrl, required this.iconUrl,
...@@ -19,6 +21,7 @@ class AppItem { ...@@ -19,6 +21,7 @@ class AppItem {
factory AppItem.fromJson(Map<String, dynamic> json) { factory AppItem.fromJson(Map<String, dynamic> json) {
return AppItem( return AppItem(
id: json['id'] ?? '',
name: json['name'] ?? '', name: json['name'] ?? '',
description: json['description'] ?? '', description: json['description'] ?? '',
iconUrl: json['icon_url'] ?? '', iconUrl: json['icon_url'] ?? '',
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../services/api_service.dart';
import '../services/apps_service.dart'; import '../services/apps_service.dart';
import '../models/app_item.dart'; import '../models/app_item.dart';
import '../pallete.dart'; import '../pallete.dart';
import '../services/storage_service.dart'; import '../services/storage_service.dart';
import '../models/user.dart'; import '../models/user.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AppsPage extends StatefulWidget { class AppsPage extends StatefulWidget {
const AppsPage({super.key}); const AppsPage({super.key});
...@@ -14,26 +22,36 @@ class AppsPage extends StatefulWidget { ...@@ -14,26 +22,36 @@ class AppsPage extends StatefulWidget {
class _AppsPageState extends State<AppsPage> { class _AppsPageState extends State<AppsPage> {
late final AppsService _appsService; late final AppsService _appsService;
List<AppItem> apps = []; List<AppItem> apps = [];
bool isLoading = true; bool isLoading = true;
String? error; String? error;
bool _isLoadingMore = false; bool _isLoadingMore = false;
int _currentPage = 1; int _currentPage = 1;
bool _hasMoreData = true; bool _hasMoreData = true;
final ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
static const int _pageSize = 4; static const int _pageSize = 4;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initializeService(); _initializeService();
_scrollController.addListener(_onScroll); _scrollController.addListener(_onScroll);
} }
@override @override
void dispose() { void dispose() {
_scrollController.dispose(); _scrollController.dispose();
super.dispose(); super.dispose();
} }
...@@ -62,6 +80,7 @@ class _AppsPageState extends State<AppsPage> { ...@@ -62,6 +80,7 @@ class _AppsPageState extends State<AppsPage> {
} else { } else {
setState(() { setState(() {
apps.addAll(newApps); apps.addAll(newApps);
_currentPage++; _currentPage++;
}); });
} }
...@@ -76,7 +95,9 @@ class _AppsPageState extends State<AppsPage> { ...@@ -76,7 +95,9 @@ class _AppsPageState extends State<AppsPage> {
Future<void> _initializeService() async { Future<void> _initializeService() async {
final User? user = await StorageService.getUser(); final User? user = await StorageService.getUser();
_appsService = AppsService(token: user?.token); _appsService = AppsService(token: user?.token);
fetchApps(); fetchApps();
} }
...@@ -86,15 +107,20 @@ class _AppsPageState extends State<AppsPage> { ...@@ -86,15 +107,20 @@ class _AppsPageState extends State<AppsPage> {
page: 1, page: 1,
pageSize: _pageSize, pageSize: _pageSize,
); );
setState(() { setState(() {
apps = appsList; apps = appsList;
isLoading = false; isLoading = false;
_currentPage = 1; _currentPage = 1;
_hasMoreData = appsList.length >= _pageSize; _hasMoreData = appsList.length >= _pageSize;
}); });
} catch (e) { } catch (e) {
setState(() { setState(() {
error = e.toString(); error = e.toString();
isLoading = false; isLoading = false;
}); });
} }
...@@ -186,4 +212,33 @@ class _AppsPageState extends State<AppsPage> { ...@@ -186,4 +212,33 @@ class _AppsPageState extends State<AppsPage> {
), ),
); );
} }
// Future<void> _onAppTap(AppItem app) async {
// try {
// final apiService = ApiService();
// final storageService =
// StorageService(await SharedPreferences.getInstance());
// final workbenchToken = await apiService.getWorkbenchToken(app.id);
// // 存储token
// await storageService.setWorkbenchToken(workbenchToken);
// if (context.mounted) {
// Navigator.pushNamed(
// context,
// '/chat',
// arguments: app,
// );
// }
// } catch (e) {
// if (context.mounted) {
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(content: Text('进入聊天失败: $e')),
// );
// }
// }
// }
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/app_item.dart'; import '../models/app_item.dart';
import '../services/storage_service.dart';
import '../home_page.dart'; import '../home_page.dart';
class ChatPage extends StatelessWidget { import '../services/api_service.dart';
class ChatPage extends ConsumerStatefulWidget {
final AppItem app; final AppItem app;
const ChatPage({super.key, required this.app}); const ChatPage({super.key, required this.app});
@override @override
ConsumerState<ChatPage> createState() => _ChatPageState();
}
class _ChatPageState extends ConsumerState<ChatPage> {
@override
void initState() {
super.initState();
_initChat();
}
Future<void> _initChat() async {
try {
final apiService = ApiService();
final workbenchToken = await apiService.getWorkbenchToken(widget.app.id);
final prefs = await SharedPreferences.getInstance();
final storageService = StorageService(prefs);
await storageService.saveWorkbenchToken(workbenchToken);
} catch (e) {
debugPrint('初始化聊天失败: $e');
}
}
@override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
...@@ -17,14 +53,14 @@ class ChatPage extends StatelessWidget { ...@@ -17,14 +53,14 @@ class ChatPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
app.name, widget.app.name,
style: const TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text( Text(
app.description, widget.app.description,
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
...@@ -38,9 +74,9 @@ class ChatPage extends StatelessWidget { ...@@ -38,9 +74,9 @@ class ChatPage extends StatelessWidget {
), ),
), ),
body: HomePage( body: HomePage(
customTitle: app.name, customTitle: widget.app.name,
customDescription: app.description, customDescription: widget.app.description,
customImageUrl: app.iconUrl, customImageUrl: widget.app.iconUrl,
hideNavigation: true, hideNavigation: true,
), ),
); );
......
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'services/api_service.dart';
import 'services/storage_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
final apiServiceProvider = Provider<ApiService>((ref) => ApiService());
final sharedPreferencesProvider = Provider<SharedPreferences>((ref) {
throw UnimplementedError();
});
final storageServiceProvider = Provider<StorageService>((ref) {
final prefs = ref.watch(sharedPreferencesProvider);
return StorageService(prefs);
});
const openAIAPIKey = 'sk-zV0MPjPserDD4gdQ8lE8aUGwxayOwuayogGidos4VO8uxdDL'; const openAIAPIKey = 'sk-zV0MPjPserDD4gdQ8lE8aUGwxayOwuayogGidos4VO8uxdDL';
const baseUrl = 'https://knowledge-web.apps.iytcloud.com/console/api'; const baseUrl = 'https://knowledge-web.apps.iytcloud.com';
import 'dart:convert'; import 'dart:convert';
import 'package:allen/services/storage_service.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../models/user.dart';
import '../secrets.dart'; import '../secrets.dart';
class ApiService { class ApiService {
static Future<Map<String, dynamic>> login( static Future<Map<String, dynamic>> login(
String email, String password) async { String email, String password) async {
final response = await http.post( final response = await http.post(
Uri.parse('$baseUrl/login/'), Uri.parse('$baseUrl/console/api/login/'),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json', 'Accept': 'application/json',
...@@ -19,4 +23,30 @@ class ApiService { ...@@ -19,4 +23,30 @@ class ApiService {
return jsonDecode(response.body); return jsonDecode(response.body);
} }
Future<String> getWorkbenchToken(String appId) async {
try {
User? user = await StorageService.getUser();
String token = user?.token ?? '';
final response = await http.post(
Uri.parse('$baseUrl/console/api/apps/workbench'),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
},
body: jsonEncode({
'app_id': appId,
}),
);
if (response.statusCode == 200) {
return jsonDecode(response.body)['data'];
}
throw Exception('获取会话token失败');
} catch (e) {
throw Exception('获取会话token失败: $e');
}
}
} }
...@@ -10,7 +10,7 @@ class AppsService { ...@@ -10,7 +10,7 @@ class AppsService {
Future<List<AppItem>> getApps({int page = 1, int pageSize = 4}) async { Future<List<AppItem>> getApps({int page = 1, int pageSize = 4}) async {
final response = await http.get( final response = await http.get(
Uri.parse('$baseUrl/apps/?page=$page&pageSize=$pageSize'), Uri.parse('$baseUrl/console/api/apps/?page=$page&pageSize=$pageSize'),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json', 'Accept': 'application/json',
......
import 'dart:convert'; import 'dart:convert';
import 'package:allen/services/storage_service.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import '../secrets.dart'; import '../secrets.dart';
class OpenAIService { class OpenAIService {
final String apiKey = 'sk-OVjS7VE9mT68Uvg7kSFoMnbU6EU836FO'; // final String apiKey = 'sk-OVjS7VE9mT68Uvg7kSFoMnbU6EU836FO';
final String appKey = 'app-FRP2s2wSx01rsE67'; // final String appKey = 'app-FRP2s2wSx01rsE67';
String? conversationId; String? conversationId;
Stream<String> chatGPTAPI(String message) async* { Stream<String> chatGPTAPI(String message) async* {
final client = http.Client(); final client = http.Client();
var buffer = StringBuffer(); var buffer = StringBuffer();
var prefs = await SharedPreferences.getInstance();
var storageService = StorageService(prefs);
String appKey = storageService.getWorkbenchToken() ?? '';
try { try {
final request = http.Request('POST', Uri.parse('$baseUrl/openapi/chat')); final request =
http.Request('POST', Uri.parse('$baseUrl/api/chat-messages'));
request.headers.addAll({ request.headers.addAll({
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': 'Bearer $apiKey', 'Authorization': 'Bearer $appKey',
}); });
Map<String, dynamic> requestBody = { Map<String, dynamic> requestBody = {
'app_key': appKey, 'inputs': {},
'query': message, 'query': message,
'stream': true, 'response_mode': 'streaming',
}; };
if (conversationId != null) { if (conversationId != null) {
......
import 'dart:convert'; import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import '../models/conversation.dart'; import '../models/conversation.dart';
import 'package:allen/models/user.dart'; import 'package:allen/models/user.dart';
class StorageService { class StorageService {
static const String _conversationsKey = 'conversations'; static const String _conversationsKey = 'conversations';
final SharedPreferences _prefs; final SharedPreferences _prefs;
StorageService(this._prefs); StorageService(this._prefs);
Future<List<Conversation>> getConversations() async { Future<List<Conversation>> getConversations() async {
final String? data = _prefs.getString(_conversationsKey); final String? data = _prefs.getString(_conversationsKey);
if (data == null) return []; if (data == null) return [];
List<dynamic> jsonList = json.decode(data); List<dynamic> jsonList = json.decode(data);
return jsonList.map((json) => Conversation.fromJson(json)).toList(); return jsonList.map((json) => Conversation.fromJson(json)).toList();
} }
...@@ -21,28 +27,36 @@ class StorageService { ...@@ -21,28 +27,36 @@ class StorageService {
final String data = json.encode( final String data = json.encode(
conversations.map((conv) => conv.toJson()).toList(), conversations.map((conv) => conv.toJson()).toList(),
); );
await _prefs.setString(_conversationsKey, data); await _prefs.setString(_conversationsKey, data);
} }
Future<void> addConversation(Conversation conversation) async { Future<void> addConversation(Conversation conversation) async {
final conversations = await getConversations(); final conversations = await getConversations();
conversations.insert(0, conversation); conversations.insert(0, conversation);
await saveConversations(conversations); await saveConversations(conversations);
} }
Future<void> updateConversation(Conversation conversation) async { Future<void> updateConversation(Conversation conversation) async {
final conversations = await getConversations(); final conversations = await getConversations();
final index = final index =
conversations.indexWhere((conv) => conv.id == conversation.id); conversations.indexWhere((conv) => conv.id == conversation.id);
if (index != -1) { if (index != -1) {
conversations[index] = conversation; conversations[index] = conversation;
await saveConversations(conversations); await saveConversations(conversations);
} }
} }
Future<void> deleteConversation(String id) async { Future<void> deleteConversation(String id) async {
final conversations = await getConversations(); final conversations = await getConversations();
conversations.removeWhere((conv) => conv.id == id); conversations.removeWhere((conv) => conv.id == id);
await saveConversations(conversations); await saveConversations(conversations);
} }
...@@ -50,18 +64,37 @@ class StorageService { ...@@ -50,18 +64,37 @@ class StorageService {
static Future<void> saveUser(User user) async { static Future<void> saveUser(User user) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.setString(_userKey, jsonEncode(user.toJson())); await prefs.setString(_userKey, jsonEncode(user.toJson()));
} }
static Future<User?> getUser() async { static Future<User?> getUser() async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final userJson = prefs.getString(_userKey); final userJson = prefs.getString(_userKey);
if (userJson == null) return null; if (userJson == null) return null;
return User.fromJson(jsonDecode(userJson)); return User.fromJson(jsonDecode(userJson));
} }
static Future<void> clearUser() async { static Future<void> clearUser() async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.remove(_userKey); await prefs.remove(_userKey);
} }
static const String _workbenchTokenKey = 'workbench_token';
Future<void> setWorkbenchToken(String token) async {
await _prefs.setString(_workbenchTokenKey, token);
}
String? getWorkbenchToken() {
return _prefs.getString(_workbenchTokenKey);
}
Future<void> saveWorkbenchToken(String token) async {
await _prefs.setString(_workbenchTokenKey, token);
}
} }
...@@ -190,6 +190,14 @@ packages: ...@@ -190,6 +190,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.6.23" version: "0.6.23"
flutter_riverpod:
dependency: "direct main"
description:
name: flutter_riverpod
sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.6.1"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
...@@ -392,6 +400,14 @@ packages: ...@@ -392,6 +400,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.8" version: "2.1.8"
riverpod:
dependency: transitive
description:
name: riverpod
sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.6.1"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -501,6 +517,14 @@ packages: ...@@ -501,6 +517,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.11.1" version: "1.11.1"
state_notifier:
dependency: transitive
description:
name: state_notifier
sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.0"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
......
name: allen name: allen
description: A new Flutter project. description: A new Flutter project.
# The following line prevents the package from being accidentally published to # The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages. # pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application. # The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43 # A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +. # followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter # Both the version and the builder number may be overridden in flutter
...@@ -19,80 +21,278 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev ...@@ -19,80 +21,278 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
sdk: '>=2.19.5 <3.0.0' sdk: '>=2.19.5 <3.0.0'
# Dependencies specify other packages that your package needs in order to work. # Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions # To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively, # consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to # dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer # the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`. # versions available, run `flutter pub outdated`.
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
http: ^1.1.0 http: ^1.1.0
flutter_riverpod: ^2.5.1
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
speech_to_text: ^6.1.1 speech_to_text: ^6.1.1
flutter_tts: ^3.6.3 flutter_tts: ^3.6.3
animate_do: ^3.0.2 animate_do: ^3.0.2
shared_preferences: ^2.0.15 shared_preferences: ^2.0.15
uuid: ^4.3.3 uuid: ^4.3.3
flutter_markdown: ^0.6.18 flutter_markdown: ^0.6.18
flutter_highlight: ^0.7.0 flutter_highlight: ^0.7.0
markdown: ^7.1.1 markdown: ^7.1.1
audioplayers: ^5.2.1 audioplayers: ^5.2.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to # The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is # encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your # activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint # package. See that file for information about deactivating specific lint
# rules and activating additional ones. # rules and activating additional ones.
flutter_lints: ^2.0.0 flutter_lints: ^2.0.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages. # The following section is specific to Flutter packages.
flutter: flutter:
# The following line ensures that the Material Icons font is # The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in # included with your application, so that you can use the icons in
# the material Icons class. # the material Icons class.
uses-material-design: true uses-material-design: true
# To add assets to your application, add an assets section, like this: # To add assets to your application, add an assets section, like this:
assets: assets:
- assets/images/ - assets/images/
- assets/sounds/ - assets/sounds/
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware # https://flutter.dev/assets-and-images/#resolution-aware
# For details regarding adding assets from package dependencies, see # For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages # https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here, # To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a # in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a # "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For # list giving the asset and other descriptors for the font. For
# example: # example:
fonts: fonts:
- family: Cera Pro - family: Cera Pro
fonts: fonts:
- asset: assets/fonts/Cera-Pro-Bold.otf - asset: assets/fonts/Cera-Pro-Bold.otf
- asset: assets/fonts/Cera-Pro-Medium.otf - asset: assets/fonts/Cera-Pro-Medium.otf
# - family: Trajan Pro # - family: Trajan Pro
# fonts: # fonts:
# - asset: fonts/TrajanPro.ttf # - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf # - asset: fonts/TrajanPro_Bold.ttf
# weight: 700 # weight: 700
# #
# For details regarding fonts from package dependencies, # For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages # see https://flutter.dev/custom-fonts/#from-packages
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论