After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 623 B |
After Width: | Height: | Size: 685 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 321 KiB |
After Width: | Height: | Size: 126 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 103 KiB |
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:project_telephony/utils/headers.dart';
|
||||||
|
|
||||||
|
const ktextPrimary = Color(0xff333333);
|
||||||
|
const ktextSubColor = Color(0xff666666);
|
||||||
|
const ktextThirdColor = Color(0xff999999);
|
||||||
|
const kForeGroundColor = Color(0xFFFFFFFF);
|
||||||
|
const kPrimaryColor = Color(0xFF027AFF);
|
||||||
|
const kDarkPrimaryColor = Color(0xFFFF8200);
|
||||||
|
const kDangerColor = Color(0xFFFF3B30);
|
||||||
|
const kDarkSubColor = Color(0xFF979797);
|
||||||
|
const kBalckSubColor = Color(0xFF000000);
|
||||||
|
const bgColor = Color(0xFFF8F9FB);
|
||||||
|
|
||||||
|
class BaseStyle {
|
||||||
|
///字体类
|
||||||
|
static final double fontSize14 = 14.sp;
|
||||||
|
|
||||||
|
static final double fontSize16 = 16.sp;
|
||||||
|
|
||||||
|
static final double fontSize18 = 18.sp;
|
||||||
|
|
||||||
|
static final double fontSize20 = 20.sp;
|
||||||
|
|
||||||
|
static final double fontSize22 = 22.sp;
|
||||||
|
|
||||||
|
static final double fontSize24 = 24.sp;
|
||||||
|
|
||||||
|
static final double fontSize26 = 26.sp;
|
||||||
|
|
||||||
|
static final double fontSize28 = 28.sp;
|
||||||
|
|
||||||
|
static final double fontSize30 = 30.sp;
|
||||||
|
|
||||||
|
static final double fontSize32 = 32.sp;
|
||||||
|
|
||||||
|
static final double fontSize34 = 34.sp;
|
||||||
|
|
||||||
|
static final double fontSize36 = 36.sp;
|
||||||
|
|
||||||
|
static final double fontSize38 = 38.sp;
|
||||||
|
|
||||||
|
static final double fontSize40 = 40.sp;
|
||||||
|
|
||||||
|
static final double fontSize48 = 48.sp;
|
||||||
|
|
||||||
|
static final double fontSize52 = 52.sp;
|
||||||
|
|
||||||
|
///颜色
|
||||||
|
|
||||||
|
static const Color color111111 = Color(0xff111111);
|
||||||
|
|
||||||
|
static const Color color333333 = Color(0xff333333);
|
||||||
|
|
||||||
|
static const Color color666666 = Color(0xff666666);
|
||||||
|
|
||||||
|
static const Color color999999 = Color(0xff999999);
|
||||||
|
|
||||||
|
static const Color colorcccccc = Color(0xffcccccc);
|
||||||
|
|
||||||
|
static const Color colordddddd = Color(0xffdddddd);
|
||||||
|
|
||||||
|
static const Color colorfafafa = Color(0xfffafafa);
|
||||||
|
|
||||||
|
static const Color colorf3f3f3 = Color(0xfff3f3f3);
|
||||||
|
|
||||||
|
static const Color colorf6f6f6 = Color(0xfff6f6f6);
|
||||||
|
|
||||||
|
static const Color colorf9f9f9 = Color(0xfff9f9f9);
|
||||||
|
|
||||||
|
static const Color color474747 = Color(0xff474747);
|
||||||
|
|
||||||
|
static const Color colord8d8d8 = Color(0xffd8d8d8);
|
||||||
|
|
||||||
|
static const Color coloreeeeee = Color(0xffeeeeee);
|
||||||
|
|
||||||
|
static const Color colorff8500 = Color(0xffff8500);
|
||||||
|
|
||||||
|
static const Color colorffd000 = Color(0xffffd000);
|
||||||
|
|
||||||
|
static const Color color575757 = Color(0xff575757);
|
||||||
|
|
||||||
|
static const Color color4a4b51 = Color(0xff4a4b51);
|
||||||
|
|
||||||
|
static const Color colorababab = Color(0xffababab);
|
||||||
|
|
||||||
|
static const Color colorffc40c = Color(0xffffc40c);
|
||||||
|
|
||||||
|
static const Color color979797 = Color(0xff979797);
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
extension ColorExt on Color {
|
||||||
|
///获得此颜色的互补色
|
||||||
|
Color get complementary {
|
||||||
|
var r = ~red;
|
||||||
|
var g = ~green;
|
||||||
|
var b = ~blue;
|
||||||
|
return Color.fromARGB(alpha, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
||||||
|
extension NumExt on num {
|
||||||
|
Widget get wb => SizedBox(width: w);
|
||||||
|
|
||||||
|
Widget get hb => SizedBox(height: w);
|
||||||
|
}
|
@ -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 = <String>[];
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'num_ext.dart';
|
||||||
|
|
||||||
|
extension WidgetListExt on List<Widget> {
|
||||||
|
List<Widget> 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<T> on List<T> {
|
||||||
|
List<T> oddList() {
|
||||||
|
List<T> _newList = [];
|
||||||
|
for (var element in this) {
|
||||||
|
if (indexOf(element).isEven) {
|
||||||
|
_newList.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _newList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension EvenListExt<T> on List<T> {
|
||||||
|
List<T> evenList() {
|
||||||
|
List<T> _newList = [];
|
||||||
|
forEach((element) {
|
||||||
|
if (indexOf(element).isOdd) {
|
||||||
|
_newList.add(element);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return _newList;
|
||||||
|
}
|
||||||
|
}
|
@ -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<double>? 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;
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
class ContentDetailsPage extends StatefulWidget {
|
||||||
|
const ContentDetailsPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ContentDetailsPageState createState() => _ContentDetailsPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ContentDetailsPageState extends State<ContentDetailsPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(
|
||||||
|
'选择短信内容',
|
||||||
|
style: Theme.of(context).textTheme.headline6,
|
||||||
|
),
|
||||||
|
leading: const CloudBackButton(isSpecial: true),
|
||||||
|
backgroundColor: kForeGroundColor
|
||||||
|
),
|
||||||
|
body: _getBox(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_getBox(){
|
||||||
|
return Column(children: [
|
||||||
|
Container(
|
||||||
|
width: 622.w,
|
||||||
|
height: 960.w,
|
||||||
|
decoration: BoxDecoration(color: BaseStyle.colorcccccc,borderRadius: BorderRadius.circular(16)),
|
||||||
|
margin: EdgeInsets.only(left: 32.w,right: 32.w,top: 32.w,bottom: 298.w),
|
||||||
|
child: const Text('请输入短信内容'),),
|
||||||
|
PloneBottom(onTap: (){
|
||||||
|
|
||||||
|
},text: "保存",)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,86 @@
|
|||||||
|
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/plone_back_button.dart';
|
||||||
|
import 'package:project_telephony/utils/headers.dart';
|
||||||
|
|
||||||
|
class ContentPage extends StatefulWidget {
|
||||||
|
const ContentPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ContentPageState createState() => _ContentPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ContentPageState extends State<ContentPage> {
|
||||||
|
List<String> textList = ['欢迎你的来电', '祝您生活愉快', '感谢您的来电我们会尽快处理的'];
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(
|
||||||
|
'选择短信内容',
|
||||||
|
style: Theme.of(context).textTheme.headline6,
|
||||||
|
),
|
||||||
|
leading: const CloudBackButton(isSpecial: true),
|
||||||
|
backgroundColor: kForeGroundColor,
|
||||||
|
),
|
||||||
|
body: Column(children: [
|
||||||
|
Expanded(
|
||||||
|
child: _getList(),
|
||||||
|
),
|
||||||
|
_getBox2("自定义短信内容"),
|
||||||
|
32.hb
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getList() {
|
||||||
|
return ListView.builder(
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return _getBox(textList[index], index == 0);
|
||||||
|
},
|
||||||
|
itemCount: textList.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getBox(String content, bool pd) {
|
||||||
|
return Container(
|
||||||
|
width: 686.w,
|
||||||
|
height: 122.w,
|
||||||
|
margin: EdgeInsets.only(top: 32.w, left: 32.w, right: 32.w),
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 30.w),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
color: pd ? Colors.blue : Colors.white,
|
||||||
|
),
|
||||||
|
child: Text(content,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: BaseStyle.fontSize28,
|
||||||
|
color: pd ? const Color(0xFFF9F9F9) : BaseStyle.color333333)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getBox2(
|
||||||
|
String content,
|
||||||
|
) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Get.to(() => const ContentDetailsPage());
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
width: 686.w,
|
||||||
|
height: 122.w,
|
||||||
|
margin: EdgeInsets.only(top: 32.w, left: 32.w, right: 32.w),
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 30.w),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
content,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: BaseStyle.fontSize28, color: const Color(0xFF000000)),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
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<HomePage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
//margin:EdgeInsets.symmetric(horizontal: 32.w,vertical: 16.w),
|
||||||
|
child: Image.asset(
|
||||||
|
Assets.images.homeBg.path,
|
||||||
|
)),
|
||||||
|
12.hb,
|
||||||
|
_getBody(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getBody() {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 32.w),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"短信助手",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 64.sp,
|
||||||
|
color: Colors.black,
|
||||||
|
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());
|
||||||
|
// print("接听");
|
||||||
|
} else {
|
||||||
|
print("未接听");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(16.w),
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: Alignment.centerLeft,
|
||||||
|
end: Alignment.centerRight,
|
||||||
|
colors: [cl1, cl2])),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 532.w,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 16.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: 28.sp,
|
||||||
|
color: const Color(0xFFFFFFFF).withOpacity(0.6)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
45.wb,
|
||||||
|
Image.asset(
|
||||||
|
image,
|
||||||
|
width: 108.w,
|
||||||
|
height: 66.h,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,369 @@
|
|||||||
|
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/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<LoginPage> {
|
||||||
|
// 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';
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 Icon(
|
||||||
|
CupertinoIcons.chevron_back,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 239.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: 138.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,
|
||||||
|
_phoneTFWidget(),
|
||||||
|
_codeWidget(),
|
||||||
|
112.hb,
|
||||||
|
PloneBottom(
|
||||||
|
onTap: () {
|
||||||
|
Get.to(() => const TabNavigator());
|
||||||
|
},
|
||||||
|
text: "立即登录",
|
||||||
|
),
|
||||||
|
32.hb,
|
||||||
|
_getText()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 输入手机号
|
||||||
|
|
||||||
|
_phoneTFWidget() {
|
||||||
|
return Container(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
// padding: EdgeInsets.symmetric(horizontal: 72.w),
|
||||||
|
height: 40 * 2.h,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
onChanged: (String phone) {
|
||||||
|
// setState(() {
|
||||||
|
// if (phone.length >= 11) {
|
||||||
|
// _getCodeEnable = true;
|
||||||
|
// } else {
|
||||||
|
// _getCodeEnable = false;
|
||||||
|
// }
|
||||||
|
// if (kDebugMode) {
|
||||||
|
// //print(_loginEnable);
|
||||||
|
// }
|
||||||
|
// }); 判断手机号长度
|
||||||
|
},
|
||||||
|
// enabled: false,
|
||||||
|
controller: _phoneController,
|
||||||
|
// focusNode: _phoneFocusNode,
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 36.sp, color: const Color(0xFF999999)),
|
||||||
|
inputFormatters: [
|
||||||
|
LengthLimitingTextInputFormatter(11),
|
||||||
|
],
|
||||||
|
cursorColor: Colors.black,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
// contentPadding: EdgeInsets.only(
|
||||||
|
// left: rSize(10), top: rSize(13)),
|
||||||
|
// prefixIcon: Container(
|
||||||
|
// // padding: EdgeInsets.only(right: 10.w),
|
||||||
|
// width: 50.w,
|
||||||
|
// alignment: Alignment.centerLeft,
|
||||||
|
// child: Text(
|
||||||
|
// "+86",
|
||||||
|
// style: TextStyle(
|
||||||
|
// fontSize: 32.sp,
|
||||||
|
// color: const Color(0xFF000000)),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
prefixText: "+86",
|
||||||
|
prefixStyle: TextStyle(
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
enabledBorder: const UnderlineInputBorder(
|
||||||
|
// 不是焦点的时候颜色
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Color(0xffdddddd),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// focusedBorder: const UnderlineInputBorder( // 焦点集中的时候颜色
|
||||||
|
// borderSide: BorderSide(
|
||||||
|
// color: Color(0x19000000)
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
//border: InputBorder.none,
|
||||||
|
hintText:
|
||||||
|
"请输入手机号", // hintText: _phone.replaceFirst(RegExp(r'\d{4}'), '****', 3),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: const Color(0xFFCCCCCC), fontSize: 32.sp),
|
||||||
|
suffixIcon: GestureDetector(
|
||||||
|
onTap: () {},
|
||||||
|
// onTap: !_getCodeEnable
|
||||||
|
// ? () {}
|
||||||
|
// : () async {
|
||||||
|
// // await apiClient
|
||||||
|
// // .request(API.login.phoneCode, data: {
|
||||||
|
// // 'phone':
|
||||||
|
// // UserTool.userProvider.userInfo.phone,
|
||||||
|
// // });
|
||||||
|
// _beginCountDown();
|
||||||
|
// if (_cantSelected) return;
|
||||||
|
// _cantSelected = true;
|
||||||
|
// Future.delayed(const Duration(seconds: 1),
|
||||||
|
// () {
|
||||||
|
// _cantSelected = false;
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
child: Container(
|
||||||
|
width: 180.w,
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: const Text("获取验证码"
|
||||||
|
// _countDownStr,
|
||||||
|
// style: TextStyle(
|
||||||
|
// color: _getCodeEnable
|
||||||
|
// ? kPrimaryColor
|
||||||
|
// : BaseStyle.colorcccccc),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
//_bottomLineWidget(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输入验证码
|
||||||
|
_codeWidget() {
|
||||||
|
return Container(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
//margin: EdgeInsets.symmetric(horizontal: 20.w),
|
||||||
|
// padding: EdgeInsets.symmetric(horizontal: 72.w),
|
||||||
|
height: 40 * 2.h,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
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),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
//_bottomLineWidget(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 倒计时
|
||||||
|
// _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)),
|
||||||
|
])),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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<TabNavigator>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
TabController? _tabController;
|
||||||
|
int _pageIndex = 0;
|
||||||
|
DateTime? _lastPressed;
|
||||||
|
|
||||||
|
// 页面列表
|
||||||
|
List<Widget> _pages = <Widget>[];
|
||||||
|
|
||||||
|
@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<BottomNavigationBarItem> _bottomNav = <BottomNavigationBarItem>[
|
||||||
|
_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);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,305 @@
|
|||||||
|
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/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 StatelessWidget {
|
||||||
|
MembersPage({Key? key}) : super(key: key);
|
||||||
|
ChooseItems? _chooseItem;
|
||||||
|
List<dynamic>? data;
|
||||||
|
final List<ChooseItems> _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}
|
||||||
|
];
|
||||||
|
@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),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// _get() {
|
||||||
|
// return Stack(
|
||||||
|
// children: [
|
||||||
|
// Align(
|
||||||
|
// child: SizedBox(
|
||||||
|
// width: 750.w,
|
||||||
|
// height: 1410.w,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// Positioned(
|
||||||
|
// child: _getBanner(),
|
||||||
|
// ),
|
||||||
|
// Positioned(
|
||||||
|
// top: 224.w,
|
||||||
|
// child: Container(
|
||||||
|
// height: 1140.w,
|
||||||
|
// width: 750.w,
|
||||||
|
// decoration: const BoxDecoration(
|
||||||
|
// color: Colors.white,
|
||||||
|
// borderRadius: BorderRadius.only(
|
||||||
|
// topLeft: Radius.circular(20),
|
||||||
|
// topRight: Radius.circular(20))),
|
||||||
|
// child: Column(children: []),
|
||||||
|
// ))
|
||||||
|
// ],
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
//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;
|
||||||
|
// 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;
|
||||||
|
// 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,
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,203 @@
|
|||||||
|
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/user/members_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();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserPageState extends State<UserPage> {
|
||||||
|
bool bl = true;
|
||||||
|
@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(),
|
||||||
|
36.hb,
|
||||||
|
_getBanner(),
|
||||||
|
120.hb,
|
||||||
|
_getSwitch(Assets.icons.switch1.path, "功能开关", true),
|
||||||
|
_getSwitch(Assets.icons.privacy.path, "隐私政策", false),
|
||||||
|
_getSwitch(Assets.icons.permissions.path, "权限说明", false),
|
||||||
|
// const Spacer(),
|
||||||
|
PloneBottom(
|
||||||
|
border: false,
|
||||||
|
onTap: () {
|
||||||
|
Get.to(() => const HomePage());
|
||||||
|
},
|
||||||
|
textColor: const Color(0xFF1890FF),
|
||||||
|
color1: const Color(0xFFEBF5FF),
|
||||||
|
color2: const Color(0xFFEBF5FF),
|
||||||
|
text: "退出登录",
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//头像
|
||||||
|
_getUser() {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.only(left: 32.w, right: 32.w, top: 199.w),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
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: 686.w,
|
||||||
|
child: Image.asset(
|
||||||
|
Assets.images.banner.path,
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
Positioned(
|
||||||
|
child: Container(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 64.w, vertical: 16.w),
|
||||||
|
child: Row(
|
||||||
|
children: [_getText(), const Spacer(), _getBotton()],
|
||||||
|
),
|
||||||
|
))
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//banner botton
|
||||||
|
_getBotton() {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Get.to(() => MembersPage());
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 16.w),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(30),
|
||||||
|
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(
|
||||||
|
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) {
|
||||||
|
bool vle = false;
|
||||||
|
return 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) {
|
||||||
|
vle = value;
|
||||||
|
// setState(() {});
|
||||||
|
})
|
||||||
|
: const Icon(Icons.keyboard_arrow_right));
|
||||||
|
}
|
||||||
|
}
|
@ -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<T> extends StatefulWidget {
|
||||||
|
final T? value;
|
||||||
|
final List<T>? 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<BeeCheckRadio> {
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
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<Widget> 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<SystemUiOverlayStyle>(
|
||||||
|
value: systemStyle,
|
||||||
|
child: Scaffold(
|
||||||
|
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<SystemUiOverlayStyle>(
|
||||||
|
value: systemStyle,
|
||||||
|
child: Scaffold(
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
class PloneAvatarWidget extends StatelessWidget {
|
||||||
|
final List<String>? 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();
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
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; //是否有边框
|
||||||
|
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,
|
||||||
|
required this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PloneBottom> createState() => _PloneBottomState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PloneBottomState extends State<PloneBottom> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: widget.onTap,
|
||||||
|
child: Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 15.w),
|
||||||
|
margin: widget.blM
|
||||||
|
? EdgeInsets.symmetric(horizontal: 32.w)
|
||||||
|
: EdgeInsets.only(left: 0.w),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: const Color(0xFF1890FF),
|
||||||
|
width: !widget.border ? 1.w : 10.w),
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: Alignment.centerLeft,
|
||||||
|
end: Alignment.centerRight,
|
||||||
|
colors: [widget.color1, widget.color2]),
|
||||||
|
borderRadius: BorderRadius.circular(8.w)),
|
||||||
|
child: Text(
|
||||||
|
widget.text,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: BaseStyle.fontSize28, color: widget.textColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
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<ChooseItems> 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
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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';
|