副本 #8

Merged
mbhvfy6mx merged 40 commits from main into cyx_branch 2 years ago

@ -18,18 +18,6 @@ migration:
- platform: android
create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
- platform: ios
create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
- platform: linux
create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
- platform: macos
create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
- platform: web
create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a
# User provided section

@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "interactive"
}

@ -1,11 +1,7 @@
<<<<<<< HEAD
=======
| 姓名 | 知士荟 | 头歌 | Github |
| ------ | -------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------- |
| 姓名 | 知士荟 | 头歌 | Github |
| ------ | ----------------------------------------------------- | ------------------------------------------------ | ---------------------------------------- |
| 葛兴海 | [@葛兴海](https://www.learnerhub.net/#/users/12147/docs) | [@葛兴海](https://code.educoder.net/user/ps9up4ig6) | [@Sheeet](https://github.com/icesheeet) |
| 庞浩 | [@庞浩](https://www.learnerhub.net/#/users/12027/docs) | [@庞浩](https://code.educoder.net/user/mbhvfy6mx) | |
| 庞浩 | [@庞浩](https://www.learnerhub.net/#/users/12027/docs) | [@庞浩](https://code.educoder.net/user/mbhvfy6mx) | |
| 卫俊钢 | [@卫俊钢](https://www.learnerhub.net/#/users/12144/docs) | [@卫俊钢](https://www.educoder.net/users/p2jf6ytqz) | [@JungangWei](https://github.com/githubwjg) |
| 邹兴云 | [@邹兴云](https://www.learnerhub.net/#/users/12026/docs) | [@邹兴云](https://www.educoder.net/users/p8fjyvg3u) | |
| 蔡玉祥 | [@蔡玉祥](https://www.learnerhub.net/#/users/12015/docs) | [@蔡玉祥](https://www.educoder.net/users/mszfy297n) | |
>>>>>>> gxh_branch
| 邹兴云 | [@邹兴云](https://www.learnerhub.net/#/users/12026/docs) | [@邹兴云](https://www.educoder.net/users/p8fjyvg3u) | |
| 蔡玉祥 | [@蔡玉祥](https://www.learnerhub.net/#/users/12015/docs) | [@蔡玉祥](https://www.educoder.net/users/mszfy297n) | |

@ -1,16 +1,3 @@
# timemanage
# 时间管理
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
一个基于Flutter框架的APP

@ -0,0 +1,2 @@
#Sat Nov 04 11:50:30 CST 2023
gradle.version=7.5

@ -23,7 +23,7 @@ if (flutterVersionName == null) {
}
android {
namespace "com.example.timemanage"
namespace "com.example.timemaneger"
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
@ -42,7 +42,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.timemanage"
applicationId "com.example.timemaneger"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion

@ -1,6 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="timemanage"
android:label="timemaneger"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity

@ -0,0 +1,44 @@
package io.flutter.plugins;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import io.flutter.Log;
import io.flutter.embedding.engine.FlutterEngine;
/**
* Generated file. Do not edit.
* This file is generated by the Flutter tool based on the
* plugins that support the Android platform.
*/
@Keep
public final class GeneratedPluginRegistrant {
private static final String TAG = "GeneratedPluginRegistrant";
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
try {
flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin package_info_plus, dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin shared_preferences_android, io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin", e);
}
try {
flutterEngine.getPlugins().add(new com.tekartik.sqflite.SqflitePlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin sqflite, com.tekartik.sqflite.SqflitePlugin", e);
}
try {
flutterEngine.getPlugins().add(new io.flutter.plugins.urllauncher.UrlLauncherPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin url_launcher_android, io.flutter.plugins.urllauncher.UrlLauncherPlugin", e);
}
}
}

@ -1,4 +1,4 @@
package com.example.timemanage
package com.example.timemaneger
import io.flutter.embedding.android.FlutterActivity

@ -0,0 +1,5 @@
sdk.dir=C:\\Users\\28749\\AppData\\Local\\Android\\sdk
flutter.sdk=C:\\flutter
flutter.buildMode=debug
flutter.versionName=1.0.0
flutter.versionCode=1

@ -0,0 +1 @@
CONTRIBUTORS.md  assetCONTRIBUTORS.md README.md  asset README.mdicon.svg  asseticon.svg2packages/cupertino_icons/assets/CupertinoIcons.ttf  asset2packages/cupertino_icons/assets/CupertinoIcons.ttf1packages/flutter_about_page/fonts/RobotoLight.ttf  asset1packages/flutter_about_page/fonts/RobotoLight.ttf2packages/flutter_about_page/fonts/RobotoMedium.ttf  asset2packages/flutter_about_page/fonts/RobotoMedium.ttf9packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf  asset9packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf:packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf  asset:packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf8packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf  asset8packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf

@ -0,0 +1 @@
{"CONTRIBUTORS.md":["CONTRIBUTORS.md"],"README.md":["README.md"],"icon.svg":["icon.svg"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"],"packages/flutter_about_page/fonts/RobotoLight.ttf":["packages/flutter_about_page/fonts/RobotoLight.ttf"],"packages/flutter_about_page/fonts/RobotoMedium.ttf":["packages/flutter_about_page/fonts/RobotoMedium.ttf"],"packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf":["packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf"],"packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf":["packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf"],"packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf":["packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf"]}

@ -0,0 +1,7 @@
| 姓名 | 知士荟 | 头歌 | Github |
| ------ | ----------------------------------------------------- | ------------------------------------------------ | ---------------------------------------- |
| 葛兴海 | [@葛兴海](https://www.learnerhub.net/#/users/12147/docs) | [@葛兴海](https://code.educoder.net/user/ps9up4ig6) | [@Sheeet](https://github.com/icesheeet) |
| 庞浩 | [@庞浩](https://www.learnerhub.net/#/users/12027/docs) | [@庞浩](https://code.educoder.net/user/mbhvfy6mx) | |
| 卫俊钢 | [@卫俊钢](https://www.learnerhub.net/#/users/12144/docs) | [@卫俊钢](https://www.educoder.net/users/p2jf6ytqz) | [@JungangWei](https://github.com/githubwjg) |
| 邹兴云 | [@邹兴云](https://www.learnerhub.net/#/users/12026/docs) | [@邹兴云](https://www.educoder.net/users/p8fjyvg3u) | |
| 蔡玉祥 | [@蔡玉祥](https://www.learnerhub.net/#/users/12015/docs) | [@蔡玉祥](https://www.educoder.net/users/mszfy297n) | |

@ -0,0 +1 @@
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]},{"family":"packages/flutter_about_page/RobotoMedium","fonts":[{"asset":"packages/flutter_about_page/fonts/RobotoMedium.ttf"}]},{"family":"packages/flutter_about_page/Roboto","fonts":[{"asset":"packages/flutter_about_page/fonts/RobotoLight.ttf"}]},{"family":"packages/font_awesome_flutter/FontAwesomeBrands","fonts":[{"weight":400,"asset":"packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf"}]},{"family":"packages/font_awesome_flutter/FontAwesomeRegular","fonts":[{"weight":400,"asset":"packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf"}]},{"family":"packages/font_awesome_flutter/FontAwesomeSolid","fonts":[{"weight":900,"asset":"packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf"}]}]

File diff suppressed because it is too large Load Diff

@ -0,0 +1,3 @@
# 时间管理
一个基于Flutter框架的APP

@ -0,0 +1 @@
<?xml version="1.0" ?><svg id="OBJECT" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:#bddbff;}.cls-2{fill:#3d9ae2;}.cls-3{fill:#fff;}</style></defs><title/><path class="cls-1" d="M484.5,206H423.74A173.54,173.54,0,0,0,410,172.75l43-43a20,20,0,0,0,0-28.28L410.5,59.07a20,20,0,0,0-28.28,0l-43,43A173.54,173.54,0,0,0,306,88.26V27.5a20,20,0,0,0-20-20H226a20,20,0,0,0-20,20V88.26A173.54,173.54,0,0,0,172.75,102l-43-43a20,20,0,0,0-28.28,0L59.07,101.5a20,20,0,0,0,0,28.28l43,43A173.54,173.54,0,0,0,88.26,206H27.5a20,20,0,0,0-20,20v60a20,20,0,0,0,20,20H88.26A173.54,173.54,0,0,0,102,339.25l-43,43a20,20,0,0,0,0,28.28l42.43,42.43a20,20,0,0,0,28.28,0l43-43A173.54,173.54,0,0,0,206,423.74V484.5a20,20,0,0,0,20,20h60a20,20,0,0,0,20-20V423.74A173.54,173.54,0,0,0,339.25,410l43,43a20,20,0,0,0,28.28,0l42.43-42.43a20,20,0,0,0,0-28.28l-43-43A173.54,173.54,0,0,0,423.74,306H484.5a20,20,0,0,0,20-20V226A20,20,0,0,0,484.5,206Z"/><path class="cls-2" d="M286,512H226a27.54,27.54,0,0,1-27.5-27.5V429.24a181.53,181.53,0,0,1-24.34-10.08l-39.08,39.07a27.53,27.53,0,0,1-38.89,0L53.77,415.81a27.53,27.53,0,0,1,0-38.89l39.07-39.08A181.53,181.53,0,0,1,82.76,313.5H27.5A27.54,27.54,0,0,1,0,286V226a27.54,27.54,0,0,1,27.5-27.5H82.76a181.53,181.53,0,0,1,10.08-24.34L53.77,135.08a27.53,27.53,0,0,1,0-38.89L96.19,53.77a27.53,27.53,0,0,1,38.89,0l39.08,39.07A181.53,181.53,0,0,1,198.5,82.76V27.5A27.54,27.54,0,0,1,226,0h60a27.54,27.54,0,0,1,27.5,27.5V82.76a181.53,181.53,0,0,1,24.34,10.08l39.08-39.07a27.53,27.53,0,0,1,38.89,0l42.42,42.42a27.53,27.53,0,0,1,0,38.89l-39.07,39.08a181.53,181.53,0,0,1,10.08,24.34H484.5A27.54,27.54,0,0,1,512,226v60a27.54,27.54,0,0,1-27.5,27.5H429.24a181.53,181.53,0,0,1-10.08,24.34l39.07,39.08a27.53,27.53,0,0,1,0,38.89l-42.42,42.42a27.53,27.53,0,0,1-38.89,0l-39.08-39.07a181.53,181.53,0,0,1-24.34,10.08V484.5A27.54,27.54,0,0,1,286,512ZM172.75,402.46a7.49,7.49,0,0,1,3.57.91,166.75,166.75,0,0,0,31.82,13.18,7.5,7.5,0,0,1,5.36,7.19V484.5A12.52,12.52,0,0,0,226,497h60a12.52,12.52,0,0,0,12.5-12.5V423.74a7.5,7.5,0,0,1,5.36-7.19,166.75,166.75,0,0,0,31.82-13.18,7.5,7.5,0,0,1,8.88,1.29l43,43a12.52,12.52,0,0,0,17.68,0l42.43-42.43a12.52,12.52,0,0,0,0-17.68l-43-43a7.5,7.5,0,0,1-1.29-8.88,166.75,166.75,0,0,0,13.18-31.82,7.5,7.5,0,0,1,7.19-5.36H484.5A12.52,12.52,0,0,0,497,286V226a12.52,12.52,0,0,0-12.5-12.5H423.74a7.5,7.5,0,0,1-7.19-5.36,166.75,166.75,0,0,0-13.18-31.82,7.5,7.5,0,0,1,1.29-8.88l43-43a12.52,12.52,0,0,0,0-17.68L405.2,64.37a12.52,12.52,0,0,0-17.68,0l-43,43a7.5,7.5,0,0,1-8.88,1.29,166.75,166.75,0,0,0-31.82-13.18,7.5,7.5,0,0,1-5.36-7.19V27.5A12.52,12.52,0,0,0,286,15H226a12.52,12.52,0,0,0-12.5,12.5V88.26a7.5,7.5,0,0,1-5.36,7.19,166.75,166.75,0,0,0-31.82,13.18,7.5,7.5,0,0,1-8.88-1.29l-43-43a12.52,12.52,0,0,0-17.68,0L64.37,106.8a12.52,12.52,0,0,0,0,17.68l43,43a7.5,7.5,0,0,1,1.29,8.88,166.75,166.75,0,0,0-13.18,31.82,7.5,7.5,0,0,1-7.19,5.36H27.5A12.52,12.52,0,0,0,15,226v60a12.52,12.52,0,0,0,12.5,12.5H88.26a7.5,7.5,0,0,1,7.19,5.36,166.75,166.75,0,0,0,13.18,31.82,7.5,7.5,0,0,1-1.29,8.88l-43,43a12.52,12.52,0,0,0,0,17.68l42.43,42.43a12.52,12.52,0,0,0,17.68,0l43-43A7.54,7.54,0,0,1,172.75,402.46Z"/><circle class="cls-3" cx="256" cy="256" r="140"/><path class="cls-2" d="M256,403.5c-81.33,0-147.5-66.17-147.5-147.5S174.67,108.5,256,108.5,403.5,174.67,403.5,256,337.33,403.5,256,403.5Zm0-280c-73.06,0-132.5,59.44-132.5,132.5S182.94,388.5,256,388.5,388.5,329.06,388.5,256,329.06,123.5,256,123.5Z"/><path class="cls-2" d="M296,303.5a7.5,7.5,0,0,1-5.32-2.21l-40-40.23a7.49,7.49,0,0,1-2.18-5.29V176a7.5,7.5,0,0,1,15,0v76.68l37.82,38A7.5,7.5,0,0,1,296,303.5Z"/><path class="cls-2" d="M146,263.5H116a7.5,7.5,0,0,1,0-15h30a7.5,7.5,0,0,1,0,15Z"/><path class="cls-2" d="M396,263.5H366a7.5,7.5,0,0,1,0-15h30a7.5,7.5,0,0,1,0,15Z"/><path class="cls-2" d="M171.15,178.65a7.48,7.48,0,0,1-5.31-2.2L151.7,162.31a7.5,7.5,0,0,1,10.61-10.61l14.14,14.14a7.51,7.51,0,0,1-5.3,12.81Z"/><path class="cls-2" d="M355,362.5a7.52,7.52,0,0,1-5.31-2.2l-14.14-14.14a7.5,7.5,0,0,1,10.61-10.61l14.14,14.14A7.51,7.51,0,0,1,355,362.5Z"/><path class="cls-2" d="M340.85,178.65a7.51,7.51,0,0,1-5.3-12.81l14.14-14.14a7.5,7.5,0,0,1,10.61,10.61l-14.14,14.14A7.48,7.48,0,0,1,340.85,178.65Z"/><path class="cls-2" d="M157,362.5a7.51,7.51,0,0,1-5.3-12.81l14.14-14.14a7.5,7.5,0,0,1,10.61,10.61L162.31,360.3A7.52,7.52,0,0,1,157,362.5Z"/><path class="cls-2" d="M256,153.5a7.5,7.5,0,0,1-7.5-7.5V116a7.5,7.5,0,0,1,15,0v30A7.5,7.5,0,0,1,256,153.5Z"/><path class="cls-2" d="M256,403.5a7.5,7.5,0,0,1-7.5-7.5V366a7.5,7.5,0,0,1,15,0v30A7.5,7.5,0,0,1,256,403.5Z"/></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

File diff suppressed because one or more lines are too long

@ -0,0 +1,14 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=F:\study\school\ruanjian\flutter\flutter
FLUTTER_APPLICATION_PATH=F:\study\school\ruanjian\timecop\timemanager
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=lib\main.dart
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.dart_tool/package_config.json

@ -0,0 +1,13 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=F:\study\school\ruanjian\flutter\flutter"
export "FLUTTER_APPLICATION_PATH=F:\study\school\ruanjian\timecop\timemanager"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib\main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"

@ -0,0 +1,19 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GeneratedPluginRegistrant_h
#define GeneratedPluginRegistrant_h
#import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface GeneratedPluginRegistrant : NSObject
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
@end
NS_ASSUME_NONNULL_END
#endif /* GeneratedPluginRegistrant_h */

@ -0,0 +1,49 @@
//
// Generated file. Do not edit.
//
// clang-format off
#import "GeneratedPluginRegistrant.h"
#if __has_include(<package_info_plus/FLTPackageInfoPlusPlugin.h>)
#import <package_info_plus/FLTPackageInfoPlusPlugin.h>
#else
@import package_info_plus;
#endif
#if __has_include(<path_provider_foundation/PathProviderPlugin.h>)
#import <path_provider_foundation/PathProviderPlugin.h>
#else
@import path_provider_foundation;
#endif
#if __has_include(<shared_preferences_foundation/SharedPreferencesPlugin.h>)
#import <shared_preferences_foundation/SharedPreferencesPlugin.h>
#else
@import shared_preferences_foundation;
#endif
#if __has_include(<sqflite/SqflitePlugin.h>)
#import <sqflite/SqflitePlugin.h>
#else
@import sqflite;
#endif
#if __has_include(<url_launcher_ios/FLTURLLauncherPlugin.h>)
#import <url_launcher_ios/FLTURLLauncherPlugin.h>
#else
@import url_launcher_ios;
#endif
@implementation GeneratedPluginRegistrant
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
[FLTPackageInfoPlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTPackageInfoPlusPlugin"]];
[PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]];
[SharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"SharedPreferencesPlugin"]];
[SqflitePlugin registerWithRegistrar:[registry registrarForPlugin:@"SqflitePlugin"]];
[FLTURLLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTURLLauncherPlugin"]];
}
@end

@ -0,0 +1,115 @@
import 'package:sqflite/sqflite.dart';
import 'package:timemanage/model/timer_entry.dart';
class TimerEntryDatabase {
static final TimerEntryDatabase instance = TimerEntryDatabase._init();
static Database? _database;
TimerEntryDatabase._init();
///
//
Future<Database> get database async {
if (_database != null) {
return _database!;
}
_database = await _initDB('timer_entry.db');
return _database!;
}
//
Future<Database> _initDB(String filePath) async {
final dbPath = await getDatabasesPath();
final path = dbPath + filePath;
//
return await openDatabase(path, version: 1, onCreate: _createDB);
}
//
Future _createDB(Database db, int version) async {
//
const idType = 'INTEGER PRIMARY KEY AUTOINCREMENT';
const textType = 'TEXT NOT NULL';
const nullTextType = 'TEXT';
//
await db.execute('''
CREATE TABLE $tableTimerEntry (
${TimerEntryFields.id} $idType,
${TimerEntryFields.name} $textType,
${TimerEntryFields.createdAt} $textType,
${TimerEntryFields.endAt} $nullTextType,
${TimerEntryFields.isActive} $textType,
${TimerEntryFields.stopWatch} $textType
)
''');
}
/// CRUD
//
Future<TimerEntry> create(TimerEntry timerEntry) async {
final db = await instance.database;
// ID
final id = await db.insert(tableTimerEntry, timerEntry.toJson());
return timerEntry.copy(id: id);
}
//
Future<TimerEntry> read(int id) async {
final db = await instance.database;
final maps = await db.query(tableTimerEntry,
columns: TimerEntryFields.values,
where: '${TimerEntryFields.id} = ?',
whereArgs: [id]);
if (maps.isNotEmpty) {
return TimerEntry.fromJson(maps.first);
} else {
throw Exception('ID $id not found');
}
}
//
Future<List<TimerEntry>> readAll() async {
final db = await instance.database;
//
// await db.insert(
// tableTimerEntry,
// TimerEntry(
// name: '测试计时器',
// ).toJson());
final result = await db.query(tableTimerEntry);
return result.map((json) => TimerEntry.fromJson(json)).toList();
}
//
Future<int> update(TimerEntry timerEntry) async {
final db = await instance.database;
return db.update(tableTimerEntry, timerEntry.toJson(),
where: '${TimerEntryFields.id} = ?', whereArgs: [timerEntry.id]);
}
//
Future<int> delete(int id) async {
final db = await instance.database;
return await db.delete(tableTimerEntry,
where: '${TimerEntryFields.id} = ?', whereArgs: [id]);
}
//
Future close() async {
final db = await instance.database;
db.close();
}
}

@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:timemanage/screens/about_screen.dart';
import 'package:timemanage/screen/dashboard/dashboard_screen.dart';
///
/// dartdoc/** */
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
@ -11,193 +13,21 @@ class MyApp extends StatelessWidget {
return MaterialApp(
//
theme: ThemeData(
//
menuBarTheme: MenuBarThemeData(
style: MenuStyle(
backgroundColor: MaterialStatePropertyAll<Color>(Colors.blueAccent),
),
),
menuTheme: MenuThemeData(
style: MenuStyle(
backgroundColor: MaterialStatePropertyAll<Color>(Colors.white)),
),
// //
// menuTheme: MenuThemeData(
// style: MenuStyle(
// backgroundColor:
// MaterialStatePropertyAll<Color>(Colors.lightBlueAccent)),
// ),
),
//
home: DashBoardScreen(),
);
}
}
class DashBoardScreen extends StatelessWidget {
const DashBoardScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueAccent, //
//
leading: MenuBar(
children: <Widget>[
SubmenuButton(
menuChildren: <Widget>[
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CourseScreen()),
);
},
child: const Text('课程表'),
),
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ProjectsScreen()),
);
},
child: const Text('项目'),
),
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ReportsScreen()),
);
},
child: const Text('统计报告'),
),
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ExportScreen()),
);
},
child: const Text('导入和导出'),
),
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SettingsScreen()),
);
},
child: const Text('设置'),
),
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const AboutScreen()),
);
},
child: const Text('关于'),
),
],
child: const Icon(Icons.menu),
),
],
),
//
title: const Text('时间管理'),
actions: [
//
IconButton(
icon: const Icon(Icons.search),
onPressed: () {},
),
//
IconButton(
icon: const Icon(Icons.filter_alt),
onPressed: () {},
)
],
),
body: const Center(
child: Text('主界面'),
),
);
}
}
class CourseScreen extends StatelessWidget {
const CourseScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('课程表'),
),
body: const Center(
child: Text('课程表界面'),
),
);
}
}
class ProjectsScreen extends StatelessWidget {
const ProjectsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('项目'),
),
body: const Center(
child: Text('项目界面'),
),
);
}
}
class ReportsScreen extends StatelessWidget {
const ReportsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('统计报告'),
),
body: const Center(
child: Text('统计报告界面'),
),
);
}
}
class ExportScreen extends StatelessWidget {
const ExportScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('导入与导出'),
),
body: const Center(
child: Text('导入与导出界面'),
),
);
}
}
class SettingsScreen extends StatelessWidget {
const SettingsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('设置'),
),
body: const Center(
child: Text('设置界面'),
),
);
}
}

@ -0,0 +1,7 @@
// DateTime
extension CloneTime on DateTime {
DateTime clone() {
return DateTime(
year, month, day, hour, minute, second, millisecond, microsecond);
}
}

@ -0,0 +1,32 @@
import 'package:flutter/material.dart'; // Color使
import 'package:equatable/equatable.dart'; //
class Project extends Equatable {
final int id;
final String name;
final Color? colour; //
final bool archived; //
//
const Project({
required this.id,
required this.name,
required this.colour,
required this.archived,
});
@override
List<Object> get props => [id, name, archived]; //
Project.clone(
Project project, {
String? name,
Color? color,
bool? archived,
}) : this(
id: project.id,
name: name ?? project.name,
colour: color ?? project.colour,
archived: archived ?? project.archived,
);
}

@ -0,0 +1,12 @@
import 'package:equatable/equatable.dart';
//
class ProjectDescriptionPair extends Equatable {
final int? project;
final String? description;
const ProjectDescriptionPair(this.project, this.description);
@override
List<Object?> get props => [project, description];
}

@ -0,0 +1,8 @@
//
extension StartOfWeek on DateTime {
DateTime startOfWeek({int startOfWeekDay = DateTime.sunday}) {
int diff = (7 + (weekday - startOfWeekDay)) % 7;
DateTime dt = add(Duration(days: -diff));
return DateTime(dt.year, dt.month, dt.day);
}
}

