diff --git a/android/app/build.gradle b/android/app/build.gradle index 20188d5..c497b2d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -39,14 +39,24 @@ android { targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName +// multiDexEnabled true +// manifestPlaceholders = [ +// JPUSH_PKGNAME : applicationId, +// JPUSH_APPKEY : "", // NOTE: JPush 上注册的包名对应的 Appkey. +// JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可. +// ] } + buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug } +// debug { +// signingConfig signingConfigs.release +// } } } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 402f27a..d1a8d3b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ SizedBox(width: w); + + Widget get hb => SizedBox(height: w); +} \ No newline at end of file diff --git a/lib/extensions/string_extension.dart b/lib/extensions/string_extension.dart new file mode 100644 index 0000000..332e1d0 --- /dev/null +++ b/lib/extensions/string_extension.dart @@ -0,0 +1,71 @@ + + +import 'package:lpinyin/lpinyin.dart'; + +// import '../constants/api/api.dart'; + +extension ImageOnString on String? { + // String get imageWithHost => '${API.imageHost}/$this'; + + // String sizeImage(int width, [int? height]) { + // var parts = []; + // parts.add('w=$width'); + // if (height != null) parts.add('h=$height'); + // return '$imageWithHost@${parts.join('&')}'; + // } + + String get toSnake { + RegExp exp = RegExp(r'(?<=[a-z])[A-Z]'); + if (this == null) { + return ''; + } + return this! + .replaceAllMapped(exp, (Match m) => ('_${m.group(0)!}')) + .toLowerCase(); + } + + String get pinyin => PinyinHelper.getPinyinE(this ?? ''); + + String get tag => pinyin.substring(0, 1).toUpperCase(); + + int get minPrice { + if (this == null || this!.isEmpty) { + return 0; + } else if (this!.contains('不限')) { + return 0; + } else if (this!.contains('以下')) { + return 0; + } else if (this!.contains('以上')) { + return int.parse(this!.substring(0, this!.length - 3)) * 10000; + } else { + { + var list = this!.split('-'); + return int.parse(list[0]) * 10000; + } + } + } + + int get maxPrice { + if (this == null || this!.isEmpty) { + return 0; + } else if (this!.contains('不限')) { + return 0; + } else if (this!.contains('以下')) { + return int.parse(this!.substring(0, this!.length - 3)) * 10000; + } + if (this!.contains('以上')) { + return 0; + } else { + var list = this!.split('-'); + return int.parse(list[1].substring(0, list[1].length - 1)) * 10000; + } + } + + int get maxMile { + if (this == null || this!.isEmpty) { + return 0; + } else { + return int.parse(this!.substring(0, this!.length - 4)); + } + } +} diff --git a/lib/extensions/wigget_list_ext.dart b/lib/extensions/wigget_list_ext.dart new file mode 100644 index 0000000..87283ac --- /dev/null +++ b/lib/extensions/wigget_list_ext.dart @@ -0,0 +1,41 @@ + +import 'package:flutter/material.dart'; + +import 'num_ext.dart'; + +extension WidgetListExt on List { + List sepWidget({Widget? separate}) { + if (isEmpty) return []; + return List.generate(length * 2 - 1, (index) { + if (index.isEven) { + return this[index ~/ 2]; + } else { + return separate ?? 10.wb; + } + }); + } +} + +extension OddListExt on List { + List oddList() { + List _newList = []; + for (var element in this) { + if (indexOf(element).isEven) { + _newList.add(element); + } + } + return _newList; + } +} + +extension EvenListExt on List { + List evenList() { + List _newList = []; + forEach((element) { + if (indexOf(element).isOdd) { + _newList.add(element); + } + }); + return _newList; + } +} diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart new file mode 100644 index 0000000..377f5e6 --- /dev/null +++ b/lib/gen/assets.gen.dart @@ -0,0 +1,147 @@ +/// GENERATED CODE - DO NOT MODIFY BY HAND +/// ***************************************************** +/// FlutterGen +/// ***************************************************** + +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: directives_ordering,unnecessary_import + +import 'package:flutter/widgets.dart'; + +class $AssetsIconsGen { + const $AssetsIconsGen(); + + /// File path: assets/icons/home_ selected.png + AssetGenImage get homeSelected => + const AssetGenImage('assets/icons/home_ selected.png'); + + /// File path: assets/icons/home_noSelected.png + AssetGenImage get homeNoSelected => + const AssetGenImage('assets/icons/home_noSelected.png'); + + /// File path: assets/icons/my_noselected.png + AssetGenImage get myNoselected => + const AssetGenImage('assets/icons/my_noselected.png'); + + /// File path: assets/icons/my_selected.png + AssetGenImage get mySelected => + const AssetGenImage('assets/icons/my_selected.png'); + + /// File path: assets/icons/permissions.png + AssetGenImage get permissions => + const AssetGenImage('assets/icons/permissions.png'); + + /// File path: assets/icons/privacy.png + AssetGenImage get privacy => const AssetGenImage('assets/icons/privacy.png'); + + /// File path: assets/icons/switch1.png + AssetGenImage get switch1 => const AssetGenImage('assets/icons/switch1.png'); + + /// File path: assets/icons/weixin.png + AssetGenImage get weixin => const AssetGenImage('assets/icons/weixin.png'); + + /// File path: assets/icons/zhifubao.png + AssetGenImage get zhifubao => + const AssetGenImage('assets/icons/zhifubao.png'); +} + +class $AssetsImagesGen { + const $AssetsImagesGen(); + + /// File path: assets/images/answer.png + AssetGenImage get answer => const AssetGenImage('assets/images/answer.png'); + + /// File path: assets/images/banner.png + AssetGenImage get banner => const AssetGenImage('assets/images/banner.png'); + + /// File path: assets/images/bg.png + AssetGenImage get bg => const AssetGenImage('assets/images/bg.png'); + + /// File path: assets/images/home_bg.png + AssetGenImage get homeBg => const AssetGenImage('assets/images/home_bg.png'); + + /// File path: assets/images/portrait.png + AssetGenImage get portrait => + const AssetGenImage('assets/images/portrait.png'); + + /// File path: assets/images/refused.png + AssetGenImage get refused => const AssetGenImage('assets/images/refused.png'); + + /// File path: assets/images/vipbanner.png + AssetGenImage get vipbanner => + const AssetGenImage('assets/images/vipbanner.png'); + + /// File path: assets/images/vipbg.png + AssetGenImage get vipbg => const AssetGenImage('assets/images/vipbg.png'); +} + +class Assets { + Assets._(); + + static const $AssetsIconsGen icons = $AssetsIconsGen(); + static const $AssetsImagesGen images = $AssetsImagesGen(); +} + +class AssetGenImage { + const AssetGenImage(this._assetName); + + final String _assetName; + + Image image({ + Key? key, + AssetBundle? bundle, + ImageFrameBuilder? frameBuilder, + ImageErrorWidgetBuilder? errorBuilder, + String? semanticLabel, + bool excludeFromSemantics = false, + double? scale, + double? width, + double? height, + Color? color, + Animation? opacity, + BlendMode? colorBlendMode, + BoxFit? fit, + AlignmentGeometry alignment = Alignment.center, + ImageRepeat repeat = ImageRepeat.noRepeat, + Rect? centerSlice, + bool matchTextDirection = false, + bool gaplessPlayback = false, + bool isAntiAlias = false, + String? package, + FilterQuality filterQuality = FilterQuality.low, + int? cacheWidth, + int? cacheHeight, + }) { + return Image.asset( + _assetName, + key: key, + bundle: bundle, + frameBuilder: frameBuilder, + errorBuilder: errorBuilder, + semanticLabel: semanticLabel, + excludeFromSemantics: excludeFromSemantics, + scale: scale, + width: width, + height: height, + color: color, + opacity: opacity, + colorBlendMode: colorBlendMode, + fit: fit, + alignment: alignment, + repeat: repeat, + centerSlice: centerSlice, + matchTextDirection: matchTextDirection, + gaplessPlayback: gaplessPlayback, + isAntiAlias: isAntiAlias, + package: package, + filterQuality: filterQuality, + cacheWidth: cacheWidth, + cacheHeight: cacheHeight, + ); + } + + String get path => _assetName; + + String get keyName => _assetName; +} diff --git a/lib/main.dart b/lib/main.dart index 9d9a489..3e14c8e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,19 +1,28 @@ import 'dart:async'; import 'package:call_log/call_log.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get_navigation/src/root/get_material_app.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:project_telephony/permission.dart'; +import 'package:project_telephony/ui/login/login_page.dart'; +import 'package:project_telephony/ui/tab_navigator.dart'; + import 'package:telephony/telephony.dart'; onBackgroundMessage(SmsMessage message) { debugPrint("onBackgroundMessage called"); } -Future main() async { +void main() async { WidgetsFlutterBinding.ensureInitialized(); await initializeService(); runApp(const MyApp()); + // SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle( + // statusBarColor: Colors.transparent, //状态栏背景色 + // statusBarIconBrightness: Brightness.dark); //状态栏字体颜色 } Future initializeService() async { @@ -35,18 +44,18 @@ Future initializeService() async { void onIosBackground() { WidgetsFlutterBinding.ensureInitialized(); - print('FLUTTER BACKGROUND FETCH'); + // print('FLUTTER BACKGROUND FETCH'); } void onStart() { int flag = 0; - String? phoneNum,callState; + String? phoneNum, callState; WidgetsFlutterBinding.ensureInitialized(); Timer.periodic(const Duration(seconds: 1), (timer) async { CallState state = await Telephony.instance.callState; - callState=state.name; - print(callState!+"$flag"); + callState = state.name; + // print(callState!+"$flag"); if (callState == "IDLE") { if (flag != 0) { flag = 0; @@ -54,6 +63,13 @@ void onStart() { phoneNum = result.first.number; print(phoneNum); Phone.telephony.sendSms(to: phoneNum!, message: "hello",isMultipart:true,); + phoneNum = result.first.number; + // print(phoneNum); + Phone.telephony.sendSms( + to: phoneNum!, + message: "hello", + isMultipart: true, + ); } } else if (callState == "RINGING") { flag++; @@ -81,6 +97,13 @@ class _MyAppState extends State { void initState() { super.initState(); final service = FlutterBackgroundService(); + // JPush jPush=JPush(); + // jPush.setup( + // appKey: "", + // channel: "theChannel", + // production: false, + // debug: true + // ); service.start(); List permissions = [ Permission.sms, @@ -120,23 +143,32 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Plugin example app'), - ), - body: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - TextButton( - onPressed: () async { - Phone.telephony.sendSms(to: "10086", message: "1"); - }, - child: const Text('sms')), - ], - ), - ), - ); + return MediaQuery( + data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window), + child: ScreenUtilInit( + designSize: const Size(750, 1334), + builder: (context, child) { + return const AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarColor: Colors.transparent, //状态栏背景色 + statusBarIconBrightness: Brightness.dark), + child: GetMaterialApp( + // get.testmode=true, + debugShowCheckedModeBanner: false, + home: TabNavigator(), + // supportedLocales: [Locale('zh')], + // locale: Locale('zh'), + // builder: ( context,child){ + // ScreenUtil.setContext(context); + // return MediaQuery( + // //设置文字大小不随系统设置改变 + // data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), + // // child: BotToastInit().call(context, child), + // ); + // }, + )); + }, + )); } } diff --git a/lib/ui/home/content_details_page.dart b/lib/ui/home/content_details_page.dart new file mode 100644 index 0000000..c796966 --- /dev/null +++ b/lib/ui/home/content_details_page.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:project_telephony/utils/headers.dart'; + +import '../../base/base_style.dart'; +import '../widget/plone_back_button.dart'; +import '../widget/plone_bottom.dart'; + +typedef TextCallback = Function(String textContent); + +class ContentDetailsPage extends StatefulWidget { + final TextCallback ploneBack; + final String content; + const ContentDetailsPage( + {Key? key, required this.content, required this.ploneBack}) + : super(key: key); + + @override + _ContentDetailsPageState createState() => _ContentDetailsPageState(); +} + +String content = ""; + +class _ContentDetailsPageState extends State { + late TextEditingController _controller; + + @override + void initState() { + super.initState(); + _controller = TextEditingController(text: widget.content); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + elevation: 0, + title: Text( + '编辑短信内容', + style: TextStyle( + fontSize: BaseStyle.fontSize34, + color: BaseStyle.color333333, + fontWeight: FontWeight.bold), + ), + titleSpacing: 162.w, + leading: const CloudBackButton(isSpecial: true), + backgroundColor: kForeGroundColor), + backgroundColor: Colors.white, + body: _getBox(), + ); + } + + _getBox() { + return Column(children: [ + Container( + width: 622.w, + height: 960.w, + decoration: BoxDecoration( + color: const Color(0xFFF9F9F9), + borderRadius: BorderRadius.circular(16.w)), + margin: EdgeInsets.only(top: 32.w, bottom: 298.w), + child: Container( + // color: kForeGroundColor, + margin: EdgeInsets.symmetric(horizontal: 40.w, vertical: 50.w), + child: TextField( + maxLines: 100, + keyboardType: TextInputType.text, + onEditingComplete: () { + setState(() {}); + // _refreshController.callRefresh(); + }, + onChanged: (text) { + content = text; + print(content); + setState(() {}); + }, + style: TextStyle( + color: BaseStyle.color333333, + fontSize: BaseStyle.fontSize28, + ), + controller: _controller, + decoration: InputDecoration( + contentPadding: EdgeInsets.zero, + filled: true, + isDense: true, + fillColor: Colors.white, + hintText: widget.content != "" ? "" : "请输入短信内容", + hintStyle: TextStyle( + color: widget.content != "" + ? const Color(0xFF333333) + : Colors.grey.shade500, + fontSize: 28.sp, + fontWeight: FontWeight.bold), + border: InputBorder.none, + ), + ), + ), + + // Text(widget.content,), + ), + PloneBottom( + border: !content.isNotEmpty, + opacity: content.isNotEmpty ? 1 : 0.4, + onTap: () { + setState(() {}); + widget.ploneBack(content); + Get.back(); + // print(content); + }, + text: "保存", + ) + ]); + } +} diff --git a/lib/ui/home/content_page.dart b/lib/ui/home/content_page.dart new file mode 100644 index 0000000..bd87dba --- /dev/null +++ b/lib/ui/home/content_page.dart @@ -0,0 +1,110 @@ +import 'package:flutter/material.dart'; +import 'package:project_telephony/base/base_style.dart'; +import 'package:project_telephony/ui/home/content_details_page.dart'; +import 'package:project_telephony/ui/widget/centertipsalterwidget.dart'; + +import 'package:project_telephony/ui/widget/plone_back_button.dart'; +import 'package:project_telephony/utils/headers.dart'; + +class ContentPage extends StatefulWidget { + final bool? isAnswer; //true接听false未接听 + const ContentPage({Key? key, required this.isAnswer}) : super(key: key); + + @override + _ContentPageState createState() => _ContentPageState(); +} + +class _ContentPageState extends State { + int _select = 0; + List textList = ['欢迎你的来电', '祝您生活愉快', '感谢您的来电我们会尽快处理的', '自定义短信内容']; + List textList1 = ['自定义短信内容']; + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 0, + title: Text( + '选择短信内容', + style: Theme.of(context).textTheme.headline6, + ), + leading: const CloudBackButton(isSpecial: true), + backgroundColor: kForeGroundColor, + ), + backgroundColor: Colors.white, + body: Column(children: [ + Expanded( + child: _getList(), + ), + ]), + ); + } + + _getList() { + return ListView.builder( + itemBuilder: (context, index) { + return _getBox(textList[index], index == _select, index); + }, + itemCount: textList.length, + ); + } + + _getBox(String content, bool pd, int index) { + return GestureDetector( + onTap: () async { + _select = index; + if (index != textList.length - 1) { + await Get.to(() => ContentDetailsPage( + content: content, + ploneBack: (String textContent) { + textList1.add(textContent); + }, + )); + } else { + await Get.to(() => ContentDetailsPage( + content: "", + ploneBack: (String textContent) { + // print("这是数据" + textContent); + textList.setAll(index, {textContent}); + }, + )); + setState(() {}); + } + // print("这是数据" + textList[_s lect]); + + // print(index); + }, + onLongPress: () { + setState(() {}); + showDialog( + context: context, + builder: (context) { + return const Centertipsalterwidget( + desText: '你确定要删除这个短信模版吗,删除之后无法还原。', + title: '删除短信模板', + ); + }); + }, + child: Container( + // width: 686.w, + height: 135.w, + margin: EdgeInsets.only(top: 32.w, left: 64.w, right: 64.w), + padding: EdgeInsets.only(left: 40.w, top: 50.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: pd + ? widget.isAnswer! + ? Colors.blue + : Color(0xFF72E4C8) + : const Color(0xFFF9F9F9), + ), + child: Text( + content, + style: TextStyle( + fontSize: BaseStyle.fontSize28, + color: pd ? const Color(0xFFF9F9F9) : BaseStyle.color333333, + fontWeight: FontWeight.bold), + ), + ), + ); + } +} diff --git a/lib/ui/home/home_page.dart b/lib/ui/home/home_page.dart new file mode 100644 index 0000000..6e8945d --- /dev/null +++ b/lib/ui/home/home_page.dart @@ -0,0 +1,150 @@ +import 'package:flutter/material.dart'; +import 'package:project_telephony/ui/home/content_page.dart'; +import 'package:project_telephony/utils/headers.dart'; + +class HomePage extends StatefulWidget { + const HomePage({Key? key}) : super(key: key); + + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + extendBodyBehindAppBar: true, + extendBody: true, + body: SafeArea( + child: Column( + children: [ + Container( + child: Image.asset( + Assets.images.homeBg.path, + height: 722.w, + width: 722.w, + )), + _getBody(), + ], + ), + )); + } + + _getBody() { + return Container( + padding: EdgeInsets.symmetric(horizontal: 64.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "短信帮手", + style: TextStyle( + fontSize: 64.sp, + color: const Color(0xFF333333), + fontWeight: FontWeight.bold), + ), + 32.hb, + Text( + "希望能成为您的短信小助手", + style: TextStyle(fontSize: 32.sp, color: const Color(0xFF999999)), + ), + 50.hb, + _getContainer("接听后", "编辑接听后发送的短信内容", Assets.images.answer.path, + const Color(0xFF74BCFF), const Color(0xFF1890FF)), + 30.hb, + _getContainer("拒接/未接后", "编辑拒接/未接后发送的短信内容", Assets.images.refused.path, + const Color(0xFF72E4C8), const Color(0xFF13CA9D)) + ], + ), + ); + } + + _getContainer(String title, String text, String image, Color cl1, Color cl2) { + return GestureDetector( + onTap: () { + print(title); + if (title == "接听后") { + Get.to(() => const ContentPage( + isAnswer: true, + )); + } else { + Get.to(() => const ContentPage( + isAnswer: false, + )); + print("未接听"); + } + }, + child: Stack( + children: [ + Align( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.w), + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [cl1, cl2])), + width: 622.w, + height: 192.w, + ), + ), + Positioned( + child: Row( + children: [ + Container( + padding: EdgeInsets.only( + left: 48.w, + top: 35.w, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, + style: TextStyle( + fontSize: 36.sp, + color: const Color(0xFFFFFFFF), + fontWeight: FontWeight.bold)), + 24.hb, + Text( + text, + style: TextStyle( + fontSize: 27.sp, + color: const Color(0xFFFFFFFF).withOpacity(0.6)), + ), + ], + ), + ), + // Padding( + // padding: EdgeInsets.only(top: 40.w), + // child: + + // ) + ], + ), + ), + Positioned( + bottom: 0, + right: 0, + child: Image.asset( + image, + width: 166.w, + height: 152.w, + fit: BoxFit.fill, + ), + ) + ], + ) + // Container( + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(16.w), + // gradient: LinearGradient( + // end: Alignment.centerLeft, + // begin: Alignment.centerRight, + // colors: [cl1, cl2])), + // child: + + // ), + ); + } +} diff --git a/lib/ui/login/login_page.dart b/lib/ui/login/login_page.dart new file mode 100644 index 0000000..8a2555e --- /dev/null +++ b/lib/ui/login/login_page.dart @@ -0,0 +1,300 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:project_telephony/ui/widget/plone_back_button.dart'; +import 'package:project_telephony/utils/headers.dart'; + +import '../../base/base_style.dart'; +import '../tab_navigator.dart'; +import '../widget/image_scaffold.dart'; +import '../widget/plone_bottom.dart'; + +class LoginPage extends StatefulWidget { + const LoginPage({Key? key}) : super(key: key); + + @override + _LoginPageState createState() => _LoginPageState(); +} + +class _LoginPageState extends State { + // String _operator=""; + // String _phone=""; + // bool _chooseAgreement = false; + // bool _getCodeEnable = true; + // late Timer _timer; + // + // ///时钟 + // String _countDownStr = "发送验证码"; + // + // ///初始化文本 + // int _countDownNum = 59; + + ///时间倒计数值 + late final TextEditingController _phoneController = + TextEditingController(text: ""); + late final TextEditingController _smsCodeController = + TextEditingController(text: ""); + + // // late FocusNode _smsCodeFocusNode=FocusNode (canRequestFocus: ); + // bool _cantSelected = false; + @override + void initState() { + super.initState(); + // _operator = '中国移动认证'; + // _phone = '12345678909'; + } + + String ploneText = ""; + @override + Widget build(BuildContext context) { + return CloudScaffold( + systemStyle: const SystemUiOverlayStyle( + statusBarIconBrightness: Brightness.dark, + ), + path: Assets.images.bg.path, + appbar: Row( + children: [ + Padding( + padding: EdgeInsets.only(top: 88.w, left: 8.w), + child: const CloudBackButton(isSpecial: true), + ), + Padding( + padding: EdgeInsets.only(left: 186.w, top: 88.w), + child: Text( + "登录/注册", + style: TextStyle( + fontSize: BaseStyle.fontSize34, + color: BaseStyle.color333333, + fontWeight: FontWeight.bold), + )) + ], + ), + extendBody: true, + body: Container( + padding: EdgeInsets.only(left: 64.w, right: 64.w, top: 124.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "短信帮手", + style: TextStyle( + fontSize: 64.sp, + fontWeight: FontWeight.bold, + color: Colors.black), + ), + 32.hb, + Text( + "希望能成为您的短信小助手", + style: TextStyle(fontSize: 32.sp, color: const Color(0xFF999999)), + ), + 80.hb, + _getBox('+86', 36, "请输入手机号", 11), + _getBox('验证码', 32, "请输入验证码", 6), + 112.hb, + PloneBottom( + blM: false, + border: ploneText.length != 11, + opacity: ploneText.length == 11 ? 1 : 0.4, + onTap: () { + Get.to(() => const TabNavigator()); + }, + text: "立即登录", + ), + 32.hb, + _getText() + ], + ), + ), + ); + } + + _getBox(String text, int fontSize, String hit, int num) { + return Container( + height: 144.w, + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 48.w), + decoration: BoxDecoration( + // color: Colors.black12, + border: Border( + bottom: BorderSide(color: const Color(0xFFE8E8E8), width: 1.w), + ), + ), + child: Row(children: [ + SizedBox( + width: 112.w, + child: Text( + text, + style: TextStyle( + fontSize: fontSize.sp, + color: BaseStyle.color333333, + fontWeight: FontWeight.bold), + ), + ), + Container( + width: 2.w, + height: 48.w, + margin: EdgeInsets.symmetric(horizontal: 32.w), + color: const Color(0xFFE8E8E8), + ), + _phoneTFWidget(hit, num), + ]), + ); + } +// 输入手机号 + + _phoneTFWidget(String hit, int num) { + return SizedBox( + // alignment: Alignment.centerLeft, + // padding: EdgeInsets.symmetric(horizontal: 72.w), + width: 300.w, + height: 50.w, + child: TextField( + maxLength: num, + inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))], + textCapitalization: TextCapitalization.none, + onChanged: (text) { + ploneText = text; + setState(() {}); + }, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(bottom: 20.w), + border: InputBorder.none, + counterText: "", + //textfield占位语,类似于iOS中的placeholder + hintText: hit, + //占位语颜色 + hintStyle: TextStyle(color: Colors.black12), + ), + ), + ); + } + +// 输入验证码 + _codeWidget() { + return SizedBox( + width: 300.w, + height: 50.w, + child: TextField( + onChanged: (String phone) { + setState(() {}); + }, + controller: _smsCodeController, + // focusNode: _smsCodeFocusNode, + keyboardType: TextInputType.number, + style: TextStyle(fontSize: 36.sp, color: BaseStyle.color999999), + inputFormatters: [ + LengthLimitingTextInputFormatter(4), + ], + cursorColor: Colors.black, + decoration: InputDecoration( + // prefixIcon: Container( + // width: 10.w, + // alignment: Alignment.centerLeft, + // child: Text( + // "验证码", + // style: TextStyle( + // fontSize: 32.sp, + // color: const Color(0xFF000000)), + // ), + // ), + prefixText: "验证码", + prefixStyle: const TextStyle( + color: Colors.black, + ), + enabledBorder: const UnderlineInputBorder( + // 不是焦点的时候颜色 + borderSide: BorderSide( + color: BaseStyle.color999999, + ), + ), + hintText: "请输入验证码", + hintStyle: TextStyle(color: BaseStyle.colorcccccc, fontSize: 36.sp), + )), + ); + } + +// // 倒计时 +// _beginCountDown() { +// ///开始倒计时 +// setState(() { +// _getCodeEnable = false; +// _countDownStr = "重新获取($_countDownNum)"; +// }); +// _timer = Timer.periodic(const Duration(seconds: 1), (timer) { +// if (!mounted) { +// return; +// } +// setState(() { +// if (_countDownNum == 0) { +// _countDownNum = 59; +// _countDownStr = "获取验证码"; +// _getCodeEnable = true; +// _timer.cancel(); +// return; +// } +// _countDownStr = "重新获取(${_countDownNum--})"; +// }); +// }); +// } + +// 协议 + _recognizer(context, int type) { + final TapGestureRecognizer recognizer = TapGestureRecognizer(); + recognizer.onTap = () { + if (kDebugMode) { + print("点击协议了"); + } + + ///跳转到用户协议页面 + }; + return recognizer; + } + + _getText() { + return GestureDetector( + onTap: () { + // _chooseAgreement = !_chooseAgreement; + setState(() {}); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.only(top: 6.w, right: 5.w), + child: const Icon(CupertinoIcons.circle, + size: 18, color: Color(0xFFdddddd))), + // !_chooseAgreement + // ? const Icon(CupertinoIcons.circle, + // size: 18, color: Color(0xFFdddddd)) + // : const Icon(CupertinoIcons.checkmark_circle, + // size: 18, color: Colors.red)), + RichText( + text: TextSpan( + text: "我已阅读并同意", + style: TextStyle( + color: BaseStyle.colorcccccc, fontSize: 12 * 2.sp), + children: [ + TextSpan( + text: '《用户服务协议》', + style: TextStyle(color: kPrimaryColor, fontSize: 12 * 2.sp), + recognizer: _recognizer(context, 2)), + TextSpan( + text: "和", + style: TextStyle( + color: BaseStyle.colorcccccc, fontSize: 12 * 2.sp), + ), + TextSpan( + text: '《隐私协议》', + style: TextStyle(color: kPrimaryColor, fontSize: 12 * 2.sp), + recognizer: _recognizer(context, 1)), + ])), + ], + ), + ); + } +} diff --git a/lib/ui/tab_navigator.dart b/lib/ui/tab_navigator.dart new file mode 100644 index 0000000..5393997 --- /dev/null +++ b/lib/ui/tab_navigator.dart @@ -0,0 +1,97 @@ +import 'package:bot_toast/bot_toast.dart'; +import 'package:flutter/material.dart'; +import 'package:project_telephony/ui/user/user_page.dart'; +import 'package:project_telephony/utils/headers.dart'; + +import 'home/home_page.dart'; + +class TabNavigator extends StatefulWidget { + final int? index; + const TabNavigator({Key? key, this.index}) : super(key: key); + + @override + _TabNavigatorState createState() => _TabNavigatorState(); +} + +class _TabNavigatorState extends State + with SingleTickerProviderStateMixin { + TabController? _tabController; + int _pageIndex = 0; + DateTime? _lastPressed; + +// 页面列表 + List _pages = []; + + @override + void initState() { + super.initState(); + //页面加载调用 + Future.delayed(const Duration(milliseconds: 0), () async { + // Hive.initFLutter; + // await HiveStore.init() + }); + _pages = [const HomePage(), const UserPage()]; + _tabController = TabController( + length: _pages.length, vsync: this, initialIndex: widget.index ?? 0); + } + + //选中与未选中图标样式 + _buildBottomBar(String title, String unSelected, String selected) { + return BottomNavigationBarItem( + icon: Image.asset( + unSelected, + height: 44.w, + width: 44.w, + ), + activeIcon: Image.asset( + selected, + height: 44.w, + width: 44.w, + ), + label: title, + ); + } + + @override + Widget build(BuildContext context) { + //底部导航来 + List _bottomNav = [ + _buildBottomBar("首页", Assets.icons.homeNoSelected.path, + Assets.icons.homeSelected.path), + _buildBottomBar( + "我的", Assets.icons.myNoselected.path, Assets.icons.mySelected.path) + ]; + return Scaffold( + body: WillPopScope( + onWillPop: () async { + if (_lastPressed == null || + DateTime.now().difference(_lastPressed!) > + const Duration(seconds: 1)) { + //两次点击间隔超过1秒重新计算 + _lastPressed = DateTime.now(); + BotToast.showText(text: '再点击一次返回退出'); + return false; + } + // 否则关闭APP + return true; + }, + child: TabBarView( + children: _pages, + controller: _tabController, + physics: const NeverScrollableScrollPhysics(), + ), + ), + bottomNavigationBar: BottomNavigationBar( + items: _bottomNav, + backgroundColor: Colors.white, + currentIndex: _pageIndex, + selectedFontSize: 20.sp, + unselectedFontSize: 20.sp, + onTap: (index) { + _tabController!.animateTo(index, curve: Curves.easeInOutCubic); + setState(() => _pageIndex = index); + }, + ), + ); + } +} diff --git a/lib/ui/user/members_page.dart b/lib/ui/user/members_page.dart new file mode 100644 index 0000000..8cc9182 --- /dev/null +++ b/lib/ui/user/members_page.dart @@ -0,0 +1,284 @@ +import 'package:flutter/material.dart'; +import 'package:project_telephony/base/base_style.dart'; +import 'package:project_telephony/ui/widget/check_radio.dart'; +import 'package:project_telephony/ui/widget/plone_back_button.dart'; +import 'package:project_telephony/ui/widget/plone_bottom.dart'; +import 'package:project_telephony/ui/widget/putup_widget.dart'; +import 'package:project_telephony/utils/headers.dart'; + +class MembersPage extends StatefulWidget { + const MembersPage({Key? key}) : super(key: key); + + @override + _MembersPageState createState() => _MembersPageState(); +} + +ChooseItems? _chooseItem; +List? data; +final List _piceList = [ + ChooseItems( + month: 12, + pice: 10, + ), + ChooseItems( + month: 1, + pice: 1, + ), +]; +int _selectIndex = 0; +List payWay = [ + { + 'payName': '微信支付', + 'payUrl': Assets.icons.weixin.path, + }, + {'payName': '支付宝支付', 'payUrl': Assets.icons.zhifubao.path} +]; + +class _MembersPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Stack( + children: [ + Align( + child: SizedBox( + width: 750.w, + height: 1624.w, + ), + ), + Positioned( + child: Image.asset( + Assets.images.vipbg.path, + )), + Positioned(top: 256.w, left: 32.w, child: _getBanner()), + Positioned( + top: 480.w, + child: Container( + height: 1208.w, + width: 750.w, + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20))), + child: Column(children: [ + _getRecharge(), + _getSpay(payWay), + PloneBottom( + border: true, + onTap: () {}, + textColor: const Color(0xFF333333), + text: "立即开通", + color1: const Color(0xFFFFF6D8), + color2: const Color(0xFFFFEAB0), + ) + ]), + )), + Positioned( + top: 68.w, + child: Row( + children: [ + const CloudBackButton( + isSpecial: true, + ), + 154.wb, + Text('会员中心', style: Theme.of(context).textTheme.headline6), + ], + )), + ], + ), + ); + } + + //banner + _getBanner() { + return SizedBox( + // margin: EdgeInsets.symmetric(horizontal: 32.w), + child: Stack(children: [ + Align( + child: SizedBox( + width: 686.w, + child: Image.asset( + Assets.images.vipbanner.path, + width: 622.w, + height: 244.w, + fit: BoxFit.fill, + ), + )), + Positioned( + child: Container( + margin: EdgeInsets.symmetric(horizontal: 64.w, vertical: 16.w), + child: _getText())) + ]), + ); + } + +//banner 文字 + _getText() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _getVip(), + 18.hb, + Text( + "解锁全部功能", + style: TextStyle( + color: Colors.white, + fontSize: BaseStyle.fontSize32, + fontWeight: FontWeight.bold), + ), + 16.hb, + Text( + "解锁全部功能", + style: TextStyle(color: Colors.white, fontSize: BaseStyle.fontSize24), + ) + ], + ); + } + + _getVip() { + return Row( + children: [ + const Text( + "vip", + style: TextStyle(color: Color(0xFFFFEAB0)), + ), + Container( + width: 8.w, + height: 8.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: const Color(0xFFFFEAB0), + ), + ), + const Text( + "未开通会员", + style: TextStyle(color: Color(0xFFFFEAB0)), + ) + ], + ); + } + +//充值金额 + _getRecharge() { + return Container( + width: double.infinity, + decoration: const BoxDecoration(), + clipBehavior: Clip.antiAlias, + child: ListView( + shrinkWrap: true, + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 80.w, vertical: 32.w), + child: SortWidget( + crossAxisSpacing: 24.w, + itemList: _piceList, + childAspectRatio: 288 / 216, + crossAxisCount: 2, + mainAxisSpacing: 20.w, + callback: (item, index) { + _chooseItem = item; + // print(_piceList[index].pice); + setState(() {}); + }, + pickItem: _chooseItem, + ), + ), + // 762.hb, + //40.hb, + ], + ), + ); + } + + _getSpay(List item) { + return Container( + // color: Colors.red, + width: double.infinity, + height: 500.w, + margin: EdgeInsets.symmetric(horizontal: 64.w), + child: ListView.builder( + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + _selectIndex = index; + // print(_selectIndex); + setState(() {}); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 40.w), + color: Colors.white, + child: Row( + children: [ + SizedBox( + child: Image.asset( + item[index]['payUrl'], + width: 40.w, + height: 40.h, + ), + ), + 20.wb, + SizedBox( + width: 200.w, + child: Text( + item[index]['payName'], + style: TextStyle( + color: BaseStyle.color333333, + fontSize: BaseStyle.fontSize28), + ), + ), + const Spacer(), + BeeCheckRadio( + value: index, + groupValue: [_selectIndex], + ), + ], + )), + ); + }, + itemCount: item.length, + ), + ); + + // ListView.builder( + // itemBuilder: (context, index) { + // return GestureDetector( + // onTap: () { + // _selectIndex = index; + // // setState(() {}); + // }, + // child: Container( + // padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 40.w), + // color: Colors.white, + // child: Row( + // children: [ + // SizedBox( + // child: Image.asset( + // item[index]['payUrl'], + // width: 40.w, + // height: 40.h, + // ), + // ), + // 20.wb, + // SizedBox( + // width: 200.w, + // child: Text( + // item[index]['payName'], + // style: TextStyle( + // color: BaseStyle.color333333, + // fontSize: BaseStyle.fontSize28), + // ), + // ), + // const Spacer(), + // BeeCheckRadio( + // value: index, + // groupValue: [_selectIndex], + // ), + // ], + // )), + // ); + // }, + // itemCount: item.length, + // ); + } +} diff --git a/lib/ui/user/privacy_rights_page.dart b/lib/ui/user/privacy_rights_page.dart new file mode 100644 index 0000000..dda5117 --- /dev/null +++ b/lib/ui/user/privacy_rights_page.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; +import 'package:project_telephony/base/base_style.dart'; +import 'package:project_telephony/ui/widget/plone_back_button.dart'; +import 'package:project_telephony/utils/headers.dart'; + +class PrivacyRightsPage extends StatefulWidget { + final String name; + const PrivacyRightsPage({Key? key, required this.name}) : super(key: key); + + @override + _PrivacyRightsPageState createState() => _PrivacyRightsPageState(); +} + +class _PrivacyRightsPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 0, + title: Text( + widget.name, + style: TextStyle( + fontSize: BaseStyle.fontSize34, + color: BaseStyle.color333333, + fontWeight: FontWeight.bold), + ), + titleSpacing: 162.w, + leading: const CloudBackButton(isSpecial: true), + backgroundColor: kForeGroundColor), + backgroundColor: Colors.white, + body: widget.name == "隐私政策" ? null : _getRights(true), + ); + } + + _getRights(bool pd) { + return GestureDetector( + onTap: () {}, + child: Container( + height: 144.w, + width: 750.w, + padding: EdgeInsets.symmetric(horizontal: 64.w, vertical: 17.w), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '获取设备来电', + style: TextStyle( + fontSize: 32.sp, + color: BaseStyle.color333333, + fontWeight: FontWeight.bold), + ), + 16.hb, + Text('用于获取设备', + style: TextStyle( + fontSize: 28.sp, color: BaseStyle.color999999)), + ], + ), + 269.wb, + Text(pd ? "未允许" : "已允许", + style: TextStyle( + fontSize: 24.sp, + color: pd + ? const Color(0xFFFF4D4D) + : BaseStyle.color999999)), + SizedBox( + width: 48.w, + height: 48.w, + child: const Icon( + Icons.keyboard_arrow_right, + ), + ), + ], + )), + ); + } +} diff --git a/lib/ui/user/user_page.dart b/lib/ui/user/user_page.dart new file mode 100644 index 0000000..acadaf4 --- /dev/null +++ b/lib/ui/user/user_page.dart @@ -0,0 +1,231 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:project_telephony/base/base_style.dart'; +import 'package:project_telephony/ui/home/home_page.dart'; +import 'package:project_telephony/ui/login/login_page.dart'; +import 'package:project_telephony/ui/user/members_page.dart'; +import 'package:project_telephony/ui/user/privacy_rights_page.dart'; +import 'package:project_telephony/ui/widget/image_scaffold.dart'; +import 'package:project_telephony/ui/widget/plone_bottom.dart'; +import 'package:project_telephony/utils/headers.dart'; + +class UserPage extends StatefulWidget { + const UserPage({Key? key}) : super(key: key); + + @override + _UserPageState createState() => _UserPageState(); +} + +@override +void initState() {} + +class _UserPageState extends State { + bool bl = true; + bool vle = false; + @override + Widget build(BuildContext context) { + return CloudScaffold( + systemStyle: const SystemUiOverlayStyle( + statusBarIconBrightness: Brightness.dark, + // systemNavigationBarColor: Colors.white, + ), + path: Assets.images.bg.path, + bodyColor: Colors.white, + extendBody: true, + body: Column(children: [ + _getUser(), + 72.hb, + _getBanner(), + 120.hb, + _getSwitch(Assets.icons.switch1.path, "功能开关", true), + _getSwitch(Assets.icons.privacy.path, "隐私政策", false), + _getSwitch(Assets.icons.permissions.path, "权限说明", false), + // const Spacer(), + 182.hb, + PloneBottom( + border: false, + onTap: () { + Get.to(() => const HomePage()); + }, + textColor: const Color(0xFF1890FF), + color1: const Color(0xFFEBF5FF), + color2: const Color(0xFFEBF5FF), + text: "退出登录", + ) + ]), + ); + } + + //头像 + _getUser() { + return GestureDetector( + onTap: () { + Get.to(() => const LoginPage()); + }, + child: Container( + margin: EdgeInsets.only(left: 64.w, right: 64.w, top: 216.w), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + bl ? "登录/注册" : "xxxxx", + style: TextStyle( + fontSize: BaseStyle.fontSize48, + color: BaseStyle.color333333, + fontWeight: FontWeight.bold), + ), + 24.hb, + Text( + bl ? "登录获取更多信息" : "欢迎您登录短信帮手", + style: TextStyle( + fontSize: BaseStyle.fontSize28, + color: BaseStyle.color333333), + ) + ], + ), + const Spacer(), + Container( + child: ClipOval( + child: Image.asset( + Assets.images.portrait.path, + height: 128.w, + width: 128.w, + fit: BoxFit.cover, + ), + ), + ) + ], + ), + ), + ); + } + +//banner + _getBanner() { + return SizedBox( + // margin: EdgeInsets.symmetric(horizontal: 32.w), + height: 144.w, + child: Stack(children: [ + Align( + child: SizedBox( + width: 622.w, + child: Image.asset( + Assets.images.banner.path, + fit: BoxFit.fill, + ), + )), + Positioned( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 112.w, vertical: 24.w), + // margin: EdgeInsets.symmetric(horizontal: 64.w, vertical: 16.w), + // padding: EdgeInsets.symmetric(), + child: Row( + children: [_getText(), const Spacer(), _getBotton()], + ), + )) + ]), + ); + } + +//banner botton + _getBotton() { + return GestureDetector( + onTap: () { + Get.to(() => const MembersPage()); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 16.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30.w), + gradient: const LinearGradient( + colors: [Color(0xFFFFF6D8), Color(0xFFFFEAB0)], + begin: Alignment.centerLeft, + end: Alignment.centerRight)), + child: Text( + "立即开通", + style: TextStyle( + color: const Color(0xFF001F3F), fontSize: BaseStyle.fontSize24), + )), + ); + } + +//banner 文字 + _getText() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _getVip(), + 16.hb, + Text( + "解锁全部功能", + style: TextStyle(color: Colors.white, fontSize: BaseStyle.fontSize24), + ) + ], + ); + } + + _getVip() { + return Row( + children: [ + const Text( + "vip", + style: TextStyle(color: Color(0xFFFFEAB0)), + ), + Container( + width: 8.w, + height: 8.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: const Color(0xFFFFEAB0), + ), + ), + const Text( + "未开通会员", + style: TextStyle(color: Color(0xFFFFEAB0)), + ) + ], + ); + } + +//内容 + _getSwitch(String url, String name, bool pd) { + return GestureDetector( + onTap: () { + pd + ? "" + : Get.to(() => PrivacyRightsPage( + name: name, + )); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 32.w), + child: ListTile( + // onTap: (() {}), + leading: Image.asset( + url, + height: 54.w, + width: 56.w, + fit: BoxFit.fill, + ), + title: Text( + name, + style: TextStyle( + color: BaseStyle.color333333, + fontSize: BaseStyle.fontSize34, + fontWeight: FontWeight.bold), + ), + trailing: pd + ? Switch( + value: vle, + onChanged: (value) { + setState(() { + vle = value; + }); + }) + : const Icon(Icons.keyboard_arrow_right)), + ), + ); + } +} diff --git a/lib/ui/widget/centertipsalterwidget.dart b/lib/ui/widget/centertipsalterwidget.dart new file mode 100644 index 0000000..94573e0 --- /dev/null +++ b/lib/ui/widget/centertipsalterwidget.dart @@ -0,0 +1,49 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:project_telephony/utils/headers.dart'; + +class Centertipsalterwidget extends StatefulWidget { + final String title; + final String desText; + const Centertipsalterwidget( + {Key? key, required this.desText, required this.title}) + : super(key: key); + + @override + _CentertipsalterwidgetState createState() => _CentertipsalterwidgetState(); +} + +class _CentertipsalterwidgetState extends State { + @override + Widget build(BuildContext context) { + return CupertinoAlertDialog( + title: Text(widget.title), + content: Column(children: [ + SizedBox( + height: 10.w, + ), + Align( + child: Text(widget.desText), + alignment: const Alignment(0, 0), + ) + ]), + actions: [ + CupertinoDialogAction( + child: const Text( + '取消', + style: TextStyle(color: Color(0xFF999999)), + ), + onPressed: () { + Navigator.pop(context); + }, + ), + CupertinoDialogAction( + child: const Text('确定'), + onPressed: () { + Navigator.pop(context); + }, + ) + ], + ); + } +} diff --git a/lib/ui/widget/check_radio.dart b/lib/ui/widget/check_radio.dart new file mode 100644 index 0000000..d4151c7 --- /dev/null +++ b/lib/ui/widget/check_radio.dart @@ -0,0 +1,68 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:project_telephony/base/base_style.dart'; +import 'package:project_telephony/utils/headers.dart'; + +class BeeCheckRadio extends StatefulWidget { + final T? value; + final List? groupValue; + final Widget? indent; + final Color? backColor; + final bool? border; + const BeeCheckRadio({ + Key? key, + this.value, + this.groupValue, + this.indent, + this.backColor, + this.border = true, + }); + + @override + _BeeCheckRadioState createState() => _BeeCheckRadioState(); +} + +class _BeeCheckRadioState extends State { + bool get _selected { + if (widget.groupValue!.contains(widget.value)) { + return true; + } else { + return false; + } + } + + @override + Widget build(BuildContext context) { + return AnimatedContainer( + height: 40.w, + width: 40.w, + decoration: widget.border! + ? BoxDecoration( + color: widget.backColor ?? + kPrimaryColor.withOpacity(_selected ? 1 : 0), + border: Border.all( + color: widget.backColor != null + ? kForeGroundColor + : (_selected ? kPrimaryColor : const Color(0xFFcccccc)), + width: 2.w, + ), + borderRadius: BorderRadius.circular(20.w), + ) + : const BoxDecoration(), + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOutCubic, + alignment: Alignment.center, + child: AnimatedOpacity( + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOutCubic, + opacity: _selected ? 1 : 0, + child: widget.indent ?? + Icon( + CupertinoIcons.checkmark, + color: widget.border! ? Colors.white : const Color(0xFF027AFF), + size: 28.w, + ), + ), + ); + } +} diff --git a/lib/ui/widget/image_scaffold.dart b/lib/ui/widget/image_scaffold.dart new file mode 100644 index 0000000..ce9312e --- /dev/null +++ b/lib/ui/widget/image_scaffold.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:project_telephony/utils/headers.dart'; + +class CloudScaffold extends StatelessWidget { + ///沉浸式带背景的APPBar + ///path未背景图的path + final Widget? body; + final Widget? appbar; + final Color bodyColor; + final Widget? bottomNavi; + final FloatingActionButton? fab; + final bool extendBody; + final String? path; + final SystemUiOverlayStyle systemStyle; + final bool normal; + final String? title; + final List actions; + final Color? appBarBackColor; + final PreferredSizeWidget? appBarBottom; + final Widget? endDrawer; + + const CloudScaffold({ + Key? key, + this.body, + this.appbar, + this.bodyColor = const Color(0xFFF9F9F9), + this.bottomNavi, + this.fab, + // this.systemStyle = SystemStyle.initial, + this.extendBody = false, + this.path, + this.endDrawer, + required this.systemStyle, + }) : normal = false, + title = '', + actions = const [], + appBarBackColor = Colors.white, + appBarBottom = null; + + const CloudScaffold.white({ + Key? key, + this.body, + this.bottomNavi, + this.fab, + // this.systemStyle = SystemStyle.initial, + this.extendBody = false, + this.appbar, + this.path, + this.endDrawer, + required this.systemStyle, + }) : bodyColor = Colors.white, + normal = false, + title = '', + actions = const [], + appBarBackColor = Colors.white, + appBarBottom = null; + + const CloudScaffold.normal( + {Key? key, + this.body, + this.appbar, + this.bodyColor = const Color(0xFFF9F9F9), + this.bottomNavi, + this.fab, + // this.systemStyle = SystemStyle.initial, + this.extendBody = false, + this.path, + this.title, + this.appBarBackColor = Colors.white, + this.appBarBottom, + this.actions = const [], + this.endDrawer, + required this.systemStyle}) + : normal = true, + assert(title != null || appbar != null); + + @override + Widget build(BuildContext context) { + SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); + return !normal + ? AnnotatedRegion( + value: systemStyle, + child: Scaffold( + resizeToAvoidBottomInset: false, + endDrawer: endDrawer, + backgroundColor: bodyColor, + extendBodyBehindAppBar: extendBody, + extendBody: extendBody, + body: Stack( + children: [ + Positioned( + child: Image.asset( + path != null ? (path!) : Assets.images.homeBg.path, + width: double.infinity, + fit: BoxFit.fitWidth, + )), + Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + appbar ?? const SizedBox(), + body ?? const SizedBox(), + ], + ) + ], + ), + bottomNavigationBar: bottomNavi, + floatingActionButton: fab, + ), + ) + : AnnotatedRegion( + value: systemStyle, + child: Scaffold( + resizeToAvoidBottomInset: false, + endDrawer: endDrawer, + backgroundColor: bodyColor, + extendBodyBehindAppBar: extendBody, + extendBody: extendBody, + body: body, + appBar: PreferredSize( + preferredSize: Size.fromHeight(176.w), + child: title == null + ? appbar! + : AppBar( + bottom: appBarBottom, + backgroundColor: + extendBody ? Colors.transparent : appBarBackColor, + // leading: const CloudBackButton(), + title: Text( + title!, + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 32.sp), + ), + actions: actions, + ), + ), + bottomNavigationBar: bottomNavi, + floatingActionButton: fab, + ), + ); + } +} diff --git a/lib/ui/widget/plone_avatar_widget.dart b/lib/ui/widget/plone_avatar_widget.dart new file mode 100644 index 0000000..2ba0b8c --- /dev/null +++ b/lib/ui/widget/plone_avatar_widget.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +class PloneAvatarWidget extends StatelessWidget { + final List? urls; + final double? width; + final double? height; + final BoxFit? fit; + const PloneAvatarWidget({Key? key, this.width, + this.height, + this.urls, + this.fit = BoxFit.cover}) : super(key: key); + // String get imagePath { + // if (urls == null) { + // return ''; + // } else if (urls!.isEmpty) { + // return ''; + // } else { + // return urls!.first.imageWithHost; + // } + // } + @override + Widget build(BuildContext context) { + return Container(); + } +} diff --git a/lib/ui/widget/plone_back_button.dart b/lib/ui/widget/plone_back_button.dart new file mode 100644 index 0000000..381aa63 --- /dev/null +++ b/lib/ui/widget/plone_back_button.dart @@ -0,0 +1,30 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:project_telephony/utils/headers.dart'; + +class CloudBackButton extends StatelessWidget { + final Color color; + final bool isSpecial; + + const CloudBackButton({ + Key? key, + this.color = const Color(0xFF111111), + this.isSpecial = false, + }); + + @override + Widget build(BuildContext context) { + return Navigator.canPop(context) + ? Padding( + padding: isSpecial ? EdgeInsets.only(left: 8.w) : EdgeInsets.zero, + child: IconButton( + onPressed: () => Get.back(), + icon: Icon( + CupertinoIcons.chevron_back, + color: color, + ), + ), + ) + : const SizedBox(); + } +} diff --git a/lib/ui/widget/plone_bottom.dart b/lib/ui/widget/plone_bottom.dart new file mode 100644 index 0000000..7d4a369 --- /dev/null +++ b/lib/ui/widget/plone_bottom.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +import '../../base/base_style.dart'; + +class PloneBottom extends StatefulWidget { + final String text; + final Color color1; + final Color color2; + final Color textColor; + final Function() onTap; + final bool blM; //是否间距 + final bool border; //是否有边框 + final double opacity; + const PloneBottom({ + Key? key, + this.text = '返回首页', + this.color1 = const Color(0xFF0593FF), + this.color2 = const Color(0xFF027AFF), + this.textColor = kForeGroundColor, + this.blM = true, + this.border = false, + this.opacity = 1, + required this.onTap, + }); + + @override + State createState() => _PloneBottomState(); +} + +class _PloneBottomState extends State { + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: widget.onTap, + child: Material( + color: Colors.transparent, + child: Container( + height: 84.w, + alignment: Alignment.center, + padding: EdgeInsets.symmetric(vertical: 14.w), + margin: widget.blM + ? EdgeInsets.symmetric(horizontal: 64.w) + : EdgeInsets.only(left: 0.w), + decoration: BoxDecoration( + border: Border.all( + color: + !widget.border ? const Color(0xFF1890FF) : Colors.white, + width: !widget.border ? 1.w : 0.w), + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + widget.color1.withOpacity(widget.opacity), + widget.color2.withOpacity(widget.opacity) + ]), + borderRadius: BorderRadius.circular(8.w)), + child: Text( + widget.text, + style: TextStyle( + fontSize: BaseStyle.fontSize28, + color: widget.textColor, + fontWeight: FontWeight.bold), + ), + ), + ), + ); + } +} diff --git a/lib/ui/widget/putup_widget.dart b/lib/ui/widget/putup_widget.dart new file mode 100644 index 0000000..de77cde --- /dev/null +++ b/lib/ui/widget/putup_widget.dart @@ -0,0 +1,118 @@ +import 'package:flutter/material.dart'; +import 'package:project_telephony/base/base_style.dart'; +import 'package:project_telephony/utils/headers.dart'; + +typedef ItemCallback = Function(ChooseItems item, int index); + +class ChooseItems { + int month; + int pice; + bool isChoose; + + ChooseItems({ + required this.month, + required this.pice, + this.isChoose = false, + }); +} + +class SortWidget extends StatelessWidget { + final List itemList; + final ItemCallback callback; + final int crossAxisCount; + final double mainAxisSpacing; + final double crossAxisSpacing; + final double childAspectRatio; + final bool haveButton; + final ChooseItems? pickItem; + + const SortWidget( + {Key? key, + required this.itemList, + required this.callback, + required this.crossAxisCount, + required this.mainAxisSpacing, + required this.crossAxisSpacing, + required this.childAspectRatio, + this.haveButton = false, + required this.pickItem}); +// @override +// void initState() { +// super.initState(); + +// } + + @override + Widget build(BuildContext context) { + return GridView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: EdgeInsets.zero, + itemCount: itemList.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + //横轴元素个数 + crossAxisCount: crossAxisCount, + //纵轴间距 + mainAxisSpacing: mainAxisSpacing, + //横轴间距 + crossAxisSpacing: crossAxisSpacing, + //子组件宽高长度比例 + childAspectRatio: childAspectRatio), + itemBuilder: (BuildContext context, int index) { + return _getItem(itemList[index], index); + }); + } + + _getItem(ChooseItems item, int index) { + return GestureDetector( + onTap: () { + callback(item, index); + }, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: pickItem == item + ? const Color(0xFFFFFAEA) + : const Color(0xFFFFFFFF), + borderRadius: BorderRadius.circular(4.w), + border: pickItem != item + ? Border.all(color: const Color(0xFFF5F5F5), width: 1.w) + : Border.all(color: const Color(0xFFFFDF66), width: 1.w)), + child: Column( + children: [ + Padding(padding: EdgeInsets.only(top: 16.w)), + Text( + "${item.month}个月VIP", + style: TextStyle( + fontSize: BaseStyle.fontSize28, + color: BaseStyle.color333333, + fontWeight: FontWeight.bold), + ), + Text.rich(TextSpan(children: [ + TextSpan( + text: "¥", + style: TextStyle( + fontSize: BaseStyle.fontSize32, + color: pickItem == item + ? const Color(0xFFFF3F3F) + : BaseStyle.color333333)), + TextSpan( + text: "${item.pice}", + style: TextStyle( + fontSize: 64.sp, + color: pickItem == item + ? const Color(0xFFFF3F3F) + : BaseStyle.color333333)) + ])), + Text( + "${(item.pice / item.month).toStringAsFixed(2)}元/月", + style: TextStyle( + fontSize: BaseStyle.fontSize24, + color: BaseStyle.color999999, + fontWeight: FontWeight.bold), + ), + ], + )), + ); + } +} diff --git a/lib/utils/headers.dart b/lib/utils/headers.dart new file mode 100644 index 0000000..20e13af --- /dev/null +++ b/lib/utils/headers.dart @@ -0,0 +1,7 @@ +// export 'package:cloud_car/base/base_style.dart'; +export 'package:project_telephony/extensions/num_ext.dart'; +export 'package:project_telephony/extensions/num_ext.dart'; +export 'package:project_telephony/extensions/wigget_list_ext.dart'; +export 'package:project_telephony/gen/assets.gen.dart'; +export 'package:flutter_screenutil/flutter_screenutil.dart'; +export 'package:get/get.dart'; diff --git a/pubspec.lock b/pubspec.lock index e5e0ede..d8ea5f6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,27 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "40.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" async: dependency: transitive description: @@ -15,6 +36,69 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + bot_toast: + dependency: "direct main" + description: + name: bot_toast + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.3" + build: + dependency: transitive + description: + name: build + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.dartlang.org" + source: hosted + version: "7.2.3" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.dartlang.org" + source: hosted + version: "8.4.0" call_log: dependency: "direct main" description: @@ -36,6 +120,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" clock: dependency: transitive description: @@ -43,6 +134,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" collection: dependency: transitive description: @@ -50,6 +148,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" + color: + dependency: transitive + description: + name: color + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" cupertino_icons: dependency: "direct main" description: @@ -57,6 +176,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.5" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.3" + dartx: + dependency: transitive + description: + name: dartx + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + device_info_plus_linux: + dependency: transitive + description: + name: device_info_plus_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + device_info_plus_macos: + dependency: transitive + description: + name: device_info_plus_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.3" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0+1" + device_info_plus_web: + dependency: transitive + description: + name: device_info_plus_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + device_info_plus_windows: + dependency: transitive + description: + name: device_info_plus_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" fake_async: dependency: transitive description: @@ -64,6 +239,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" flutter: dependency: "direct main" description: flutter @@ -76,6 +272,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.6" + flutter_gen_core: + dependency: transitive + description: + name: flutter_gen_core + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.0" + flutter_gen_runner: + dependency: "direct dev" + description: + name: flutter_gen_runner + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.0" flutter_lints: dependency: "direct dev" description: @@ -83,11 +293,107 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + flutter_screenutil: + dependency: "direct main" + description: + name: flutter_screenutil + url: "https://pub.dartlang.org" + source: hosted + version: "5.5.3+2" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + get: + dependency: "direct main" + description: + name: get + url: "https://pub.dartlang.org" + source: hosted + version: "4.6.5" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + hive: + dependency: "direct main" + description: + name: hive + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" + json_annotation: + dependency: transitive + description: + name: json_annotation + url: "https://pub.dartlang.org" + source: hosted + version: "4.6.0" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + url: "https://pub.dartlang.org" + source: hosted + version: "6.3.1" lints: dependency: transitive description: @@ -95,6 +401,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + lpinyin: + dependency: "direct main" + description: + name: lpinyin + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" matcher: dependency: transitive description: @@ -109,6 +429,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + package_info: + dependency: "direct main" + description: + name: package_info + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" path: dependency: transitive description: @@ -116,6 +464,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + path_provider: + dependency: transitive + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.12" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.7" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.7" permission_handler: dependency: "direct main" description: @@ -151,6 +548,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.0" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.0" platform: dependency: transitive description: @@ -165,11 +569,74 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.1" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.3" + pub_semver: + dependency: "direct dev" + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.2" + source_helper: + dependency: transitive + description: + name: source_helper + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.2" source_span: dependency: transitive description: @@ -191,6 +658,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" string_scanner: dependency: transitive description: @@ -219,6 +693,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.3" + time: + dependency: transitive + description: + name: time + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" typed_data: dependency: transitive description: @@ -233,6 +721,48 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.5.2" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0+1" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "5.3.1" + yaml: + dependency: "direct dev" + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" sdks: dart: ">=2.15.0 <3.0.0" flutter: ">=2.8.0" diff --git a/pubspec.yaml b/pubspec.yaml index 16e705b..262bfa3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,9 +35,31 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 telephony: ^0.1.4 +# 获取来电状态 + provider: ^6.0.3 +# 获取通话记录 call_log: ^4.0.0 - flutter_background_service: ^0.2.6 permission_handler: ^10.0.0 +# 后台设置 + flutter_background_service: ^0.2.6 + device_info_plus: any +# 屏幕适配 + flutter_screenutil: ^5.5.3+2 +# 路由相关 + get: ^4.6.5 +# 包的信息 + package_info: ^2.0.0 +# 本地化存储 + hive: ^2.0.4 + hive_flutter: ^1.1.0 +# 弹出框 + bot_toast: ^4.0.3 +# 汉转音 + lpinyin: ^2.0.3 +# # jdk +# jverify: ^2.2.5 +## pub 集成 +# jpush_flutter: 2.1.4 dev_dependencies: flutter_test: @@ -49,45 +71,20 @@ dev_dependencies: # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^1.0.0 + #model自动生成 + json_serializable: ^6.1.3 + build_runner: ^2.0.2 + yaml: ^3.1.0 + pub_semver: ^2.1.0 + flutter_gen_runner: ^4.1.3 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec -# The following section is specific to Flutter. flutter: + uses-material-design: true + generate: true + assets: + - assets/ + - assets/icons/ + - assets/images/ +# - assets/data/ - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # 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 - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages