├── lib
├── route
│ └── routers.dart
├── models
│ ├── reply.dart
│ ├── topic.dart
│ ├── vo.dart
│ ├── response.dart
│ ├── user.dart
│ ├── comment.dart
│ ├── user_message.dart
│ └── moving.dart
├── utils
│ ├── convert_server_data.dart
│ ├── bju_timeline_util.dart
│ └── db_util.dart
├── settings
│ └── settings.dart
├── providers
│ ├── bju_app_provider.dart
│ └── login_provider.dart
├── pages
│ ├── details
│ │ ├── person_moving_details.dart
│ │ └── message_details.dart
│ ├── browser.dart
│ ├── back_management
│ │ └── management.dart
│ ├── message_page.dart
│ ├── modules
│ │ ├── campus_voice.dart
│ │ ├── part_time_recruitment.dart
│ │ └── wall_and_you.dart
│ ├── main_page.dart
│ ├── at_choose_page.dart
│ ├── mine
│ │ ├── draft_moving_page.dart
│ │ ├── all_moving_page.dart
│ │ └── safty_setting_page.dart
│ └── login_page.dart
├── constants
│ └── bju_constant.dart
├── main.dart
├── net
│ └── bju_net.dart
└── api
│ └── api.dart
├── ios
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── AppFrameworkInfo.plist
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── LaunchImage.imageset
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Runner.xcworkspace
│ └── contents.xcworkspacedata
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
└── .gitignore
├── assets
├── gif
│ ├── loading.gif
│ └── loading.jpg
├── avatar
│ ├── bju_xh.jpg
│ └── default_avatar.jpg
├── icon
│ └── bju_app.png
├── swiper
│ ├── bju_1.jpg
│ ├── bju_2.jpg
│ ├── bju_3.jpg
│ └── bju_4.jpg
├── splash
│ └── bju_splash.gif
└── background_imgs
│ ├── bg_login.png
│ └── bg_personal.jpg
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── drawable
│ │ │ │ │ ├── notice_icon.png
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ ├── bju_app.png
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ └── values
│ │ │ │ │ └── styles.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── bju_information_app
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── proguard-rules.pro
│ └── build.gradle
├── .gitignore
├── key.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── settings.gradle
└── build.gradle
├── readme
└── 功能分析.md
├── .metadata
├── .gitignore
├── widgets
└── bju_widgets.dart
├── test
└── widget_test.dart
├── README.md
└── pubspec.yaml
/lib/route/routers.dart:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/lib/models/reply.dart:
--------------------------------------------------------------------------------
1 |
2 | class Reply{
3 |
4 | }
5 |
6 | class ReplyVO{
7 |
8 | }
--------------------------------------------------------------------------------
/assets/gif/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/gif/loading.gif
--------------------------------------------------------------------------------
/assets/gif/loading.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/gif/loading.jpg
--------------------------------------------------------------------------------
/assets/avatar/bju_xh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/avatar/bju_xh.jpg
--------------------------------------------------------------------------------
/assets/icon/bju_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/icon/bju_app.png
--------------------------------------------------------------------------------
/assets/swiper/bju_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/swiper/bju_1.jpg
--------------------------------------------------------------------------------
/assets/swiper/bju_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/swiper/bju_2.jpg
--------------------------------------------------------------------------------
/assets/swiper/bju_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/swiper/bju_3.jpg
--------------------------------------------------------------------------------
/assets/swiper/bju_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/swiper/bju_4.jpg
--------------------------------------------------------------------------------
/assets/splash/bju_splash.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/splash/bju_splash.gif
--------------------------------------------------------------------------------
/assets/avatar/default_avatar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/avatar/default_avatar.jpg
--------------------------------------------------------------------------------
/lib/utils/convert_server_data.dart:
--------------------------------------------------------------------------------
1 | ///
2 | /// 服务器数据格式化类
3 | /// 2020/04/04 16:30
4 | ///
5 | class Util{
6 |
7 | }
--------------------------------------------------------------------------------
/assets/background_imgs/bg_login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/background_imgs/bg_login.png
--------------------------------------------------------------------------------
/assets/background_imgs/bg_personal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/assets/background_imgs/bg_personal.jpg
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/notice_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/android/app/src/main/res/drawable/notice_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/bju_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/android/app/src/main/res/mipmap-hdpi/bju_app.png
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/settings/settings.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SettingsProvider extends ChangeNotifier{
4 |
5 | // 用于显示指定的
6 |
7 |
8 | }
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/models/topic.dart:
--------------------------------------------------------------------------------
1 | ///
2 | /// 话题
3 | /// 2020/02/28 15:15
4 | class Topic {
5 |
6 | int topicId;
7 | String topicName;
8 |
9 |
10 |
11 |
12 | }
--------------------------------------------------------------------------------
/android/key.properties:
--------------------------------------------------------------------------------
1 | storePassword=mongo0516.
2 | keyPassword=mongo0516.
3 | keyAlias=key
4 | storeFile=E:/graduationDesign/back/flutter-apk-settting/Users/H-Mongo/key.jks
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/H-Mongo/flutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/readme/功能分析.md:
--------------------------------------------------------------------------------
1 | #主要模块
2 | ##校园快讯
3 | ##校园之声
4 | ##墙上有你
5 | ##兼职招聘
6 | ##个人主页
7 | #页面设计
8 | ##底部导航栏
9 | -首页:主要包括用户头像,搜索框,滑动页,校园介绍,热点新闻等
10 | -广场:包括最新动态,热点动态
11 | -加号:用于发表文章,动态等
12 | -消息:艾特用户提示信息,系统提醒信息,评论信息,回复信息等
13 | -我的:包括用户个人信息,系统版本等,修改密码,注销登录,个人资料编辑等等
--------------------------------------------------------------------------------
/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | ## Flutter wrapper 混淆器规则
2 | -keep class io.flutter.app.** { *; }
3 | -keep class io.flutter.plugin.** { *; }
4 | -keep class io.flutter.util.** { *; }
5 | -keep class io.flutter.view.** { *; }
6 | -keep class io.flutter.** { *; }
7 | -keep class io.flutter.plugins.** { *; }
8 | -dontwarn io.flutter.embedding.**
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 27321ebbad34b0a3fafe99fac037102196d655ff
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "idiom": "universal",
5 | "filename": "LaunchImage.png",
6 | "scale": "1x"
7 | },
8 | {
9 | "idiom": "universal",
10 | "filename": "LaunchImage@2x.png",
11 | "scale": "2x"
12 | },
13 | {
14 | "idiom": "universal",
15 | "filename": "LaunchImage@3x.png",
16 | "scale": "3x"
17 | }
18 | ],
19 | "info": {
20 | "version": 1,
21 | "author": "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/bju_information_app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.bju_information_app
2 |
3 | import androidx.annotation.NonNull;
4 | import io.flutter.embedding.android.FlutterActivity
5 | import io.flutter.embedding.engine.FlutterEngine
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity : FlutterActivity() {
9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
10 | GeneratedPluginRegistrant.registerWith(flutterEngine);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/providers/bju_app_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | ///
3 | /// BJU APP的全局状态及settings管理
4 | ///
5 | class BjuAppSettingsProvider extends ChangeNotifier{
6 |
7 | // 主题色彩
8 | ThemeData _bjuThemeData;
9 | String _appTitle;
10 |
11 | ThemeData get bjuThemeData => _bjuThemeData;
12 | String get appTitle => _appTitle;
13 |
14 | /// 初始化Setting
15 | void init(){
16 | _bjuThemeData = ThemeData(
17 | primaryColor: Color(0xFF42A5F5)
18 | );
19 | _appTitle = '宝鸡大学信息服务平台';
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/lib/pages/details/person_moving_details.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 |
4 | ///
5 | /// 用户动态详情页面
6 | ///
7 | class PersonMovingDetailsPage extends StatefulWidget {
8 | PersonMovingDetailsPage({Key key}) : super(key: key);
9 |
10 | @override
11 | _PersonMovingDetailsPageState createState() => _PersonMovingDetailsPageState();
12 | }
13 |
14 | class _PersonMovingDetailsPageState extends State {
15 | @override
16 | Widget build(BuildContext context) {
17 | return Scaffold(
18 | appBar: AppBar(
19 | leading: BackButton(onPressed:()=>Navigator.of(context).pop()),
20 | title: Text('个人主页'),
21 | ),
22 | );
23 | }
24 | }
--------------------------------------------------------------------------------
/lib/constants/bju_constant.dart:
--------------------------------------------------------------------------------
1 | ///
2 | /// BJU常量
3 | /// 2020/04/19 12:13
4 | ///
5 | class BJUConstants{
6 | // SharedPreferences的常量键值的定义=======start
7 |
8 | /// 登录用户手机号码的存储key
9 | static final String loginUserMobile = 'LOGIN_USER_MOBILE';
10 |
11 | /// 应用通知DB存储时的owner
12 | static final String alertOwner = 'APP_ALERT';
13 |
14 | /// 应用通知Count
15 | static final String appAlertCount = 'APP_ALERT_COUNT';
16 |
17 | /// @我的Count
18 | static final String atMineCount = 'AT_MINE_COUNT';
19 |
20 | /// 评论我Count
21 | static final String commentMeCount = 'COMMENT_ME_COUNT';
22 |
23 | /// 赞我Count
24 | static final String likeMeCount = 'LIKE_ME_COUNT';
25 |
26 | // SharedPreferences的常量键值的定义=======end
27 |
28 |
29 |
30 |
31 |
32 |
33 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Exceptions to above rules.
37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
38 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/lib/models/vo.dart:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 视图模型对应的dart文件
4 | *
5 | * 时间:2020/04/15 12:19
6 | * 描述: 主要用来存储用于视图展示所需要的View Model类型
7 | *
8 | */
9 |
10 |
11 | ///
12 | /// 用于展示 @ 用户的视图模型,返回存储 @ 时所需要的信息
13 | /// 2020/04/15 12:20
14 | ///
15 | class AtUserVO{
16 |
17 | /// @用户手机号
18 | String phone;
19 |
20 | /// @用户昵称
21 | String nickname;
22 |
23 | /// @用户头像
24 | String avatar;
25 |
26 | /// @用户个性签名
27 | String motto;
28 |
29 | AtUserVO({this.phone,this.nickname,this.avatar,this.motto});
30 |
31 | /// 将Map数据模型化
32 | factory AtUserVO.fromJson(Map json){
33 | return AtUserVO(
34 | phone: json.putIfAbsent('phone', () => ''),
35 | nickname: json.putIfAbsent('nickname', () => ''),
36 | avatar: json.putIfAbsent('avatar', () => ''),
37 | motto: json.putIfAbsent('motto', () => '')
38 | );
39 | }
40 |
41 | @override
42 | String toString() {
43 |
44 | return '{'
45 | + ', phone:' + this.phone
46 | + ', nickname:' + this.nickname
47 | + ', avatar:' + this.avatar
48 | + ', motto:' + this.motto
49 | +'}';
50 | }
51 |
52 |
53 | }
54 |
55 |
56 |
--------------------------------------------------------------------------------
/widgets/bju_widgets.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_screenutil/flutter_screenutil.dart';
3 | import 'package:oktoast/oktoast.dart';
4 |
5 | ///
6 | /// 加载动画
7 | ///
8 | void showLoading(BuildContext context){
9 | showToastWidget(
10 | Container(
11 | width: MediaQuery.of(context).size.width,
12 | height: MediaQuery.of(context).size.height,
13 | color: Colors.white54,
14 | child: Center(
15 | child: Column(
16 | mainAxisSize: MainAxisSize.min,
17 | mainAxisAlignment: MainAxisAlignment.center,
18 | children: [
19 | CircularProgressIndicator(),
20 | SizedBox(height: ScreenUtil().setHeight(6),),
21 | Text('加载中...', style: TextStyle(
22 | fontSize: 16,
23 | fontWeight: FontWeight.w500,
24 | wordSpacing: 2,
25 | color: Colors.lightBlue,
26 | ),
27 | ),
28 | ],
29 | ),
30 | ),
31 | ),
32 | duration: Duration(seconds: 3),
33 | // position: ToastPosition.center,
34 | );
35 | }
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:bju_information_app/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(BJUInformationServiceApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/lib/models/response.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'dart:convert';
3 |
4 | ///
5 | /// 服务端返回的response对象
6 | /// 2020-3-2 16:11
7 | ///
8 | class ResponseData {
9 |
10 |
11 | /// 版本号
12 | String ver;
13 |
14 | /// 提示信息
15 | String message;
16 |
17 | /// 状态码
18 | /// * [0] 成功
19 | /// * [1] 失败
20 | int statusCode;
21 |
22 | /// 返回的数据
23 | dynamic res;
24 |
25 | ResponseData({this.ver,this.message,this.statusCode,this.res});
26 |
27 |
28 | @override
29 | String toString() {
30 | return '{'
31 | + 'ver: ' + this.ver
32 | +', message: ' + this.message
33 | +', statusCode: ' + this.statusCode.toString()
34 | +', res: ' + res.toString()
35 | + '}';
36 | }
37 |
38 |
39 | /// Json转对象
40 | factory ResponseData.fromJson(Map json){
41 | return ResponseData(
42 | ver:json['ver'],
43 | message:json['message'],
44 | statusCode:int.parse(json['statusCode'].toString()),
45 | res:json.putIfAbsent('res', () => null)
46 | );
47 | }
48 |
49 |
50 | Map toJson(){
51 | return {
52 | 'ver':this.ver,
53 | 'message':this.message,
54 | 'statusCode':this.statusCode,
55 | 'res':this.res
56 | };
57 | }
58 |
59 |
60 | }
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | // google()
5 | // jcenter()
6 | maven { url 'https://maven.aliyun.com/repository/google' }
7 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
8 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public'}
9 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin'}
10 | }
11 |
12 | dependencies {
13 | classpath 'com.android.tools.build:gradle:3.5.0'
14 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | // google()
21 | // jcenter()
22 | maven { url 'https://maven.aliyun.com/repository/google' }
23 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
24 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public'}
25 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin'}
26 | }
27 | }
28 |
29 | rootProject.buildDir = '../build'
30 | subprojects {
31 | project.buildDir = "${rootProject.buildDir}/${project.name}"
32 | }
33 | subprojects {
34 | project.evaluationDependsOn(':app')
35 | }
36 |
37 | task clean(type: Delete) {
38 | delete rootProject.buildDir
39 | }
40 |
--------------------------------------------------------------------------------
/lib/pages/browser.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:webview_flutter/webview_flutter.dart';
3 |
4 | ///
5 | /// 网页视图
6 | /// 2020/04/02 15:20
7 | ///
8 | class BrowserPage extends StatefulWidget {
9 |
10 | /// 页面标题
11 | final String _pageTitle;
12 | /// 网页连接
13 | final String _url;
14 |
15 | BrowserPage(this._pageTitle,this._url,{Key key}) : super(key: key);
16 |
17 | @override
18 | _BrowserPageState createState() => _BrowserPageState();
19 | }
20 |
21 | class _BrowserPageState extends State {
22 |
23 |
24 |
25 |
26 | ///
27 | /// web页面体
28 | Widget _webBody(){
29 |
30 | return widget._url == null || widget._url == ''
31 | ? Center(child: Text('无效页面!连接地址错误...', style: TextStyle(color: Colors.red),),)
32 | : WebView(
33 | /* onWebViewCreated: (webViewController){
34 | webViewController.
35 | }, */
36 | initialUrl: widget._url,
37 | javascriptMode: JavascriptMode.unrestricted,
38 |
39 | );
40 |
41 | }
42 |
43 |
44 | @override
45 | Widget build(BuildContext context) {
46 | return Scaffold(
47 | appBar: AppBar(
48 | leading: BackButton(onPressed:(){
49 | Navigator.of(context).pop();
50 | }),
51 | title: Text(widget._pageTitle??'无效页面'),
52 | ),
53 | body: _webBody(),
54 | );
55 | }
56 | }
--------------------------------------------------------------------------------
/lib/utils/bju_timeline_util.dart:
--------------------------------------------------------------------------------
1 | import 'package:flustars/flustars.dart';
2 |
3 | ///
4 | /// 应用时间线工具类
5 | /// 2020/04/07 12:55
6 | ///
7 | class BjuTimelineUtil{
8 |
9 | /// 将时间格式化为时间线的形式
10 | /// * dateStr 时间字符串
11 | static String formatDateStr(String dateStr){
12 | // print('时间字符串为: dateStr=' + dateStr);
13 | // 设置时间线信息
14 | setLocaleInfo('zh_BjuApp',ZHBjuAppTimelineInfo());
15 | // 将时间字符串转为DateTime对象
16 | final DateTime dateTime = DateTime.parse(dateStr);
17 | // print('转换时间为:');
18 | // print(dateTime);
19 | // 时间线工具
20 | // TimelineUtil.format();
21 | final String timelineStr = TimelineUtil.formatByDateTime(dateTime,locale: 'zh_BjuApp', dayFormat: DayFormat.Common);
22 | print('时间线形式:timelineStr= ' + timelineStr);
23 | return timelineStr;
24 | }
25 |
26 | }
27 |
28 | ///
29 | /// 自定义的时间线格式类
30 | /// 2020/04/07 13:18
31 | ///
32 | class ZHBjuAppTimelineInfo implements TimelineInfo {
33 | String suffixAgo() => '前';
34 | String suffixAfter() => '后';
35 | String lessThanTenSecond() => '刚刚';
36 | String customYesterday() => '昨天';
37 | bool keepOneDay() => true;
38 | bool keepTwoDays() => false;
39 | String oneMinute(int minutes) => '$minutes分';
40 | String minutes(int minutes) => '$minutes分';
41 | String anHour(int hours) => '$hours小时';
42 | String hours(int hours) => '$hours小时';
43 | String oneDay(int days) => '$days天';
44 | String days(int days) => '$days天';
45 | }
46 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | bju_information_app
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/lib/providers/login_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:bju_information_app/constants/bju_constant.dart';
2 | import 'package:bju_information_app/models/user.dart';
3 | import 'package:bju_information_app/net/bju_net.dart';
4 | import 'package:flustars/flustars.dart';
5 | import 'package:flutter/material.dart';
6 |
7 |
8 | ///
9 | /// 登录状态Provider
10 | ///
11 | class LoginProvider extends ChangeNotifier{
12 | /// 登录否
13 | bool _isLogin = false;
14 | /// 登录的用户信息
15 | User _user;
16 | /// 用户主页计数项
17 | Map _allCounts = Map();
18 |
19 | bool get isLogin => _isLogin;
20 |
21 | User get loginUser => _user;
22 |
23 | int get userId => loginUser.userId;
24 |
25 | Map get allCounts => _allCounts;
26 |
27 |
28 |
29 | ///
30 | /// 用户登录操作
31 | ///
32 | void doLogin(User user){
33 | _user = user;
34 | _isLogin = user != null ? true : false;
35 | // 存储用户的信息
36 | SpUtil.putString(BJUConstants.loginUserMobile, user.userMobile);
37 | notifyListeners();
38 | }
39 |
40 | ///
41 | /// 更新用户信息
42 | ///
43 | void updateUserInfo(User user){
44 | _user = user;
45 | notifyListeners();
46 | }
47 |
48 | /// 更新用户头像信息
49 | /// * [avatarUrl] 用户头像地址
50 | void refreshUserAvatar(String avatarUrl){
51 | _user.userAvatar = avatarUrl;
52 | notifyListeners();
53 | }
54 |
55 | /// 用户退出登录
56 | void logout(){
57 | // 消除dio中的token信息
58 | BjuHttp.disposeToken();
59 | // 删除登录的用户信息
60 | _user = null;
61 | // 登录标志为false
62 | _isLogin = false;
63 | // 删除本地持久化的用户号码
64 | SpUtil.remove(BJUConstants.loginUserMobile);
65 | notifyListeners();
66 | }
67 |
68 | /// 刷新用户主页计数项
69 | void refreshAllCounts(Map counts){
70 |
71 | // 更新counts
72 | _allCounts = counts;
73 | notifyListeners();
74 |
75 | }
76 |
77 |
78 | @override
79 | String toString() {
80 |
81 | return '[isLogin : '+this.isLogin.toString()+' ; user: '+this._user.toString()+']';
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "size": "20x20",
5 | "idiom": "iphone",
6 | "filename": "Icon-App-20x20@2x.png",
7 | "scale": "2x"
8 | },
9 | {
10 | "size": "20x20",
11 | "idiom": "iphone",
12 | "filename": "Icon-App-20x20@3x.png",
13 | "scale": "3x"
14 | },
15 | {
16 | "size": "29x29",
17 | "idiom": "iphone",
18 | "filename": "Icon-App-29x29@1x.png",
19 | "scale": "1x"
20 | },
21 | {
22 | "size": "29x29",
23 | "idiom": "iphone",
24 | "filename": "Icon-App-29x29@2x.png",
25 | "scale": "2x"
26 | },
27 | {
28 | "size": "29x29",
29 | "idiom": "iphone",
30 | "filename": "Icon-App-29x29@3x.png",
31 | "scale": "3x"
32 | },
33 | {
34 | "size": "40x40",
35 | "idiom": "iphone",
36 | "filename": "Icon-App-40x40@2x.png",
37 | "scale": "2x"
38 | },
39 | {
40 | "size": "40x40",
41 | "idiom": "iphone",
42 | "filename": "Icon-App-40x40@3x.png",
43 | "scale": "3x"
44 | },
45 | {
46 | "size": "60x60",
47 | "idiom": "iphone",
48 | "filename": "Icon-App-60x60@2x.png",
49 | "scale": "2x"
50 | },
51 | {
52 | "size": "60x60",
53 | "idiom": "iphone",
54 | "filename": "Icon-App-60x60@3x.png",
55 | "scale": "3x"
56 | },
57 | {
58 | "size": "20x20",
59 | "idiom": "ipad",
60 | "filename": "Icon-App-20x20@1x.png",
61 | "scale": "1x"
62 | },
63 | {
64 | "size": "20x20",
65 | "idiom": "ipad",
66 | "filename": "Icon-App-20x20@2x.png",
67 | "scale": "2x"
68 | },
69 | {
70 | "size": "29x29",
71 | "idiom": "ipad",
72 | "filename": "Icon-App-29x29@1x.png",
73 | "scale": "1x"
74 | },
75 | {
76 | "size": "29x29",
77 | "idiom": "ipad",
78 | "filename": "Icon-App-29x29@2x.png",
79 | "scale": "2x"
80 | },
81 | {
82 | "size": "40x40",
83 | "idiom": "ipad",
84 | "filename": "Icon-App-40x40@1x.png",
85 | "scale": "1x"
86 | },
87 | {
88 | "size": "40x40",
89 | "idiom": "ipad",
90 | "filename": "Icon-App-40x40@2x.png",
91 | "scale": "2x"
92 | },
93 | {
94 | "size": "76x76",
95 | "idiom": "ipad",
96 | "filename": "Icon-App-76x76@1x.png",
97 | "scale": "1x"
98 | },
99 | {
100 | "size": "76x76",
101 | "idiom": "ipad",
102 | "filename": "Icon-App-76x76@2x.png",
103 | "scale": "2x"
104 | },
105 | {
106 | "size": "83.5x83.5",
107 | "idiom": "ipad",
108 | "filename": "Icon-App-83.5x83.5@2x.png",
109 | "scale": "2x"
110 | },
111 | {
112 | "size": "1024x1024",
113 | "idiom": "ios-marketing",
114 | "filename": "Icon-App-1024x1024@1x.png",
115 | "scale": "1x"
116 | }
117 | ],
118 | "info": {
119 | "version": 1,
120 | "author": "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:bju_information_app/net/bju_net.dart';
2 | import 'package:bju_information_app/pages/main_page.dart';
3 | import 'package:bju_information_app/providers/bju_app_provider.dart';
4 | import 'package:bju_information_app/providers/jpush_provider.dart';
5 | import 'package:bju_information_app/providers/login_provider.dart';
6 | import 'package:flustars/flustars.dart';
7 | import 'package:flutter/cupertino.dart';
8 | import 'package:flutter/material.dart';
9 | import 'package:oktoast/oktoast.dart';
10 | import 'package:provider/provider.dart';
11 | import 'package:provider/single_child_widget.dart';
12 | import 'package:splashscreen/splashscreen.dart';
13 |
14 | void main() {
15 |
16 | runApp(BJUInformationServiceApp());
17 |
18 | }
19 |
20 | class BJUInformationServiceApp extends StatefulWidget {
21 | BJUInformationServiceApp({Key key}) : super(key: key);
22 |
23 | @override
24 | _BJUInformationServiceAppState createState() => _BJUInformationServiceAppState();
25 | }
26 |
27 | class _BJUInformationServiceAppState extends State {
28 |
29 | List _providers = [
30 | buildProvider(BjuAppSettingsProvider()..init()),
31 | buildProvider(LoginProvider()),
32 | buildProvider(JPushProvider()..initNotificationPlugin()..initJPush()..setUpJPush())
33 | ];
34 |
35 |
36 | static ChangeNotifierProvider buildProvider(T value){
37 | return ChangeNotifierProvider.value(value: value);
38 | }
39 |
40 | @override
41 | void initState() {
42 | super.initState();
43 | // 初始化项目中的各种配置信息
44 | _initConfig();
45 |
46 |
47 | }
48 |
49 | void _initConfig() async {
50 | // 初始化请求Dio配置
51 | BjuHttp.initConfig();
52 | // 初始化SharedPreferences工具类
53 | await SpUtil.getInstance();
54 |
55 | }
56 |
57 |
58 | @override
59 | Widget build(BuildContext context) {
60 |
61 | return MultiProvider(
62 | providers: _providers,
63 | child: Consumer(builder: (context, BjuAppSettingsProvider, child){
64 | return OKToast(
65 | child: MaterialApp(
66 | title: BjuAppSettingsProvider.appTitle,
67 | debugShowCheckedModeBanner: false,
68 | theme: BjuAppSettingsProvider.bjuThemeData,
69 | // home: Scaffold(
70 | // body:this._buildSplashScreenPage(MainPage()),
71 | // ),
72 | home: this._buildSplashScreenPage(MainPage()),
73 | ),
74 | );
75 | })
76 | );
77 | }
78 |
79 | SplashScreen _buildSplashScreenPage(Widget rootPage){
80 | return SplashScreen(
81 | seconds: 3,
82 | navigateAfterSeconds: rootPage,
83 | title: new Text('欢迎使用宝大IS平台',
84 | style: new TextStyle(
85 | fontWeight: FontWeight.bold,
86 | fontSize: 20.0
87 | ),),
88 | image: new Image.asset('assets/splash/bju_splash.gif'),
89 | backgroundColor: Colors.white,
90 | styleTextUnderTheLoader: new TextStyle(),
91 | photoSize: 100.0,
92 | onClick: ()=>print("Flutter Egypt"),
93 | loaderColor: Colors.red
94 | );
95 | }
96 |
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # flutterApp
2 | 基于flutter框架的微校园实战项目。
3 |
4 | #### 项目介绍
5 | 该项目算是本人对flutter学习的一个实战项目,同时又是作为毕业的课题项目。主要是针对校园信息输出的一个小APP,功能比较简单,重点在于对flutter技术的运用以及如何通过flutter快速开发跨平台的移动端APP程序。这算是一次学习,也算是我个人对flutter的致敬!
6 | ***
7 | #### 微校园部分截图
8 | 以下便是微校园的部分页面截图信息,由于截图过多就不全贴了
9 | |  |  |  |  |  |
10 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
11 | |  |  |  |  |  |
12 | ***
13 | #### 使用指南
14 | 该项目采用的前后分离开发,此处为移动端程序,后端已在阿里云中完成了部署,打开即可使用体验!假如您也想了解服务端程序,请移步到:[微校园服务端程序入口](https://github.com/H-Mongo/flutterAppServer)
15 | - 首先您需要将该项目download本地,打开git客户端,执行如下命令,完成项目的下载。
16 | ```git
17 | $ git clone https://github.com/H-Mongo/flutterApp.git
18 | ```
19 | - 打开VSCode,导入已经download的微校园项目。然后打开命令面板,如下操作:
20 | * 真实手机调试,确保您手机开启了,开发者模式(未开启的话,自行百度打开即可)。执行命令:`flutter run`即可运行。
21 | * 模拟器测试,保证您的电脑安装了模拟器软件,(未安装的话,可以使用夜神模拟器,挺不错的!)同样执行命令:`flutter run`即可。
22 | * 您也可以选择打包程序,通过安装包的方式完成软件安装:`flutter build apk`(安装打包方式,IOS打包与命令有点不同)。
23 |
24 | ***
25 |
26 | #### 联系作者
27 | * E-Mail:h2uwei@163.com | 1290499013@qq.com
28 | * QQ:1290499013(WeChat同)
29 |
30 |
--------------------------------------------------------------------------------
/lib/models/user.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'dart:convert';
3 |
4 | ///
5 | /// 用户模型
6 | /// 用于登录,视图渲染,修改更新用户信息
7 | ///
8 | /// [userId] 用户ID
9 | /// [roleId] 角色ID
10 | ///
11 | class User {
12 | int userId;
13 | int roleId;
14 | String userAvatar;
15 | String userNickname;
16 | String userMobile;
17 | String userBorth;
18 | String userAddress;
19 | String userHobby;
20 | String userMotto;
21 | int facultyId;
22 | int specialtyId;
23 | /// 院系名称
24 | String facultyName;
25 | /// 专业名称
26 | String specialtyName;
27 |
28 | User({
29 | this.userId,
30 | this.roleId,
31 | this.userAvatar,
32 | this.userNickname,
33 | this.userMobile,
34 | this.userBorth,
35 | this.userAddress,
36 | this.userHobby,
37 | this.userMotto,
38 | this.facultyId,
39 | this.specialtyId,
40 | this.facultyName,
41 | this.specialtyName
42 | });
43 |
44 | // ///
45 | // /// 创建用户登录模型
46 | // ///
47 | // factory User.createLoginUser(String loginMoblie, String loginPwd){
48 | // return User(userMobile: loginMoblie, userPwd: loginPwd);
49 | // }
50 |
51 | @override
52 | String toString() {
53 | return '{userId: '+this.userId.toString()
54 | +', roleId: '+this.roleId.toString()
55 | +', userAvatar: '+this.userAvatar
56 | +', userNickname: '+this.userNickname
57 | +', userMobile: '+this.userMobile
58 | +', userBorth: '+this.userBorth
59 | +', userAddress: '+this.userAddress
60 | +', userHobby: '+this.userHobby
61 | +', userMotto: '+this.userMotto
62 | +', facultyId: '+this.facultyId.toString()
63 | +', specialtyId: '+this.specialtyId.toString()
64 | +', facultyName: '+this.facultyName
65 | +', specialtyName: '+this.specialtyName+'}';
66 | }
67 |
68 | ///
69 | /// Json数据转换
70 | ///
71 | factory User.fromJson(Map json){
72 | print('用户model获取服务器数据信息:json=$json');
73 | return User(
74 | userId:int.parse(json['userId'].toString()), // 非空
75 | roleId:int.parse(json['roleId'].toString()), // 非空
76 | userAvatar:json.putIfAbsent('userAvatar', () => ''),
77 | userNickname:json.putIfAbsent('userNickname',() => null), // 非空
78 | userMobile:json.putIfAbsent('userMobile',() => null), // 非空
79 | userBorth:json.putIfAbsent('userBorth', () => ''),
80 | userAddress:json.putIfAbsent('userAddress', () => ''),
81 | userHobby:json.putIfAbsent('userHobby', () => ''),
82 | userMotto:json.putIfAbsent('userMotto', () => ''),
83 | facultyId:int.parse(json['facultyId'].toString()), // 非空
84 | specialtyId:int.parse(json['specialtyId'].toString()), // 非空
85 | facultyName:json.putIfAbsent('facultyName', () => null),
86 | specialtyName:json.putIfAbsent('specialtyName', () => null)
87 | );
88 | }
89 |
90 | ///
91 | /// 将Model转为Json
92 | ///
93 | Map toJson(User user){
94 | return {
95 | 'userId':userId,
96 | 'roleId':roleId,
97 | 'userAvatar':userAvatar,
98 | 'userNickname':userNickname,
99 | 'userMobile':userMobile,
100 | 'userBorth':userBorth,
101 | 'userAddress':userAddress,
102 | 'userHobby':userHobby,
103 | 'userMotto':userMotto,
104 | 'facultyId':facultyId,
105 | 'specialtyId':facultyId
106 | };
107 | }
108 |
109 |
110 |
111 | }
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | // APK秘钥配置
29 | def keystoreProperties = new Properties()
30 | def keystorePropertiesFile = rootProject.file('key.properties')
31 | if (keystorePropertiesFile.exists()) {
32 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
33 | }
34 |
35 |
36 | android {
37 | compileSdkVersion 28
38 |
39 | sourceSets {
40 | main.java.srcDirs += 'src/main/kotlin'
41 | }
42 |
43 | lintOptions {
44 | disable 'InvalidPackage'
45 | }
46 |
47 | defaultConfig {
48 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
49 | applicationId "com.hzuwei.bju" // JPush推送设置
50 | minSdkVersion 19
51 | targetSdkVersion 28
52 | versionCode flutterVersionCode.toInteger()
53 | versionName flutterVersionName
54 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
55 |
56 | ndk {
57 | //选择要添加的对应 cpu 类型的 .so 库。
58 | abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64', 'mips', 'mips64', 'arm64-v8a'
59 | }
60 |
61 | manifestPlaceholders = [
62 | JPUSH_PKGNAME : "com.hzuwei.bju",
63 | JPUSH_APPKEY : "2180c05fa8c52f21d907cbf3", // NOTE: JPush 上注册的包名对应的 Appkey.
64 | JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.
65 | ]
66 |
67 | }
68 |
69 | // 配置APK秘钥信息
70 | signingConfigs {
71 | release {
72 | keyAlias keystoreProperties['keyAlias']
73 | keyPassword keystoreProperties['keyPassword']
74 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
75 | storePassword keystoreProperties['storePassword']
76 | }
77 | }
78 | buildTypes {
79 | release {
80 | // TODO: Add your own signing config for the release build.
81 | // Signing with the debug keys for now, so `flutter run --release` works.
82 | signingConfig signingConfigs.release
83 | // 启用混淆以及/或压缩
84 | minifyEnabled true
85 | useProguard true
86 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
87 | }
88 | }
89 | }
90 |
91 | flutter {
92 | source '../..'
93 | }
94 |
95 | dependencies {
96 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
97 | testImplementation 'junit:junit:4.12'
98 | androidTestImplementation 'androidx.test:runner:1.1.1'
99 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
100 | }
101 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/lib/pages/back_management/management.dart:
--------------------------------------------------------------------------------
1 | import 'package:bju_information_app/api/api.dart';
2 | import 'package:bju_information_app/models/response.dart';
3 | import 'package:bju_information_app/net/bju_net.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:oktoast/oktoast.dart';
6 |
7 | ///
8 | /// 推送信息到全员用户
9 | /// 2020/04/20 15:15
10 | ///
11 | class BackManagement extends StatefulWidget {
12 | BackManagement({Key key}) : super(key: key);
13 |
14 | @override
15 | _BackManagementState createState() => _BackManagementState();
16 | }
17 |
18 | class _BackManagementState extends State {
19 |
20 |
21 | /// 文本编辑控制器
22 | TextEditingController _contentTextController = TextEditingController();
23 |
24 |
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | return Scaffold(
29 | appBar: AppBar(
30 | leading: BackButton(onPressed:(){
31 | Navigator.of(context).pop();
32 | }),
33 | title: Text('后台管理'),
34 | ),
35 | body: SingleChildScrollView(
36 | child: ListView(
37 | shrinkWrap: true,
38 | children: [
39 | Padding(
40 | padding: EdgeInsets.all(5),
41 | child: TextField(
42 | controller: _contentTextController,
43 | keyboardType: TextInputType.text,
44 | maxLines: 3,
45 | decoration: InputDecoration(
46 | hintText: '请输入全平台推送通知的信息...',
47 | border: OutlineInputBorder(),
48 | ),
49 | ),
50 | ),
51 | Divider(),
52 | Padding(
53 | padding: EdgeInsets.only(left: 10, right: 10,),
54 | child: RaisedButton(
55 | padding: EdgeInsets.fromLTRB(0, 3, 0, 3),
56 | color: Colors.lightBlue[400],
57 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
58 | child: Text('全员推送(ALL STAFF PUSH)',style: TextStyle(
59 | fontSize: 18,
60 | fontWeight: FontWeight.w500,
61 | letterSpacing: 2,
62 | color: Colors.white,
63 | ),
64 | ),
65 | onPressed: () async {
66 | print('全员信息推送开始...');
67 | if(!(_contentTextController.text.trim().length > 0)){
68 | showToast('请输入推送的内容!');
69 | return;
70 | }
71 | // 向服务器发起推送请求
72 | ResponseData resData = await BjuHttp.post(API.pushAll,params: {
73 | 'messageType' : 0,
74 | 'content' : _contentTextController.text
75 | }).then((onValue) => ResponseData.fromJson(onValue.data))
76 | .catchError((onError){
77 | print('全员推送,请求服务器异常!');
78 | print(onError);
79 | showToast('服务器请求异常!');
80 | return;
81 | });
82 |
83 | if(resData == null){
84 | Future.delayed(Duration(milliseconds: 1500),() => showToast('请求失败!'));
85 | return;
86 | }
87 | // 弹出提示
88 | showToast(resData.message);
89 | if(resData.statusCode == 0){
90 | // 清空输入框文本
91 | _contentTextController.clear();
92 | }
93 |
94 |
95 |
96 | }
97 | ),
98 | )
99 | ],
100 | ),
101 | ),
102 | );
103 | }
104 | }
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: bju_information_app
2 | description: A new Flutter project.
3 |
4 | # The following defines the version and build number for your application.
5 | # A version number is three numbers separated by dots, like 1.2.43
6 | # followed by an optional build number separated by a +.
7 | # Both the version and the builder number may be overridden in flutter
8 | # build by specifying --build-name and --build-number, respectively.
9 | # In Android, build-name is used as versionName while build-number used as versionCode.
10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
12 | # Read more about iOS versioning at
13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
14 | version: 1.0.0+1
15 |
16 | environment:
17 | sdk: ">=2.1.0 <3.0.0"
18 |
19 | dependencies:
20 | flutter:
21 | sdk: flutter
22 |
23 | # The following adds the Cupertino Icons font to your application.
24 | # Use with the CupertinoIcons class for iOS style icons.
25 | cupertino_icons: ^0.1.2
26 | provider: ^4.0.4
27 | # 闪屏
28 | splashscreen:
29 | # 网络
30 | dio: ^3.0.8
31 | # 轮播图
32 | flutter_swiper: ^1.1.6
33 | # 屏幕适配插件
34 | flutter_screenutil: ^1.0.2
35 | # 第三方 icon 图标插件
36 | font_awesome_flutter: ^8.5.0
37 | # 本地通知
38 | flutter_local_notifications: ^1.1.6
39 | # 路由
40 | fluro: ^1.5.2
41 | # JPush
42 | jpush_flutter: ^0.1.0
43 | # UI
44 | getflutter: ^1.0.8
45 | # 图片上传
46 | image_picker: ^0.6.5
47 | # 多图片上传
48 | multi_image_picker: ^4.6.1
49 | # 设备信息
50 | device_info: ^0.4.1+5
51 | # 获取定位
52 | # location: ^2.5.3
53 | # 徽章
54 | badges: ^1.1.1
55 | # 自定义对话框
56 | flutter_custom_dialog: ^1.0.16
57 | # 省市县三级联动
58 | city_pickers: ^0.1.30
59 | # 日期选择器
60 | flutter_datetime_picker: ^1.3.4
61 | # flutter picker
62 | flutter_picker: ^1.1.0
63 | # 地理编码
64 | # geocoder: ^0.2.1
65 | # 定位
66 | geolocator: ^5.3.0
67 | # toast
68 | oktoast: ^2.3.1+1
69 | # 打开网页
70 | webview_flutter: ^0.3.19+9
71 | # 工具类
72 | flustars: ^0.2.6+1
73 | # 底部动态导航
74 | curved_navigation_bar: ^0.3.2
75 | #SQLLite数据库
76 | sqflite: ^1.3.0
77 | #文件路径工具
78 | path_provider: ^1.6.5
79 | #路径
80 | # path: ^1.7.0
81 |
82 |
83 | dev_dependencies:
84 | flutter_test:
85 | sdk: flutter
86 |
87 |
88 | # For information on the generic Dart part of this file, see the
89 | # following page: https://dart.dev/tools/pub/pubspec
90 |
91 | # The following section is specific to Flutter.
92 | flutter:
93 | uses-material-design: true
94 | # 添加固定的图片信息
95 | assets:
96 | - assets/swiper/
97 | - assets/splash/
98 | - assets/avatar/
99 | - assets/icon/
100 | - assets/background_imgs/
101 | - assets/gif/
102 | # - assets/background_imgs/bg_login.png
103 | # - images/a_dot_ham.jpeg
104 |
105 | # An image asset can refer to one or more resolution-specific "variants", see
106 | # https://flutter.dev/assets-and-images/#resolution-aware.
107 |
108 | # For details regarding adding assets from package dependencies, see
109 | # https://flutter.dev/assets-and-images/#from-packages
110 |
111 | # To add custom fonts to your application, add a fonts section here,
112 | # in this "flutter" section. Each entry in this list should have a
113 | # "family" key with the font family name, and a "fonts" key with a
114 | # list giving the asset and other descriptors for the font. For
115 | # example:
116 | # fonts:
117 | # - family: Schyler
118 | # fonts:
119 | # - asset: fonts/Schyler-Regular.ttf
120 | # - asset: fonts/Schyler-Italic.ttf
121 | # style: italic
122 | # - family: Trajan Pro
123 | # fonts:
124 | # - asset: fonts/TrajanPro.ttf
125 | # - asset: fonts/TrajanPro_Bold.ttf
126 | # weight: 700
127 | #
128 | # For details regarding fonts from package dependencies,
129 | # see https://flutter.dev/custom-fonts/#from-packages
130 |
--------------------------------------------------------------------------------
/lib/pages/message_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:bju_information_app/constants/bju_constant.dart';
2 | import 'package:bju_information_app/pages/details/message_details.dart';
3 | import 'package:bju_information_app/providers/jpush_provider.dart';
4 | import 'package:bju_information_app/providers/login_provider.dart';
5 | import 'package:bju_information_app/utils/db_util.dart';
6 | import 'package:flutter/cupertino.dart';
7 | import 'package:flutter/material.dart';
8 | import 'package:flutter_screenutil/flutter_screenutil.dart';
9 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
10 | import 'package:provider/provider.dart';
11 |
12 | class MessagePage extends StatefulWidget {
13 | MessagePage({Key key}) : super(key: key);
14 |
15 | @override
16 | _MessagePageState createState() => _MessagePageState();
17 | }
18 |
19 | class _MessagePageState extends State {
20 |
21 | final List _msgItems = ['平台通知','@我的','评论我','赞我'];
22 |
23 | final List _msgItemIcons = [
24 | Icon(FontAwesomeIcons.bullhorn, color: Colors.lightBlue[400],),
25 | Icon(FontAwesomeIcons.at, color: Colors.lightBlue[400]),
26 | Icon(FontAwesomeIcons.comments, color: Colors.lightBlue[400]),
27 | Icon(FontAwesomeIcons.thumbsUp,color: Colors.lightBlue[400])
28 | ];
29 |
30 |
31 |
32 |
33 | @override
34 | Widget build(BuildContext context) {
35 |
36 | // 初始化屏幕大小用于适配
37 | ScreenUtil.init(context, width:750,height:1334);
38 |
39 | return Scaffold(
40 | appBar: AppBar(
41 | centerTitle: true,
42 | //leading:Icon(Icons.account_circle),
43 | title: Text('消息'),
44 | actions: [
45 | Padding(
46 | padding: EdgeInsets.only(right: 15),
47 | child: Icon(Icons.help_outline),
48 | )
49 | ],
50 | ),
51 | body: Consumer2(
52 | builder: (context, loginProvider, jpushProvider, child){
53 | // loginProvider.isLogin ? Center(child: Text('同学,您还没有登录唷~')) :
54 | return ListView.separated(
55 | padding: EdgeInsets.only(left:5, right:5),
56 | itemBuilder: (context,index){
57 |
58 | return ListTile(
59 | leading: _msgItemIcons[index],
60 | title: Text(_msgItems[index]),
61 | trailing: Icon(FontAwesomeIcons.chevronRight, size: 32, color: Colors.grey[400],),
62 | onTap: (){
63 | // 用户未登录并点击了 ['@我','评论我','赞我'],给出提示信息
64 | if(!loginProvider.isLogin && index != 0){
65 | showCupertinoDialog(context: context, builder: (context){
66 | return CupertinoAlertDialog(
67 | title: Icon(Icons.warning,color: Colors.deepOrangeAccent,),
68 | content: Text('同学请先登录,在查看!'),
69 | actions:[
70 | FlatButton(
71 | onPressed: () => Navigator.pop(context),
72 | child: Text('知道了'),
73 | ),
74 | ]
75 | );
76 | });
77 | return;
78 | }
79 | print('用户点击了---$index]');
80 | print('messageList:'+jpushProvider.messageList(index).toString());
81 |
82 | // 跳转到消息详情页面
83 | Navigator.push(context, MaterialPageRoute(
84 | builder: (context) => MessageDetailsPage(index)
85 | )
86 | );
87 |
88 | },
89 | );
90 | },
91 | separatorBuilder: (context,index){
92 | return child;
93 | },
94 | itemCount: _msgItems.length
95 | );
96 | },
97 | child: Divider(height:10),
98 | ),
99 | );
100 | }
101 |
102 |
103 |
104 |
105 |
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/lib/models/comment.dart:
--------------------------------------------------------------------------------
1 |
2 | ///
3 | /// 评论实体
4 | /// 2020/03/26 15:56
5 | ///
6 | class Comment{
7 |
8 |
9 | }
10 |
11 | ///
12 | /// 评论VO
13 | /// 2020/03/24 16:45
14 | ///
15 | class CommentVO {
16 |
17 |
18 | /// 评论ID
19 | int commentId;
20 | /// 评论内容
21 | String commentContent;
22 | /// 评论点赞量
23 | int commentLike;
24 | /// 点赞用户列表
25 | List commentLikeUsers;
26 | /// 评论时间
27 | String commentCreateTime;
28 | /// 评论人ID
29 | int commentAuthorId;
30 | /// 评论人头像
31 | String commentAuthorAvatar;
32 | /// 评论人昵称
33 | String commentAuthorName;
34 | /// 评论人手机号
35 | String commentAuthorPhone;
36 | /// 父评论ID
37 | int parentCommentId;
38 | /// 父评论内容
39 | String parentCommentContent;
40 | /// 父评论点赞量
41 | int parentCommentLike;
42 | /// 父评论创建时间
43 | String parentCommentCreateTime;
44 | /// 父评论作者ID
45 | int parentCommentAuthorId;
46 | /// 父评论作者头像
47 | String parentCommentAuthorAvatar;
48 | /// 父评论作者昵称
49 | String parentCommentAuthorName;
50 | /// 父评论作者手机号码
51 | String parentCommentAuthorPhone;
52 |
53 |
54 | CommentVO({
55 | this.commentId,
56 | this.commentContent,
57 | this.commentLike,
58 | this.commentLikeUsers,
59 | this.commentCreateTime,
60 | this.commentAuthorId,
61 | this.commentAuthorAvatar,
62 | this.commentAuthorName,
63 | this.commentAuthorPhone,
64 | this.parentCommentId,
65 | this.parentCommentContent,
66 | this.parentCommentLike,
67 | this.parentCommentCreateTime,
68 | this.parentCommentAuthorId,
69 | this.parentCommentAuthorAvatar,
70 | this.parentCommentAuthorName,
71 | this.parentCommentAuthorPhone,
72 | });
73 |
74 |
75 | factory CommentVO.fromJson(Map json) => CommentVO(
76 | commentId: int.parse(json['commentId'].toString()),
77 | commentContent: json['commentContent'],
78 | commentLike: int.parse(json['commentLike'].toString()),
79 | commentLikeUsers: json.putIfAbsent('commentLikeUsers', () => [])?.toString()?.split(','),
80 | commentCreateTime: json['commentCreateTime'],
81 | commentAuthorId: int.parse(json['commentLike'].toString()),
82 | commentAuthorAvatar: json['commentAuthorAvatar'],
83 | commentAuthorName: json['commentAuthorName'],
84 | commentAuthorPhone: json['commentAuthorPhone'],
85 | parentCommentId: json.putIfAbsent('parentCommentId', () => null),
86 | parentCommentContent: json.putIfAbsent('parentCommentContent', () => null),
87 | parentCommentLike: json.putIfAbsent('parentCommentLike', () => null),
88 | parentCommentCreateTime: json.putIfAbsent('parentCommentCreateTime', () => null),
89 | parentCommentAuthorId: json.putIfAbsent('parentCommentAuthorId', () => null),
90 | parentCommentAuthorAvatar: json.putIfAbsent('parentCommentAuthorAvatar', () => null),
91 | parentCommentAuthorName: json.putIfAbsent('parentCommentAuthorName', () => null),
92 | parentCommentAuthorPhone: json.putIfAbsent('parentCommentAuthorPhone', () => null),
93 | );
94 |
95 | @override
96 | String toString() {
97 | return '{: commentId: ' + this.commentId.toString()
98 | +', commentContent: ' + this.commentContent
99 | +', commentLike: ' + this.commentLike.toString()
100 | +', commentLikeUsers: ' + this.commentLikeUsers.toString()
101 | +', commentCreateTime: ' + this.commentCreateTime
102 | +', commentAuthorId: ' + this.commentAuthorId.toString()
103 | +', commentAuthorAvatar: ' + this.commentAuthorAvatar
104 | +', commentAuthorName: ' + this.commentAuthorName
105 | +', commentAuthorPhone: ' + this.commentAuthorPhone
106 | +', parentCommentId: ' + this.parentCommentId.toString()??''
107 | +', parentCommentContent: ' + this.parentCommentContent??''
108 | +', parentCommentLike: ' + this.parentCommentLike.toString()??''
109 | +', parentCommentCreateTime: ' + this.parentCommentCreateTime??''
110 | +', parentCommentAuthorId: ' + this.parentCommentAuthorId.toString()??''
111 | +', parentCommentAuthorAvatar: ' + this.parentCommentAuthorAvatar??''
112 | +', parentCommentAuthorName: ' + this.parentCommentAuthorName??''
113 | +', parentCommentAuthorPhone: ' + this.parentCommentAuthorPhone??'' + '}';
114 | }
115 |
116 | }
--------------------------------------------------------------------------------
/lib/net/bju_net.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:bju_information_app/api/api.dart';
3 | import 'package:dio/dio.dart';
4 |
5 | ///
6 | /// BJU网络
7 | ///
8 | class BjuHttp {
9 |
10 | /// Dio 请求的配置
11 | // static final BaseOptions baseOptions = BaseOptions(
12 | // // baseUrl: API.baseUri,
13 | // connectTimeout: 6000,
14 | // receiveTimeout: 4000,
15 | // contentType: Headers.jsonContentType,
16 | // headers: {
17 | // Headers.contentTypeHeader: Headers.jsonContentType,
18 | // 'Authorization': 'Bearer '
19 | // }
20 | // );
21 |
22 | /// Dio请求
23 | static final Dio dio = Dio();
24 |
25 |
26 |
27 | /// 初始化Dio配置
28 | static void initConfig(){
29 | // 基础选项设置
30 | // dio.options = BaseOptions(
31 | // // baseUrl: API.baseUri,
32 | // // connectTimeout: 6000,
33 | // // receiveTimeout: 4000,
34 | // // contentType: Headers.jsonContentType,
35 | // // headers: {
36 | // // // Headers.contentTypeHeader: Headers.jsonContentType,
37 | // // // 'Authorization': 'Bearer '
38 | // // }
39 | // );
40 | // print('DIO请求配置信息为: ');
41 | // print('connectTimeout: ' + dio.options?.connectTimeout.toString());
42 | // print('receiveTimeout: ' + dio.options?.receiveTimeout.toString());
43 | // print('contentType: ' + dio?.options?.contentType??null);
44 | // print('headers: ' + dio?.options?.headers.toString()??null);
45 | // print('params: ' + dio?.options?.queryParameters.toString()??null);
46 | // 请求拦截器设置
47 | dio.interceptors.add(InterceptorsWrapper(
48 | onRequest:(RequestOptions options) async {
49 | print('请求前打印options: ');
50 | print('contentType: ' + options.contentType);
51 | print('headers: ' + options.headers.toString());
52 | print('data: ' + options.data.toString());
53 | print('params: ' + options.queryParameters.toString());
54 | // Do something before request is sent
55 | return options; //continue
56 | // If you want to resolve the request with some custom data,
57 | // you can return a `Response` object or return `dio.resolve(data)`.
58 | // If you want to reject the request with a error message,
59 | // you can return a `DioError` object or return `dio.reject(errMsg)`
60 | },
61 | onResponse:(Response response) async {
62 | // Do something with response data
63 | return response; // continue
64 | },
65 | onError: (DioError e) async {
66 | // Do something with response error
67 | return e;//continue
68 | }
69 | ));
70 |
71 | }
72 | /// 设置访问Token
73 | static token(dynamic token){
74 | dio.options.contentType = 'application/json';
75 | dio.options.headers['Authorization'] = token;
76 | print('[set token] dio header :'+dio.options.headers.toString());
77 | }
78 |
79 | // 销毁token
80 | static disposeToken(){
81 | dio.options.contentType = 'application/json';
82 | dio.options.headers['Authorization'] = 'Bearer ';
83 | print('[dispose token] dio header :'+dio.options.headers.toString());
84 | }
85 |
86 |
87 | //Dio get instance => _dio;
88 |
89 | ///
90 | /// GET请求
91 | /// * [path] 路径字符串
92 | /// * [params] 请求参数
93 | ///
94 | static Future get(String path,{Map params}) async => await dio.get(path, queryParameters: params);
95 |
96 | ///
97 | /// POST请求
98 | /// * [path] 路径字符串
99 | /// * [data] body数据
100 | /// * [params] 请求参数(URL编码后)
101 | /// * [options] 请求设置
102 | ///
103 | static Future post(String path,{dynamic data, Map params, Options options}) async => await dio.post(path, queryParameters: params, options: options);
104 |
105 | ///
106 | /// POST请求
107 | /// * [path] 路径字符串
108 | /// * [data] body数据(支持FormData)
109 | /// * [params] 请求参数(URL编码后)
110 | ///
111 | static Future put(String path,{dynamic data, Map params}) async => await dio.put(path, queryParameters: params);
112 |
113 | ///
114 | /// POST请求
115 | /// * [path] 路径字符串
116 | /// * [data] body数据
117 | /// * [params] 请求参数(URL编码后)
118 | ///
119 | static Future delete(String path,{dynamic data, Map params}) async => await dio.delete(path, queryParameters: params);
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | }
--------------------------------------------------------------------------------
/lib/api/api.dart:
--------------------------------------------------------------------------------
1 |
2 | ///
3 | /// BJU应用的API接口
4 | ///
5 | class API {
6 |
7 | // ****************** 服务器信息 ***********************
8 | static final String protocol = 'http://';
9 | // static final String hostName = '192.168.85.1'; // 服务器IP地址 (本机模拟器使用)
10 | static final String hostName = 'bju.server.hzwei.top'; // 服务器IP地址 手机(真机)使用
11 | static final int port = 8080;
12 | static final String appName = 'bjuInformationService'; // app name
13 | // static final String baseUri = '$protocol$hostName:$port/$appName'; // 基本路径地址(本机模拟器使用)
14 | static final String baseUri = '$protocol$hostName/$appName'; // 基本路径地址 手机(真机)使用
15 |
16 |
17 |
18 |
19 | // ******************** passport ********************
20 | /// 账号密码登录 === [POST]
21 | static final String npLogin = '$baseUri/passport/login/upLogin';
22 | /// 新用户注册接口 === [POST]
23 | static final String register = '$baseUri/passport/register/doRegister';
24 | /// 阿里手机验证码发送接口 [SMS/verifyCode/{phoneNumber}]===[POST]
25 | static final String sms = '$baseUri/SMS/verifyCode/';
26 | /// 验证码验证 === [GET]
27 | static final String verifyCode = '$baseUri/passport/register/validate/code';
28 | /// 检测昵称唯一性接口 [passport/register/validate/nickname] === [POST]
29 | static final String existNickname = '$baseUri/passport/register/validate/nickname';
30 | /// 检测手机号码唯一性接口 [passport/register/validate/mobile] === [POST]
31 | static final String existMobile = '$baseUri/passport/register/validate/mobile';
32 | /// JPush推送接口 === [POST]
33 | static final String pushAll = '$baseUri/notification/all'; // 用于管理员发送公告推送信息
34 |
35 | /// 动态发布接口 === [POST]
36 | static final String publishMoving = '$baseUri/moving/publish';
37 |
38 | /// 用户中心计数项接口 === [GET]
39 | static final String allCounts = "$baseUri/user/info/counts";
40 |
41 | /// 获取模块下话题接口 === [GET]
42 | static final String topics = '$baseUri/module/topic';
43 |
44 | /// 获取院系及专业信息 === [GET]
45 | static final String allFacultyAndSpecialty = '$baseUri/faculties';
46 |
47 | /// 获取最新动态 === [GET]
48 | static final String newMoving = '$baseUri/moving/new';
49 |
50 | /// 获取最新动态 === [GET]
51 | static final String hotMoving = '$baseUri/moving/hot';
52 |
53 | /// 获取指定动态的详情(路径参数) === [GET]
54 | static final String movingDetailsById = '$baseUri/moving/details/';
55 |
56 | /// 添加评论 === [POST]
57 | static final String addComment = '$baseUri/moving/comment/add';
58 |
59 | /// 模糊搜索@用户列表 === [GET]
60 | static final String searchAtUser = '$baseUri/user/fuzzy';
61 |
62 | /// 按照id获取用户信息(路径参数)=== [GET]
63 | static final String getUserInfoById = '$baseUri/user/info/';
64 |
65 | /// 校园新闻地址
66 | static final String campusNews = 'http://www.bjwlxy.edu.cn/index/xwdt/xyzx.htm';
67 |
68 | /// 平台系统用户默认头像地址
69 | static final String defaultAvatarURL = '$baseUri/static/avatars/default_avatar.jpg';
70 |
71 | /// 修改用户信息 === [PUT]
72 | static final String updateUserInfo = '$baseUri/user/info/edit';
73 |
74 | /// 模糊搜索动态信息({searchKeyword}) === [GET]
75 | static final String fuzzySearchMoving = '$baseUri/moving/fuzzy/';
76 |
77 | /// 按照模块ID获取动态信息({moduleId}) === [GET]
78 | static final String queryMovingByModuleId = '$baseUri/moving/module/';
79 |
80 | /// 退出登录APP == [POST]
81 | static final String logout = '$baseUri/passport/login/logout';
82 |
83 | /// 动态浏览量更新 === [PUT]
84 | static final String updateBrowseCount = '$baseUri/refresh/browse';
85 |
86 | /// 动态点赞量及点赞用户列表的更新 === [PUT]
87 | static final String updateMovingLikeData = '$baseUri/moving/refresh/like';
88 |
89 | /// 评论点赞量及点赞用户列表的更新 === [PUT]
90 | static final String updateCommentLikeData = '$baseUri/moving/comment/like';
91 |
92 | /// 动态图片访问的URL前缀
93 | static final String movingImagesBaseUrl = '$baseUri';
94 |
95 | /// 用户密码修改 === [PUT]
96 | static final String modifyPassword = '$baseUri/user/safe/password/modify';
97 |
98 | /// 用户头像修改 === [POST]
99 | static final String modifyAvatar = '$baseUri/user/info/avatar';
100 |
101 | /// 获取指定用户所有已发布的动态 === [GET]
102 | /// * 路径参数 userId
103 | static final String allMovingWithUser = '$baseUri/moving/published/';
104 |
105 | /// 获取指定用户草稿箱 === [GET]
106 | /// * 路径参数 userId
107 | static final String draftMovingWithUser = '$baseUri/moving/draft/';
108 |
109 | /// 保存动态到草稿箱 === [POST]
110 | /// * multipart/form-data
111 | static final String saveDraftMoving = '$baseUri/moving/temporary';
112 |
113 | /// 重新发布动态(草稿箱中的)=== [PUT]
114 | /// * 路径参数 movingId
115 | static final String republishMoving = '$baseUri/moving/republish/';
116 |
117 | /// 删除动态(已发布or草稿箱)=== [DELETE]
118 | /// * 路径参数 movingId
119 | static final String deleteMoving = '$baseUri/moving/delete/';
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | }
--------------------------------------------------------------------------------
/lib/models/user_message.dart:
--------------------------------------------------------------------------------
1 | ///
2 | /// 用户消息(服务端通知用户,并携带的用户消息)2020/04/17 21:02
3 | /// * 0 ==> 应用通知
4 | /// * 1 ==> mongo@大宝
5 | /// * 2 ==> mongo评论了你的动态
6 | /// * 3 ==> mongo回复了你的评论
7 | /// * 4 ==> mongo赞了你的动态
8 | /// * 5 ==> mongo赞了你的评论
9 | /// * **其中,[2,3]均为APP端评论我类型;[4,5]均为APP端赞我类型**
10 | ///
11 | ///
12 | class UserMessage {
13 |
14 | ///
15 | /// 消息的编号
16 | ///
17 | //String sendno;
18 | ///
19 | /// 消息头
20 | /// 例如:
21 | /// 0. 应用通知
22 | /// 1. mongo@大宝
23 | /// 2. mongo评论了你的动态
24 | /// 3. mongo回复了你的评论
25 | /// 4. mongo赞了你的动态
26 | /// 5. mongo赞了你的评论
27 | ///
28 | ///
29 | String title; //
30 |
31 | ///
32 | /// 消息体
33 | /// 显示的具体内容,用于在消息页面中进行显示
34 | String content;
35 |
36 | ///
37 | /// 消息类型
38 | /// 参照消息头中的编号
39 | int messageType;
40 |
41 | /// 目标用户名
42 | String toUserName;
43 |
44 | /// 来源用户名
45 | String fromUserName;
46 |
47 | /// 来源用户的ID
48 | int fromUserId;
49 |
50 | /// 来源用户头像
51 | String fromUserAvatar;
52 |
53 | /// 用于查询消息context所对应的具体moving
54 | int queryId;
55 |
56 | /// 接收时间
57 | String receivedTime;
58 |
59 | /// 是否已读
60 | String read;
61 |
62 | /* int commentId; // 评论ID
63 |
64 | int movingId; // 动态ID
65 |
66 | int replyId; // 评论回复ID */
67 | /*
68 | String commentContext; // 评论内容
69 |
70 | String movingContext; // 动态内容
71 |
72 | String replyContext; // 评论回复内容
73 | */
74 |
75 | UserMessage({this.title,this.content,this.messageType,this.fromUserId,this.fromUserName,this.fromUserAvatar,this.read = 'false',this.toUserName = '',this.queryId = 0,this.receivedTime});
76 |
77 | @override
78 | String toString() {
79 | return '{'
80 | +', title= ' + this.title
81 | +', content= ' + this.content
82 | +', messageType= ' + this.messageType.toString()
83 | +', fromUserName= ' + this.fromUserName
84 | +', fromUserId= ' + this.fromUserId.toString()
85 | +', fromUserAvatar= ' + this.fromUserAvatar
86 | +', toUserName= ' + this.toUserName
87 | +', queryId= ' + this.queryId.toString()
88 | +', receivedTime= ' + this.receivedTime
89 | +', read= ' + this.read.toString()+
90 | '}';
91 | }
92 |
93 | ///
94 | /// Json模型化
95 | ///
96 | factory UserMessage.fromJson(Map json){
97 | // print('UserMessage接收消息:'+json.toString());
98 | // print(json.runtimeType.toString());
99 | if(json.isEmpty){
100 | print('没有信息可以构造UserMessage!');
101 | return null;
102 | }
103 |
104 | // final String tilte = json['title'];
105 | // final String content = json['content'];
106 | // final int messageType = int.parse(json['messageType'].toString());
107 | // final String fromUserName = json.putIfAbsent('fromUserName', () => null);
108 | // final int fromUserId = int.parse(json['fromUserId'].toString());
109 | // final String fromUserAvatar = json.putIfAbsent('fromUserAvatar',() => null);
110 | // final int queryId = int.parse(json['queryId'].toString());
111 | // final String receivedTime = json['receivedTime'];
112 | // final String read = json['read'];
113 | // print('UserMessage中的Map取出来的信息值:');
114 | // print(tilte);
115 | // print(content);
116 | // print(messageType.toString());
117 | // print(fromUserName);
118 | // print(fromUserId.toString());
119 | // print(fromUserAvatar);
120 | // print(queryId.toString());
121 | // print(receivedTime);
122 | // print(read);
123 | UserMessage userMessage;
124 |
125 |
126 |
127 | try{
128 | userMessage = UserMessage(
129 | title : json['title'],
130 | content : json['content'],
131 | messageType : int.parse(json['messageType'].toString()),
132 | fromUserName : json.putIfAbsent('fromUserName', () => ''),
133 | fromUserId : int.parse(json['fromUserId'].toString()),
134 | fromUserAvatar : json.putIfAbsent('fromUserAvatar',() => ''),
135 | // toUserName : null,
136 | queryId : int.parse(json['queryId'].toString()),
137 | receivedTime : json['receivedTime'],
138 | read : json['read'],
139 | );
140 | }catch (e){
141 | print('构造用户信息模型异常了!');
142 | print(e);
143 | }
144 | print('用户信息类中创建的对象为:');
145 | print(userMessage);
146 |
147 | return userMessage;
148 | }
149 |
150 | ///
151 | /// UserMessage转为Map
152 | ///
153 | Map toMap(){
154 |
155 | Map messageMap = {
156 | "title" : this.title,
157 | "content" : this.content,
158 | "messageType" : this.messageType,
159 | "fromUserName" : this.fromUserName,
160 | "fromUserId" : this.fromUserId,
161 | "fromUserAvatar" : this.fromUserAvatar,
162 | "toUserName" : this.toUserName,
163 | "queryId" : this.queryId,
164 | "receivedTime" : this.receivedTime,
165 | "read" : this.read
166 | };
167 | print('当前UserMessage转为Map,转换结果:messageMap= ' + messageMap.toString());
168 | return messageMap;
169 |
170 | }
171 |
172 | }
--------------------------------------------------------------------------------
/lib/models/moving.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:bju_information_app/models/comment.dart';
4 |
5 |
6 | ///
7 | /// 动态模型
8 | /// 2020/2/23 22:06
9 | ///
10 | class Moving {
11 |
12 | int movingAuthorId;
13 | String movingAuthorAvatar;
14 | String movingAuthorName;
15 | String movingAuthorPhone;
16 | String movingContent;
17 | int movingId;
18 | /// 图片组:英文‘,’分割
19 | List movingImages;
20 | String movingType;
21 | /// 话题组:英文‘,’分割
22 | List movingTopics;
23 | int movingLike;
24 | /// 点赞用户组:英文‘,’分割
25 | List movingLikeUsers;
26 | int movingBrowse;
27 | int movingCommentCount;
28 | String movingCreateTime;
29 |
30 | Moving({
31 | this.movingAuthorId,
32 | this.movingAuthorAvatar,
33 | this.movingAuthorName,
34 | this.movingAuthorPhone,
35 | this.movingContent,
36 | this.movingId,
37 | this.movingImages,
38 | this.movingType,
39 | this.movingTopics,
40 | this.movingLike,
41 | this.movingLikeUsers,
42 | this.movingBrowse,
43 | this.movingCommentCount,
44 | this.movingCreateTime
45 | });
46 |
47 | factory Moving.fromJson(Map json) => Moving(
48 | movingAuthorId: int.parse(json['movingAuthorId'].toString()),
49 | movingAuthorAvatar: json['movingAuthorAvatar'],
50 | movingAuthorName: json['movingAuthorName'],
51 | movingAuthorPhone: json['movingAuthorPhone'],
52 | movingContent: json['movingContent'],
53 | movingId: int.parse(json['movingId'].toString()),
54 | movingImages: json.putIfAbsent('movingImages', () => [])?.toString()?.split(','),
55 | movingType: json['movingType'],
56 | movingTopics: json.putIfAbsent('movingTopics', () => [])?.toString()?.split(','),
57 | movingLike: int.parse(json['movingLike'].toString()),
58 | movingLikeUsers: json.putIfAbsent('movingLikeUsers', () => [])?.toString()?.split(','),
59 | movingBrowse: int.parse(json['movingBrowse'].toString()),
60 | movingCommentCount: int.parse(json['movingCommentCount'].toString()),
61 | movingCreateTime: json['movingCreateTime']
62 | );
63 |
64 | @override
65 | String toString() {
66 |
67 | return '{movingAuthorId: '+this.movingAuthorId.toString()
68 | +', movingAuthorAvatar: '+this.movingAuthorAvatar
69 | +', movingAuthorName: '+this.movingAuthorName
70 | +', movingAuthorPhone: '+ this.movingAuthorPhone
71 | +', movingContent: '+this.movingContent
72 | +', movingId: '+this.movingId.toString()
73 | +', movingImages: '+ this.movingImages.toString()
74 | +', movingType: '+this.movingType
75 | +', movingTopics: '+ this.movingTopics.toString()
76 | +', movingLike: '+ this.movingLike.toString()
77 | +', movingLikeUsers: '+ this.movingLikeUsers.toString()
78 | +', movingBrowse: '+this.movingBrowse.toString()
79 | +', movingCommentCount: '+ this.movingCommentCount.toString()
80 | +', movingCreateTime: '+ this.movingCreateTime+'}';
81 | }
82 |
83 | }
84 |
85 | /// 动态详情模型
86 | /// 2020/3/20 15:42
87 | class MovingDetails {
88 |
89 |
90 | int movingAuthorId;
91 | // String movingAuthorAvatar;
92 | String movingAuthorName;
93 | String movingAuthorPhone;
94 | String movingContent;
95 | int movingId;
96 | /// 图片组:英文‘,’分割
97 | List movingImages;
98 | String movingType;
99 | /// 话题组:英文‘,’分割
100 | List movingTopics;
101 | int movingLike;
102 | /// 点赞用户组:英文‘,’分割
103 | List movingLikeUsers;
104 | int movingBrowse;
105 | String movingCreateTime;
106 |
107 | // 评论列表
108 | List commentReplyList;
109 |
110 |
111 | MovingDetails({
112 | this.movingAuthorId,
113 | // this.movingAuthorAvatar,
114 | this.movingAuthorName,
115 | this.movingAuthorPhone,
116 | this.movingContent,
117 | this.movingId,
118 | this.movingImages,
119 | this.movingType,
120 | this.movingTopics,
121 | this.movingLike,
122 | this.movingLikeUsers,
123 | this.movingBrowse,
124 | this.movingCreateTime,
125 | this.commentReplyList
126 | });
127 |
128 | factory MovingDetails.fromJson(Map json) => MovingDetails(
129 | movingAuthorId: int.parse(json['movingAuthorId'].toString()),
130 | // movingAuthorAvatar: json['movingAuthorAvatar'],
131 | movingAuthorName: json['movingAuthorName'],
132 | movingAuthorPhone: json['movingAuthorPhone'],
133 | movingContent: json['movingContent'],
134 | movingId: int.parse(json['movingId'].toString()),
135 | movingImages: json.putIfAbsent('movingImages', () => [])?.toString()?.split(','),
136 | movingType: json['movingType'],
137 | movingTopics: json.putIfAbsent('movingTopics', () => [])?.toString()?.split(','),
138 | movingLike: int.parse(json['movingLike'].toString()),
139 | movingLikeUsers: json.putIfAbsent('movingLikeUsers', () => [])?.toString()?.split(','),
140 | movingBrowse: int.parse(json['movingBrowse'].toString()),
141 | movingCreateTime: json['movingCreateTime'],
142 | commentReplyList: (json.putIfAbsent('commentReplyList', () => []) as List)?.map((m)=> CommentVO.fromJson(m))?.toList()
143 | );
144 |
145 | @override
146 | String toString() {
147 |
148 | return '{movingAuthorId: ' + this.movingAuthorId.toString()
149 | // +', movingAuthorAvatar:' + this.movingAuthorAvatar
150 | +', movingAuthorName:' + this.movingAuthorName
151 | +', movingAuthorPhone:' + this.movingAuthorPhone
152 | +', movingContent:' + this.movingContent
153 | +', movingId:' + this.movingId.toString()
154 | +', movingImages:' + this.movingImages.toString()
155 | +', movingType:' + this.movingType
156 | +', movingTopics:' + this.movingTopics.toString()
157 | +', movingLike:' + this.movingLike.toString()
158 | +', movingLikeUsers:' + this.movingLikeUsers.toString()
159 | +', movingBrowse:' + this.movingBrowse.toString()
160 | +', movingCreateTime:' + this.movingCreateTime
161 | +', commentReplyList:' + this.commentReplyList.toString() + '}';
162 | }
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | }
177 |
178 |
--------------------------------------------------------------------------------
/lib/pages/modules/campus_voice.dart:
--------------------------------------------------------------------------------
1 | import 'package:bju_information_app/api/api.dart';
2 | import 'package:bju_information_app/models/moving.dart';
3 | import 'package:bju_information_app/models/response.dart';
4 | import 'package:bju_information_app/net/bju_net.dart';
5 | import 'package:bju_information_app/pages/details/moving_details.dart';
6 | import 'package:bju_information_app/utils/bju_timeline_util.dart';
7 | import 'package:flutter/material.dart';
8 | import 'package:flutter_screenutil/flutter_screenutil.dart' as SU;
9 | import 'package:oktoast/oktoast.dart';
10 |
11 | ///
12 | /// 校园之声
13 | /// 2020/04/06 17:30
14 | ///
15 | class CampusVoiceModule extends StatefulWidget {
16 | CampusVoiceModule({Key key}) : super(key: key);
17 |
18 | @override
19 | _CampusVoiceModuleState createState() => _CampusVoiceModuleState();
20 | }
21 |
22 | class _CampusVoiceModuleState extends State {
23 |
24 | // 模块Id号码
25 | int _moduleId = 3;
26 |
27 | /// 校园之声数据列表
28 | List _campusVoiceList = [];
29 |
30 |
31 | @override
32 | void initState() {
33 | super.initState();
34 |
35 | }
36 |
37 | @override
38 | void didChangeDependencies() {
39 | super.didChangeDependencies();
40 | // 初始化数据
41 | _loadData();
42 | }
43 |
44 | @override
45 | void dispose() {
46 |
47 | super.dispose();
48 | }
49 |
50 | /// 加载数据
51 | void _loadData() async {
52 | // 向服务器获取数据信息
53 | ResponseData resData = await BjuHttp.get(API.queryMovingByModuleId + _moduleId.toString())
54 | .then((onValue) => ResponseData.fromJson(onValue.data))
55 | .catchError((onError){
56 | print('获取校园之声模块数据异常!');
57 | print(onError);
58 | showToast('请求服务器异常!');
59 | });
60 | if(resData == null){
61 | Future.delayed(Duration(microseconds: 1500), () => showToast('网络请求失败!'));
62 | return;
63 | }
64 | if(resData != null && resData.statusCode == 1){
65 | showToast(resData.message);
66 | return;
67 | }
68 | if(!mounted) return;
69 | setState(() {
70 | // 刷新数据
71 | _campusVoiceList = (resData.res as List).map((m) => Moving.fromJson(m)).toList();
72 | });
73 |
74 | }
75 |
76 | /// 创建模块体
77 | Widget _buildModuleBody(){
78 | print('校园之声模块的数据为:');
79 | print(_campusVoiceList);
80 | return RefreshIndicator(
81 | color: Colors.lightBlue,
82 | backgroundColor: Colors.white54,
83 | child: _campusVoiceList.isEmpty
84 | ? Center(child: Text('没有谏言类相关信息!', style: TextStyle(
85 | fontSize: 18,
86 | fontWeight: FontWeight.w500,
87 | color: Colors.black38,
88 | wordSpacing: 2,
89 | )
90 | )
91 | )
92 | : ListView.separated(
93 | itemBuilder: (context,index){
94 | return Card(
95 | elevation: 4,
96 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
97 | margin: EdgeInsets.fromLTRB(4, 3, 4, index == (_campusVoiceList.length -1) ? 10 : 0),
98 | child: Column(
99 | mainAxisSize: MainAxisSize.min,
100 | mainAxisAlignment: MainAxisAlignment.center,
101 | children: [
102 | // 发布时间
103 | Row(
104 | mainAxisAlignment: MainAxisAlignment.start,
105 | children: [
106 | Padding(
107 | padding: EdgeInsets.only(left: 10, top: 5),
108 | child: Text(BjuTimelineUtil.formatDateStr(_campusVoiceList[index].movingCreateTime) + ' 发布', style: TextStyle(
109 | fontSize: 14,
110 | fontWeight: FontWeight.w300,
111 | wordSpacing: 2,
112 | color: Colors.lightBlue,
113 | ),),
114 | )
115 | ],
116 | ),
117 | Divider(),
118 | // 主要内容
119 | Padding(
120 | padding: EdgeInsets.fromLTRB(8, 0, 8, 0),
121 | child: Text(_campusVoiceList[index].movingContent, style: TextStyle(
122 | fontSize: 14,
123 | fontWeight: FontWeight.w400,
124 | wordSpacing: 2,
125 | // color: Colors.lightBlue,
126 | ),
127 | )
128 | ),
129 | Divider(),
130 | // 详情链接
131 | GestureDetector(
132 | child: Padding(
133 | padding: EdgeInsets.only(bottom: 8),
134 | child: Text('详情信息', style: TextStyle(
135 | fontSize: 16,
136 | fontWeight: FontWeight.w500,
137 | wordSpacing: 4,
138 | color: Colors.lightBlue,
139 | ),
140 | ),
141 | ),
142 | onTap: (){
143 | // 进入详情页面
144 | print('校园之声点击了详情:' + _campusVoiceList[index].movingId.toString());
145 | final int movingId = _campusVoiceList[index].movingId;
146 | if(movingId == 0){
147 | print('跳转的动态ID不存在!');
148 | showToast('动态信息有误!');
149 | return;
150 | }
151 | // 跳转到动态详情页面
152 | Navigator.push