@ -0,0 +1 @@
// TODO:

@ -0,0 +1,106 @@
const String tableTimerEntry = 'timer_entry'; //
//
class TimerEntryFields {
static const String id = '_id';
static const String name = 'name';
static const String createdAt = 'createdAt';
static const String endAt = 'endAt';
static const String isActive = 'isActive';
static const String stopWatch = 'stopWatch';
static final List<String> values = [
/// Add all fields
id, name, createdAt, endAt, isActive, stopWatch
];
}
class TimerEntry {
int? id; // ID
String name; //
Stopwatch? stopwatch; //
bool isActice; //
DateTime createdAt; //
DateTime? endAt; //
//
TimerEntry({required this.name})
: stopwatch = Stopwatch(),
isActice = false,
createdAt = DateTime.now(),
endAt = DateTime.now();
bool get isActive => isActice;
num get stopWatch => stopWatch;
//
void start() {
stopwatch!.start();
isActice = true;
}
//
void pause() {
stopwatch!.stop();
isActice = false;
}
//
void stop() {
stopwatch!.stop();
isActice = false;
endAt = DateTime.now();
}
//
void reset() {
stopwatch!.reset();
isActice = false;
endAt = null;
}
//
TimerEntry copy({
int? id,
String? name,
DateTime? createdAt,
DateTime? endAt,
bool? isActive,
Stopwatch? stopwatch,
}) =>
TimerEntry(
name: name ?? this.name,
)
..id = id ?? this.id
..createdAt = createdAt ?? this.createdAt
..endAt = endAt ?? this.endAt
..isActice = isActive ?? this.isActice
..stopwatch = stopwatch ?? this.stopwatch;
// fromJson
static TimerEntry fromJson(Map<String, Object?> json) {
return TimerEntry(
name: json[TimerEntryFields.name] as String,
)
..id = json[TimerEntryFields.id] as int?
..createdAt = DateTime.parse(json[TimerEntryFields.createdAt] as String)
..endAt = json[TimerEntryFields.endAt] == null
? null
: DateTime.parse(json[TimerEntryFields.endAt] as String)
..isActice = json[TimerEntryFields.isActive] == 1 ? true : false
..stopwatch = Stopwatch();
}
// toJson
Map<String, Object?> toJson() {
return {
TimerEntryFields.id: id,
TimerEntryFields.name: name,
TimerEntryFields.createdAt: createdAt.toIso8601String(),
TimerEntryFields.endAt: endAt?.toIso8601String(),
TimerEntryFields.isActive: isActice ? 1 : 0,
TimerEntryFields.stopWatch: stopwatch!.elapsed.inMilliseconds,
};
}
}

