├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── README.md ├── assets └── images │ ├── baike.svg │ ├── baike_active.svg │ ├── banners.png │ ├── daibi.svg │ ├── jinbi.svg │ ├── jinshu.svg │ ├── loading.svg │ ├── logo.png │ ├── logo_icon.png │ ├── shandian.svg │ ├── shandian_active.svg │ ├── zixun.svg │ └── zixun_active.svg ├── lib ├── main.dart ├── model │ ├── arms_class_model.dart │ ├── arms_details.dart │ ├── arms_model.dart │ ├── bootstrap_model.dart │ ├── commit_model.dart │ ├── headlines_details_model.dart │ ├── headlines_model.dart │ ├── hero_details_model.dart │ ├── hero_model.dart │ ├── map_details_model.dart │ └── shop_details_model.dart ├── pages │ ├── encyclopedia │ │ ├── armsDetails │ │ │ ├── arms_calss.dart │ │ │ ├── arms_details.dart │ │ │ └── widgets │ │ │ │ └── arms_skin.dart │ │ ├── control.dart │ │ ├── heroDetails │ │ │ ├── control.dart │ │ │ ├── index.dart │ │ │ └── widgets │ │ │ │ ├── frame_page.dart │ │ │ │ └── skin_page.dart │ │ ├── index.dart │ │ ├── mapDetails │ │ │ └── index.dart │ │ └── widgets │ │ │ ├── arms_page.dart │ │ │ ├── legend_page.dart │ │ │ └── map_page.dart │ ├── headlines │ │ ├── control.dart │ │ ├── headDatails │ │ │ └── index.dart │ │ └── index.dart │ ├── mine │ │ └── index.dart │ ├── navigation │ │ └── bottom_bar_page.dart │ └── shop │ │ ├── index.dart │ │ ├── shop_all.dart │ │ └── shop_details.dart ├── provider │ ├── arms_provider.dart │ ├── hero_provider.dart │ └── news_provider.dart ├── routes │ └── router_config.dart ├── utils │ ├── dio.dart │ ├── instances.dart │ ├── relative_dareformat.dart │ ├── storage.dart │ └── time_format.dart └── widgets │ └── apex_tabbar.dart ├── mpdart ├── mpdart.bat ├── mpflutter ├── mpflutter.bat ├── pubspec.lock ├── pubspec.yaml ├── scripts ├── build_plugins.dart ├── build_swanapp.dart ├── build_weapp.dart ├── build_web.dart └── help.dart ├── weapp ├── app.js ├── app.json ├── app.wxss ├── kbone │ ├── miniprogram-element │ │ ├── base.js │ │ ├── base.js.map │ │ ├── custom-component │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ ├── index-vhost.js │ │ ├── index-vhost.json │ │ ├── index-vhost.wxml │ │ ├── index-vhost.wxss │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ └── template │ │ │ ├── inner-component.wxml │ │ │ ├── subtree-cover.wxml │ │ │ └── subtree.wxml │ └── miniprogram-render │ │ ├── index.js │ │ └── index.js.map ├── main.dart.js ├── mp-custom-components.js ├── mpdom.min.js ├── package.json ├── pages │ └── index │ │ ├── index.js │ │ ├── index.json │ │ └── index.wxml ├── plugins.min.js ├── plugins.wxml ├── project.config.json └── sitemap.json └── web ├── index.html └── plugins.min.js /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .dart_tool/ 3 | .packages 4 | .DS_Store 5 | lib/generated_plugin_registrant.dart 6 | .flutter-plugins 7 | .flutter-plugins-dependencies 8 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | 5 | { 6 | "name": "MPFlutter", 7 | "request": "launch", 8 | "type": "dart", 9 | "program": "lib/main.dart", 10 | "preLaunchTask": "Pre-compile MPFlutter Plugins" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dart.env": { 3 | "PUB_HOSTED_URL": "https://pub.mpflutter.com" 4 | } 5 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Pre-compile MPFlutter Plugins", 6 | "type": "shell", 7 | "command": "dart scripts/build_plugins.dart", 8 | "presentation": { 9 | "echo": false, 10 | "reveal": "silent", 11 | "focus": false, 12 | "panel": "shared", 13 | "showReuseMessage": false, 14 | "clear": true 15 | }, 16 | "problemMatcher": [] 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 环境准备 2 | 3 | 至少需要以下开发环境 4 | 5 | - 操作系统:macOS / Windows / Linux 任一操作系统 6 | - 代码编辑器:VSCode 7 | - VSCode 扩展:Dart 和 Flutter 8 | - Flutter 开发环境 9 | - Chrome 浏览器 10 | 11 | Flutter 开发环境可以在 https://flutter.dev 或 https://flutter-io.cn 下载安装。 12 | 13 | ## 开发 14 | 15 | 1. 使用 Git clone 或直接下载本仓库,使用 VSCode 打开本仓库根目录。 16 | 2. 使用命令行,locate 到本仓库根目录,执行命令 `./mpdart pub get`(*划重点,这里是执行 ./dart 而不是 dart*)。 17 | 2. 按下键盘上的 'F5' 键,开始调试,在 VSCode 的调试控制台上出现如下输出。 18 | 19 | ``` 20 | Connecting to VM Service at http://127.0.0.1:61276/OgoUGNgV_fE=/ 21 | lib/main.dart: Warning: Interpreting this as package URI, 'package:mpflutter_template/main.dart'. 22 | Hot reloading enabled 23 | Listening for file changes at ./lib 24 | Serve on 0.0.0.0:9898 25 | Use browser open http://0.0.0.0:9898/index.html or use MiniProgram Developer Tools import './dist/weapp' for dev. 26 | ``` 27 | 28 | 3. 打开 Chrome 浏览器,输入网址 http://0.0.0.0:9898/index.html ,如无意外,你将看到 Hello, MPFlutter! 提示。 29 | 4. 在 VSCode 中打开 `lib/main.dart`,尝试修改 Hello, MPFlutter! 文本,并保存,看看是否可以实现 Hot-Reload? 30 | 5. 如果没有问题,你可以在 lib 目录下开展业务开发了。 31 | 32 | ### 微信小程序 33 | 34 | 如果需要在微信小程序中实现边开发边调试能力,可以直接将 weapp 目录导入到『微信开发者工具』中。 35 | 36 | 你也可以通过修改 weapp 目录下的文件,实现定制化功能。 37 | 38 | ### iOS 39 | 40 | 如果需要在 iOS 中实现边开发边调试能力,可以使用 XCode 直接打开 iosproj 目录下的 `template.xcworkspace`,使用模拟器运行应用。 41 | 42 | 你也可以通过修改 iosproj 目录下的文件,实现定制化功能。 43 | 44 | ## 构建 45 | 46 | ### H5 47 | 48 | 使用操作系统的命令行工具,locate 到工程根目录,执行以下命令。 49 | 50 | ```sh 51 | dart scripts/build_web.dart 52 | ``` 53 | 54 | 执行完成后,H5 产物在 build 目录下,你可以上传到 HTTP 服务器上使用。 55 | 56 | ### 微信小程序 57 | 58 | 使用操作系统的命令行工具,locate 到工程根目录,执行以下命令。 59 | 60 | ```sh 61 | dart scripts/build_weapp.dart 62 | ``` 63 | 64 | 执行完成后,微信小程序产物在 build 目录下,你可以打开『微信开发者工具』,导入 build 目录,进一步编译、测试并上传审核。 65 | 66 | ### iOS 67 | 68 | 使用操作系统的命令行工具,locate 到工程根目录,执行以下命令。 69 | 70 | ```sh 71 | dart scripts/build_ios.dart 72 | ``` 73 | 74 | 执行完成后,使用 XCode 打开 iosproj/template.xcworkspace,进一步构建 ipa 包,并上传到 AppStore 审核。 75 | 76 | 注意:iOS 工程需要使用 CocoaPods 安装依赖。 -------------------------------------------------------------------------------- /assets/images/baike.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/baike_active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/banners.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itMcdull/apex_wechat/17516a3e746271259a3271fd029d9816ab497adb/assets/images/banners.png -------------------------------------------------------------------------------- /assets/images/daibi.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/jinbi.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/jinshu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/loading.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itMcdull/apex_wechat/17516a3e746271259a3271fd029d9816ab497adb/assets/images/logo.png -------------------------------------------------------------------------------- /assets/images/logo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itMcdull/apex_wechat/17516a3e746271259a3271fd029d9816ab497adb/assets/images/logo_icon.png -------------------------------------------------------------------------------- /assets/images/shandian.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/shandian_active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/zixun.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/zixun_active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/pages/navigation/bottom_bar_page.dart'; 2 | import 'package:apex_wechat/provider/arms_provider.dart'; 3 | import 'package:apex_wechat/provider/hero_provider.dart'; 4 | import 'package:apex_wechat/provider/news_provider.dart'; 5 | import 'package:apex_wechat/utils/instances.dart'; 6 | import 'package:flutter/widgets.dart'; 7 | import 'package:get/get.dart'; 8 | import 'package:mpcore/mpcore.dart'; 9 | import 'package:provider/provider.dart'; 10 | 11 | void main() { 12 | // WidgetsFlutterBinding.ensureInitialized(); 13 | initStore(); 14 | runApp(MultiProvider( 15 | providers: [ 16 | ChangeNotifierProvider( 17 | create: (_) => HeroProvider(), 18 | ), 19 | ChangeNotifierProvider( 20 | create: (_) => ArmsProvider(), 21 | ), 22 | ChangeNotifierProvider( 23 | create: (_) => NewsProvider(), 24 | ), 25 | ], 26 | child: MyApp(), 27 | )); 28 | MPCore().connectToHostChannel(); 29 | } 30 | 31 | Future initStore() async {} 32 | 33 | class MyApp extends StatelessWidget { 34 | @override 35 | Widget build(BuildContext context) { 36 | return GetMPApp( 37 | title: 'APEX', 38 | color: Colors.blue, 39 | navigatorKey: Instances.navigatorKey, 40 | routes: { 41 | '/': (context) => MainTabViewPage(), 42 | }, 43 | navigatorObservers: [MPCore.getNavigationObserver()], 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/model/arms_class_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'hero_model.dart'; 4 | 5 | class ArmsClassModel { 6 | ArmsClassModel({ 7 | this.version, 8 | this.reqId, 9 | required this.code, 10 | required this.msg, 11 | required this.data, 12 | }); 13 | 14 | factory ArmsClassModel.fromJson(Map jsonRes) => 15 | ArmsClassModel( 16 | version: asT(jsonRes['version']), 17 | reqId: asT(jsonRes['reqId']), 18 | code: asT(jsonRes['code'])!, 19 | msg: asT(jsonRes['msg'])!, 20 | data: Data.fromJson(asT>(jsonRes['data'])!), 21 | ); 22 | 23 | Object? version; 24 | Object? reqId; 25 | int code; 26 | String msg; 27 | Data data; 28 | 29 | @override 30 | String toString() { 31 | return jsonEncode(this); 32 | } 33 | 34 | Map toJson() => { 35 | 'version': version, 36 | 'reqId': reqId, 37 | 'code': code, 38 | 'msg': msg, 39 | 'data': data, 40 | }; 41 | 42 | ArmsClassModel copy() { 43 | return ArmsClassModel( 44 | version: version, 45 | reqId: reqId, 46 | code: code, 47 | msg: msg, 48 | data: data.copy(), 49 | ); 50 | } 51 | } 52 | 53 | class Data { 54 | Data({ 55 | required this.items, 56 | required this.params, 57 | }); 58 | 59 | factory Data.fromJson(Map jsonRes) { 60 | final List? items = jsonRes['items'] is List ? [] : null; 61 | if (items != null) { 62 | for (final dynamic item in jsonRes['items']!) { 63 | if (item != null) { 64 | tryCatch(() { 65 | items.add(Items.fromJson(asT>(item)!)); 66 | }); 67 | } 68 | } 69 | } 70 | 71 | final List? params = jsonRes['params'] is List ? [] : null; 72 | if (params != null) { 73 | for (final dynamic item in jsonRes['params']!) { 74 | if (item != null) { 75 | tryCatch(() { 76 | params.add(Params.fromJson(asT>(item)!)); 77 | }); 78 | } 79 | } 80 | } 81 | return Data( 82 | items: items!, 83 | params: params!, 84 | ); 85 | } 86 | 87 | List items; 88 | List params; 89 | 90 | @override 91 | String toString() { 92 | return jsonEncode(this); 93 | } 94 | 95 | Map toJson() => { 96 | 'items': items, 97 | 'params': params, 98 | }; 99 | 100 | Data copy() { 101 | return Data( 102 | items: items.map((Items e) => e.copy()).toList(), 103 | params: params.map((Params e) => e.copy()).toList(), 104 | ); 105 | } 106 | } 107 | 108 | class Items { 109 | Items({ 110 | required this.id, 111 | required this.sortId, 112 | required this.topicId, 113 | required this.armsName, 114 | required this.armsIco, 115 | required this.armsImg, 116 | required this.quickDps, 117 | required this.quickCapacity, 118 | required this.quickShotSpeed, 119 | required this.quickShotHeadDistance, 120 | required this.quickShotHeadTimes, 121 | required this.headDamage, 122 | required this.bodyDamage, 123 | required this.limbDamage, 124 | }); 125 | 126 | factory Items.fromJson(Map jsonRes) => Items( 127 | id: asT(jsonRes['id'])!, 128 | sortId: asT(jsonRes['sortId'])!, 129 | topicId: asT(jsonRes['topicId'])!, 130 | armsName: asT(jsonRes['armsName'])!, 131 | armsIco: asT(jsonRes['armsIco'])!, 132 | armsImg: asT(jsonRes['armsImg'])!, 133 | quickDps: asT(jsonRes['quickDps'])!, 134 | quickCapacity: asT(jsonRes['quickCapacity'])!, 135 | quickShotSpeed: asT(jsonRes['quickShotSpeed'])!, 136 | quickShotHeadDistance: asT(jsonRes['quickShotHeadDistance'])!, 137 | quickShotHeadTimes: asT(jsonRes['quickShotHeadTimes'])!, 138 | headDamage: asT(jsonRes['headDamage'])!, 139 | bodyDamage: asT(jsonRes['bodyDamage'])!, 140 | limbDamage: asT(jsonRes['limbDamage'])!, 141 | ); 142 | 143 | int id; 144 | int sortId; 145 | int topicId; 146 | String armsName; 147 | String armsIco; 148 | String armsImg; 149 | String quickDps; 150 | String quickCapacity; 151 | String quickShotSpeed; 152 | String quickShotHeadDistance; 153 | String quickShotHeadTimes; 154 | String headDamage; 155 | String bodyDamage; 156 | String limbDamage; 157 | 158 | @override 159 | String toString() { 160 | return jsonEncode(this); 161 | } 162 | 163 | Map toJson() => { 164 | 'id': id, 165 | 'sortId': sortId, 166 | 'topicId': topicId, 167 | 'armsName': armsName, 168 | 'armsIco': armsIco, 169 | 'armsImg': armsImg, 170 | 'quickDps': quickDps, 171 | 'quickCapacity': quickCapacity, 172 | 'quickShotSpeed': quickShotSpeed, 173 | 'quickShotHeadDistance': quickShotHeadDistance, 174 | 'quickShotHeadTimes': quickShotHeadTimes, 175 | 'headDamage': headDamage, 176 | 'bodyDamage': bodyDamage, 177 | 'limbDamage': limbDamage, 178 | }; 179 | 180 | Items copy() { 181 | return Items( 182 | id: id, 183 | sortId: sortId, 184 | topicId: topicId, 185 | armsName: armsName, 186 | armsIco: armsIco, 187 | armsImg: armsImg, 188 | quickDps: quickDps, 189 | quickCapacity: quickCapacity, 190 | quickShotSpeed: quickShotSpeed, 191 | quickShotHeadDistance: quickShotHeadDistance, 192 | quickShotHeadTimes: quickShotHeadTimes, 193 | headDamage: headDamage, 194 | bodyDamage: bodyDamage, 195 | limbDamage: limbDamage, 196 | ); 197 | } 198 | } 199 | 200 | class Params { 201 | Params({ 202 | required this.param, 203 | required this.value, 204 | required this.name, 205 | required this.remark, 206 | }); 207 | 208 | factory Params.fromJson(Map jsonRes) => Params( 209 | param: asT(jsonRes['param'])!, 210 | value: asT(jsonRes['value'])!, 211 | name: asT(jsonRes['name'])!, 212 | remark: asT(jsonRes['remark'])!, 213 | ); 214 | 215 | String param; 216 | String value; 217 | String name; 218 | String remark; 219 | 220 | @override 221 | String toString() { 222 | return jsonEncode(this); 223 | } 224 | 225 | Map toJson() => { 226 | 'param': param, 227 | 'value': value, 228 | 'name': name, 229 | 'remark': remark, 230 | }; 231 | 232 | Params copy() { 233 | return Params( 234 | param: param, 235 | value: value, 236 | name: name, 237 | remark: remark, 238 | ); 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /lib/model/arms_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'hero_model.dart'; 4 | 5 | class ArmsModel { 6 | ArmsModel({ 7 | this.version, 8 | this.reqId, 9 | required this.code, 10 | required this.msg, 11 | required this.data, 12 | }); 13 | 14 | factory ArmsModel.fromJson(Map jsonRes) { 15 | final List? data = jsonRes['data'] is List ? [] : null; 16 | if (data != null) { 17 | for (final dynamic item in jsonRes['data']!) { 18 | if (item != null) { 19 | tryCatch(() { 20 | data.add(Data.fromJson(asT>(item)!)); 21 | }); 22 | } 23 | } 24 | } 25 | return ArmsModel( 26 | version: asT(jsonRes['version']), 27 | reqId: asT(jsonRes['reqId']), 28 | code: asT(jsonRes['code'])!, 29 | msg: asT(jsonRes['msg'])!, 30 | data: data!, 31 | ); 32 | } 33 | 34 | Object? version; 35 | Object? reqId; 36 | int code; 37 | String msg; 38 | List data; 39 | 40 | @override 41 | String toString() { 42 | return jsonEncode(this); 43 | } 44 | 45 | Map toJson() => { 46 | 'version': version, 47 | 'reqId': reqId, 48 | 'code': code, 49 | 'msg': msg, 50 | 'data': data, 51 | }; 52 | 53 | ArmsModel copy() { 54 | return ArmsModel( 55 | version: version, 56 | reqId: reqId, 57 | code: code, 58 | msg: msg, 59 | data: data.map((Data e) => e.copy()).toList(), 60 | ); 61 | } 62 | } 63 | 64 | class Data { 65 | Data({ 66 | required this.type, 67 | required this.id, 68 | required this.name, 69 | required this.img, 70 | this.items, 71 | }); 72 | 73 | factory Data.fromJson(Map jsonRes) => Data( 74 | type: asT(jsonRes['type'])!, 75 | id: asT(jsonRes['id'])!, 76 | name: asT(jsonRes['name'])!, 77 | img: asT(jsonRes['img'])!, 78 | items: asT(jsonRes['items']), 79 | ); 80 | 81 | int type; 82 | int id; 83 | String name; 84 | String img; 85 | Object? items; 86 | 87 | @override 88 | String toString() { 89 | return jsonEncode(this); 90 | } 91 | 92 | Map toJson() => { 93 | 'type': type, 94 | 'id': id, 95 | 'name': name, 96 | 'img': img, 97 | 'items': items, 98 | }; 99 | 100 | Data copy() { 101 | return Data( 102 | type: type, 103 | id: id, 104 | name: name, 105 | img: img, 106 | items: items, 107 | ); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/model/commit_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'hero_model.dart'; 4 | 5 | class CommitModel { 6 | CommitModel({ 7 | this.version, 8 | this.reqId, 9 | required this.code, 10 | required this.msg, 11 | required this.data, 12 | }); 13 | 14 | factory CommitModel.fromJson(Map jsonRes) => CommitModel( 15 | version: asT(jsonRes['version']), 16 | reqId: asT(jsonRes['reqId']), 17 | code: asT(jsonRes['code'])!, 18 | msg: asT(jsonRes['msg'])!, 19 | data: Data.fromJson(asT>(jsonRes['data'])!), 20 | ); 21 | 22 | Object? version; 23 | Object? reqId; 24 | int code; 25 | String msg; 26 | Data data; 27 | 28 | @override 29 | String toString() { 30 | return jsonEncode(this); 31 | } 32 | 33 | Map toJson() => { 34 | 'version': version, 35 | 'reqId': reqId, 36 | 'code': code, 37 | 'msg': msg, 38 | 'data': data, 39 | }; 40 | 41 | CommitModel copy() { 42 | return CommitModel( 43 | version: version, 44 | reqId: reqId, 45 | code: code, 46 | msg: msg, 47 | data: data.copy(), 48 | ); 49 | } 50 | } 51 | 52 | class Data { 53 | Data({ 54 | required this.lists, 55 | required this.pageNow, 56 | required this.pageSize, 57 | required this.totalSize, 58 | required this.totalPage, 59 | }); 60 | 61 | factory Data.fromJson(Map jsonRes) { 62 | final List? lists = jsonRes['list'] is List ? [] : null; 63 | if (lists != null) { 64 | for (final dynamic item in jsonRes['list']!) { 65 | if (item != null) { 66 | tryCatch(() { 67 | lists.add(Lists.fromJson(asT>(item)!)); 68 | }); 69 | } 70 | } 71 | } 72 | return Data( 73 | lists: lists!, 74 | pageNow: asT(jsonRes['pageNow'])!, 75 | pageSize: asT(jsonRes['pageSize'])!, 76 | totalSize: asT(jsonRes['totalSize'])!, 77 | totalPage: asT(jsonRes['totalPage'])!, 78 | ); 79 | } 80 | 81 | List lists; 82 | int pageNow; 83 | int pageSize; 84 | int totalSize; 85 | int totalPage; 86 | 87 | @override 88 | String toString() { 89 | return jsonEncode(this); 90 | } 91 | 92 | Map toJson() => { 93 | 'list': lists, 94 | 'pageNow': pageNow, 95 | 'pageSize': pageSize, 96 | 'totalSize': totalSize, 97 | 'totalPage': totalPage, 98 | }; 99 | 100 | Data copy() { 101 | return Data( 102 | lists: lists.map((Lists e) => e.copy()).toList(), 103 | pageNow: pageNow, 104 | pageSize: pageSize, 105 | totalSize: totalSize, 106 | totalPage: totalPage, 107 | ); 108 | } 109 | } 110 | 111 | class Lists { 112 | Lists({ 113 | required this.id, 114 | required this.articleId, 115 | required this.userId, 116 | required this.comment, 117 | required this.likeCount, 118 | required this.createTime, 119 | required this.liked, 120 | this.publisherName, 121 | this.publisherHeadImg, 122 | }); 123 | 124 | factory Lists.fromJson(Map jsonRes) => Lists( 125 | id: asT(jsonRes['id'])!, 126 | articleId: asT(jsonRes['articleId'])!, 127 | userId: asT(jsonRes['userId'])!, 128 | comment: asT(jsonRes['comment'])!, 129 | likeCount: asT(jsonRes['likeCount'])!, 130 | createTime: asT(jsonRes['createTime'])!, 131 | liked: asT(jsonRes['liked'])!, 132 | publisherName: asT(jsonRes['publisherName']), 133 | publisherHeadImg: asT(jsonRes['publisherHeadImg']), 134 | ); 135 | 136 | int id; 137 | int articleId; 138 | int userId; 139 | String comment; 140 | int likeCount; 141 | int createTime; 142 | bool liked; 143 | String? publisherName; 144 | String? publisherHeadImg; 145 | 146 | @override 147 | String toString() { 148 | return jsonEncode(this); 149 | } 150 | 151 | Map toJson() => { 152 | 'id': id, 153 | 'articleId': articleId, 154 | 'userId': userId, 155 | 'comment': comment, 156 | 'likeCount': likeCount, 157 | 'createTime': createTime, 158 | 'liked': liked, 159 | 'publisherName': publisherName, 160 | 'publisherHeadImg': publisherHeadImg, 161 | }; 162 | 163 | Lists copy() { 164 | return Lists( 165 | id: id, 166 | articleId: articleId, 167 | userId: userId, 168 | comment: comment, 169 | likeCount: likeCount, 170 | createTime: createTime, 171 | liked: liked, 172 | publisherName: publisherName, 173 | publisherHeadImg: publisherHeadImg, 174 | ); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /lib/model/headlines_details_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'hero_model.dart'; 4 | 5 | class HeadLinesDetailsModel { 6 | HeadLinesDetailsModel({ 7 | this.version, 8 | this.reqId, 9 | required this.code, 10 | required this.msg, 11 | required this.data, 12 | }); 13 | 14 | factory HeadLinesDetailsModel.fromJson(Map jsonRes) => 15 | HeadLinesDetailsModel( 16 | version: asT(jsonRes['version']), 17 | reqId: asT(jsonRes['reqId']), 18 | code: asT(jsonRes['code'])!, 19 | msg: asT(jsonRes['msg'])!, 20 | data: Data.fromJson(asT>(jsonRes['data'])!), 21 | ); 22 | 23 | Object? version; 24 | Object? reqId; 25 | int code; 26 | String msg; 27 | Data data; 28 | 29 | @override 30 | String toString() { 31 | return jsonEncode(this); 32 | } 33 | 34 | Map toJson() => { 35 | 'version': version, 36 | 'reqId': reqId, 37 | 'code': code, 38 | 'msg': msg, 39 | 'data': data, 40 | }; 41 | 42 | HeadLinesDetailsModel copy() { 43 | return HeadLinesDetailsModel( 44 | version: version, 45 | reqId: reqId, 46 | code: code, 47 | msg: msg, 48 | data: data.copy(), 49 | ); 50 | } 51 | } 52 | 53 | class Data { 54 | Data({ 55 | required this.id, 56 | required this.title, 57 | required this.coverImg, 58 | required this.readCount, 59 | required this.likeCount, 60 | this.commentCount, 61 | required this.createTime, 62 | required this.publisherName, 63 | required this.publisherHeadImg, 64 | required this.content, 65 | required this.liked, 66 | }); 67 | 68 | factory Data.fromJson(Map jsonRes) => Data( 69 | id: asT(jsonRes['id'])!, 70 | title: asT(jsonRes['title'])!, 71 | coverImg: asT(jsonRes['coverImg'])!, 72 | readCount: asT(jsonRes['readCount'])!, 73 | likeCount: asT(jsonRes['likeCount'])!, 74 | commentCount: asT(jsonRes['commentCount']), 75 | createTime: asT(jsonRes['createTime'])!, 76 | publisherName: asT(jsonRes['publisherName'])!, 77 | publisherHeadImg: asT(jsonRes['publisherHeadImg'])!, 78 | content: asT(jsonRes['content'])!, 79 | liked: asT(jsonRes['liked'])!, 80 | ); 81 | 82 | int id; 83 | String title; 84 | String coverImg; 85 | int readCount; 86 | int likeCount; 87 | Object? commentCount; 88 | int createTime; 89 | String publisherName; 90 | String publisherHeadImg; 91 | String content; 92 | bool liked; 93 | 94 | @override 95 | String toString() { 96 | return jsonEncode(this); 97 | } 98 | 99 | Map toJson() => { 100 | 'id': id, 101 | 'title': title, 102 | 'coverImg': coverImg, 103 | 'readCount': readCount, 104 | 'likeCount': likeCount, 105 | 'commentCount': commentCount, 106 | 'createTime': createTime, 107 | 'publisherName': publisherName, 108 | 'publisherHeadImg': publisherHeadImg, 109 | 'content': content, 110 | 'liked': liked, 111 | }; 112 | 113 | Data copy() { 114 | return Data( 115 | id: id, 116 | title: title, 117 | coverImg: coverImg, 118 | readCount: readCount, 119 | likeCount: likeCount, 120 | commentCount: commentCount, 121 | createTime: createTime, 122 | publisherName: publisherName, 123 | publisherHeadImg: publisherHeadImg, 124 | content: content, 125 | liked: liked, 126 | ); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /lib/model/headlines_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'hero_model.dart'; 4 | 5 | class HeadlinesModel { 6 | HeadlinesModel({ 7 | this.version, 8 | this.reqId, 9 | required this.code, 10 | required this.msg, 11 | required this.data, 12 | }); 13 | 14 | factory HeadlinesModel.fromJson(Map jsonRes) => 15 | HeadlinesModel( 16 | version: asT(jsonRes['version']), 17 | reqId: asT(jsonRes['reqId']), 18 | code: asT(jsonRes['code'])!, 19 | msg: asT(jsonRes['msg'])!, 20 | data: Data.fromJson(asT>(jsonRes['data'])!), 21 | ); 22 | 23 | Object? version; 24 | Object? reqId; 25 | int code; 26 | String msg; 27 | Data data; 28 | 29 | @override 30 | String toString() { 31 | return jsonEncode(this); 32 | } 33 | 34 | Map toJson() => { 35 | 'version': version, 36 | 'reqId': reqId, 37 | 'code': code, 38 | 'msg': msg, 39 | 'data': data, 40 | }; 41 | 42 | HeadlinesModel copy() { 43 | return HeadlinesModel( 44 | version: version, 45 | reqId: reqId, 46 | code: code, 47 | msg: msg, 48 | data: data.copy(), 49 | ); 50 | } 51 | } 52 | 53 | class Data { 54 | Data({ 55 | required this.lists, 56 | required this.pageNow, 57 | required this.pageSize, 58 | required this.totalSize, 59 | required this.totalPage, 60 | }); 61 | 62 | factory Data.fromJson(Map jsonRes) { 63 | final List? lists = jsonRes['list'] is List ? [] : null; 64 | if (lists != null) { 65 | for (final dynamic item in jsonRes['list']!) { 66 | if (item != null) { 67 | tryCatch(() { 68 | lists.add(Lists.fromJson(asT>(item)!)); 69 | }); 70 | } 71 | } 72 | } 73 | return Data( 74 | lists: lists!, 75 | pageNow: asT(jsonRes['pageNow'])!, 76 | pageSize: asT(jsonRes['pageSize'])!, 77 | totalSize: asT(jsonRes['totalSize'])!, 78 | totalPage: asT(jsonRes['totalPage'])!, 79 | ); 80 | } 81 | 82 | List lists; 83 | int pageNow; 84 | int pageSize; 85 | int totalSize; 86 | int totalPage; 87 | 88 | @override 89 | String toString() { 90 | return jsonEncode(this); 91 | } 92 | 93 | Map toJson() => { 94 | 'list': lists, 95 | 'pageNow': pageNow, 96 | 'pageSize': pageSize, 97 | 'totalSize': totalSize, 98 | 'totalPage': totalPage, 99 | }; 100 | 101 | Data copy() { 102 | return Data( 103 | lists: lists.map((Lists e) => e.copy()).toList(), 104 | pageNow: pageNow, 105 | pageSize: pageSize, 106 | totalSize: totalSize, 107 | totalPage: totalPage, 108 | ); 109 | } 110 | } 111 | 112 | class Lists { 113 | Lists({ 114 | required this.id, 115 | required this.title, 116 | required this.coverImg, 117 | required this.readCount, 118 | this.likeCount, 119 | this.commentCount, 120 | required this.createTime, 121 | required this.publisherName, 122 | required this.publisherHeadImg, 123 | }); 124 | 125 | factory Lists.fromJson(Map jsonRes) => Lists( 126 | id: asT(jsonRes['id'])!, 127 | title: asT(jsonRes['title'])!, 128 | coverImg: asT(jsonRes['coverImg'])!, 129 | readCount: asT(jsonRes['readCount'])!, 130 | likeCount: asT(jsonRes['likeCount']), 131 | commentCount: asT(jsonRes['commentCount']), 132 | createTime: asT(jsonRes['createTime'])!, 133 | publisherName: asT(jsonRes['publisherName'])!, 134 | publisherHeadImg: asT(jsonRes['publisherHeadImg'])!, 135 | ); 136 | 137 | int id; 138 | String title; 139 | String coverImg; 140 | int readCount; 141 | int? likeCount; 142 | Object? commentCount; 143 | int createTime; 144 | String publisherName; 145 | String publisherHeadImg; 146 | 147 | @override 148 | String toString() { 149 | return jsonEncode(this); 150 | } 151 | 152 | Map toJson() => { 153 | 'id': id, 154 | 'title': title, 155 | 'coverImg': coverImg, 156 | 'readCount': readCount, 157 | 'likeCount': likeCount, 158 | 'commentCount': commentCount, 159 | 'createTime': createTime, 160 | 'publisherName': publisherName, 161 | 'publisherHeadImg': publisherHeadImg, 162 | }; 163 | 164 | Lists copy() { 165 | return Lists( 166 | id: id, 167 | title: title, 168 | coverImg: coverImg, 169 | readCount: readCount, 170 | likeCount: likeCount, 171 | commentCount: commentCount, 172 | createTime: createTime, 173 | publisherName: publisherName, 174 | publisherHeadImg: publisherHeadImg, 175 | ); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /lib/model/hero_details_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'hero_model.dart'; 4 | 5 | class HeroDetailsModel { 6 | HeroDetailsModel({ 7 | this.version, 8 | this.reqId, 9 | required this.code, 10 | required this.msg, 11 | required this.data, 12 | }); 13 | 14 | factory HeroDetailsModel.fromJson(Map jsonRes) => 15 | HeroDetailsModel( 16 | version: asT(jsonRes['version']), 17 | reqId: asT(jsonRes['reqId']), 18 | code: asT(jsonRes['code'])!, 19 | msg: asT(jsonRes['msg'])!, 20 | data: Data.fromJson(asT>(jsonRes['data'])!), 21 | ); 22 | 23 | Object? version; 24 | Object? reqId; 25 | int code; 26 | String msg; 27 | Data data; 28 | 29 | @override 30 | String toString() { 31 | return jsonEncode(this); 32 | } 33 | 34 | Map toJson() => { 35 | 'version': version, 36 | 'reqId': reqId, 37 | 'code': code, 38 | 'msg': msg, 39 | 'data': data, 40 | }; 41 | 42 | HeroDetailsModel copy() { 43 | return HeroDetailsModel( 44 | version: version, 45 | reqId: reqId, 46 | code: code, 47 | msg: msg, 48 | data: data.copy(), 49 | ); 50 | } 51 | } 52 | 53 | class Data { 54 | Data({ 55 | required this.id, 56 | required this.sortId, 57 | required this.heroName, 58 | required this.heroImg, 59 | required this.heroVideo, 60 | required this.gameName, 61 | required this.realName, 62 | required this.sex, 63 | required this.nickName, 64 | required this.age, 65 | required this.height, 66 | required this.weight, 67 | required this.homeland, 68 | required this.moveSpeed, 69 | required this.motto, 70 | required this.backStory, 71 | required this.skillDesc, 72 | required this.strategy, 73 | required this.historyUpdate, 74 | required this.skills, 75 | required this.attrs, 76 | }); 77 | 78 | factory Data.fromJson(Map jsonRes) { 79 | final List? skills = jsonRes['skills'] is List ? [] : null; 80 | if (skills != null) { 81 | for (final dynamic item in jsonRes['skills']!) { 82 | if (item != null) { 83 | tryCatch(() { 84 | skills.add(Skills.fromJson(asT>(item)!)); 85 | }); 86 | } 87 | } 88 | } 89 | 90 | final List? attrs = jsonRes['attrs'] is List ? [] : null; 91 | if (attrs != null) { 92 | for (final dynamic item in jsonRes['attrs']!) { 93 | if (item != null) { 94 | tryCatch(() { 95 | attrs.add(Attrs.fromJson(asT>(item)!)); 96 | }); 97 | } 98 | } 99 | } 100 | return Data( 101 | id: asT(jsonRes['id'])!, 102 | sortId: asT(jsonRes['sortId'])!, 103 | heroName: asT(jsonRes['heroName'])!, 104 | heroImg: asT(jsonRes['heroImg'])!, 105 | heroVideo: asT(jsonRes['heroVideo'])!, 106 | gameName: asT(jsonRes['gameName'])!, 107 | realName: asT(jsonRes['realName'])!, 108 | sex: asT(jsonRes['sex'])!, 109 | nickName: asT(jsonRes['nickName'])!, 110 | age: asT(jsonRes['age'])!, 111 | height: asT(jsonRes['height'])!, 112 | weight: asT(jsonRes['weight'])!, 113 | homeland: asT(jsonRes['homeland'])!, 114 | moveSpeed: asT(jsonRes['moveSpeed'])!, 115 | motto: asT(jsonRes['motto'])!, 116 | backStory: asT(jsonRes['backStory'])!, 117 | skillDesc: asT(jsonRes['skillDesc'])!, 118 | strategy: asT(jsonRes['strategy'])!, 119 | historyUpdate: asT(jsonRes['historyUpdate'])!, 120 | skills: skills!, 121 | attrs: attrs!, 122 | ); 123 | } 124 | 125 | int id; 126 | int sortId; 127 | String heroName; 128 | String heroImg; 129 | String heroVideo; 130 | String gameName; 131 | String realName; 132 | int sex; 133 | String nickName; 134 | String age; 135 | String height; 136 | String weight; 137 | String homeland; 138 | String moveSpeed; 139 | String motto; 140 | String backStory; 141 | String skillDesc; 142 | String strategy; 143 | String historyUpdate; 144 | List skills; 145 | List attrs; 146 | 147 | @override 148 | String toString() { 149 | return jsonEncode(this); 150 | } 151 | 152 | Map toJson() => { 153 | 'id': id, 154 | 'sortId': sortId, 155 | 'heroName': heroName, 156 | 'heroImg': heroImg, 157 | 'heroVideo': heroVideo, 158 | 'gameName': gameName, 159 | 'realName': realName, 160 | 'sex': sex, 161 | 'nickName': nickName, 162 | 'age': age, 163 | 'height': height, 164 | 'weight': weight, 165 | 'homeland': homeland, 166 | 'moveSpeed': moveSpeed, 167 | 'motto': motto, 168 | 'backStory': backStory, 169 | 'skillDesc': skillDesc, 170 | 'strategy': strategy, 171 | 'historyUpdate': historyUpdate, 172 | 'skills': skills, 173 | 'attrs': attrs, 174 | }; 175 | 176 | Data copy() { 177 | return Data( 178 | id: id, 179 | sortId: sortId, 180 | heroName: heroName, 181 | heroImg: heroImg, 182 | heroVideo: heroVideo, 183 | gameName: gameName, 184 | realName: realName, 185 | sex: sex, 186 | nickName: nickName, 187 | age: age, 188 | height: height, 189 | weight: weight, 190 | homeland: homeland, 191 | moveSpeed: moveSpeed, 192 | motto: motto, 193 | backStory: backStory, 194 | skillDesc: skillDesc, 195 | strategy: strategy, 196 | historyUpdate: historyUpdate, 197 | skills: skills.map((Skills e) => e.copy()).toList(), 198 | attrs: attrs.map((Attrs e) => e.copy()).toList(), 199 | ); 200 | } 201 | } 202 | 203 | class Skills { 204 | Skills({ 205 | required this.id, 206 | required this.heroId, 207 | required this.skillName, 208 | required this.skillTitle, 209 | required this.skillImg, 210 | required this.skillContent, 211 | }); 212 | 213 | factory Skills.fromJson(Map jsonRes) => Skills( 214 | id: asT(jsonRes['id'])!, 215 | heroId: asT(jsonRes['heroId'])!, 216 | skillName: asT(jsonRes['skillName'])!, 217 | skillTitle: asT(jsonRes['skillTitle'])!, 218 | skillImg: asT(jsonRes['skillImg'])!, 219 | skillContent: asT(jsonRes['skillContent'])!, 220 | ); 221 | 222 | int id; 223 | int heroId; 224 | String skillName; 225 | String skillTitle; 226 | String skillImg; 227 | String skillContent; 228 | 229 | @override 230 | String toString() { 231 | return jsonEncode(this); 232 | } 233 | 234 | Map toJson() => { 235 | 'id': id, 236 | 'heroId': heroId, 237 | 'skillName': skillName, 238 | 'skillTitle': skillTitle, 239 | 'skillImg': skillImg, 240 | 'skillContent': skillContent, 241 | }; 242 | 243 | Skills copy() { 244 | return Skills( 245 | id: id, 246 | heroId: heroId, 247 | skillName: skillName, 248 | skillTitle: skillTitle, 249 | skillImg: skillImg, 250 | skillContent: skillContent, 251 | ); 252 | } 253 | } 254 | 255 | class Attrs { 256 | Attrs({ 257 | required this.type, 258 | required this.levels, 259 | }); 260 | 261 | factory Attrs.fromJson(Map jsonRes) { 262 | final List? levels = jsonRes['levels'] is List ? [] : null; 263 | if (levels != null) { 264 | for (final dynamic item in jsonRes['levels']!) { 265 | if (item != null) { 266 | tryCatch(() { 267 | levels.add(Levels.fromJson(asT>(item)!)); 268 | }); 269 | } 270 | } 271 | } 272 | return Attrs( 273 | type: asT(jsonRes['type'])!, 274 | levels: levels!, 275 | ); 276 | } 277 | 278 | int type; 279 | List levels; 280 | 281 | @override 282 | String toString() { 283 | return jsonEncode(this); 284 | } 285 | 286 | Map toJson() => { 287 | 'type': type, 288 | 'levels': levels, 289 | }; 290 | 291 | Attrs copy() { 292 | return Attrs( 293 | type: type, 294 | levels: levels.map((Levels e) => e.copy()).toList(), 295 | ); 296 | } 297 | } 298 | 299 | class Levels { 300 | Levels({ 301 | required this.level, 302 | required this.items, 303 | }); 304 | 305 | factory Levels.fromJson(Map jsonRes) { 306 | final List? items = jsonRes['items'] is List ? [] : null; 307 | if (items != null) { 308 | for (final dynamic item in jsonRes['items']!) { 309 | if (item != null) { 310 | tryCatch(() { 311 | items.add(Items.fromJson(asT>(item)!)); 312 | }); 313 | } 314 | } 315 | } 316 | return Levels( 317 | level: asT(jsonRes['level'])!, 318 | items: items!, 319 | ); 320 | } 321 | 322 | int level; 323 | List items; 324 | 325 | @override 326 | String toString() { 327 | return jsonEncode(this); 328 | } 329 | 330 | Map toJson() => { 331 | 'level': level, 332 | 'items': items, 333 | }; 334 | 335 | Levels copy() { 336 | return Levels( 337 | level: level, 338 | items: items.map((Items e) => e.copy()).toList(), 339 | ); 340 | } 341 | } 342 | 343 | class Items { 344 | Items({ 345 | required this.id, 346 | required this.targetId, 347 | required this.type, 348 | required this.level, 349 | required this.attrName, 350 | required this.attrImg, 351 | required this.attrDesc, 352 | required this.attrFeature, 353 | required this.token, 354 | required this.metal, 355 | required this.coin, 356 | }); 357 | 358 | factory Items.fromJson(Map jsonRes) => Items( 359 | id: asT(jsonRes['id'])!, 360 | targetId: asT(jsonRes['targetId'])!, 361 | type: asT(jsonRes['type'])!, 362 | level: asT(jsonRes['level'])!, 363 | attrName: asT(jsonRes['attrName'])!, 364 | attrImg: asT(jsonRes['attrImg'])!, 365 | attrDesc: asT(jsonRes['attrDesc'])!, 366 | attrFeature: asT(jsonRes['attrFeature'])!, 367 | token: asT(jsonRes['token'])!, 368 | metal: asT(jsonRes['metal'])!, 369 | coin: asT(jsonRes['coin'])!, 370 | ); 371 | 372 | int id; 373 | int targetId; 374 | int type; 375 | int level; 376 | String attrName; 377 | String attrImg; 378 | String attrDesc; 379 | String attrFeature; 380 | String token; 381 | String metal; 382 | String coin; 383 | 384 | @override 385 | String toString() { 386 | return jsonEncode(this); 387 | } 388 | 389 | Map toJson() => { 390 | 'id': id, 391 | 'targetId': targetId, 392 | 'type': type, 393 | 'level': level, 394 | 'attrName': attrName, 395 | 'attrImg': attrImg, 396 | 'attrDesc': attrDesc, 397 | 'attrFeature': attrFeature, 398 | 'token': token, 399 | 'metal': metal, 400 | 'coin': coin, 401 | }; 402 | 403 | Items copy() { 404 | return Items( 405 | id: id, 406 | targetId: targetId, 407 | type: type, 408 | level: level, 409 | attrName: attrName, 410 | attrImg: attrImg, 411 | attrDesc: attrDesc, 412 | attrFeature: attrFeature, 413 | token: token, 414 | metal: metal, 415 | coin: coin, 416 | ); 417 | } 418 | } 419 | -------------------------------------------------------------------------------- /lib/model/hero_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:developer'; 3 | 4 | void tryCatch(Function? f) { 5 | try { 6 | f?.call(); 7 | } catch (e, stack) { 8 | log('$e'); 9 | log('$stack'); 10 | } 11 | } 12 | 13 | class FFConvert { 14 | FFConvert._(); 15 | static T? Function(dynamic value) convert = 16 | (dynamic value) { 17 | if (value == null) { 18 | return null; 19 | } 20 | return json.decode(value.toString()) as T?; 21 | }; 22 | } 23 | 24 | T? asT(dynamic value, [T? defaultValue]) { 25 | if (value is T) { 26 | return value; 27 | } 28 | try { 29 | if (value != null) { 30 | final String valueS = value.toString(); 31 | if ('' is T) { 32 | return valueS as T; 33 | } else if (0 is T) { 34 | return int.parse(valueS) as T; 35 | } else if (0.0 is T) { 36 | return double.parse(valueS) as T; 37 | } else if (false is T) { 38 | if (valueS == '0' || valueS == '1') { 39 | return (valueS == '1') as T; 40 | } 41 | return (valueS == 'true') as T; 42 | } else { 43 | return FFConvert.convert(value); 44 | } 45 | } 46 | } catch (e, stackTrace) { 47 | log('asT<$T>', error: e, stackTrace: stackTrace); 48 | return defaultValue; 49 | } 50 | 51 | return defaultValue; 52 | } 53 | 54 | class HeroModel { 55 | HeroModel({ 56 | this.version, 57 | this.reqId, 58 | required this.code, 59 | required this.msg, 60 | required this.data, 61 | }); 62 | 63 | factory HeroModel.fromJson(Map jsonRes) { 64 | final List? data = jsonRes['data'] is List ? [] : null; 65 | if (data != null) { 66 | for (final dynamic item in jsonRes['data']!) { 67 | if (item != null) { 68 | tryCatch(() { 69 | data.add(Data.fromJson(asT>(item)!)); 70 | }); 71 | } 72 | } 73 | } 74 | return HeroModel( 75 | version: asT(jsonRes['version']), 76 | reqId: asT(jsonRes['reqId']), 77 | code: asT(jsonRes['code'])!, 78 | msg: asT(jsonRes['msg'])!, 79 | data: data!, 80 | ); 81 | } 82 | 83 | Object? version; 84 | Object? reqId; 85 | int code; 86 | String msg; 87 | List data; 88 | 89 | @override 90 | String toString() { 91 | return jsonEncode(this); 92 | } 93 | 94 | Map toJson() => { 95 | 'version': version, 96 | 'reqId': reqId, 97 | 'code': code, 98 | 'msg': msg, 99 | 'data': data, 100 | }; 101 | 102 | HeroModel copy() { 103 | return HeroModel( 104 | version: version, 105 | reqId: reqId, 106 | code: code, 107 | msg: msg, 108 | data: data.map((Data e) => e.copy()).toList(), 109 | ); 110 | } 111 | } 112 | 113 | class Data { 114 | Data({ 115 | required this.id, 116 | required this.sortId, 117 | required this.heroName, 118 | required this.heroImg, 119 | }); 120 | 121 | factory Data.fromJson(Map jsonRes) => Data( 122 | id: asT(jsonRes['id'])!, 123 | sortId: asT(jsonRes['sortId'])!, 124 | heroName: asT(jsonRes['heroName'])!, 125 | heroImg: asT(jsonRes['heroImg'])!, 126 | ); 127 | 128 | int id; 129 | int sortId; 130 | String heroName; 131 | String heroImg; 132 | 133 | @override 134 | String toString() { 135 | return jsonEncode(this); 136 | } 137 | 138 | Map toJson() => { 139 | 'id': id, 140 | 'sortId': sortId, 141 | 'heroName': heroName, 142 | 'heroImg': heroImg, 143 | }; 144 | 145 | Data copy() { 146 | return Data( 147 | id: id, 148 | sortId: sortId, 149 | heroName: heroName, 150 | heroImg: heroImg, 151 | ); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /lib/model/map_details_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'hero_model.dart'; 4 | 5 | class MapDetailsModel { 6 | MapDetailsModel({ 7 | this.version, 8 | this.reqId, 9 | required this.code, 10 | required this.msg, 11 | required this.data, 12 | }); 13 | 14 | factory MapDetailsModel.fromJson(Map jsonRes) => 15 | MapDetailsModel( 16 | version: asT(jsonRes['version']), 17 | reqId: asT(jsonRes['reqId']), 18 | code: asT(jsonRes['code'])!, 19 | msg: asT(jsonRes['msg'])!, 20 | data: Data.fromJson(asT>(jsonRes['data'])!), 21 | ); 22 | 23 | Object? version; 24 | Object? reqId; 25 | int code; 26 | String msg; 27 | Data data; 28 | 29 | @override 30 | String toString() { 31 | return jsonEncode(this); 32 | } 33 | 34 | Map toJson() => { 35 | 'version': version, 36 | 'reqId': reqId, 37 | 'code': code, 38 | 'msg': msg, 39 | 'data': data, 40 | }; 41 | 42 | MapDetailsModel copy() { 43 | return MapDetailsModel( 44 | version: version, 45 | reqId: reqId, 46 | code: code, 47 | msg: msg, 48 | data: data.copy(), 49 | ); 50 | } 51 | } 52 | 53 | class Data { 54 | Data({ 55 | required this.id, 56 | required this.mapType, 57 | required this.mapName, 58 | required this.mapImg, 59 | required this.mapDesc, 60 | required this.mapHistory, 61 | required this.mapHistoryVersion, 62 | }); 63 | 64 | factory Data.fromJson(Map jsonRes) => Data( 65 | id: asT(jsonRes['id'])!, 66 | mapType: asT(jsonRes['mapType'])!, 67 | mapName: asT(jsonRes['mapName'])!, 68 | mapImg: asT(jsonRes['mapImg'])!, 69 | mapDesc: asT(jsonRes['mapDesc'])!, 70 | mapHistory: asT(jsonRes['mapHistory'])!, 71 | mapHistoryVersion: asT(jsonRes['mapHistoryVersion'])!, 72 | ); 73 | 74 | int id; 75 | int mapType; 76 | String mapName; 77 | String mapImg; 78 | String mapDesc; 79 | String mapHistory; 80 | String mapHistoryVersion; 81 | 82 | @override 83 | String toString() { 84 | return jsonEncode(this); 85 | } 86 | 87 | Map toJson() => { 88 | 'id': id, 89 | 'mapType': mapType, 90 | 'mapName': mapName, 91 | 'mapImg': mapImg, 92 | 'mapDesc': mapDesc, 93 | 'mapHistory': mapHistory, 94 | 'mapHistoryVersion': mapHistoryVersion, 95 | }; 96 | 97 | Data copy() { 98 | return Data( 99 | id: id, 100 | mapType: mapType, 101 | mapName: mapName, 102 | mapImg: mapImg, 103 | mapDesc: mapDesc, 104 | mapHistory: mapHistory, 105 | mapHistoryVersion: mapHistoryVersion, 106 | ); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /lib/model/shop_details_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'hero_model.dart'; 4 | 5 | class ShopDatailsModel { 6 | ShopDatailsModel({ 7 | this.version, 8 | this.reqId, 9 | required this.code, 10 | required this.msg, 11 | required this.data, 12 | }); 13 | 14 | factory ShopDatailsModel.fromJson(Map jsonRes) => 15 | ShopDatailsModel( 16 | version: asT(jsonRes['version']), 17 | reqId: asT(jsonRes['reqId']), 18 | code: asT(jsonRes['code'])!, 19 | msg: asT(jsonRes['msg'])!, 20 | data: Data.fromJson(asT>(jsonRes['data'])!), 21 | ); 22 | 23 | Object? version; 24 | Object? reqId; 25 | int code; 26 | String msg; 27 | Data data; 28 | 29 | @override 30 | String toString() { 31 | return jsonEncode(this); 32 | } 33 | 34 | Map toJson() => { 35 | 'version': version, 36 | 'reqId': reqId, 37 | 'code': code, 38 | 'msg': msg, 39 | 'data': data, 40 | }; 41 | 42 | ShopDatailsModel copy() { 43 | return ShopDatailsModel( 44 | version: version, 45 | reqId: reqId, 46 | code: code, 47 | msg: msg, 48 | data: data.copy(), 49 | ); 50 | } 51 | } 52 | 53 | class Data { 54 | Data({ 55 | required this.id, 56 | required this.topicId, 57 | required this.itemName, 58 | required this.itemImg, 59 | required this.content, 60 | required this.contentPics, 61 | required this.createTime, 62 | }); 63 | 64 | factory Data.fromJson(Map jsonRes) { 65 | final List? contentPics = 66 | jsonRes['contentPics'] is List ? [] : null; 67 | if (contentPics != null) { 68 | for (final dynamic item in jsonRes['contentPics']!) { 69 | if (item != null) { 70 | tryCatch(() { 71 | contentPics.add(asT(item)!); 72 | }); 73 | } 74 | } 75 | } 76 | return Data( 77 | id: asT(jsonRes['id'])!, 78 | topicId: asT(jsonRes['topicId'])!, 79 | itemName: asT(jsonRes['itemName'])!, 80 | itemImg: asT(jsonRes['itemImg'])!, 81 | content: asT(jsonRes['content'])!, 82 | contentPics: contentPics!, 83 | createTime: asT(jsonRes['createTime'])!, 84 | ); 85 | } 86 | 87 | int id; 88 | int topicId; 89 | String itemName; 90 | String itemImg; 91 | String content; 92 | List contentPics; 93 | int createTime; 94 | 95 | @override 96 | String toString() { 97 | return jsonEncode(this); 98 | } 99 | 100 | Map toJson() => { 101 | 'id': id, 102 | 'topicId': topicId, 103 | 'itemName': itemName, 104 | 'itemImg': itemImg, 105 | 'content': content, 106 | 'contentPics': contentPics, 107 | 'createTime': createTime, 108 | }; 109 | 110 | Data copy() { 111 | return Data( 112 | id: id, 113 | topicId: topicId, 114 | itemName: itemName, 115 | itemImg: itemImg, 116 | content: content, 117 | contentPics: contentPics.map((String e) => e).toList(), 118 | createTime: createTime, 119 | ); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/armsDetails/arms_calss.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/arms_class_model.dart'; 2 | import 'package:apex_wechat/pages/encyclopedia/armsDetails/arms_details.dart'; 3 | import 'package:apex_wechat/utils/dio.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/widgets.dart'; 6 | import 'package:get/get.dart'; 7 | import 'package:mpcore/mpcore.dart'; 8 | 9 | class ArmsClassPage extends StatefulWidget { 10 | final int id; 11 | final String name; 12 | ArmsClassPage({Key? key, required this.id, required this.name}) 13 | : super(key: key); 14 | 15 | @override 16 | _ArmsClassPageState createState() => _ArmsClassPageState(); 17 | } 18 | 19 | class _ArmsClassPageState extends State { 20 | ArmsClassModel? _armsClassModel; 21 | @override 22 | void initState() { 23 | super.initState(); 24 | WidgetsBinding.instance?.addPostFrameCallback((timeStamp) async { 25 | await Call.dispatch('/wiki/arms/sorts/${widget.id}').then((result) { 26 | if (result['code'] == 0) { 27 | _armsClassModel = ArmsClassModel.fromJson(result); 28 | if (!mounted) return; 29 | setState(() {}); 30 | } 31 | }); 32 | }); 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return MPScaffold( 38 | name: '枪械类型', 39 | backgroundColor: Color(0xffeeeeee), 40 | body: _armsClassModel == null 41 | ? Container( 42 | width: 120, 43 | height: 120, 44 | child: Image.asset('assets/images/loading.svg'), 45 | ) 46 | : Container( 47 | padding: EdgeInsets.all(10), 48 | child: ListView(children: [ 49 | _banners(widget.name), 50 | Column( 51 | children: _armsClassModel!.data.items.map((e) { 52 | return GestureDetector( 53 | onTap: () { 54 | Get.to(() => ArmsDetailsPage( 55 | id: e.id, 56 | name: e.armsName, 57 | )); 58 | }, 59 | child: Container( 60 | height: 90, 61 | alignment: Alignment.centerRight, 62 | padding: EdgeInsets.all(10), 63 | decoration: BoxDecoration( 64 | gradient: LinearGradient(colors: [ 65 | Color(0xffabbaab), 66 | // Color(0xff6dd5fa), 67 | Color(0xffffffff), 68 | ]), 69 | image: DecorationImage( 70 | image: AssetImage( 71 | 'assets/images/logo_icon.png'), 72 | fit: BoxFit.cover), 73 | borderRadius: 74 | BorderRadius.all(Radius.circular(10))), 75 | margin: EdgeInsets.only(bottom: 10), 76 | width: MediaQuery.of(context).size.width, 77 | child: Row( 78 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 79 | children: [ 80 | Expanded( 81 | child: Column( 82 | mainAxisAlignment: MainAxisAlignment.end, 83 | crossAxisAlignment: 84 | CrossAxisAlignment.start, 85 | children: [ 86 | Text( 87 | e.armsName, 88 | style: TextStyle( 89 | color: Colors.white, fontSize: 14), 90 | ), 91 | SizedBox( 92 | height: 5, 93 | ), 94 | Row( 95 | children: [ 96 | _armsDetailsItem( 97 | title: "弹容", 98 | value: e.quickCapacity), 99 | SizedBox( 100 | width: 5, 101 | ), 102 | _armsDetailsItem( 103 | title: "射速", 104 | value: e.quickShotSpeed), 105 | ], 106 | ), 107 | SizedBox( 108 | height: 5, 109 | ), 110 | Row( 111 | children: [ 112 | _armsDetailsItem( 113 | title: "爆头倍率", 114 | value: e.quickShotHeadTimes), 115 | SizedBox( 116 | width: 5, 117 | ), 118 | _armsDetailsItem( 119 | title: "秒伤", value: e.quickDps), 120 | ], 121 | ), 122 | ], 123 | ), 124 | ), 125 | Container( 126 | width: 140, 127 | height: 40, 128 | child: Image.network( 129 | e.armsImg, 130 | ), 131 | ), 132 | ], 133 | )), 134 | ); 135 | }).toList(), 136 | ), 137 | _banners(widget.name + '默认数据'), 138 | Container( 139 | width: MediaQuery.of(context).size.width, 140 | height: 24, 141 | padding: EdgeInsets.only(left: 10), 142 | child: Text( 143 | '此表格内所有数据来自游戏资源拆包', 144 | style: TextStyle( 145 | color: Color(0xff333333), 146 | ), 147 | ), 148 | ), 149 | Container( 150 | width: MediaQuery.of(context).size.width, 151 | padding: EdgeInsets.only(left: 10), 152 | child: Text( 153 | '游戏中如果枪械没有单独设计数据,则会使用下表中的数据。', 154 | softWrap: true, 155 | style: TextStyle(fontSize: 14), 156 | ), 157 | ), 158 | Container( 159 | width: MediaQuery.of(context).size.width, 160 | color: Color(0xfff8f8f8), 161 | padding: EdgeInsets.symmetric(horizontal: 10), 162 | height: 30, 163 | child: Row( 164 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 165 | children: [ 166 | Expanded(child: Text('数据名')), 167 | Container( 168 | width: 40, 169 | alignment: Alignment.center, 170 | child: Text('值'), 171 | ), 172 | Expanded( 173 | child: Container( 174 | alignment: Alignment.centerRight, 175 | child: Text('备注'), 176 | )) 177 | ], 178 | ), 179 | ), 180 | Column( 181 | children: _armsClassModel!.data.params.map((e) { 182 | return Container( 183 | width: MediaQuery.of(context).size.width, 184 | padding: EdgeInsets.symmetric(horizontal: 10), 185 | decoration: BoxDecoration( 186 | border: Border( 187 | bottom: BorderSide( 188 | color: Color(0xffeeeeee), width: 1)), 189 | color: Colors.white, 190 | ), 191 | height: 40, 192 | child: Row( 193 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 194 | children: [ 195 | Expanded( 196 | child: Text(e.name), 197 | ), 198 | Container( 199 | width: 40, 200 | alignment: Alignment.center, 201 | child: Text(e.value), 202 | ), 203 | Expanded( 204 | child: Container( 205 | alignment: Alignment.centerRight, 206 | child: Text(e.remark), 207 | ), 208 | ), 209 | ], 210 | ), 211 | ); 212 | }).toList(), 213 | ), 214 | SizedBox( 215 | height: 80, 216 | ) 217 | ]), 218 | )); 219 | } 220 | 221 | _banners(String name) { 222 | return Container( 223 | margin: EdgeInsets.symmetric(vertical: 10), 224 | padding: EdgeInsets.symmetric(horizontal: 8), 225 | decoration: BoxDecoration( 226 | color: Colors.black, 227 | ), 228 | height: 40, 229 | alignment: Alignment.centerLeft, 230 | child: Row( 231 | children: [ 232 | SizedBox( 233 | height: 20, 234 | width: 20, 235 | child: Image.asset( 236 | 'assets/images/logo_icon.png', 237 | fit: BoxFit.cover, 238 | ), 239 | ), 240 | SizedBox( 241 | width: 10, 242 | ), 243 | Text( 244 | name, 245 | style: TextStyle( 246 | fontSize: 16, 247 | fontWeight: FontWeight.bold, 248 | color: Colors.white), 249 | ), 250 | ], 251 | )); 252 | } 253 | 254 | _armsDetailsItem({ 255 | required String title, 256 | required String value, 257 | }) { 258 | return Row( 259 | children: [ 260 | Text( 261 | '$title:', 262 | style: TextStyle( 263 | color: Color(0xff666666), 264 | ), 265 | ), 266 | Text( 267 | value, 268 | style: TextStyle( 269 | fontSize: 12, 270 | foreground: Paint() 271 | ..shader = LinearGradient(colors: [ 272 | Colors.red, 273 | Colors.black, 274 | ]).createShader(Rect.fromLTWH(0, 0, 150, 0))), 275 | ), 276 | ], 277 | ); 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/armsDetails/arms_details.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/arms_details.dart'; 2 | import 'package:apex_wechat/pages/encyclopedia/armsDetails/widgets/arms_skin.dart'; 3 | import 'package:apex_wechat/utils/dio.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | import 'package:mpcore/mpcore.dart'; 6 | 7 | class ArmsDetailsPage extends StatefulWidget { 8 | final String name; 9 | final int id; 10 | ArmsDetailsPage({Key? key, required this.name, required this.id}) 11 | : super(key: key); 12 | 13 | @override 14 | _ArmsDetailsPageState createState() => _ArmsDetailsPageState(); 15 | } 16 | 17 | class _ArmsDetailsPageState extends State { 18 | ArmsDetailsModel? _armsDetailsModel; 19 | List> _list = []; 20 | @override 21 | void initState() { 22 | super.initState(); 23 | WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { 24 | Call.dispatch('/wiki/arms/${widget.id}').then((result) { 25 | if (result['code'] == 0) { 26 | _armsDetailsModel = ArmsDetailsModel.fromJson(result); 27 | _list = [ 28 | {'title': '距离', 'value': _armsDetailsModel!.data.distance}, 29 | {'title': '精准度', 'value': _armsDetailsModel!.data.accuracy}, 30 | {'title': '射速', 'value': _armsDetailsModel!.data.shotSpeed}, 31 | {'title': '头部伤害', 'value': _armsDetailsModel!.data.headDamage}, 32 | {'title': '身体伤害', 'value': _armsDetailsModel!.data.bodyDamage}, 33 | {'title': '四肢伤害', 'value': _armsDetailsModel!.data.limbDamage}, 34 | {'title': '秒伤', 'value': _armsDetailsModel!.data.dps}, 35 | {'title': '弹道速度', 'value': _armsDetailsModel!.data.trajectorySpeed}, 36 | { 37 | 'title': '战术换弹', 38 | 'value': _armsDetailsModel!.data.bulletChangeSpeed 39 | }, 40 | { 41 | 'title': '完整换弹', 42 | 'value': _armsDetailsModel!.data.bulletFullChangeSpeed 43 | }, 44 | {'title': '弹夹容量', 'value': _armsDetailsModel!.data.capacity}, 45 | {'title': '竞技场价格', 'value': _armsDetailsModel!.data.arenaPrice}, 46 | ]; 47 | if (!mounted) return; 48 | setState(() {}); 49 | } 50 | }); 51 | }); 52 | } 53 | 54 | @override 55 | Widget build(BuildContext context) { 56 | return MPScaffold( 57 | name: widget.name, 58 | backgroundColor: Color(0xffeeeeee), 59 | body: _armsDetailsModel == null 60 | ? Container( 61 | width: 120, 62 | height: 120, 63 | child: Image.asset('assets/images/loading.svg'), 64 | ) 65 | : Container( 66 | padding: EdgeInsets.symmetric(horizontal: 10), 67 | child: ListView( 68 | children: [ 69 | // _banners(widget.name), 70 | Container( 71 | height: 140, 72 | alignment: Alignment.centerRight, 73 | padding: EdgeInsets.all(10), 74 | decoration: BoxDecoration( 75 | gradient: LinearGradient(colors: [ 76 | Color(0xffabbaab), 77 | Color(0xffffffff), 78 | ]), 79 | ), 80 | margin: EdgeInsets.only(bottom: 10, top: 10), 81 | width: MediaQuery.of(context).size.width, 82 | child: Row( 83 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 84 | children: [ 85 | Expanded( 86 | child: Column( 87 | mainAxisAlignment: MainAxisAlignment.center, 88 | children: [ 89 | Text( 90 | _armsDetailsModel!.data.armsName, 91 | style: TextStyle( 92 | fontSize: 16, 93 | fontWeight: FontWeight.bold), 94 | ), 95 | SizedBox(height: 10), 96 | Text( 97 | _armsDetailsModel!.data.armsType, 98 | style: TextStyle( 99 | color: Color(0xffeeeeee), fontSize: 14), 100 | ), 101 | SizedBox(height: 10), 102 | Text( 103 | _armsDetailsModel!.data.armsShotType, 104 | style: TextStyle( 105 | color: Color(0xffeeeeee), fontSize: 14), 106 | ), 107 | ], 108 | ), 109 | ), 110 | Container( 111 | width: 140, 112 | height: 40, 113 | child: Image.network( 114 | _armsDetailsModel!.data.armsImg, 115 | ), 116 | ), 117 | ], 118 | )), 119 | 120 | SizedBox( 121 | height: 5, 122 | ), 123 | Container( 124 | decoration: BoxDecoration( 125 | color: Colors.red, 126 | borderRadius: BorderRadius.all(Radius.circular(5))), 127 | child: Column( 128 | children: _list 129 | .map( 130 | (e) => Container( 131 | height: 30, 132 | padding: EdgeInsets.symmetric(horizontal: 10), 133 | decoration: BoxDecoration( 134 | color: Colors.white, 135 | border: Border( 136 | bottom: BorderSide( 137 | color: Color(0xffeeeeee), width: 1)), 138 | // gradient: LinearGradient(colors: [ 139 | // Color(0xffabbaab), 140 | // Color(0xffffffff), 141 | // ]), 142 | ), 143 | child: Row( 144 | mainAxisAlignment: 145 | MainAxisAlignment.spaceBetween, 146 | children: [ 147 | Text(e['title']), 148 | Text(e['value']), 149 | ], 150 | ), 151 | ), 152 | ) 153 | .toList(), 154 | ), 155 | ), 156 | _banners('配件'), 157 | Container( 158 | child: Column( 159 | children: _attrItem(type: 3), 160 | ), 161 | ), 162 | _banners('瞄准镜'), 163 | Container( 164 | child: Column( 165 | children: _attrItem(type: 4), 166 | ), 167 | ), 168 | _banners('皮肤'), 169 | ArmsWidgetPage(skin: _armsDetailsModel!.data.attrs), 170 | SizedBox( 171 | height: 80, 172 | ) 173 | ], 174 | ), 175 | ), 176 | ); 177 | } 178 | 179 | _attrItem({required int type}) { 180 | List item = []; 181 | List list = _armsDetailsModel!.data.attrs 182 | .where((element) => element.type == type) 183 | .toList(); 184 | for (var i = 0; i < list.length; i++) { 185 | for (var k = 0; k < list[i].levels.length; k++) { 186 | for (var j = 0; j < list[i].levels[k].items.length; j++) { 187 | item.add(Container( 188 | height: 40, 189 | color: Colors.white, 190 | padding: EdgeInsets.all(5), 191 | margin: EdgeInsets.only(bottom: 10), 192 | child: Row( 193 | children: [ 194 | SizedBox( 195 | width: 10, 196 | ), 197 | SizedBox( 198 | width: 25, 199 | height: 25, 200 | child: Image.network( 201 | list[i].levels[k].items[j].attrImg, 202 | fit: BoxFit.contain, 203 | ), 204 | ), 205 | SizedBox( 206 | width: 10, 207 | ), 208 | Text(list[i].levels[k].items[j].attrName) 209 | ], 210 | ), 211 | )); 212 | } 213 | } 214 | } 215 | return item; 216 | } 217 | 218 | _banners(String name) { 219 | return Container( 220 | margin: EdgeInsets.symmetric(vertical: 10), 221 | padding: EdgeInsets.symmetric(horizontal: 8), 222 | decoration: BoxDecoration( 223 | color: Colors.black, 224 | ), 225 | height: 40, 226 | alignment: Alignment.centerLeft, 227 | child: Row( 228 | children: [ 229 | SizedBox( 230 | height: 20, 231 | width: 20, 232 | child: Image.asset( 233 | 'assets/images/logo_icon.png', 234 | fit: BoxFit.cover, 235 | ), 236 | ), 237 | SizedBox( 238 | width: 10, 239 | ), 240 | Text( 241 | name, 242 | style: TextStyle( 243 | fontSize: 16, 244 | fontWeight: FontWeight.bold, 245 | color: Colors.white), 246 | ), 247 | ], 248 | )); 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/armsDetails/widgets/arms_skin.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/arms_details.dart'; 2 | import 'package:apex_wechat/widgets/apex_tabbar.dart'; 3 | import 'package:flutter/widgets.dart'; 4 | import 'package:universal_miniprogram_api/wechat_mini_program/map_view.dart'; 5 | 6 | class ArmsWidgetPage extends StatefulWidget { 7 | final List skin; 8 | ArmsWidgetPage({Key? key, required this.skin}) : super(key: key); 9 | 10 | @override 11 | _ArmsWidgetPageState createState() => _ArmsWidgetPageState(); 12 | } 13 | 14 | class _ArmsWidgetPageState extends State { 15 | List> _attrsList = [ 16 | {'title': '传说', 'type': 2}, 17 | {'title': '史诗', 'type': 3}, 18 | {'title': '稀有', 'type': 4}, 19 | {'title': '普通', 'type': 5}, 20 | ]; 21 | @override 22 | Widget build(BuildContext context) { 23 | return ApexTabbarView( 24 | key: ValueKey('armsPifu'), 25 | tab: _attrsList.map((e) => e['title']).toList(), 26 | children: 27 | _attrsList.map((e) => _renderSkilItem(e['type'])).toList()); 28 | } 29 | 30 | _renderSkilItem(int type) { 31 | List item = []; 32 | List list = 33 | widget.skin.where((element) => element.type == 1).toList(); 34 | for (var i = 0; i < list.length; i++) { 35 | for (var k = 0; k < list[i].levels.length; k++) { 36 | for (var j = 0; j < list[i].levels[k].items.length; j++) { 37 | if (list[i].levels[k].items[j].level == type) { 38 | item.add(UnconstrainedBox( 39 | child: GestureDetector( 40 | onTap: () { 41 | UniversalMiniProgramApi.uni.previewImage(PreviewImageOption( 42 | showmenu: true, 43 | urls: [list[i].levels[k].items[j].attrImg], 44 | )); 45 | }, 46 | child: Container( 47 | decoration: BoxDecoration( 48 | color: Colors.white, 49 | image: DecorationImage( 50 | fit: BoxFit.cover, 51 | image: AssetImage('assets/images/logo.png'), 52 | ), 53 | borderRadius: BorderRadius.all(Radius.circular(10))), 54 | margin: EdgeInsets.symmetric(horizontal: 5), 55 | width: MediaQuery.of(context).size.width / 2.42, 56 | height: 220, 57 | child: Stack( 58 | alignment: AlignmentDirectional.bottomEnd, 59 | children: [ 60 | ClipRRect( 61 | borderRadius: BorderRadius.circular(10), 62 | child: Image.network( 63 | list[i].levels[k].items[j].attrImg, 64 | // fit: type == 3 ? BoxFit.fill : BoxFit.cover, 65 | ), 66 | ), 67 | Positioned( 68 | child: Container( 69 | width: MediaQuery.of(context).size.width / 2, 70 | height: 70, 71 | padding: EdgeInsets.all(10), 72 | child: Column( 73 | crossAxisAlignment: CrossAxisAlignment.start, 74 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 75 | children: [ 76 | SizedBox( 77 | height: 20, 78 | child: Text( 79 | list[i].levels[k].items[j].attrName, 80 | style: TextStyle( 81 | color: Colors.white, 82 | fontWeight: FontWeight.bold, 83 | fontSize: 14), 84 | ), 85 | ), 86 | SizedBox( 87 | height: 15, 88 | child: Text( 89 | list[i].levels[k].items[j].attrDesc + 90 | '' + 91 | list[i].levels[k].items[j].attrFeature, 92 | style: TextStyle( 93 | color: Colors.white, fontSize: 10), 94 | ), 95 | ), 96 | _priceRender( 97 | coin: list[i].levels[k].items[j].coin, 98 | metal: list[i].levels[k].items[j].metal, 99 | token: list[i].levels[k].items[j].token) 100 | ], 101 | ), 102 | decoration: BoxDecoration( 103 | gradient: LinearGradient( 104 | colors: [Color(0xff200122), Color(0xff6f0000)], 105 | begin: Alignment.centerLeft, 106 | end: Alignment.centerRight), 107 | borderRadius: BorderRadius.vertical( 108 | bottom: Radius.circular(10))), 109 | )) 110 | ], 111 | )), 112 | ))); 113 | } 114 | } 115 | } 116 | } 117 | 118 | return Container( 119 | height: 220, 120 | child: ListView( 121 | scrollDirection: Axis.horizontal, 122 | children: item, 123 | ), 124 | ); 125 | } 126 | 127 | Widget _priceRender( 128 | {required String token, required String metal, required String coin}) { 129 | String img = 'assets/images/jinbi.svg'; 130 | String value = ''; 131 | Color textColor = Colors.yellow; 132 | if (token != '') { 133 | img = 'assets/images/daibi.svg'; 134 | textColor = Colors.deepOrange; 135 | value = token; 136 | } else if (metal != '') { 137 | img = 'assets/images/jinshu.svg'; 138 | textColor = Colors.white; 139 | value = metal; 140 | } else { 141 | value = coin; 142 | } 143 | if (token == '' && metal == '' && coin == '') { 144 | img = ''; 145 | } 146 | return Container( 147 | height: 20, 148 | child: Row( 149 | children: [ 150 | img != '' 151 | ? Image.asset( 152 | img, 153 | width: 18, 154 | height: 18, 155 | ) 156 | : SizedBox(), 157 | SizedBox( 158 | width: 5, 159 | ), 160 | Text(value, 161 | style: TextStyle( 162 | color: textColor, fontSize: 12, fontWeight: FontWeight.bold)) 163 | ], 164 | ), 165 | ); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/control.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/arms_model.dart'; 2 | import 'package:apex_wechat/model/bootstrap_model.dart'; 3 | import 'package:apex_wechat/model/hero_model.dart'; 4 | import 'package:apex_wechat/provider/arms_provider.dart'; 5 | import 'package:apex_wechat/provider/hero_provider.dart'; 6 | import 'package:apex_wechat/utils/dio.dart'; 7 | import 'package:apex_wechat/utils/instances.dart'; 8 | import 'package:provider/provider.dart'; 9 | 10 | class EncyclopediaControl { 11 | ///获取传奇数据列表 12 | static gethero({String value = '0'}) async { 13 | await Call.dispatch('/wiki/hero/sort/$value').then((result) { 14 | if (result['code'] == 0) { 15 | Provider.of(currentContext!, listen: false) 16 | .setHero(HeroModel.fromJson(result)); 17 | } 18 | }); 19 | } 20 | 21 | ///获取枪械列表 22 | static getArms() async { 23 | await Call.dispatch('/wiki/arms/sorts').then((result) { 24 | if (result['code'] == 0) { 25 | Future.delayed(Duration(seconds: 3), () { 26 | Provider.of(currentContext!, listen: false) 27 | .setHero(ArmsModel.fromJson(result)); 28 | }); 29 | } else {} 30 | }); 31 | } 32 | 33 | ///获取枪械分类 34 | static armsTopics() async { 35 | await Call.dispatch('/wiki/arms/topics').then((result) { 36 | if (result['code'] == 0) { 37 | } else {} 38 | }); 39 | } 40 | 41 | /// 总和数据 包含所有百科页所有数据 42 | static bootstrap() async { 43 | await Call.dispatch('/wiki/bootstrap').then((result) { 44 | if (result['code'] == 0) { 45 | Provider.of(currentContext!, listen: false) 46 | .setBootstrap(BootstrapModel.fromJson(result)); 47 | } else {} 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/heroDetails/control.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/hero_details_model.dart'; 2 | import 'package:apex_wechat/provider/hero_provider.dart'; 3 | import 'package:apex_wechat/utils/dio.dart'; 4 | import 'package:apex_wechat/utils/instances.dart'; 5 | import 'package:provider/provider.dart'; 6 | 7 | class HeroDetailsControl { 8 | ///获取传奇数据列表 9 | static gethero( 10 | {int value = 1, 11 | Function(HeroDetailsModel)? onSuccess, 12 | Function(bool)? onError}) async { 13 | await Call.dispatch('/wiki/hero/$value').then((result) { 14 | if (result['code'] == 0) { 15 | onSuccess?.call(HeroDetailsModel.fromJson(result)); 16 | Provider.of(currentContext!, listen: false) 17 | .setHeroDetails(HeroDetailsModel.fromJson(result)); 18 | } else { 19 | onError?.call(false); 20 | } 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/heroDetails/widgets/frame_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/widgets/apex_tabbar.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:universal_miniprogram_api/wechat_mini_program/map_view.dart'; 4 | 5 | class JumpWidgetPage extends StatefulWidget { 6 | final List skin; 7 | JumpWidgetPage({Key? key, required this.skin}) : super(key: key); 8 | 9 | @override 10 | _JumpWidgetPageState createState() => _JumpWidgetPageState(); 11 | } 12 | 13 | class _JumpWidgetPageState extends State { 14 | List> _jumpList = [ 15 | {'title': '终结技', 'type': 4}, 16 | {'title': '跳伞动作', 'type': 5}, 17 | ]; 18 | @override 19 | Widget build(BuildContext context) { 20 | return ApexTabbarView( 21 | key: ValueKey('jumping'), 22 | tab: _jumpList.map((e) => e['title']).toList(), 23 | children: 24 | _jumpList.map((e) => _renderSkilItem(e['type'])).toList()); 25 | } 26 | 27 | _renderSkilItem(int type) { 28 | List item = []; 29 | for (var i = 0; i < widget.skin.length; i++) { 30 | for (var k = 0; k < widget.skin[i].items.length; k++) { 31 | if (widget.skin[i].items[k].type == type) { 32 | item.add(UnconstrainedBox( 33 | child: GestureDetector( 34 | onTap: () { 35 | UniversalMiniProgramApi.uni.previewImage(PreviewImageOption( 36 | showmenu: true, 37 | urls: [widget.skin[i].items[k].attrImg], 38 | )); 39 | }, 40 | child: Container( 41 | decoration: BoxDecoration( 42 | image: DecorationImage( 43 | fit: BoxFit.cover, 44 | image: AssetImage('assets/images/logo.png'), 45 | ), 46 | color: Colors.white, 47 | borderRadius: BorderRadius.all(Radius.circular(10))), 48 | margin: EdgeInsets.symmetric(horizontal: 5), 49 | width: MediaQuery.of(context).size.width / 1.5, 50 | height: 200, 51 | child: Stack( 52 | alignment: AlignmentDirectional.bottomEnd, 53 | children: [ 54 | ClipRRect( 55 | borderRadius: BorderRadius.circular(10), 56 | child: Image.network( 57 | widget.skin[i].items[k].attrImg, 58 | fit: BoxFit.contain, 59 | ), 60 | ), 61 | Positioned( 62 | child: Container( 63 | width: MediaQuery.of(context).size.width / 1.5, 64 | height: 50, 65 | padding: EdgeInsets.all(10), 66 | child: Row( 67 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 68 | crossAxisAlignment: CrossAxisAlignment.start, 69 | children: [ 70 | Column( 71 | crossAxisAlignment: CrossAxisAlignment.start, 72 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 73 | children: [ 74 | SizedBox( 75 | height: 20, 76 | child: Text( 77 | widget.skin[i].items[k].attrName, 78 | style: TextStyle( 79 | color: Colors.white, 80 | fontWeight: FontWeight.bold, 81 | fontSize: 14), 82 | ), 83 | ), 84 | SizedBox( 85 | height: 15, 86 | child: Text( 87 | widget.skin[i].items[k].attrDesc + 88 | '' + 89 | widget.skin[i].items[k].attrFeature, 90 | style: TextStyle( 91 | color: Colors.white, fontSize: 10), 92 | ), 93 | ), 94 | ], 95 | ), 96 | _priceRender( 97 | coin: widget.skin[i].items[k].coin, 98 | metal: widget.skin[i].items[k].metal, 99 | token: widget.skin[i].items[k].token) 100 | ], 101 | ), 102 | decoration: BoxDecoration( 103 | gradient: LinearGradient( 104 | colors: [Color(0xff200122), Color(0xff6f0000)], 105 | begin: Alignment.centerLeft, 106 | end: Alignment.centerRight), 107 | borderRadius: BorderRadius.vertical( 108 | bottom: Radius.circular(10))), 109 | )) 110 | ], 111 | )), 112 | ))); 113 | } 114 | } 115 | } 116 | return Container( 117 | height: 250, 118 | child: ListView( 119 | scrollDirection: Axis.horizontal, 120 | children: item, 121 | ), 122 | ); 123 | } 124 | 125 | Widget _priceRender( 126 | {required String token, required String metal, required String coin}) { 127 | String img = 'assets/images/jinbi.svg'; 128 | String value = ''; 129 | Color textColor = Colors.yellow; 130 | if (token != '') { 131 | img = 'assets/images/daibi.svg'; 132 | textColor = Colors.deepOrange; 133 | value = token; 134 | } else if (metal != '') { 135 | img = 'assets/images/jinshu.svg'; 136 | textColor = Colors.white; 137 | value = metal; 138 | } else { 139 | value = coin; 140 | } 141 | if (token == '' && metal == '' && coin == '') { 142 | img = ''; 143 | } 144 | return Container( 145 | height: 20, 146 | child: Row( 147 | children: [ 148 | img != '' 149 | ? Image.asset( 150 | img, 151 | width: 18, 152 | height: 18, 153 | ) 154 | : SizedBox(), 155 | SizedBox( 156 | width: 5, 157 | ), 158 | Text(value, 159 | style: TextStyle( 160 | color: textColor, fontSize: 12, fontWeight: FontWeight.bold)) 161 | ], 162 | ), 163 | ); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/heroDetails/widgets/skin_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/widgets/apex_tabbar.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:universal_miniprogram_api/wechat_mini_program/map_view.dart'; 4 | 5 | class SkinWidgetPage extends StatefulWidget { 6 | final List skin; 7 | SkinWidgetPage({Key? key, required this.skin}) : super(key: key); 8 | 9 | @override 10 | _SkinWidgetPageState createState() => _SkinWidgetPageState(); 11 | } 12 | 13 | class _SkinWidgetPageState extends State { 14 | List> _attrsList = [ 15 | {'title': '传说', 'type': 2}, 16 | {'title': '史诗', 'type': 3}, 17 | {'title': '稀有', 'type': 4}, 18 | {'title': '普通', 'type': 5}, 19 | ]; 20 | @override 21 | Widget build(BuildContext context) { 22 | return ApexTabbarView( 23 | key: ValueKey('pifu'), 24 | tab: _attrsList.map((e) => e['title']).toList(), 25 | children: 26 | _attrsList.map((e) => _renderSkilItem(e['type'])).toList()); 27 | } 28 | 29 | _renderSkilItem(int type) { 30 | List item = []; 31 | for (var i = 0; i < widget.skin.length; i++) { 32 | for (var k = 0; k < widget.skin[i].items.length; k++) { 33 | if (widget.skin[i].items[k].level == type) { 34 | item.add(UnconstrainedBox( 35 | child: GestureDetector( 36 | onTap: () { 37 | UniversalMiniProgramApi.uni.previewImage(PreviewImageOption( 38 | showmenu: true, 39 | urls: [widget.skin[i].items[k].attrImg], 40 | )); 41 | }, 42 | child: Container( 43 | decoration: BoxDecoration( 44 | color: Colors.white, 45 | image: DecorationImage( 46 | fit: BoxFit.cover, 47 | image: AssetImage('assets/images/logo.png'), 48 | ), 49 | borderRadius: BorderRadius.all(Radius.circular(10))), 50 | margin: EdgeInsets.symmetric(horizontal: 5), 51 | width: MediaQuery.of(context).size.width / 2.42, 52 | height: 250, 53 | child: Stack( 54 | alignment: AlignmentDirectional.bottomEnd, 55 | children: [ 56 | ClipRRect( 57 | borderRadius: BorderRadius.circular(10), 58 | child: Image.network( 59 | widget.skin[i].items[k].attrImg, 60 | // fit: type == 3 ? BoxFit.fill : BoxFit.cover, 61 | ), 62 | ), 63 | Positioned( 64 | child: Container( 65 | width: MediaQuery.of(context).size.width / 2, 66 | height: 70, 67 | padding: EdgeInsets.all(10), 68 | child: Column( 69 | crossAxisAlignment: CrossAxisAlignment.start, 70 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 71 | children: [ 72 | SizedBox( 73 | height: 20, 74 | child: Text( 75 | widget.skin[i].items[k].attrName, 76 | style: TextStyle( 77 | color: Colors.white, 78 | fontWeight: FontWeight.bold, 79 | fontSize: 14), 80 | ), 81 | ), 82 | SizedBox( 83 | height: 15, 84 | child: Text( 85 | widget.skin[i].items[k].attrDesc + 86 | '' + 87 | widget.skin[i].items[k].attrFeature, 88 | style: 89 | TextStyle(color: Colors.white, fontSize: 10), 90 | ), 91 | ), 92 | _priceRender( 93 | coin: widget.skin[i].items[k].coin, 94 | metal: widget.skin[i].items[k].metal, 95 | token: widget.skin[i].items[k].token) 96 | ], 97 | ), 98 | decoration: BoxDecoration( 99 | gradient: LinearGradient( 100 | colors: [Color(0xff200122), Color(0xff6f0000)], 101 | begin: Alignment.centerLeft, 102 | end: Alignment.centerRight), 103 | borderRadius: BorderRadius.vertical( 104 | bottom: Radius.circular(10))), 105 | )) 106 | ], 107 | )), 108 | ))); 109 | } 110 | } 111 | } 112 | return Container( 113 | height: 250, 114 | child: ListView( 115 | scrollDirection: Axis.horizontal, 116 | children: item, 117 | ), 118 | ); 119 | } 120 | 121 | Widget _priceRender( 122 | {required String token, required String metal, required String coin}) { 123 | String img = 'assets/images/jinbi.svg'; 124 | String value = ''; 125 | Color textColor = Colors.yellow; 126 | if (token != '') { 127 | img = 'assets/images/daibi.svg'; 128 | textColor = Colors.deepOrange; 129 | value = token; 130 | } else if (metal != '') { 131 | img = 'assets/images/jinshu.svg'; 132 | textColor = Colors.white; 133 | value = metal; 134 | } else { 135 | value = coin; 136 | } 137 | if (token == '' && metal == '' && coin == '') { 138 | img = ''; 139 | } 140 | return Container( 141 | height: 20, 142 | child: Row( 143 | children: [ 144 | img != '' 145 | ? Image.asset( 146 | img, 147 | width: 18, 148 | height: 18, 149 | ) 150 | : SizedBox(), 151 | SizedBox( 152 | width: 5, 153 | ), 154 | Text(value, 155 | style: TextStyle( 156 | color: textColor, fontSize: 12, fontWeight: FontWeight.bold)) 157 | ], 158 | ), 159 | ); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/index.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/pages/encyclopedia/widgets/arms_page.dart'; 2 | import 'package:apex_wechat/pages/encyclopedia/control.dart'; 3 | import 'package:apex_wechat/pages/encyclopedia/widgets/legend_page.dart'; 4 | import 'package:apex_wechat/pages/encyclopedia/widgets/map_page.dart'; 5 | import 'package:apex_wechat/utils/instances.dart'; 6 | import 'package:apex_wechat/widgets/apex_tabbar.dart'; 7 | import 'package:flutter/widgets.dart'; 8 | import 'package:mpcore/mpcore.dart'; 9 | 10 | typedef ListClass = List; 11 | typedef JsonClass = List>; 12 | 13 | const JsonClass ApexType = [ 14 | {'title': '全部', 'id': 0}, 15 | {'title': '突击型', 'id': 1}, 16 | {'title': '防御型', 'id': 4}, 17 | {'title': '支援型', 'id': 3}, 18 | {'title': '侦擦型', 'id': 2}, 19 | ]; 20 | const JsonClass MaoType = [ 21 | {'title': '大逃杀', 'id': 1}, 22 | {'title': '竞技场', 'id': 2}, 23 | ]; 24 | const JsonClass ArmsType = [ 25 | {'title': '全部', "id": 0}, 26 | {'title': '轻型', "id": 2}, 27 | {'title': '重型', "id": 3}, 28 | {'title': '能量', "id": 5}, 29 | {'title': '霰弹', "id": 4}, 30 | {'title': '弓', "id": 1}, 31 | {'title': '空投', "id": 7}, 32 | {'title': '狙击', "id": 6}, 33 | ]; 34 | const ListClass TabPageClass = ['传奇', '枪械', '地图']; 35 | 36 | class EncyclopediaPage extends StatefulWidget { 37 | final String title; 38 | EncyclopediaPage({Key? key, required this.title}) : super(key: key); 39 | 40 | @override 41 | _EncyclopediaPageState createState() => _EncyclopediaPageState(); 42 | } 43 | 44 | class _EncyclopediaPageState extends State { 45 | @override 46 | void initState() { 47 | super.initState(); 48 | // _getHeroData(); 49 | _getBootstrapData(); 50 | } 51 | 52 | // _getHeroData() { 53 | // EncyclopediaControl.gethero(); 54 | // } 55 | 56 | // _getArmsData() { 57 | // EncyclopediaControl.getArms(); 58 | // } 59 | 60 | _getBootstrapData() { 61 | EncyclopediaControl.bootstrap(); 62 | } 63 | 64 | @override 65 | Widget build(BuildContext context) { 66 | return MPScaffold( 67 | name: '百科', 68 | body: Container( 69 | constraints: BoxConstraints.expand(), 70 | child: SingleChildScrollView( 71 | child: Column( 72 | children: [ 73 | Container( 74 | height: MediaQuery.of(currentContext!).size.height / 3.3, 75 | color: Colors.red, 76 | width: MediaQuery.of(currentContext!).size.width, 77 | child: Image.asset( 78 | 'assets/images/logo.png', 79 | fit: BoxFit.cover, 80 | ), 81 | ), 82 | ApexTabbarView( 83 | key: ValueKey('all'), 84 | tab: TabPageClass, 85 | onTap: (index) {}, 86 | children: [_heroWidget, _armsWidget, _mapWidget], 87 | ), 88 | ], 89 | )))); 90 | } 91 | 92 | ///[传奇] 93 | get _heroWidget => ApexTabbarView( 94 | isDivider: false, 95 | tab: ApexType.map((e) => e['title']).toList(), 96 | key: ValueKey('hero'), 97 | children: ApexType.map((e) => ApexHeroListView( 98 | type: e['id'], 99 | )).toList(), 100 | ); 101 | 102 | ///[枪械] 103 | get _armsWidget => ApexTabbarView( 104 | key: ValueKey('arms'), 105 | isDivider: false, 106 | tab: ArmsType.map((e) => e['title']).toList(), 107 | children: ArmsType.map((e) => ApexArmsListView( 108 | type: e['id'], 109 | )).toList(), 110 | ); 111 | 112 | ///[地图] 113 | get _mapWidget => ApexTabbarView( 114 | key: ValueKey('map'), 115 | isDivider: false, 116 | tab: MaoType.map((e) => e['title']).toList(), 117 | children: MaoType.map((e) => ApexMapListView( 118 | type: e['id'], 119 | )).toList(), 120 | ); 121 | } 122 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/mapDetails/index.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:apex_wechat/model/map_details_model.dart'; 4 | import 'package:apex_wechat/utils/dio.dart'; 5 | import 'package:flutter/widgets.dart'; 6 | import 'package:mpcore/mpcore.dart'; 7 | import 'package:simple_html_css/simple_html_css.dart'; 8 | 9 | class MapDetailsPage extends StatefulWidget { 10 | final int id; 11 | final String name; 12 | MapDetailsPage({Key? key, required this.id, required this.name}) 13 | : super(key: key); 14 | 15 | @override 16 | _MapDetailsPageState createState() => _MapDetailsPageState(); 17 | } 18 | 19 | class _MapDetailsPageState extends State { 20 | MapDetailsModel? _mapDetailsModel; 21 | @override 22 | void initState() { 23 | super.initState(); 24 | WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { 25 | Call.dispatch("/wiki/map/${widget.id}").then((result) { 26 | print(json.encode(result)); 27 | if (result['code'] == 0) { 28 | _mapDetailsModel = MapDetailsModel.fromJson(result); 29 | if (!mounted) return; 30 | setState(() {}); 31 | } 32 | }); 33 | }); 34 | } 35 | 36 | @override 37 | Widget build(BuildContext context) { 38 | return MPScaffold( 39 | name: widget.name, 40 | body: _mapDetailsModel == null 41 | ? Center( 42 | child: Container( 43 | width: 120, 44 | height: 120, 45 | child: Image.asset('assets/images/loading.svg'), 46 | ), 47 | ) 48 | : Container( 49 | padding: EdgeInsets.all(10), 50 | child: ListView( 51 | children: [ 52 | _banners(_mapDetailsModel!.data.mapName), 53 | Container( 54 | padding: EdgeInsets.all(10), 55 | child: Builder( 56 | builder: (context) { 57 | return RichText( 58 | text: HTML.toTextSpan( 59 | context, 60 | _mapDetailsModel!.data.mapDesc, 61 | defaultTextStyle: TextStyle( 62 | color: Color(0xff585858), fontSize: 12), 63 | ), 64 | ); 65 | }, 66 | ), 67 | ), 68 | Container( 69 | constraints: 70 | BoxConstraints(maxHeight: 300, minHeight: 200), 71 | child: Image.network(_mapDetailsModel!.data.mapImg), 72 | ), 73 | _banners('历史更新'), 74 | Container( 75 | padding: EdgeInsets.all(10), 76 | child: Builder( 77 | builder: (context) { 78 | return RichText( 79 | text: HTML.toTextSpan( 80 | context, 81 | _mapDetailsModel!.data.mapHistory, 82 | defaultTextStyle: TextStyle( 83 | color: Color(0xff585858), fontSize: 12), 84 | ), 85 | ); 86 | }, 87 | ), 88 | ), 89 | _banners('历史地图版本'), 90 | Container( 91 | padding: EdgeInsets.all(10), 92 | child: Builder( 93 | builder: (context) { 94 | return RichText( 95 | text: HTML.toTextSpan( 96 | context, 97 | _mapDetailsModel!.data.mapHistoryVersion, 98 | defaultTextStyle: TextStyle( 99 | color: Color(0xff585858), fontSize: 12), 100 | ), 101 | ); 102 | }, 103 | ), 104 | ), 105 | SizedBox( 106 | height: 80, 107 | ) 108 | ], 109 | ), 110 | )); 111 | } 112 | 113 | /// 广告横幅 114 | Widget _banners(title) { 115 | return Container( 116 | margin: EdgeInsets.symmetric(vertical: 10), 117 | padding: EdgeInsets.symmetric(horizontal: 8), 118 | decoration: BoxDecoration( 119 | color: Colors.black, 120 | borderRadius: BorderRadius.all(Radius.circular(8))), 121 | height: 40, 122 | alignment: Alignment.centerLeft, 123 | child: Row( 124 | children: [ 125 | SizedBox( 126 | height: 20, 127 | width: 20, 128 | child: Image.asset( 129 | 'assets/images/logo_icon.png', 130 | fit: BoxFit.cover, 131 | ), 132 | ), 133 | SizedBox( 134 | width: 10, 135 | ), 136 | Text( 137 | title, 138 | style: TextStyle( 139 | fontSize: 16, 140 | fontWeight: FontWeight.bold, 141 | color: Colors.white), 142 | ), 143 | ], 144 | )); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/widgets/arms_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/bootstrap_model.dart'; 2 | import 'package:apex_wechat/pages/encyclopedia/armsDetails/arms_calss.dart'; 3 | import 'package:apex_wechat/pages/encyclopedia/armsDetails/arms_details.dart'; 4 | import 'package:apex_wechat/provider/hero_provider.dart'; 5 | import 'package:apex_wechat/utils/instances.dart'; 6 | import 'package:flutter/widgets.dart'; 7 | import 'package:get/get.dart'; 8 | import 'package:provider/provider.dart'; 9 | 10 | class ApexArmsListView extends StatelessWidget { 11 | final int type; 12 | const ApexArmsListView({Key? key, this.type = 0}) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Consumer( 17 | key: ValueKey(type), 18 | builder: (BuildContext context, HeroProvider state, Widget? child) { 19 | return Container( 20 | alignment: Alignment.centerLeft, 21 | padding: EdgeInsets.only(bottom: 56, top: 10, left: 10, right: 10), 22 | child: Wrap( 23 | spacing: 10, 24 | runSpacing: 10, 25 | alignment: WrapAlignment.start, 26 | children: _renderItem( 27 | list: state.bootstrapModel?.data.arms.groups ?? null, 28 | id: type)), 29 | ); 30 | }, 31 | ); 32 | } 33 | 34 | _renderItem({required List? list, int id = 0}) { 35 | List item = []; 36 | if (list == null) { 37 | return [ 38 | Center( 39 | child: Container( 40 | width: 120, 41 | height: 120, 42 | child: Image.asset('assets/images/loading.svg'), 43 | ), 44 | ) 45 | ]; 46 | } 47 | for (var i = 0; i < list.length; i++) { 48 | for (var k = 0; k < list[i].items.length; k++) { 49 | if (id == list[i].id) { 50 | item.add(GestureDetector( 51 | child: Container( 52 | height: 100, 53 | width: MediaQuery.of(currentContext!).size.width / 3.5, 54 | decoration: BoxDecoration( 55 | color: Color(0xffeeeeee), 56 | borderRadius: BorderRadius.all(Radius.circular(10))), 57 | child: Column( 58 | mainAxisAlignment: MainAxisAlignment.center, 59 | children: [ 60 | Container( 61 | padding: EdgeInsets.all(5), 62 | child: Image.network( 63 | list[i].items[k].img, 64 | fit: BoxFit.contain, 65 | ), 66 | height: 50, 67 | width: MediaQuery.of(currentContext!).size.width / 3.5, 68 | ), 69 | SizedBox( 70 | height: 10, 71 | ), 72 | Text(list[i].items[k].name, 73 | style: TextStyle( 74 | fontSize: 14, 75 | color: Color(0xff585858), 76 | )), 77 | ], 78 | ), 79 | ), 80 | onTap: () { 81 | if (id == 0) { 82 | Get.to(() => ArmsClassPage( 83 | id: list[i].items[k].id, 84 | name: list[i].items[k].name, 85 | )); 86 | } else { 87 | Get.to(() => ArmsDetailsPage( 88 | id: list[i].items[k].id, 89 | name: list[i].items[k].name, 90 | )); 91 | } 92 | }, 93 | )); 94 | } 95 | } 96 | } 97 | return item; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/widgets/legend_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/bootstrap_model.dart'; 2 | import 'package:apex_wechat/pages/encyclopedia/heroDetails/index.dart'; 3 | import 'package:apex_wechat/provider/hero_provider.dart'; 4 | import 'package:apex_wechat/utils/instances.dart'; 5 | import 'package:flutter/widgets.dart'; 6 | import 'package:get/get.dart'; 7 | import 'package:provider/provider.dart'; 8 | 9 | class ApexHeroListView extends StatelessWidget { 10 | final int type; 11 | const ApexHeroListView({Key? key, this.type = 0}) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Consumer( 16 | key: ValueKey(type), 17 | builder: (BuildContext context, HeroProvider state, Widget? child) { 18 | return Container( 19 | alignment: Alignment.centerLeft, 20 | padding: EdgeInsets.only(bottom: 56, top: 10, left: 10, right: 10), 21 | child: Wrap( 22 | spacing: 10, 23 | runSpacing: 10, 24 | alignment: WrapAlignment.start, 25 | children: _renderItem( 26 | list: state.bootstrapModel?.data.hero.sorts ?? null, 27 | id: type)), 28 | ); 29 | }, 30 | ); 31 | } 32 | 33 | _renderItem({required List? list, int id = 0}) { 34 | List item = []; 35 | if (list == null) { 36 | return [ 37 | Center( 38 | child: Container( 39 | width: 120, 40 | height: 120, 41 | child: Image.asset('assets/images/loading.svg'), 42 | ), 43 | ) 44 | ]; 45 | } 46 | for (var i = 0; i < list.length; i++) { 47 | for (var k = 0; k < list[i].heroes.length; k++) { 48 | if (id == list[i].id) { 49 | item.add(GestureDetector( 50 | child: Container( 51 | child: Column( 52 | children: [ 53 | SizedBox( 54 | child: Image.network( 55 | list[i].heroes[k].heroImg, 56 | fit: BoxFit.cover, 57 | ), 58 | height: 147, 59 | width: MediaQuery.of(currentContext!).size.width / 3.5, 60 | ), 61 | SizedBox( 62 | height: 10, 63 | ), 64 | Text(list[i].heroes[k].heroName, 65 | style: TextStyle( 66 | fontSize: 14, 67 | color: Color(0xff585858), 68 | )), 69 | ], 70 | ), 71 | ), 72 | onTap: () { 73 | Get.to(() => HeroDetails( 74 | id: list[i].heroes[k].id, 75 | name: list[i].heroes[k].heroName, 76 | )); 77 | }, 78 | )); 79 | } 80 | } 81 | } 82 | return item; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/pages/encyclopedia/widgets/map_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/bootstrap_model.dart'; 2 | import 'package:apex_wechat/pages/encyclopedia/mapDetails/index.dart'; 3 | import 'package:apex_wechat/provider/hero_provider.dart'; 4 | import 'package:apex_wechat/utils/instances.dart'; 5 | import 'package:flutter/widgets.dart'; 6 | import 'package:get/get.dart'; 7 | import 'package:provider/provider.dart'; 8 | 9 | class ApexMapListView extends StatelessWidget { 10 | final int type; 11 | const ApexMapListView({Key? key, this.type = 0}) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Consumer( 16 | key: ValueKey(type), 17 | builder: (BuildContext context, HeroProvider state, Widget? child) { 18 | return Container( 19 | padding: EdgeInsets.only(bottom: 56, top: 10, left: 10, right: 10), 20 | child: Wrap( 21 | spacing: 10, 22 | runSpacing: 10, 23 | alignment: WrapAlignment.start, 24 | children: _renderItem( 25 | list: state.bootstrapModel?.data.map.groups ?? null, 26 | id: type)), 27 | ); 28 | }, 29 | ); 30 | } 31 | 32 | _renderItem({required List? list, int id = 0}) { 33 | List item = []; 34 | if (list == null) { 35 | return [ 36 | Center( 37 | child: Container( 38 | width: 120, 39 | height: 120, 40 | child: Image.asset('assets/images/loading.svg'), 41 | ), 42 | ) 43 | ]; 44 | } 45 | for (var i = 0; i < list.length; i++) { 46 | for (var k = 0; k < list[i].items.length; k++) { 47 | if (id == list[i].type) { 48 | item.add(GestureDetector( 49 | onTap: () { 50 | Get.to(() => MapDetailsPage( 51 | id: list[i].items[k].id, 52 | name: list[i].items[k].mapName, 53 | )); 54 | }, 55 | child: Container( 56 | height: 140, 57 | // decoration: BoxDecoration( 58 | // color: Color(0xffeeeeee), 59 | // borderRadius: BorderRadius.all(Radius.circular(10))), 60 | width: MediaQuery.of(currentContext!).size.width / 2.3, 61 | child: Column( 62 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 63 | children: [ 64 | Container( 65 | height: 100, 66 | width: MediaQuery.of(currentContext!).size.width / 2.3, 67 | child: ClipRRect( 68 | // borderRadius: BorderRadius.only( 69 | // topLeft: Radius.circular(12), 70 | // topRight: Radius.circular(12)), 71 | child: Image.network( 72 | list[i].items[k].mapImg, 73 | fit: BoxFit.cover, 74 | ), 75 | ), 76 | ), 77 | SizedBox( 78 | height: 10, 79 | ), 80 | Text(list[i].items[k].mapName, 81 | style: TextStyle( 82 | fontSize: 14, 83 | fontWeight: FontWeight.bold, 84 | color: Color(0xff585858), 85 | )), 86 | SizedBox( 87 | height: 10, 88 | ), 89 | ], 90 | ), 91 | ), 92 | )); 93 | } 94 | } 95 | } 96 | return item; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /lib/pages/headlines/control.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/headlines_model.dart'; 2 | import 'package:apex_wechat/provider/news_provider.dart'; 3 | import 'package:apex_wechat/utils/dio.dart'; 4 | import 'package:apex_wechat/utils/instances.dart'; 5 | import 'package:provider/provider.dart'; 6 | 7 | class HeadlinesControl { 8 | /// 获取头条数据列表 9 | static getData() async { 10 | await Call.dispatch('/article/latest').then((result) { 11 | if (result['code'] == 0) { 12 | print(result); 13 | Provider.of(currentContext!, listen: false) 14 | .setHero(HeadlinesModel.fromJson(result)); 15 | } 16 | }); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/pages/headlines/index.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/pages/headlines/control.dart'; 2 | import 'package:apex_wechat/pages/headlines/headDatails/index.dart'; 3 | import 'package:apex_wechat/provider/news_provider.dart'; 4 | import 'package:apex_wechat/utils/time_format.dart'; 5 | import 'package:flutter/widgets.dart'; 6 | import 'package:get/get.dart'; 7 | import 'package:mpcore/mpcore.dart'; 8 | import 'package:provider/provider.dart'; 9 | 10 | class HeadlinesPage extends StatefulWidget { 11 | final String title; 12 | HeadlinesPage({Key? key, required this.title}) : super(key: key); 13 | 14 | @override 15 | _HeadlinesPageState createState() => _HeadlinesPageState(); 16 | } 17 | 18 | class _HeadlinesPageState extends State { 19 | @override 20 | void initState() { 21 | super.initState(); 22 | HeadlinesControl.getData(); 23 | if (!mounted) return; 24 | setState(() {}); 25 | } 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return MPScaffold( 30 | name: '头条', 31 | body: Consumer( 32 | builder: (BuildContext context, NewsProvider state, Widget? child) { 33 | return Container( 34 | padding: 35 | EdgeInsets.only(bottom: 56, right: 15, top: 15, left: 15), 36 | child: SingleChildScrollView( 37 | child: Column( 38 | children: (state.headlinesModel?.data.lists ?? []) 39 | .map((e) { 40 | return GestureDetector( 41 | onTap: () { 42 | Get.to(() => HeadlinesDetailsPage( 43 | id: e.id, 44 | )); 45 | }, 46 | child: Container( 47 | margin: EdgeInsets.only(bottom: 10), 48 | width: MediaQuery.of(context).size.width, 49 | height: 110, 50 | decoration: BoxDecoration( 51 | border: Border( 52 | left: BorderSide( 53 | color: Color.fromRGBO(221, 0, 0, 1), 54 | width: 5))), 55 | child: Row( 56 | children: [ 57 | Expanded( 58 | child: Container( 59 | color: Colors.black, 60 | padding: EdgeInsets.all(15), 61 | child: Column( 62 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 63 | crossAxisAlignment: CrossAxisAlignment.start, 64 | children: [ 65 | Text( 66 | e.title, 67 | style: TextStyle( 68 | fontSize: 14, color: Colors.white), 69 | ), 70 | Row( 71 | mainAxisAlignment: 72 | MainAxisAlignment.spaceBetween, 73 | children: [ 74 | Text( 75 | TimeFormat.dateFormat(e.createTime), 76 | style: TextStyle( 77 | fontSize: 10, color: Colors.white), 78 | ), 79 | Row( 80 | children: [ 81 | MPIcon( 82 | MaterialIcons.message, 83 | color: Colors.white, 84 | size: 14, 85 | ), 86 | SizedBox( 87 | width: 5, 88 | ), 89 | Text( 90 | (e.commentCount ?? '0').toString(), 91 | style: TextStyle( 92 | fontSize: 10, 93 | color: Colors.white), 94 | ), 95 | ], 96 | ) 97 | ], 98 | ) 99 | ], 100 | ), 101 | )), 102 | Expanded( 103 | child: SizedBox( 104 | height: 110, 105 | child: Image.network( 106 | e.coverImg, 107 | fit: BoxFit.cover, 108 | ), 109 | )), 110 | ], 111 | ), 112 | ), 113 | ); 114 | }).toList()), 115 | ), 116 | ); 117 | }, 118 | )); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /lib/pages/mine/index.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:mpcore/mpcore.dart'; 3 | 4 | class MinePage extends StatefulWidget { 5 | final String title; 6 | 7 | MinePage({Key? key, required this.title}) : super(key: key); 8 | 9 | @override 10 | _MinePageState createState() => _MinePageState(); 11 | } 12 | 13 | class _MinePageState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MPScaffold( 17 | name: '我的', 18 | body: Center( 19 | child: GestureDetector( 20 | child: Container( 21 | width: 200, 22 | height: 200, 23 | color: Colors.amber, 24 | child: Center( 25 | child: Text( 26 | 'Hello, MPFlutter!', 27 | style: TextStyle( 28 | fontSize: 18, 29 | fontWeight: FontWeight.bold, 30 | color: Colors.white, 31 | ), 32 | ), 33 | ), 34 | ), 35 | ), 36 | ), 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/pages/navigation/bottom_bar_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/pages/encyclopedia/index.dart'; 2 | import 'package:apex_wechat/pages/headlines/index.dart'; 3 | import 'package:apex_wechat/pages/mine/index.dart'; 4 | import 'package:apex_wechat/pages/shop/index.dart'; 5 | import 'package:apex_wechat/utils/instances.dart'; 6 | import 'package:flutter/widgets.dart'; 7 | import 'package:mpcore/mpkit/mpkit.dart'; 8 | import 'package:mpcore/mpcore.dart'; 9 | 10 | enum TabViewPageValue { ency, head, mine } 11 | List> _tabBarData = [ 12 | { 13 | "title": '百科', 14 | 'page': EncyclopediaPage( 15 | title: '百科', 16 | ), 17 | "icon": 'assets/images/baike.svg', 18 | "icon_active": 'assets/images/baike_active.svg' 19 | }, 20 | { 21 | "title": '商店', 22 | 'page': ShopPage( 23 | title: '商店', 24 | ), 25 | "icon": 'assets/images/shandian.svg', 26 | "icon_active": 'assets/images/shandian_active.svg' 27 | }, 28 | { 29 | "title": '头条', 30 | "page": HeadlinesPage( 31 | title: '头条', 32 | ), 33 | "icon": 'assets/images/zixun.svg', 34 | "icon_active": 'assets/images/zixun_active.svg' 35 | }, 36 | { 37 | "title": '我的', 38 | "page": MinePage( 39 | title: '我的', 40 | ), 41 | "icon": 'assets/images/zixun.svg', 42 | "icon_active": 'assets/images/zixun_active.svg' 43 | }, 44 | ]; 45 | 46 | class MainTabViewPage extends StatefulWidget { 47 | MainTabViewPage({Key? key}) : super(key: key); 48 | 49 | @override 50 | _MainTabViewPageState createState() => _MainTabViewPageState(); 51 | } 52 | 53 | class _MainTabViewPageState extends State { 54 | @override 55 | Widget build(BuildContext context) { 56 | return MPMainTabView( 57 | tabs: _renderItem(), 58 | ); 59 | } 60 | 61 | _renderItem() { 62 | List item = []; 63 | for (var i = 0; i < _tabBarData.length; i++) { 64 | item.add(bottomBarItem( 65 | icon: _tabBarData[i]['icon'], 66 | page: _tabBarData[i]['page'], 67 | activeIcon: _tabBarData[i]['icon_active'], 68 | title: _tabBarData[i]['title'])); 69 | } 70 | return item; 71 | } 72 | 73 | /// [单个item] 74 | MPMainTabItem bottomBarItem( 75 | {required String title, 76 | required Widget page, 77 | required String icon, 78 | required String activeIcon}) { 79 | return MPMainTabItem( 80 | activeTabWidget: renderIcon( 81 | icon: icon, title: title, actived: true, activeIcon: activeIcon), 82 | inactiveTabWidget: renderIcon( 83 | icon: icon, title: title, actived: false, activeIcon: activeIcon), 84 | builder: (context) => page, 85 | ); 86 | } 87 | 88 | /// [底部图标激活] 89 | Widget renderIcon( 90 | {required String icon, 91 | required String title, 92 | required bool actived, 93 | required String activeIcon}) { 94 | return Container( 95 | width: MediaQuery.of(currentContext!).size.width / _tabBarData.length, 96 | color: Color(0xffeeeeee), 97 | height: 56, 98 | child: Column( 99 | crossAxisAlignment: CrossAxisAlignment.center, 100 | mainAxisAlignment: MainAxisAlignment.center, 101 | children: [ 102 | // MPIcon(icon, color: actived ? Colors.blue : Colors.grey), 103 | SizedBox( 104 | width: 15, 105 | height: 15, 106 | child: Image.asset( 107 | actived ? activeIcon : icon, 108 | ), 109 | ), 110 | SizedBox( 111 | height: 3, 112 | ), 113 | Text( 114 | title, 115 | style: TextStyle( 116 | fontSize: 12, 117 | color: actived ? Color(0xff1296db) : Colors.black, 118 | ), 119 | ), 120 | ], 121 | )); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /lib/pages/shop/index.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/bootstrap_model.dart'; 2 | import 'package:apex_wechat/pages/shop/shop_all.dart'; 3 | import 'package:apex_wechat/pages/shop/shop_details.dart'; 4 | import 'package:apex_wechat/provider/hero_provider.dart'; 5 | import 'package:apex_wechat/utils/instances.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:get/get.dart'; 8 | import 'package:mpcore/mpcore.dart'; 9 | import 'package:provider/provider.dart'; 10 | 11 | class ShopPage extends StatefulWidget { 12 | final String title; 13 | ShopPage({Key? key, required this.title}) : super(key: key); 14 | 15 | @override 16 | _ShopPageState createState() => _ShopPageState(); 17 | } 18 | 19 | class _ShopPageState extends State { 20 | @override 21 | void initState() { 22 | super.initState(); 23 | } 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return MPScaffold( 28 | name: widget.title, 29 | body: Container( 30 | padding: EdgeInsets.all(10), 31 | child: ListView( 32 | children: [ 33 | Consumer(builder: 34 | (BuildContext context, HeroProvider state, Widget? widget) { 35 | return Column( 36 | children: _renderItem(state.bootstrapModel!.data.shop.topics), 37 | ); 38 | }), 39 | SizedBox( 40 | height: 80, 41 | ) 42 | ], 43 | ), 44 | )); 45 | } 46 | 47 | _renderItem(List topics) { 48 | List item = []; 49 | for (var i = 0; i < topics.length; i++) { 50 | item.add(Column( 51 | children: [ 52 | Container( 53 | margin: EdgeInsets.symmetric(vertical: 10), 54 | padding: EdgeInsets.symmetric(horizontal: 8), 55 | decoration: BoxDecoration( 56 | image: DecorationImage( 57 | image: AssetImage('assets/images/banners.png'), 58 | fit: BoxFit.cover), 59 | ), 60 | height: 60, 61 | alignment: Alignment.centerLeft, 62 | child: Row( 63 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 64 | children: [ 65 | Text( 66 | topics[i].topicName, 67 | style: TextStyle(fontSize: 16, color: Colors.white), 68 | ), 69 | Container( 70 | child: GestureDetector( 71 | onTap: () { 72 | Get.to(() => ShopAllPage( 73 | id: topics[i].id, 74 | name: topics[i].topicName, 75 | )); 76 | }, 77 | child: Text( 78 | '全部 >', 79 | style: TextStyle( 80 | color: Colors.white, 81 | fontSize: 12, 82 | ), 83 | ), 84 | ), 85 | ) 86 | ], 87 | )), 88 | Container( 89 | height: 180, 90 | child: Row( 91 | children: [ 92 | _shopImageItem(topics[i].items[0]), 93 | topics[i].items.length > 2 94 | ? Container( 95 | width: 130, 96 | child: Column( 97 | children: [ 98 | _shopImageItem(topics[i].items[1]), 99 | _shopImageItem(topics[i].items[2]), 100 | ], 101 | ), 102 | ) 103 | : SizedBox() 104 | ], 105 | ), 106 | ) 107 | ], 108 | )); 109 | } 110 | return item; 111 | } 112 | 113 | _shopImageItem(TopicsItems item) { 114 | return Expanded( 115 | child: GestureDetector( 116 | onTap: () { 117 | Get.to(() => ShopDetailsPage( 118 | name: item.itemName, 119 | id: item.id, 120 | )); 121 | }, 122 | child: Container( 123 | padding: EdgeInsets.all(5), 124 | height: MediaQuery.of(currentContext!).size.height, 125 | width: MediaQuery.of(currentContext!).size.width, 126 | child: Stack( 127 | alignment: Alignment.bottomLeft, 128 | children: [ 129 | ClipRRect( 130 | borderRadius: BorderRadius.circular(10), 131 | child: Image.network( 132 | item.itemImg, 133 | fit: BoxFit.cover, 134 | ), 135 | ), 136 | Container( 137 | padding: EdgeInsets.all(10), 138 | child: Text( 139 | item.itemName, 140 | style: TextStyle(color: Colors.white, fontSize: 12), 141 | ), 142 | ) 143 | ], 144 | )), 145 | )); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /lib/pages/shop/shop_all.dart: -------------------------------------------------------------------------------- 1 | // import 'package:flutter/material.dart'; 2 | import 'package:apex_wechat/model/bootstrap_model.dart'; 3 | import 'package:apex_wechat/pages/shop/shop_details.dart'; 4 | import 'package:apex_wechat/provider/hero_provider.dart'; 5 | import 'package:flutter/widgets.dart'; 6 | import 'package:get/get.dart'; 7 | import 'package:mpcore/mpcore.dart'; 8 | import 'package:provider/provider.dart'; 9 | 10 | class ShopAllPage extends StatefulWidget { 11 | final int id; 12 | final String name; 13 | ShopAllPage({Key? key, required this.id, required this.name}) 14 | : super(key: key); 15 | 16 | @override 17 | _ShopAllPageState createState() => _ShopAllPageState(); 18 | } 19 | 20 | class _ShopAllPageState extends State { 21 | @override 22 | Widget build(BuildContext context) { 23 | return MPScaffold( 24 | name: widget.name, 25 | body: Container( 26 | child: ListView( 27 | children: [ 28 | Container( 29 | margin: EdgeInsets.symmetric(vertical: 10, horizontal: 10), 30 | padding: EdgeInsets.symmetric(horizontal: 8), 31 | decoration: BoxDecoration( 32 | image: DecorationImage( 33 | image: AssetImage('assets/images/banners.png'), 34 | fit: BoxFit.cover), 35 | ), 36 | height: 60, 37 | alignment: Alignment.centerLeft, 38 | child: Text( 39 | widget.name, 40 | style: TextStyle(fontSize: 16, color: Colors.white), 41 | ), 42 | ), 43 | Consumer(builder: 44 | (BuildContext context, HeroProvider state, Widget? widgets) { 45 | return Container( 46 | child: Wrap( 47 | runSpacing: 10, 48 | spacing: 10, 49 | children: _renderItem(state.bootstrapModel!.data.shop.topics), 50 | )); 51 | }) 52 | ], 53 | ), 54 | ), 55 | ); 56 | } 57 | 58 | _renderItem(List state) { 59 | List item = []; 60 | for (var i = 0; i < state.length; i++) { 61 | if (state[i].id == widget.id) { 62 | for (var k = 0; k < state[i].items.length; k++) { 63 | item.add(GestureDetector( 64 | child: Column( 65 | children: [ 66 | Container( 67 | width: MediaQuery.of(context).size.width / 2.2, 68 | height: 100, 69 | child: Image.network(state[i].items[k].itemImg), 70 | ), 71 | Text( 72 | state[i].items[k].itemName, 73 | style: TextStyle(fontSize: 14), 74 | ) 75 | ], 76 | ), 77 | onTap: () { 78 | Get.to(() => ShopDetailsPage( 79 | name: state[i].items[k].itemName, 80 | id: state[i].items[k].id, 81 | )); 82 | }, 83 | )); 84 | } 85 | } 86 | } 87 | return item; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lib/pages/shop/shop_details.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/shop_details_model.dart'; 2 | import 'package:apex_wechat/utils/dio.dart'; 3 | import 'package:flutter/widgets.dart'; 4 | import 'package:mpcore/mpcore.dart'; 5 | import 'package:universal_miniprogram_api/universal_miniprogram_api.dart'; 6 | 7 | class ShopDetailsPage extends StatefulWidget { 8 | final String name; 9 | final int id; 10 | ShopDetailsPage({Key? key, required this.name, required this.id}) 11 | : super(key: key); 12 | 13 | @override 14 | _ShopDetailsPageState createState() => _ShopDetailsPageState(); 15 | } 16 | 17 | class _ShopDetailsPageState extends State { 18 | ShopDatailsModel? _shopDatailsModel; 19 | @override 20 | void initState() { 21 | super.initState(); 22 | WidgetsBinding.instance?.addPostFrameCallback((timeStamp) async { 23 | await Call.dispatch('/wiki/shop/topic/item/${widget.id}').then((result) { 24 | if (result['code'] == 0) { 25 | _shopDatailsModel = ShopDatailsModel.fromJson(result); 26 | if (!mounted) return; 27 | setState(() {}); 28 | } 29 | }); 30 | }); 31 | } 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return MPScaffold( 36 | name: widget.name, 37 | body: Container( 38 | child: _shopDatailsModel == null 39 | ? Center( 40 | child: Container( 41 | width: 120, 42 | height: 120, 43 | child: Image.asset('assets/images/loading.svg'), 44 | ), 45 | ) 46 | : ListView( 47 | children: [ 48 | Container( 49 | margin: EdgeInsets.symmetric(vertical: 10), 50 | padding: EdgeInsets.symmetric(horizontal: 8), 51 | decoration: BoxDecoration( 52 | image: DecorationImage( 53 | image: AssetImage('assets/images/banners.png'), 54 | fit: BoxFit.cover), 55 | ), 56 | height: 60, 57 | alignment: Alignment.centerLeft, 58 | child: Text( 59 | widget.name, 60 | style: TextStyle(fontSize: 16, color: Colors.white), 61 | ), 62 | ), 63 | Column( 64 | children: _shopDatailsModel!.data.contentPics 65 | .map( 66 | (e) => GestureDetector( 67 | onTap: () { 68 | UniversalMiniProgramApi.uni 69 | .previewImage(PreviewImageOption( 70 | showmenu: true, 71 | urls: [e], 72 | )); 73 | }, 74 | child: Container( 75 | width: MediaQuery.of(context).size.width, 76 | height: 250, 77 | child: Image.network(e), 78 | )), 79 | ) 80 | .toList(), 81 | ), 82 | SizedBox( 83 | height: 200, 84 | ) 85 | ], 86 | ), 87 | ), 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/provider/arms_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/arms_model.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class ArmsProvider with ChangeNotifier { 5 | ArmsModel? _amrsModel; 6 | 7 | void setHero(ArmsModel model) { 8 | this._amrsModel = model; 9 | notifyListeners(); 10 | } 11 | 12 | ArmsModel? get amrsModel => _amrsModel; 13 | } 14 | -------------------------------------------------------------------------------- /lib/provider/hero_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/bootstrap_model.dart'; 2 | import 'package:apex_wechat/model/hero_details_model.dart'; 3 | import 'package:apex_wechat/model/hero_model.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | class HeroProvider with ChangeNotifier { 7 | HeroModel? _heroModel; 8 | BootstrapModel? _bootstrapModel; 9 | HeroDetailsModel? _heroDetailsModel; 10 | 11 | void setHero(HeroModel model) { 12 | this._heroModel = model; 13 | notifyListeners(); 14 | } 15 | 16 | void setHeroDetails(HeroDetailsModel model) { 17 | this._heroDetailsModel = model; 18 | notifyListeners(); 19 | } 20 | 21 | void setBootstrap(BootstrapModel model) { 22 | this._bootstrapModel = model; 23 | notifyListeners(); 24 | } 25 | 26 | HeroModel? get heroModel => _heroModel; 27 | BootstrapModel? get bootstrapModel => this._bootstrapModel; 28 | HeroDetailsModel? get heroDetailsModel => this._heroDetailsModel; 29 | } 30 | 31 | enum ApexType { assault, defense, support, scout } 32 | -------------------------------------------------------------------------------- /lib/provider/news_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/model/headlines_model.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class NewsProvider with ChangeNotifier { 5 | HeadlinesModel? _headlinesModel; 6 | 7 | void setHero(HeadlinesModel model) { 8 | this._headlinesModel = model; 9 | notifyListeners(); 10 | } 11 | 12 | HeadlinesModel? get headlinesModel => this._headlinesModel; 13 | } 14 | 15 | enum ApexType { assault, defense, support, scout } 16 | -------------------------------------------------------------------------------- /lib/routes/router_config.dart: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lib/utils/dio.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | 3 | class Call { 4 | static Dio? _dio; 5 | 6 | //单例初始化配置 7 | static BaseOptions _options = new BaseOptions( 8 | receiveTimeout: 5000, 9 | sendTimeout: 4000, 10 | connectTimeout: 10000, 11 | contentType: Headers.jsonContentType, 12 | ); 13 | 14 | //实例化 15 | static Dio? buildDio() { 16 | if (_dio == null) { 17 | _dio = new Dio(_options); 18 | } 19 | return _dio; 20 | } 21 | 22 | //调用方法 23 | static dispatch( 24 | url, { 25 | bool loading = false, 26 | Map? data, 27 | String? options, 28 | int? timeout, 29 | bool forceRefresh = true, 30 | bool isfilter = false, 31 | isGetData = false, 32 | }) async { 33 | Map parameter = data ?? {}; 34 | String method = options ?? "GET"; 35 | // String token = Storage.token.value ?? ''; 36 | _options.baseUrl = 'https://api.xiuxf.xyz'; 37 | _options.headers = { 38 | 'content-type': "application/json; charset=utf-8", 39 | }; 40 | 41 | Dio? dio = buildDio(); 42 | Response response; 43 | // dio.interceptors.add(LogInterceptor(error: true)); // 打印头或主体信息,调试用 44 | dio?.options.connectTimeout = timeout ?? 10000; 45 | 46 | try { 47 | //请求 48 | // if (isGetData) { 49 | // response = await dio!.request( 50 | // url, 51 | // queryParameters: parameter, 52 | // options: Options( 53 | // method: method, 54 | // ), 55 | // ); 56 | // } else { 57 | response = await dio!.request( 58 | url, 59 | data: parameter, 60 | options: Options( 61 | method: method, 62 | ), 63 | ); 64 | // } 65 | 66 | return response.data; 67 | } on DioError catch (e) { 68 | var error = formatError(e); 69 | return {'code': -998, 'msg': error, 'data': ''}; 70 | } 71 | } 72 | } 73 | 74 | formatError(DioError e) { 75 | var item = 'Network Error'; 76 | if (e.type == DioErrorType.connectTimeout) { 77 | item = '连接超时'; 78 | print("连接超时"); 79 | } else if (e.type == DioErrorType.sendTimeout) { 80 | item = '请求超时'; 81 | print("请求超时"); 82 | } else if (e.type == DioErrorType.receiveTimeout) { 83 | item = '响应超时'; 84 | print("响应超时"); 85 | } else if (e.type == DioErrorType.response) { 86 | item = '出现异常'; 87 | print("出现异常"); 88 | } else if (e.type == DioErrorType.cancel) { 89 | item = '请求取消'; 90 | print("请求取消"); 91 | } else if (e.type == DioErrorType.other) { 92 | item = '服务器开小差了~~'; 93 | } else { 94 | item = '未知错误'; 95 | print("未知错误"); 96 | } 97 | return item; 98 | } 99 | -------------------------------------------------------------------------------- /lib/utils/instances.dart: -------------------------------------------------------------------------------- 1 | //获取全局的currentState 2 | import 'package:flutter/widgets.dart'; 3 | 4 | NavigatorState? get navigatorState => Instances.navigatorKey.currentState; 5 | //获取全局的上下文 6 | BuildContext? get currentContext => navigatorState?.context; 7 | //获取当前时间 8 | DateTime get currentTime => DateTime.now(); 9 | 10 | RouteObserver> get routeObserver => Instances.routeObserver; 11 | 12 | //实列对象 13 | class Instances { 14 | const Instances._(); 15 | 16 | static final GlobalKey navigatorKey = 17 | GlobalKey(); 18 | static final RouteObserver> routeObserver = RouteObserver(); 19 | } 20 | -------------------------------------------------------------------------------- /lib/utils/relative_dareformat.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/utils/time_format.dart'; 2 | 3 | class RelativeDateFormat { 4 | static final num oneMinute = 60000; 5 | static final num oneHour = 3600000; 6 | static final num oneDay = 86400000; 7 | static final num oneWeek = 604800000; 8 | 9 | static final String oneSecondAgo = "秒前"; 10 | static final String oneMinuteAgo = "分钟前"; 11 | static final String oneHourAgo = "小时前"; 12 | static final String oneDayAgo = "天前"; 13 | static final String oneMonthAgo = "月前"; 14 | static final String oneYearAgo = "年前"; 15 | 16 | //时间转换 17 | static String format(int date) { 18 | num delta = DateTime.now().millisecondsSinceEpoch - date * 1000; 19 | if (delta < 1 * oneMinute) { 20 | num seconds = toSeconds(delta); 21 | return (seconds <= 0 ? 1 : seconds).toInt().toString() + oneSecondAgo; 22 | } 23 | if (delta < 45 * oneMinute) { 24 | num minutes = toMinutes(delta); 25 | return (minutes <= 0 ? 1 : minutes).toInt().toString() + oneMinuteAgo; 26 | } 27 | if (delta < 24 * oneHour) { 28 | num hours = toHours(delta); 29 | return (hours <= 0 ? 1 : hours).toInt().toString() + oneHourAgo; 30 | } 31 | if (delta < 48 * oneHour) { 32 | return "昨天"; 33 | } 34 | // if (delta < 30 * oneDay) { 35 | // num days = toDays(delta); 36 | // return (days <= 0 ? 1 : days).toInt().toString() + oneDayAgo; 37 | // } 38 | return TimeFormat.dateFormat(date); 39 | } 40 | 41 | static num toSeconds(num date) { 42 | return date / 1000; 43 | } 44 | 45 | static num toMinutes(num date) { 46 | return toSeconds(date) / 60; 47 | } 48 | 49 | static num toHours(num date) { 50 | return toMinutes(date) / 60; 51 | } 52 | 53 | static num toDays(num date) { 54 | return toHours(date) / 24; 55 | } 56 | 57 | static num toMonths(num date) { 58 | return toDays(date) / 30; 59 | } 60 | 61 | static num toYears(num date) { 62 | return toMonths(date) / 365; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/utils/storage.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'package:shared_preferences/shared_preferences.dart'; 3 | 4 | // 本地存储 5 | class SpUtil { 6 | SpUtil._internal(); 7 | static final SpUtil _instance = SpUtil._internal(); 8 | 9 | factory SpUtil() { 10 | return _instance; 11 | } 12 | 13 | SharedPreferences? prefs; 14 | 15 | Future init() async { 16 | prefs = await SharedPreferences.getInstance(); 17 | } 18 | 19 | Future setJSON(String key, dynamic jsonVal) { 20 | String jsonString = jsonEncode(jsonVal); 21 | return prefs!.setString(key, jsonString); 22 | } 23 | 24 | dynamic getJSON(String key) { 25 | String? jsonString = prefs?.getString(key); 26 | return jsonString == null ? null : jsonDecode(jsonString); 27 | } 28 | 29 | Future setBool(String key, bool val) { 30 | return prefs!.setBool(key, val); 31 | } 32 | 33 | bool? getBool(String key) { 34 | return prefs!.getBool(key); 35 | } 36 | 37 | Future remove(String key) { 38 | return prefs!.remove(key); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/utils/time_format.dart: -------------------------------------------------------------------------------- 1 | import 'package:date_format/date_format.dart'; 2 | 3 | class TimeFormat { 4 | const TimeFormat._(); 5 | 6 | ///[时间戳转换年月日] 7 | static dateFormat(createtime) { 8 | if (createtime == 0) { 9 | return ''; 10 | } 11 | var time = createtime * 1000; 12 | return formatDate( 13 | DateTime.fromMillisecondsSinceEpoch(time), [yyyy, '-', mm, '-', dd]); 14 | } 15 | 16 | ///[时间戳转换年月日] 17 | static dateMmFormat(createtime) { 18 | if (createtime == 0) { 19 | return ''; 20 | } 21 | var time = createtime * 1000; 22 | return formatDate(DateTime.fromMillisecondsSinceEpoch(time), [mm, '-', dd]); 23 | } 24 | 25 | static dateFormatMMDD(createtime) { 26 | if (createtime == null) return ''; 27 | if (createtime == 0) { 28 | return ''; 29 | } 30 | var time = createtime * 1000; 31 | 32 | return formatDate(DateTime.fromMillisecondsSinceEpoch(time), 33 | [mm, '月', dd, '日 ', HH, ':', nn]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/widgets/apex_tabbar.dart: -------------------------------------------------------------------------------- 1 | import 'package:apex_wechat/utils/instances.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | 4 | class ApexTabbarView extends StatefulWidget { 5 | final List tab; 6 | final List children; 7 | final bool isDivider; 8 | final bool isImage; 9 | final Function(int index)? onTap; 10 | ApexTabbarView({ 11 | Key? key, 12 | required this.tab, 13 | required this.children, 14 | this.onTap, 15 | this.isDivider = true, 16 | this.isImage = false, 17 | }) : super(key: key); 18 | 19 | @override 20 | _ApexTabbarViewState createState() => _ApexTabbarViewState(); 21 | } 22 | 23 | class _ApexTabbarViewState extends State { 24 | int currentIndex = 0; 25 | Widget? _widget; 26 | @override 27 | void initState() { 28 | super.initState(); 29 | } 30 | 31 | ///[tabbar] 32 | _randerItem() { 33 | List item = []; 34 | 35 | for (var i = 0; i < widget.tab.length; i++) { 36 | item.add(Expanded( 37 | child: GestureDetector( 38 | onTap: () { 39 | widget.onTap?.call(i); 40 | setState(() { 41 | currentIndex = i; 42 | _widget = widget.children[i]; 43 | }); 44 | }, 45 | child: Column( 46 | mainAxisAlignment: MainAxisAlignment.center, 47 | children: [ 48 | !widget.isImage 49 | ? Text( 50 | widget.tab[i], 51 | style: TextStyle( 52 | color: currentIndex == i 53 | ? Color(0xff3C3C3C) 54 | : Color(0xff969696), 55 | fontSize: 16), 56 | ) 57 | : Image.network( 58 | widget.tab[i], 59 | width: 20, 60 | height: 20, 61 | ), 62 | SizedBox(height: 5), 63 | Opacity( 64 | opacity: currentIndex == i ? 1 : 0, 65 | child: Container( 66 | width: 30, 67 | decoration: BoxDecoration( 68 | border: Border( 69 | bottom: 70 | BorderSide(color: Color(0xff1A1616), width: 3))), 71 | )) 72 | ], 73 | ), 74 | ))); 75 | } 76 | setState(() {}); 77 | return item; 78 | } 79 | 80 | @override 81 | Widget build(BuildContext context) { 82 | return SingleChildScrollView( 83 | child: Column( 84 | children: [ 85 | Container( 86 | height: 55, 87 | decoration: widget.isDivider 88 | ? BoxDecoration( 89 | border: Border( 90 | bottom: BorderSide(color: Color(0xffE8E8E8), width: 1))) 91 | : null, 92 | width: MediaQuery.of(currentContext!).size.width, 93 | child: Row(children: _randerItem()), 94 | ), 95 | Container(child: _widget ?? widget.children[0]) 96 | ], 97 | )); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /mpdart: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export PUB_HOSTED_URL=https://pub.mpflutter.com 4 | dart $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 -------------------------------------------------------------------------------- /mpdart.bat: -------------------------------------------------------------------------------- 1 | set PUB_HOSTED_URL=https://pub.mpflutter.com 2 | dart %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 -------------------------------------------------------------------------------- /mpflutter: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export PUB_HOSTED_URL=https://pub.mpflutter.com 4 | flutter $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 -------------------------------------------------------------------------------- /mpflutter.bat: -------------------------------------------------------------------------------- 1 | set PUB_HOSTED_URL=https://pub.mpflutter.com 2 | flutter %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.mpflutter.com" 9 | source: hosted 10 | version: "2.8.2" 11 | characters: 12 | dependency: transitive 13 | description: 14 | name: characters 15 | url: "https://pub.mpflutter.com" 16 | source: hosted 17 | version: "1.1.0" 18 | charcode: 19 | dependency: transitive 20 | description: 21 | name: charcode 22 | url: "https://pub.mpflutter.com" 23 | source: hosted 24 | version: "1.3.1" 25 | cli_dialog: 26 | dependency: transitive 27 | description: 28 | name: cli_dialog 29 | url: "https://pub.mpflutter.com" 30 | source: hosted 31 | version: "0.5.0" 32 | collection: 33 | dependency: transitive 34 | description: 35 | name: collection 36 | url: "https://pub.mpflutter.com" 37 | source: hosted 38 | version: "1.15.0" 39 | crypto: 40 | dependency: transitive 41 | description: 42 | name: crypto 43 | url: "https://pub.mpflutter.com" 44 | source: hosted 45 | version: "3.0.1" 46 | dart_console: 47 | dependency: transitive 48 | description: 49 | name: dart_console 50 | url: "https://pub.mpflutter.com" 51 | source: hosted 52 | version: "1.0.0" 53 | date_format: 54 | dependency: "direct main" 55 | description: 56 | name: date_format 57 | url: "https://pub.mpflutter.com" 58 | source: hosted 59 | version: "2.0.4" 60 | dio: 61 | dependency: "direct main" 62 | description: 63 | name: dio 64 | url: "https://pub.mpflutter.com" 65 | source: hosted 66 | version: "4.0.0" 67 | ffi: 68 | dependency: transitive 69 | description: 70 | name: ffi 71 | url: "https://pub.mpflutter.com" 72 | source: hosted 73 | version: "1.1.2" 74 | file: 75 | dependency: transitive 76 | description: 77 | name: file 78 | url: "https://pub.mpflutter.com" 79 | source: hosted 80 | version: "6.1.2" 81 | flutter: 82 | dependency: "direct main" 83 | description: 84 | name: flutter 85 | url: "https://pub.mpflutter.com" 86 | source: hosted 87 | version: "0.11.3" 88 | flutter_web_plugins: 89 | dependency: "direct main" 90 | description: 91 | name: flutter_web_plugins 92 | url: "https://pub.mpflutter.com" 93 | source: hosted 94 | version: "0.11.3" 95 | get: 96 | dependency: "direct main" 97 | description: 98 | name: get 99 | url: "https://pub.mpflutter.com" 100 | source: hosted 101 | version: "4.3.8" 102 | glob: 103 | dependency: transitive 104 | description: 105 | name: glob 106 | url: "https://pub.mpflutter.com" 107 | source: hosted 108 | version: "2.0.2" 109 | html_unescape: 110 | dependency: transitive 111 | description: 112 | name: html_unescape 113 | url: "https://pub.mpflutter.com" 114 | source: hosted 115 | version: "2.0.0" 116 | http: 117 | dependency: transitive 118 | description: 119 | name: http 120 | url: "https://pub.mpflutter.com" 121 | source: hosted 122 | version: "0.13.1" 123 | http_parser: 124 | dependency: transitive 125 | description: 126 | name: http_parser 127 | url: "https://pub.mpflutter.com" 128 | source: hosted 129 | version: "4.0.0" 130 | json_patch: 131 | dependency: transitive 132 | description: 133 | name: json_patch 134 | url: "https://pub.mpflutter.com" 135 | source: hosted 136 | version: "2.1.1" 137 | meta: 138 | dependency: transitive 139 | description: 140 | name: meta 141 | url: "https://pub.mpflutter.com" 142 | source: hosted 143 | version: "1.3.0" 144 | mime_type: 145 | dependency: transitive 146 | description: 147 | name: mime_type 148 | url: "https://pub.mpflutter.com" 149 | source: hosted 150 | version: "1.0.0" 151 | mp_build_tools: 152 | dependency: "direct main" 153 | description: 154 | name: mp_build_tools 155 | url: "https://pub.mpflutter.com" 156 | source: hosted 157 | version: "0.11.3" 158 | mpcore: 159 | dependency: "direct main" 160 | description: 161 | name: mpcore 162 | url: "https://pub.mpflutter.com" 163 | source: hosted 164 | version: "0.11.3" 165 | nested: 166 | dependency: transitive 167 | description: 168 | name: nested 169 | url: "https://pub.mpflutter.com" 170 | source: hosted 171 | version: "1.0.0" 172 | path: 173 | dependency: transitive 174 | description: 175 | name: path 176 | url: "https://pub.mpflutter.com" 177 | source: hosted 178 | version: "1.8.0" 179 | path_provider: 180 | dependency: "direct main" 181 | description: 182 | name: path_provider 183 | url: "https://pub.mpflutter.com" 184 | source: hosted 185 | version: "2.0.8" 186 | path_provider_android: 187 | dependency: transitive 188 | description: 189 | name: path_provider_android 190 | url: "https://pub.mpflutter.com" 191 | source: hosted 192 | version: "2.0.9" 193 | path_provider_ios: 194 | dependency: transitive 195 | description: 196 | name: path_provider_ios 197 | url: "https://pub.mpflutter.com" 198 | source: hosted 199 | version: "2.0.7" 200 | path_provider_linux: 201 | dependency: transitive 202 | description: 203 | name: path_provider_linux 204 | url: "https://pub.mpflutter.com" 205 | source: hosted 206 | version: "2.1.4" 207 | path_provider_macos: 208 | dependency: transitive 209 | description: 210 | name: path_provider_macos 211 | url: "https://pub.mpflutter.com" 212 | source: hosted 213 | version: "2.0.4" 214 | path_provider_platform_interface: 215 | dependency: transitive 216 | description: 217 | name: path_provider_platform_interface 218 | url: "https://pub.mpflutter.com" 219 | source: hosted 220 | version: "2.0.1" 221 | path_provider_windows: 222 | dependency: transitive 223 | description: 224 | name: path_provider_windows 225 | url: "https://pub.mpflutter.com" 226 | source: hosted 227 | version: "2.0.4" 228 | pedantic: 229 | dependency: transitive 230 | description: 231 | name: pedantic 232 | url: "https://pub.mpflutter.com" 233 | source: hosted 234 | version: "1.11.1" 235 | petitparser: 236 | dependency: transitive 237 | description: 238 | name: petitparser 239 | url: "https://pub.mpflutter.com" 240 | source: hosted 241 | version: "4.1.0" 242 | platform: 243 | dependency: transitive 244 | description: 245 | name: platform 246 | url: "https://pub.mpflutter.com" 247 | source: hosted 248 | version: "3.1.0" 249 | plugin_platform_interface: 250 | dependency: transitive 251 | description: 252 | name: plugin_platform_interface 253 | url: "https://pub.mpflutter.com" 254 | source: hosted 255 | version: "2.0.2" 256 | process: 257 | dependency: transitive 258 | description: 259 | name: process 260 | url: "https://pub.mpflutter.com" 261 | source: hosted 262 | version: "4.2.4" 263 | provider: 264 | dependency: "direct main" 265 | description: 266 | name: provider 267 | url: "https://pub.mpflutter.com" 268 | source: hosted 269 | version: "6.0.1" 270 | shared_preferences: 271 | dependency: "direct main" 272 | description: 273 | name: shared_preferences 274 | url: "https://pub.mpflutter.com" 275 | source: hosted 276 | version: "2.0.8" 277 | simple_html_css: 278 | dependency: "direct main" 279 | description: 280 | name: simple_html_css 281 | url: "https://pub.mpflutter.com" 282 | source: hosted 283 | version: "3.0.1+1" 284 | source_span: 285 | dependency: transitive 286 | description: 287 | name: source_span 288 | url: "https://pub.mpflutter.com" 289 | source: hosted 290 | version: "1.8.1" 291 | string_scanner: 292 | dependency: transitive 293 | description: 294 | name: string_scanner 295 | url: "https://pub.mpflutter.com" 296 | source: hosted 297 | version: "1.1.0" 298 | term_glyph: 299 | dependency: transitive 300 | description: 301 | name: term_glyph 302 | url: "https://pub.mpflutter.com" 303 | source: hosted 304 | version: "1.2.0" 305 | typed_data: 306 | dependency: transitive 307 | description: 308 | name: typed_data 309 | url: "https://pub.mpflutter.com" 310 | source: hosted 311 | version: "1.3.0" 312 | universal_miniprogram_api: 313 | dependency: "direct main" 314 | description: 315 | name: universal_miniprogram_api 316 | url: "https://pub.mpflutter.com" 317 | source: hosted 318 | version: "0.0.3" 319 | usage: 320 | dependency: transitive 321 | description: 322 | name: usage 323 | url: "https://pub.mpflutter.com" 324 | source: hosted 325 | version: "4.0.2" 326 | vector_math: 327 | dependency: transitive 328 | description: 329 | name: vector_math 330 | url: "https://pub.mpflutter.com" 331 | source: hosted 332 | version: "2.1.0" 333 | vm_service: 334 | dependency: transitive 335 | description: 336 | name: vm_service 337 | url: "https://pub.mpflutter.com" 338 | source: hosted 339 | version: "6.2.0" 340 | watcher: 341 | dependency: transitive 342 | description: 343 | name: watcher 344 | url: "https://pub.mpflutter.com" 345 | source: hosted 346 | version: "1.0.1" 347 | win32: 348 | dependency: transitive 349 | description: 350 | name: win32 351 | url: "https://pub.mpflutter.com" 352 | source: hosted 353 | version: "2.3.1" 354 | xdg_directories: 355 | dependency: transitive 356 | description: 357 | name: xdg_directories 358 | url: "https://pub.mpflutter.com" 359 | source: hosted 360 | version: "0.2.0" 361 | xml: 362 | dependency: transitive 363 | description: 364 | name: xml 365 | url: "https://pub.mpflutter.com" 366 | source: hosted 367 | version: "5.1.2" 368 | sdks: 369 | dart: ">=2.15.0 <3.0.0" 370 | flutter: ">=2.5.0" 371 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: apex_wechat 2 | description: A new MPFlutter project. 3 | publish_to: "none" 4 | version: 1.0.0+1 5 | environment: 6 | sdk: ">=2.15.0 <3.0.0" 7 | dependencies: 8 | flutter: "0.11.3" 9 | flutter_web_plugins: "0.11.3" 10 | mpcore: "0.11.3" 11 | mp_build_tools: "0.11.3" 12 | path_provider: ^2.0.7 13 | dio: ^4.0.0 14 | shared_preferences: ^2.0.8 15 | provider: ^6.0.1 16 | date_format: ^2.0.4 17 | get: ^4.3.8 18 | simple_html_css: ^3.0.1+1 19 | universal_miniprogram_api: ^0.0.1 20 | dependency_overrides: 21 | flutter: "0.11.3" 22 | mpcore: "0.11.3" 23 | flutter_web_plugins: "0.11.3" 24 | flutter: 25 | assets: 26 | - assets/images/ -------------------------------------------------------------------------------- /scripts/build_plugins.dart: -------------------------------------------------------------------------------- 1 | import 'package:mp_build_tools/build_plugins.dart' as builder; 2 | 3 | main(List args) { 4 | builder.main(args); 5 | } 6 | -------------------------------------------------------------------------------- /scripts/build_swanapp.dart: -------------------------------------------------------------------------------- 1 | import 'package:mp_build_tools/build_swanapp.dart' as builder; 2 | 3 | main(List args) { 4 | builder.main(args); 5 | } 6 | -------------------------------------------------------------------------------- /scripts/build_weapp.dart: -------------------------------------------------------------------------------- 1 | import 'package:mp_build_tools/build_weapp.dart' as builder; 2 | 3 | main(List args) { 4 | builder.main(args); 5 | } 6 | -------------------------------------------------------------------------------- /scripts/build_web.dart: -------------------------------------------------------------------------------- 1 | import 'package:mp_build_tools/build_web.dart' as builder; 2 | 3 | main(List args) { 4 | builder.main(args); 5 | } 6 | -------------------------------------------------------------------------------- /scripts/help.dart: -------------------------------------------------------------------------------- 1 | import 'package:mp_build_tools/help.dart' as help; 2 | 3 | main(List args) { 4 | help.main(args); 5 | } 6 | -------------------------------------------------------------------------------- /weapp/app.js: -------------------------------------------------------------------------------- 1 | // app.js 2 | App({ 3 | onLaunch() { 4 | const { MPEnv, Engine, WXApp } = require("./mpdom.min"); 5 | MPEnv.platformAppInstance = this; 6 | try { 7 | require("./plugins.min"); 8 | } catch (error) {} 9 | const engine = new Engine(); 10 | var dev = true; 11 | if (dev) { 12 | engine.initWithDebuggerServerAddr("127.0.0.1:9898"); 13 | } else { 14 | engine.initWithCodeBlock(Engine.codeBlockWithFile("./main.dart.js")); 15 | } 16 | const app = new WXApp("pages/index/index", engine); 17 | this.app = app; 18 | engine.start(); 19 | }, 20 | globalData: {}, 21 | }); 22 | -------------------------------------------------------------------------------- /weapp/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": ["pages/index/index"], 3 | "window": { 4 | "backgroundTextStyle": "light", 5 | "navigationBarBackgroundColor": "#fff", 6 | "navigationBarTitleText": "", 7 | "navigationBarTextStyle": "black" 8 | }, 9 | "style": "v2", 10 | "sitemapLocation": "sitemap.json" 11 | } 12 | -------------------------------------------------------------------------------- /weapp/app.wxss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itMcdull/apex_wechat/17516a3e746271259a3271fd029d9816ab497adb/weapp/app.wxss -------------------------------------------------------------------------------- /weapp/kbone/miniprogram-element/custom-component/index.js: -------------------------------------------------------------------------------- 1 | const mp=require("../../miniprogram-render/index"),{Event:Event,cache:cache,tool:tool}=mp.$$adapter;function isEqual(t,e){if("number"==typeof t&&"number"==typeof e)return parseInt(1e3*t,10)===parseInt(1e3*e,10);if("object"==typeof t&&"object"==typeof e){if(null===t||null===e)return t===e;const o=Array.isArray(t),n=Array.isArray(e);if(o&&n){if(t.length!==e.length)return!1;for(let o=0,n=t.length;o{const e=t.$$domInfo;return{slot:e.slot,nodeId:e.nodeId,pageId:e.pageId,id:e.id,className:"element"===e.type?`h5-${e.tagName} node-${e.nodeId} ${e.className||""}`:"",style:e.style}}).filter(t=>!!t.slot);s.hasSlots=l.length,s.slots=l}function setData(t,e){tool.setData?tool.setData(t,e):t.setData(e)}Component({properties:{kboneCustomComponentName:{type:String,value:""}},options:{addGlobalClass:!0,virtualHost:!0},attached(){const t=this.dataset.privateNodeId,e=this.dataset.privatePageId,o={};this.nodeId=t,this.pageId=e,this.domNode=cache.getNode(e,t);const n=cache.getConfig();this.compConfig=n.runtime&&n.runtime.usingComponents&&n.runtime.usingComponents[this.domNode.behavior]||{},this.onSelfNodeUpdate=tool.throttle(this.onSelfNodeUpdate.bind(this)),this.domNode.$$clearEvent("$$domNodeUpdate",{$$namespace:"proxy"}),this.domNode.addEventListener("$$domNodeUpdate",this.onSelfNodeUpdate,{$$namespace:"proxy"});const{events:s=[]}=this.compConfig;if(s.length)for(const t of s)this["on"+t]=e=>this.callSimpleEvent(t,e);checkComponentAttr(this.compConfig,this.domNode.behavior,this.domNode,o),Object.keys(o).length&&setData(this,o),this.domNode._wxCustomComponent=this.selectComponent(".node-"+this.domNode.$$nodeId)},detached(){this.nodeId=null,this.pageId=null,this.domNode._wxCustomComponent=null,this.domNode=null},methods:{onSelfNodeUpdate(){if(!this.pageId||!this.nodeId)return;const t={};checkComponentAttr(this.compConfig,this.domNode.behavior,this.domNode,t,this.data),setData(this,t),this.domNode._wxCustomComponent=this.selectComponent(".node-"+this.domNode.$$nodeId)},callSimpleEvent(t,e){const o=this.domNode;o&&o.$$trigger(t,{event:new Event({name:t,target:o,eventPhase:Event.AT_TARGET,detail:e&&e.detail}),currentTarget:o})}}}); -------------------------------------------------------------------------------- /weapp/kbone/miniprogram-element/custom-component/index.json: -------------------------------------------------------------------------------- 1 | {"component":true,"usingComponents":{}} -------------------------------------------------------------------------------- /weapp/kbone/miniprogram-element/custom-component/index.wxml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itMcdull/apex_wechat/17516a3e746271259a3271fd029d9816ab497adb/weapp/kbone/miniprogram-element/custom-component/index.wxml -------------------------------------------------------------------------------- /weapp/kbone/miniprogram-element/custom-component/index.wxss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itMcdull/apex_wechat/17516a3e746271259a3271fd029d9816ab497adb/weapp/kbone/miniprogram-element/custom-component/index.wxss -------------------------------------------------------------------------------- /weapp/kbone/miniprogram-element/index-vhost.js: -------------------------------------------------------------------------------- 1 | const base=require("./base");Component({behaviors:[base],options:{addGlobalClass:!0,virtualHost:!0}}); -------------------------------------------------------------------------------- /weapp/kbone/miniprogram-element/index-vhost.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": { 4 | "element": "./index", 5 | "element-vhost": "./index-vhost" 6 | }, 7 | "componentGenerics": { 8 | "custom-component": { 9 | "default": "./custom-component/index" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /weapp/kbone/miniprogram-element/index-vhost.wxml: -------------------------------------------------------------------------------- 1 |