@ -1,3 +1,5 @@
// 使pubspec.yamldependenciesflutter pub get
// Javaimportpythonimportpip install package_name
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
@ -5,8 +7,10 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:about/about.dart';
//
class AboutScreen extends StatelessWidget {
const AboutScreen({Key? key}) : super(key: key);
// buildWidget
@override
Widget build(BuildContext context) {
return FutureBuilder(
@ -18,32 +22,48 @@ class AboutScreen extends StatelessWidget {
String buildNumber = packageInfo.buildNumber;
return AboutPage(
key: const Key("aboutPage"),
//
title: Text("关于"),
//
/* 所有要使用的资源需要在pubspec.yaml文件中的flutter节点下的assets节点声明否则无法访问资源 */
// FIXME: APP
applicationIcon: SvgPicture.asset(
"icon.svg",
semanticsLabel: "Time Manager",
height: 100,
),
// app
applicationVersion: "v$version+$buildNumber",
// app
applicationDescription: Text(
"一个也许能够管理你的时间的APP。",
textAlign: TextAlign.justify,
),
applicationLegalese:
"Copyright © 2023 中国民航大学 计算机科学与技术学院 \n 计算机科学与技术专业 21034102班 \n 庞浩,葛兴海,蔡玉祥,邹兴云,卫俊钢 小组",
//
applicationLegalese: '''
Copyright © 2023
21034102
''',
/**
* ListTile
*/
children: <Widget>[
//
MarkdownPageListTile(
// TODO: markdown
// TODO: README
filename: 'README.md',
title: Text("帮助文档"),
icon: const Icon(FontAwesomeIcons.readme),
),
//
// FIXME: md
MarkdownPageListTile(
filename: 'CONTRIBUTORS.md',
title: Text("开发者"),
icon: const Icon(FontAwesomeIcons.userAstronaut),
),
//
ListTile(
leading: const Icon(FontAwesomeIcons.blog),
title: Text("知士荟博客"),
@ -51,12 +71,12 @@ class AboutScreen extends StatelessWidget {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("请横屏查看"),
// FIXME: 3
duration: Duration(seconds: 3)),
);
launchUrl(Uri.parse(
"https://www.learnerhub.net/#/users/12147/docs"));
}),
//
ListTile(
leading: const Icon(FontAwesomeIcons.code),
title: Text("头歌源代码"),

@ -0,0 +1,305 @@
import 'package:flutter/material.dart';
class CourseScreen extends StatefulWidget {
const CourseScreen({super.key});
@override
State<StatefulWidget> createState() => CourseScreenState();
}
class CourseScreenState extends State<CourseScreen> {
var colorList = [
Colors.red,
Colors.lightBlueAccent,
Colors.grey,
Colors.cyan,
Colors.amber,
Colors.deepPurpleAccent,
Colors.purpleAccent
];
var infoList = ["高等数学-周某某教授@综合楼201", "大学英语-王某某讲师@行政楼501"];
var weekList = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
var dateList = [];
var currentWeekIndex = 0;
@override
void initState() {
super.initState();
var monday = 1;
var mondayTime = DateTime.now();
//
while (mondayTime.weekday != monday) {
mondayTime = mondayTime.subtract(Duration(days: 1));
}
for (int i = 0; i < 7; i++) {
dateList.add("${mondayTime.month}-${mondayTime.day}");
mondayTime = mondayTime.add(Duration(days: 1));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
child: GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 8,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 8, childAspectRatio: 1 / 1),
itemBuilder: (BuildContext context, int index) {
return Container(
color: index == currentWeekIndex
? Color(0x00f7f7f7)
: Colors.white,
child: Center(
child: index == 0
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text("星期",
style: TextStyle(
fontSize: 14, color: Colors.black87)),
SizedBox(height: 5),
Text("日期", style: TextStyle(fontSize: 12)),
],
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(weekList[index - 1],
style: TextStyle(
fontSize: 14,
color: index == currentWeekIndex
? Colors.lightBlue
: Colors.black87)),
SizedBox(height: 5),
Text(dateList[index - 1],
style: TextStyle(
fontSize: 12,
color: index == currentWeekIndex
? Colors.lightBlue
: Colors.black87)),
],
),
),
);
}),
),
Expanded(
child: SingleChildScrollView(
child: Row(
children: [
Expanded(
flex: 1,
child: GridView.builder(
shrinkWrap: true,
// physics:ClampingScrollPhysics(),
itemCount: 10,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1, childAspectRatio: 1 / 2),
itemBuilder: (BuildContext context, int index) {
return Container(
decoration: BoxDecoration(
color: Color(0x00ff5ff5),
// border: Border.all(color: Colors.black12, width: 0.5),
border: Border(
bottom: BorderSide(
color: Colors.black12, width: 0.5),
right: BorderSide(
color: Colors.black12, width: 0.5),
),
),
// width: 25,
// height:s 80,
child: Center(
child: Text(
(index + 1).toInt().toString(),
style: TextStyle(fontSize: 15),
),
));
}),
),
Expanded(
flex: 7,
child: GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 35,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 7, childAspectRatio: 1 / 4),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
// onTap: () {
// //
// print('点击了课程');
// },
// onTap: () {
// // EditCoursePage
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => EditCoursePage(
// onSave: (String) {},
// )),
// );
// },
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditCoursePage(
onSave: (courseInfo) {
//
setState(() {
//
infoList[index % 2] = courseInfo;
});
},
),
),
);
},
child: Stack(
children: [
Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Flexible(
flex: 1,
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(
color: Colors.black12,
width: 0.5),
right: BorderSide(
color: Colors.black12,
width: 0.5),
),
)),
),
Flexible(
flex: 1,
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(
color: Colors.black12,
width: 0.5),
right: BorderSide(
color: Colors.black12,
width: 0.5),
),
)),
),
],
),
if (index % 5 == 0 || index % 5 == 1)
Container(
margin: EdgeInsets.all(0.5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
color: colorList[index % 7],
),
child: Center(
child: Text(
infoList[index % 2],
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 11,
letterSpacing: 1),
),
),
)
],
),
);
}),
)
],
),
),
),
_bottomView
],
),
);
}
String pageTitle() => "我的课表";
final Widget _bottomView = SizedBox(
height: 30,
child: Row(
children: const [
//view
],
),
);
}
class EditCoursePage extends StatefulWidget {
final Function(String) onSave;
const EditCoursePage({super.key, required this.onSave});
@override
EditCoursePageState createState() => EditCoursePageState();
}
class EditCoursePageState extends State<EditCoursePage> {
final _formKey = GlobalKey<FormState>();
final _courseController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('编辑课程'),
),
body: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _courseController,
decoration: InputDecoration(labelText: '课程信息'),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入课程信息';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
widget.onSave(_courseController.text);
Navigator.pop(context);
}
},
child: Text('保存'),
),
],
),
),
);
}
}

@ -0,0 +1,75 @@
import 'package:flutter/material.dart';
import 'package:timemanage/screen/reports_screen.dart';
import 'package:timemanage/screen/export_screen.dart';
import 'package:timemanage/screen/settings_screen.dart';
import 'package:timemanage/screen/about_screen.dart';
import 'package:timemanage/screen/course_screen.dart';
class HomeMenuBar extends StatefulWidget {
const HomeMenuBar({Key? key}) : super(key: key);
@override
HomeMenuBarState createState() => HomeMenuBarState();
}
class HomeMenuBarState extends State<HomeMenuBar> {
@override
Widget build(BuildContext context) {
return MenuBar(
children: <Widget>[
SubmenuButton(
menuChildren: <Widget>[
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CourseScreen()),
);
},
child: const Text('课程表'),
),
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ReportsScreen()),
);
},
child: const Text('统计报告'),
),
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const ExportScreen()),
);
},
child: const Text('导入和导出'),
),
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SettingsScreen()),
);
},
child: const Text('设置'),
),
MenuItemButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AboutScreen()),
);
},
child: const Text('关于'),
),
],
child: const Icon(Icons.menu),
),
],
);
}
}

@ -0,0 +1,214 @@
import 'package:flutter/material.dart';
import 'package:timemanage/db/timer_entry_database.dart';
import 'package:timemanage/model/timer_entry.dart';
import 'package:timemanage/screen/dashboard/components/home_menu_bar.dart';
//
class DashBoardScreen extends StatefulWidget {
const DashBoardScreen({Key? key}) : super(key: key);
@override
DashBoardScreenState createState() => DashBoardScreenState();
}
class DashBoardScreenState extends State<DashBoardScreen> {
late List<TimerEntry> timers; //
bool isLoading = false; //
//
@override
void initState() {
super.initState();
refreshTimers();
}
//
@override
void dispose() {
TimerEntryDatabase.instance.close();
super.dispose();
}
//
Future refreshTimers() async {
setState(() {
isLoading = true;
});
timers = await TimerEntryDatabase.instance.readAll();
setState(() {
timers = timers;
isLoading = false;
});
}
//
void _addTimer() {
final controller = TextEditingController();
showDialog<String>(
context: context,
builder: (context) => AlertDialog(
title: const Text('新建计时器'),
//
content: SizedBox(
height: 100,
child: Column(
children: [
TextField(
decoration: InputDecoration(hintText: '计时器名称'),
controller: controller,
),
],
),
),
// or
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('取消'),
),
TextButton(
onPressed: () {
final name = controller.text;
// TODO:
if (name.isNotEmpty) {
TimerEntry timerEntry = TimerEntry(
name: name,
);
setState(() {
timers.add(timerEntry);
});
//
TimerEntryDatabase.instance.create(timerEntry);
}
Navigator.pop(context, 'OK');
},
child: const Text('确定'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
//
appBar: AppBar(
backgroundColor: Colors.blueAccent, //
//
leading: HomeMenuBar(),
//
title: const Text('时间管理'),
actions: [
//
// TODO:
IconButton(
icon: const Icon(Icons.search),
onPressed: () {},
),
// //
// IconButton(
// icon: const Icon(Icons.filter_alt),
// onPressed: () {},
// )
],
),
//
body: isLoading
? const Center(child: CircularProgressIndicator())
: timers.isEmpty
? const Center(child: Text('还没有计时器,先添加一个吧!'))
: buildTimers(),
//
floatingActionButton: FloatingActionButton(
onPressed: _addTimer,
child: const Icon(Icons.add),
),
);
}
//
Widget buildTimers() {
return ListView.builder(
itemCount: timers.length,
itemBuilder: (context, index) {
return Column(
children: [
ListTile(
leading: CircleAvatar(
child: Text((index + 1).toString()),
),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
timers[index].createdAt.toString().substring(0, 16),
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
Text(
timers[index].name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
StreamBuilder<int>(
stream: Stream.periodic(const Duration(milliseconds: 100),
(_) => timers[index].stopwatch!.elapsed.inSeconds),
builder: (context, snapshot) {
final seconds = snapshot.data ?? 0;
final hours = seconds ~/ 3600;
final minutes = (seconds % 3600) ~/ 60;
final remainingSeconds = seconds % 60;
return Text(
'${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}',
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
);
},
),
],
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: timers[index].isActive
? const Icon(Icons.pause)
: const Icon(Icons.play_arrow),
onPressed: () {
setState(() {
if (timers[index].isActive) {
timers[index].stop();
} else {
timers[index].start();
}
});
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
setState(() {
timers[index].stopwatch!.stop(); //
timers.removeAt(index);
});
},
),
],
),
),
const SizedBox(height: 10), //
],
);
},
);
}
}

@ -0,0 +1,16 @@
import 'package:flutter/material.dart';
class ExportScreen extends StatelessWidget {
const ExportScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('导入与导出'),
),
body: const Center(
child: Text('导入与导出界面'),
),
);
}
}

@ -0,0 +1,110 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:timemanage/db/timer_entry_database.dart';
class ReportsScreen extends StatefulWidget {
const ReportsScreen({super.key});
@override
State<ReportsScreen> createState() => _ReportsScreenState();
}
//
class _ReportsScreenState extends State<ReportsScreen> {
//
var timers = TimerEntryDatabase.instance.readAll();
Map<String, num> persentMap = {};
@override
void initState() {
super.initState();
classifyTimers().then((value) {
setState(() {
persentMap = value;
});
});
for (var key in persentMap.keys) {
log(key);
}
}
Future<Map<String, num>> classifyTimers() async {
var timers = await TimerEntryDatabase.instance.readAll();
Map<String, num> persentMap = {};
for (var timer in timers) {
var response = await postData(timer.name);
var classification =
jsonDecode(response.body)['item']['lv1_tag_list'][0]['tag'];
// APIISO-8859-1
classification = utf8.decode(classification.runes.toList());
persentMap[classification] = timer.stopWatch;
log('classification: $classification');
}
return persentMap;
}
// API
Future<http.Response> postData(String name) async {
// ignore: non_constant_identifier_names
var API_KEY = "YGxSMNdWKO5Gpt12dNVY2nGq";
// ignore: non_constant_identifier_names
var SECRET_KEY = "G5NBDTiRPhsBqMi1Od0XZw4RSMlFgeek";
var accessToken = await getAccessToken(API_KEY, SECRET_KEY);
var url = Uri.parse(
'https://aip.baidubce.com/rpc/2.0/nlp/v1/topic?charset=UTF-8&access_token=$accessToken');
var payload = jsonEncode({
"title": name,
"content": name,
});
var headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
};
var response = await http.post(
url,
headers: headers,
body: payload,
);
return response;
}
// ignore: non_constant_identifier_names
Future<String> getAccessToken(String API_KEY, String SECRET_KEY) async {
var url = 'https://aip.baidubce.com/oauth/2.0/token';
var params = {
'grant_type': 'client_credentials',
'client_id': API_KEY,
'client_secret': SECRET_KEY,
};
var response = await http.post(
Uri.parse(url),
body: params,
);
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
return data['access_token'];
} else {
throw Exception('Failed to get access token');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('统计报告'),
),
body: ListView.builder(
itemCount: persentMap.length,
itemBuilder: (context, index) => ListTile(
title: Text(persentMap.keys.toList()[index]),
subtitle: Text(persentMap.values.toList()[index].toString()),
),
),
);
}
}

@ -0,0 +1,15 @@
import 'package:flutter/material.dart';
class SettingsScreen extends StatelessWidget {
const SettingsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('设置'),
),
body: const Center(
child: Text('设置界面'),
));
}
}

@ -6,9 +6,15 @@ import FlutterMacOS
import Foundation
import package_info_plus
import path_provider_foundation
import shared_preferences_foundation
import sqflite
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}

@ -0,0 +1,11 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=F:\study\school\ruanjian\flutter\flutter
FLUTTER_APPLICATION_PATH=F:\study\school\ruanjian\timecop\timemanager
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.dart_tool/package_config.json

@ -0,0 +1,12 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=F:\study\school\ruanjian\flutter\flutter"
export "FLUTTER_APPLICATION_PATH=F:\study\school\ruanjian\timecop\timemanager"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"

@ -33,6 +33,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.11.0"
bloc:
dependency: "direct main"
description:
name: bloc
sha256: "6f1b87b6eca9041d5672b6e29273cd1594db48ebb66fd2471066e9f3c3a516bd"
url: "https://pub.dev"
source: hosted
version: "7.2.1"
boolean_selector:
dependency: transitive
description:
@ -89,6 +97,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.6"
equatable:
dependency: "direct main"
description:
name: equatable
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
url: "https://pub.dev"
source: hosted
version: "2.0.5"
fake_async:
dependency: transitive
description:
@ -105,6 +121,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.0"
file:
dependency: transitive
description:
name: file
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
flutter:
dependency: "direct main"
description: flutter
@ -118,6 +142,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.0.1"
flutter_bloc:
dependency: "direct main"
description:
name: flutter_bloc
sha256: cdd1351ced09eeb46cfa7946e095b7679344af927415ca9cd972928fa6d5b23f
url: "https://pub.dev"
source: hosted
version: "7.3.3"
flutter_launcher_icons:
dependency: "direct dev"
description:
@ -169,13 +201,13 @@ packages:
source: hosted
version: "9.2.0"
http:
dependency: transitive
dependency: "direct main"
description:
name: http
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
version: "0.13.6"
http_parser:
dependency: transitive
description:
@ -192,6 +224,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.0"
intl:
dependency: "direct main"
description:
name: intl
sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
url: "https://pub.dev"
source: hosted
version: "0.17.0"
js:
dependency: transitive
description:
@ -248,6 +288,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
package_info_plus:
dependency: "direct main"
description:
@ -265,7 +313,7 @@ packages:
source: hosted
version: "2.0.1"
path:
dependency: transitive
dependency: "direct main"
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
@ -280,6 +328,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
path_provider:
dependency: "direct main"
description:
name: path_provider
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
petitparser:
dependency: transitive
description:
@ -288,6 +384,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.4.0"
platform:
dependency: transitive
description:
name: platform
sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
url: "https://pub.dev"
source: hosted
version: "3.1.3"
plugin_platform_interface:
dependency: transitive
description:
@ -304,6 +408,70 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.7.3"
provider:
dependency: transitive
description:
name: provider
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
url: "https://pub.dev"
source: hosted
version: "6.0.5"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
url: "https://pub.dev"
source: hosted
version: "2.2.2"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7"
url: "https://pub.dev"
source: hosted
version: "2.3.4"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a
url: "https://pub.dev"
source: hosted
version: "2.3.1"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
url: "https://pub.dev"
source: hosted
version: "2.2.1"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
simple_mustache:
dependency: transitive
description:
@ -325,6 +493,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.0"
sqflite:
dependency: "direct main"
description:
name: sqflite
sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a"
url: "https://pub.dev"
source: hosted
version: "2.5.0"
stack_trace:
dependency: transitive
description:
@ -349,6 +533,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
synchronized:
dependency: transitive
description:
name: synchronized
sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
term_glyph:
dependency: transitive
description:
@ -485,6 +677,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.0.8"
xdg_directories:
dependency: "direct main"
description:
name: xdg_directories
sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
xml:
dependency: transitive
description:

@ -36,11 +36,20 @@ dependencies:
about: ^2.1.3
font_awesome_flutter: ^9.2.0
url_launcher: ^6.1.14
equatable: ^2.0.3 # 用于对象比较
xdg_directories: ^1.0.0
flutter_bloc: ^7.0.0
bloc: ^7.0.0
path: ^1.8.0
shared_preferences: ^2.0.8
sqflite: ^2.0.0+3 # 用于数据库
intl: ^0.17.0 # 用于时间格式化
http: ^0.13.3 # 用于网络请求
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
path_provider: ^2.1.1
dev_dependencies:
flutter_test:
@ -105,3 +114,5 @@ flutter:
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages

@ -5,26 +5,6 @@
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:timemanage/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
print('Hello World!');
}

Loading…
Cancel
Save