commit f41919ba5a0a3ea0d797bda54c8dd88b63b06eaf Author: 18631081161 <2088094923@qq.com> Date: Mon Jun 3 15:30:15 2024 +0800 首次提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..489faea --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release +/pubspec.lock diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..1b95e72 --- /dev/null +++ b/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c + base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c + - platform: android + create_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c + base_revision: 4f9d92fbbdf072a70a70d2179a9f87392b94104c + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/README.md b/README.md new file mode 100644 index 0000000..ed55099 --- /dev/null +++ b/README.md @@ -0,0 +1,92 @@ +# Ai_drawing + +AI绘图包 + +## Getting started + +To make it easy for you to get started with GitLab, here's a list of recommended next steps. + +Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! + +## Add your files + +- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files +- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: + +``` +cd existing_repo +git remote add origin http://192.168.1.33/mogu_flutter/ai_drawing.git +git branch -M main +git push -uf origin main +``` + +## Integrate with your tools + +- [ ] [Set up project integrations](http://192.168.1.33/mogu_flutter/ai_drawing/-/settings/integrations) + +## Collaborate with your team + +- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) +- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) +- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) +- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) +- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) + +## Test and Deploy + +Use the built-in continuous integration in GitLab. + +- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) +- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) +- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) +- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) +- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) + +*** + +# Editing this README + +When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. + +## Suggestions for a good README +Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. + +## Name +Choose a self-explaining name for your project. + +## Description +Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. + +## Badges +On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. + +## Visuals +Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. + +## Installation +Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. + +## Usage +Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. + +## Support +Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. + +## Roadmap +If you have ideas for releases in the future, it is a good idea to list them in the README. + +## Contributing +State if you are open to contributions and what your requirements are for accepting them. + +For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. + +You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. + +## Authors and acknowledgment +Show your appreciation to those who have contributed to the project. + +## License +For open source projects, say how it is licensed. + +## Project status +If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..41e1d54 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,85 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 33 + ndkVersion flutter.ndkVersion + + + signingConfigs { + //签名的配置 + signConfig { + storeFile file("aiDraw.jks") + storePassword '123456' + keyAlias 'aiDraw' + keyPassword '123456' + } + } + + lintOptions { + //如打包出现Failed to transform libs.jar to match attributes + checkReleaseBuilds false + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.hissai.draw" + minSdkVersion 19 + targetSdkVersion 33 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + + multiDexEnabled true + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + signingConfig signingConfigs.signConfig //打包命令行:gradlew assembleRelease + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + //关闭混淆 + minifyEnabled false //删除无用代码 + shrinkResources false //删除无用资源 + } + debug { + signingConfig signingConfigs.signConfig + } + } + + dependencies { + implementation 'androidx.appcompat:appcompat:1.6.1' + } +} + +flutter { + source '../..' +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..04f4627 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/assets/holybladeCloud.properties b/android/app/src/main/assets/holybladeCloud.properties new file mode 100644 index 0000000..9100c19 --- /dev/null +++ b/android/app/src/main/assets/holybladeCloud.properties @@ -0,0 +1,2 @@ +BossId=27014 +AppId=1001 \ No newline at end of file diff --git a/android/app/src/main/java/com/hissai/draw/App.java b/android/app/src/main/java/com/hissai/draw/App.java new file mode 100644 index 0000000..3ee8bea --- /dev/null +++ b/android/app/src/main/java/com/hissai/draw/App.java @@ -0,0 +1,30 @@ +package com.hissai.draw; + +import android.content.Context; + +import io.flutter.app.FlutterApplication; + +public class App extends FlutterApplication { + + + private static App instance; + + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + } + + @Override + public void onCreate() { + super.onCreate(); + instance = this; + + } + + + public static App getInstance() { + return instance; + } + + +} diff --git a/android/app/src/main/java/com/hissai/draw/MainActivity.java b/android/app/src/main/java/com/hissai/draw/MainActivity.java new file mode 100644 index 0000000..570774b --- /dev/null +++ b/android/app/src/main/java/com/hissai/draw/MainActivity.java @@ -0,0 +1,82 @@ +package com.hissai.draw; + +import android.os.Bundle; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.hissai.draw.utils.AppUtil; +import com.hissai.draw.utils.Configs; +import com.hissai.draw.utils.MacInfo; +import com.hissai.draw.utils.NetWork; +import com.hissai.draw.utils.ThreadUtil; + +import java.util.HashMap; +import java.util.Map; + +import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.StandardMethodCodec; + +public class MainActivity extends FlutterActivity { + private static final String CHANNEL = "samples.flutter.dev/battery"; + private MethodChannel nativeChannel; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ThreadUtil.INST.excute(() -> NetWork.getConfigs(MainActivity.this)); + + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + + //flutter 通道 + @Override + public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { + super.configureFlutterEngine(flutterEngine); + Log.d("TAG", "configureFlutterEngine: flutterEngine"); + nativeChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL, StandardMethodCodec.INSTANCE); + nativeChannel.setMethodCallHandler((call, result) -> { + switch (call.method) { + case "getRequestHeaders": + Map map = new HashMap<>(); + map.put("AppId", Configs.appId); + map.put("BossId", Configs.bossId); + map.put("Version", Configs.versionName); + map.put("CPU", Configs.cpu); + MacInfo.imsi = MacInfo.getSubscriptionOperatorType(); + map.put("imsi", MacInfo.imsi != null ? MacInfo.imsi : ""); + map.put("ip", Configs.ip); + map.put("timeZone", AppUtil.getTimeZone()); + map.put("statusHeight", AppUtil.px2dip(App.getInstance(), AppUtil.getStatusBarHeight(App.getInstance())));//状态栏高度 + result.success(map); + break; + + case "initAPI"://同意隐私初始化信息 + ThreadUtil.INST.excute(() -> { + NetWork.getInit(MainActivity.this); + }); + break; + } + + }); + } +} diff --git a/android/app/src/main/java/com/hissai/draw/utils/AppUtil.java b/android/app/src/main/java/com/hissai/draw/utils/AppUtil.java new file mode 100644 index 0000000..7b7a08e --- /dev/null +++ b/android/app/src/main/java/com/hissai/draw/utils/AppUtil.java @@ -0,0 +1,807 @@ +package com.hissai.draw.utils; + +import android.Manifest; +import android.app.Activity; +import android.app.ActivityManager; +import android.app.AppOpsManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.media.AudioManager; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.provider.Settings; +import android.telephony.TelephonyManager; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.RequiresApi; +import androidx.core.app.ActivityCompat; +import androidx.core.app.NotificationManagerCompat; + +import com.hissai.draw.App; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * App工具类 + */ +public class AppUtil { + + public static boolean checkURL(String url) { + boolean value = false; + try { + HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + int code = conn.getResponseCode(); + if (code != 200) { + value = false; + } else { + value = true; + } + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return value; + } + + /** + * 获得屏幕宽度 + * + * @param context + * @return + */ + public static int getScreenWidth(Context context) { + WindowManager wm = (WindowManager) context + .getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics outMetrics = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(outMetrics); + return outMetrics.widthPixels; + } + + /** + * 获得屏幕高度 + * 小于android4.4去掉状态栏高度 + * + * @param context + * @return + */ + public static int getScreenHeight(Context context) { + WindowManager wm = (WindowManager) context + .getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics outMetrics = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(outMetrics); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + return outMetrics.heightPixels; + } else { + return outMetrics.heightPixels - getStatusBarHeight(context); + } + + } + + /** + * 获取状态栏高度 + * + * @param context + * @return + */ + public static int getStatusBarHeight(Context context) { + int result = 0; + try { + int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + result = context.getResources().getDimensionPixelSize(resourceId); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return result; + } + + // 根据手机的分辨率从 px(像素) 的单位 转成为 dp + public static int px2dip(Context context, float pxValue) { + // 获取当前手机的像素密度(1个dp对应几个px) + float scale = context.getResources().getDisplayMetrics().density; + return (int) (pxValue / scale + 0.5f); // 四舍五入取整 + } + + /** + * 获取屏幕宽度 + * + * @param context + * @return + */ + public static int getWindowWidth(Context context) { + // 获取屏幕分辨率 + WindowManager wm = (WindowManager) (context + .getSystemService(Context.WINDOW_SERVICE)); + DisplayMetrics dm = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(dm); + int mScreenWidth = dm.widthPixels; + return mScreenWidth; + } + + /** + * 获取屏幕高度 + * + * @param context + * @return + */ + public static int getWindowHight(Context context) { + // 获取屏幕分辨率 + WindowManager wm = (WindowManager) (context.getSystemService(Context.WINDOW_SERVICE)); + DisplayMetrics dm = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(dm); + int mScreenHight = dm.heightPixels; + return mScreenHight; + } + + /** + * 检测耳机是否接入 + * 0:无插入,1:耳机和话筒均插入,2:仅插入话筒 + * + * @return + */ + public static boolean isHeadsetExists(Context context) { + AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + return audioManager.isWiredHeadsetOn(); + } + + public static boolean isBlueTooth(Context context) { + + AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + return audioManager.isBluetoothA2dpOn(); + } + + + /** + * 获取唯一设备号 + * + * @param context + * @return + */ + public static String getDeviceId(Context context) { + String android_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); + Log.d("TAG", "getDeviceId: android_id==" + android_id); + return android_id; + } + + /** + * 隐藏软键盘 + * + * @param context + * @param editText + * @return + */ + public static void hideInputMethod(Context context, EditText editText) { + InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); + } + + /** + * 隐藏软键盘 + * + * @param activity + * @return + */ + public static boolean hideInputMethod(Activity activity) { + InputMethodManager imm = (InputMethodManager) activity + .getSystemService(Context.INPUT_METHOD_SERVICE); + if (activity.getCurrentFocus() == null) + return false; + return imm.hideSoftInputFromWindow(activity.getCurrentFocus() + .getApplicationWindowToken(), + InputMethodManager.HIDE_NOT_ALWAYS); + } + + /** + * 显示或者隐藏状态栏;true隐藏,false显示 + * + * @param @param context + * @param @param enable + * @return void + * @description + * @author yanqin + */ + public static void full(Context context, boolean enable) { + if (enable) { + ((Activity) context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏 + } else { + ((Activity) context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); //显示状态栏 + } + } + + + //打开扬声器 + public static void OpenSpeaker(Context mContext) { + try { + //判断扬声器是否在打开 + AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + audioManager.setMode(AudioManager.ROUTE_SPEAKER); + //获取当前通话音量 + audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL); + if (!audioManager.isSpeakerphoneOn()) { + audioManager.setSpeakerphoneOn(true); + audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, + audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL), + AudioManager.STREAM_VOICE_CALL); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + + //关闭扬声器 + public static void CloseSpeaker(Context mContext) { + try { + AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + if (audioManager != null) { + if (audioManager.isSpeakerphoneOn()) { + audioManager.setSpeakerphoneOn(false); + audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, 50, + AudioManager.STREAM_VOICE_CALL); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static String getUserAgent(Context context) { + String userAgent = ""; + if (context != null) { + PackageManager pm = context.getPackageManager(); + + if (pm != null) { + String appName = context.getApplicationInfo().loadLabel(pm).toString(); + String packageName = context.getPackageName(); + userAgent = packageName.substring(packageName.lastIndexOf(".") + 1, packageName.length()); + userAgent = userAgent + "/" + getVersionName(context); + userAgent = userAgent + "(" + Build.MODEL + ";" + getAndroidSDKVersionString() + ")"; + } + } + + if (userAgent != null) { + if (isChinese(userAgent)) { + userAgent = chinaToUnicode(userAgent); + } + } + return userAgent; + } + + // 判断一个字符是否是中文 + public static boolean isChinese(char c) { + return c >= 0x4E00 && c <= 0x9FA5;// 根据字节码判断 + } + + // 判断一个字符串是否含有中文 + public static boolean isChinese(String str) { + if (str == null) + return false; + for (char c : str.toCharArray()) { + if (isChinese(c)) + return true;// 有一个中文字符就返回 + } + return false; + } + + public static String chinaToUnicode(String str) { + String result = null; + for (int i = 0; i < str.length(); i++) { + int chr1 = (char) str.charAt(i); + result += "\\u" + Integer.toHexString(chr1); + } + return result; + } + + + /** + * 描述:判断网络是否有效. + * + * @param context the context + * @return true, if is network available + */ + public static boolean isNetworkAvailable(Context context) { + try { + ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivity != null) { + NetworkInfo info = connectivity.getActiveNetworkInfo(); + if (info != null && info.isConnected()) { + if (info.getState() == NetworkInfo.State.CONNECTED) { + return true; + } + } + } + } catch (Exception e) { + return false; + } + return false; + } + + + /** + * 描述:判断网络是否有效.没有网络时进行提示 + * + * @param context the context + * @return true, if is network available + */ + public static boolean isNetworkAvailableMsg(Context context, int msgId) { + try { + ConnectivityManager connectivity = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivity != null) { + NetworkInfo info = connectivity.getActiveNetworkInfo(); + if (info != null && info.isConnected()) { + if (info.getState() == NetworkInfo.State.CONNECTED) { + return true; + } else { + Toast.makeText(context, msgId, Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(context, msgId, Toast.LENGTH_SHORT).show(); + } + } + } catch (Exception e) { + return false; + } + return false; + } + + /** + * 判断当前网络是否是wifi网络. + * + * @param context the context + * @return boolean + */ + public static boolean isWifi(Context context) { + ConnectivityManager connectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo(); + if (activeNetInfo != null + && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) { + return true; + } + return false; + } + + //版本号 + public static int getVersionCode(Context context) { + return getPackageInfo(context).versionCode; + } + + private static PackageInfo getPackageInfo(Context context) { + PackageInfo pi = null; + + try { + PackageManager pm = context.getPackageManager(); + pi = pm.getPackageInfo(context.getPackageName(), + PackageManager.GET_CONFIGURATIONS); + + + return pi; + } catch (Exception e) { + e.printStackTrace(); + } + + return pi; + } + + + /** + * 获取当前应用的版本名 + * + * @return + */ + public static String getVersionName(Context context) { + // 获取packagemanager的实例 + if (context == null) { + return ""; + } + PackageManager packageManager = context.getPackageManager(); + if (packageManager == null) + return ""; + // getPackageName()是你当前类的包名,0代表是获取版本信息 + PackageInfo packInfo; + String version = ""; + try { + packInfo = packageManager.getPackageInfo(context.getPackageName(), + 0); + version = packInfo.versionName; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return version; + } + + + /** + * 初始化手机屏幕的宽高 + * + * @param activity + */ + public static DisplayMetrics getScreenSize(Activity activity) { + DisplayMetrics dm = new DisplayMetrics(); + activity.getWindowManager().getDefaultDisplay().getMetrics(dm); + return dm; + } + + /** + * 根据手机的分辨率从 dp 的单位 转成为 px(像素) + */ + public static int dip2px(Context context, double dpValue) { + Context mContext = context;//防止获取的上下文为空 + final float scale = mContext.getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + /** + * 判断是否有sim卡 + * + * @param context + * @return + */ + public static boolean hasSimCard(Context context) { + TelephonyManager telMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + int simState = telMgr.getSimState(); + boolean result = true; + switch (simState) { + case TelephonyManager.SIM_STATE_ABSENT: + result = false; // 没有SIM卡 + break; + case TelephonyManager.SIM_STATE_UNKNOWN: + result = false; + break; + } + return result; + } + + /** + * 判断是否是通话设备 + * + * @param context + * @return + */ + public static boolean isPhoneDevice(Context context) { + TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + int type = telephony.getPhoneType(); + if (type == TelephonyManager.PHONE_TYPE_NONE) { + //是通话设备 + return false; + } else { + //不是通话设备 + return true; + } + + } + + + /** + * 获取手机系统版本 + * + * @param @return + * @return String + * @description + * @author yanqin + */ + public static String getAndroidSDKVersionString() { + + return "Android " + Build.VERSION.RELEASE; + } + + + /** + * 获取外网的IP(要访问Url,要放到后台线程里处理) + * + * @param @return + * @return String + * @throws + * @Title: GetNetIp + * @Description: + */ + public static String getNetIp() { + URL infoUrl = null; + InputStream inStream = null; + String ipLine = ""; + HttpURLConnection httpConnection = null; + try { + infoUrl = new URL("http://pv.sohu.com/cityjson?ie=utf-8");//必须要用这个网址,因为这个网址返回了我们的ip地址。 + URLConnection connection = infoUrl.openConnection(); + httpConnection = (HttpURLConnection) connection; + int responseCode = httpConnection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + inStream = httpConnection.getInputStream(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(inStream, "utf-8")); + StringBuilder strber = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + strber.append(line + "\n"); + } + + Pattern pattern = Pattern + .compile("((?:(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d))))"); + Matcher matcher = pattern.matcher(strber.toString()); + if (matcher.find()) { + ipLine = matcher.group(); + } + //释放资源 + reader.close(); + } + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + inStream.close(); + httpConnection.disconnect(); + } catch (IOException e) { + e.printStackTrace(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + return ipLine; + } + + /** + * 判断android activity是否运行(可见) + * + * @param mContext + * @param activityClassName + * @return + */ + public static boolean isActivityRunning(Context mContext, String activityClassName) { + ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + List info = activityManager.getRunningTasks(1); + if (info != null && info.size() > 0) { + ComponentName component = info.get(0).topActivity; + if (activityClassName.equals(component.getClassName())) { + return true; + } + } + return false; + } + + /** + * 获取手机型号 + * + * @return 手机型号 + */ + public static String getSystemModel() { + return Build.MODEL; + } + + /** + * 获取手机厂商 + * + * @return 手机厂商 + */ + public static String getDeviceBrand() { + return Build.BRAND; + } + + /** + * 获取手机IMEI(需要“android.permission.READ_PHONE_STATE”权限) + * + * @return 手机IMEI + */ + public static String getIMEI(Context ctx) { + TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Activity.TELEPHONY_SERVICE); + if (tm != null) { + if (ActivityCompat.checkSelfPermission(ctx, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { + return ""; + } + return tm.getDeviceId(); + } + return null; + } + + /** + * 获取手机mac地址 + * 注:并不是所有机型都适配 + * + * @param ctx + * @return + */ + public static String getWifiMac(Context ctx) { + WifiManager wifi = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE); + WifiInfo info = wifi.getConnectionInfo(); + String str = info.getMacAddress(); + if (str == null) str = ""; + return str; + } + + /** + * 这是使用adb shell命令来获取mac地址的方式 + * + * @return + */ + public static String getMac(Context ctx) { + String macSerial = null; + String str = ""; + + try { + Process pp = Runtime.getRuntime().exec("cat /sys/class/net/wlan0/address "); + InputStreamReader ir = new InputStreamReader(pp.getInputStream()); + LineNumberReader input = new LineNumberReader(ir); + + for (; null != str; ) { + str = input.readLine(); + if (str != null) { + macSerial = str.trim();// 去空格 + break; + } + } + //释放资源 + ir.close(); + input.close(); + } catch (IOException ex) { + // 赋予默认值 + ex.printStackTrace(); + } + if ("".equals(str)) { + return getWifiMac(ctx); + } + + + return macSerial; + } + + /** + * 获取系统音量 + * + * @return + */ + public static int getMediaVolume(Context context) { + AudioManager audioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + return audioMgr.getStreamVolume(AudioManager.STREAM_MUSIC); + } + + /** + * 获取系统最大音量 + * + * @param streamType AudioManager.STREAM_MUSIC 声道 + * @return + */ + public static int getMediaMaxVolume(Context context, int streamType) { + AudioManager audioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + return audioMgr.getStreamMaxVolume(streamType); + } + + /** + * 设置音量 + * + * @param volume + */ + public static void setMediaVolume(int volume, Context context) { + AudioManager audioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + audioMgr.setStreamVolume(AudioManager.STREAM_MUSIC, volume, AudioManager.FLAG_PLAY_SOUND); + } + + /** + * 设置音量 + * + * @param volume + */ + public static void setMediaVolumeNoSound(int volume, Context context) { + AudioManager audioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + audioMgr.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); + } + + /** + * 获取是否存在NavigationBar(虚拟按键) + * + * @param @param context + * @param @return + * @return boolean + * @description + * @author yanqin + */ + private static boolean checkDeviceHasNavigationBar(Context context) { + boolean hasNavigationBar = false; + Resources rs = context.getResources(); + int id = rs + .getIdentifier("config_showNavigationBar", "bool", "android"); + if (id > 0) { + hasNavigationBar = rs.getBoolean(id); + } + try { + Class systemPropertiesClass = Class + .forName("android.os.SystemProperties"); + Method m = systemPropertiesClass.getMethod("get", String.class); + String navBarOverride = (String) m.invoke(systemPropertiesClass, + "qemu.hw.mainkeys"); + if ("1".equals(navBarOverride)) { + hasNavigationBar = false; + } else if ("0".equals(navBarOverride)) { + hasNavigationBar = true; + } + } catch (Exception e) { + + } + return hasNavigationBar; + } + + + /** + * 获取NavigationBar(虚拟按键)的高度: + * + * @param @param context + * @param @return + * @return int + * @description + * @author yangqin + */ + public static int getNavigationBarHeight(Context context) { + int navigationBarHeight = 0; + Resources rs = context.getResources(); + int id = rs.getIdentifier("navigation_bar_height", "dimen", "android"); + if (id > 0 && checkDeviceHasNavigationBar(context)) { + navigationBarHeight = rs.getDimensionPixelSize(id); + } + return navigationBarHeight; + } + + + + //获取系统语言 + public static String getSystemLan() { + Locale locale = App.getInstance().getResources().getConfiguration().locale; + + String language = locale.getLanguage(); + + String local = Locale.getDefault().toString(); + + String country = App.getInstance().getResources().getConfiguration().locale.getCountry(); + + Log.e("HJL", "tjCountry: language:" + language + ",local:" + local + ",country:" + country); + return language; + } + + //获取系统时区 + public static String getTimeZone() { + TimeZone timeZone = TimeZone.getDefault(); + String id = timeZone.getID(); //获取时区id,如“Asia/Shanghai” + String name = timeZone.getDisplayName(); //获取名字,如“” + String shotName = timeZone.getDisplayName(false, TimeZone.SHORT); //获取名字,如“GMT+08:00” + int time = timeZone.getRawOffset(); //获取时差,返回值毫秒 + + /*Log.d("TAG", "getTimeZone: id==" + id); + Log.d("TAG", "getTimeZone: name==" + name); + Log.d("TAG", "getTimeZone: shotName==" + shotName); + Log.d("TAG", "getTimeZone: time==" + time);*/ + return shotName; + } + + +} diff --git a/android/app/src/main/java/com/hissai/draw/utils/Configs.java b/android/app/src/main/java/com/hissai/draw/utils/Configs.java new file mode 100644 index 0000000..fec21bf --- /dev/null +++ b/android/app/src/main/java/com/hissai/draw/utils/Configs.java @@ -0,0 +1,14 @@ +package com.hissai.draw.utils; + +public class Configs { + + public static String bossId = "24001"; + public static String serverURL = "https://ecdnjyouapihw.cnrplay.com/phone300_Api/"; + public static String ip = "";//本机ip地址 + public static String deviceId = "";//设备ID + public static String appId = "1"; + public static String versionName = "";//版本号 + public static String deviceModel = "";//设备的硬件厂商和型号 + public static String systemVersion = "";//操作系统版本号 + public static String cpu = "";// +} diff --git a/android/app/src/main/java/com/hissai/draw/utils/MacInfo.java b/android/app/src/main/java/com/hissai/draw/utils/MacInfo.java new file mode 100644 index 0000000..f4268cc --- /dev/null +++ b/android/app/src/main/java/com/hissai/draw/utils/MacInfo.java @@ -0,0 +1,365 @@ +package com.hissai.draw.utils; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.telephony.TelephonyManager; +import android.util.Log; + +import com.hissai.draw.App; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.UUID; + +public class MacInfo { + + public static String getMac(Activity activity) { + return md5s(getDeviceUDID(activity)); + } + + private static String md5s(String plainText) { + + String str = ""; + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(plainText.getBytes()); + byte b[] = md.digest(); + + int i; + + StringBuffer buf = new StringBuffer(""); + for (int offset = 0; offset < b.length; offset++) { + i = b[offset]; + if (i < 0) + i += 256; + if (i < 16) + buf.append("0"); + buf.append(Integer.toHexString(i)); + } + str = buf.toString(); + str = str.toUpperCase(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + + } + return str; + } + + public static String android_id = ""; + public static String imei = ""; + public static String imei2 = ""; + public static String imsi = ""; + public static String imsi2 = ""; + public static String sn = ""; + public static String mac = ""; + public static String device_id = ""; + public static String oaId = ""; + + @SuppressLint("MissingPermission") + private static String getDeviceUDID(Activity activity) { + + android_id = Configs.deviceId; + + try { + TelephonyManager tm = (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE); + if (tm != null) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { + if (tm.hasCarrierPrivileges()) { + imei = tm.getImei(0); + imei2 = tm.getImei(1); + } else { + System.out.println("Can not get IMEI info."); + } + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + imei = tm.getImei(0); + imei2 = tm.getImei(1); + } else { + imei = tm.getDeviceId(); + + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + try { + device_id = getUUID(); + } catch (Exception e) { + e.printStackTrace(); + } + + if (device_id == null) { + device_id = ""; + } + if (imei == null) { + imei = ""; + } + try { + // sn + sn = Build.SERIAL; + if (sn == null) + sn = ""; + } catch (Exception e) { + sn = ""; + } + + try { + // mac address + WifiManager wifi = (WifiManager) activity.getApplicationContext() + .getSystemService(Context.WIFI_SERVICE); + WifiInfo info = wifi.getConnectionInfo(); + mac = info.getMacAddress(); + + if (mac == null || mac.equals("") + || mac.equals("00:00:00:00:00:00") || mac.equals("02:00:00:00:00:00")) { + mac = getLocalMacAddressFromIp(); + } + + if (mac == null || mac.equals("") + || mac.equals("00:00:00:00:00:00") || mac.equals("02:00:00:00:00:00")) { + mac = getNewMac(); + } + + if (mac == null || mac.equals("") + || mac.equals("00:00:00:00:00:00") || mac.equals("02:00:00:00:00:00")) { + mac = ""; + } + } catch (Exception e) { + mac = ""; + } + + return android_id + ":" + imei + ":" + sn + ":" + mac; + } + + public static String getOAID(Activity activity) { + try { + oaId = ""; + } catch (Exception e) { + e.printStackTrace(); + } + return oaId; + } + + + @SuppressLint("MissingPermission") + public static String getUUID() { + + String serial = null; + + String m_szDevIDShort = "35" + + Build.BOARD.length() % 10 + Build.BRAND.length() % 10 + + + Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 + + + Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 + + + Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 + + + Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 + + + Build.TAGS.length() % 10 + Build.TYPE.length() % 10 + + + Build.USER.length() % 10; //13 位 + + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + serial = Build.getSerial(); + } else { + serial = Build.SERIAL; + } + //API>=9 使用serial号 + return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString(); + } catch (Exception exception) { + //serial需要一个初始化 + serial = "serial"; // 随便一个初始化 + } + //使用硬件信息拼凑出来的15位号码 + return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString(); + } + + + /** + * 通过网络接口取 + * + * @return + */ + private static String getNewMac() { + try { + List all = Collections.list(NetworkInterface.getNetworkInterfaces()); + for (NetworkInterface nif : all) { + if (!nif.getName().equalsIgnoreCase("wlan0")) continue; + byte[] macBytes = nif.getHardwareAddress(); + if (macBytes == null) { + return null; + } + StringBuilder res1 = new StringBuilder(); + for (byte b : macBytes) { + res1.append(String.format("%02X:", b)); + } + if (res1.length() > 0) { + res1.deleteCharAt(res1.length() - 1); + } + return res1.toString(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + /** + *  * 根据IP地址获取MAC地址 + *  * @return + *   + */ + private static String getLocalMacAddressFromIp() { + String strMacAddr = null; + try { + //获得IpD地址 + InetAddress ip = getLocalInetAddress(); + byte[] b = NetworkInterface.getByInetAddress(ip).getHardwareAddress(); + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < b.length; i++) { + if (i != 0) { + buffer.append(':'); + } + String str = Integer.toHexString(b[i] & 0xFF); + buffer.append(str.length() == 1 ? 0 + str : str); + } + strMacAddr = buffer.toString().toUpperCase(); + } catch (Exception e) { + } + return strMacAddr; + } + + /** + *  * 获取移动设备本地IP + *  * @return + *   + */ + private static InetAddress getLocalInetAddress() { + InetAddress ip = null; + try { + //列举 + Enumeration en_netInterface = NetworkInterface.getNetworkInterfaces(); + while (en_netInterface.hasMoreElements()) {//是否还有元素 + NetworkInterface ni = (NetworkInterface) en_netInterface.nextElement();//得到下一个元素 + Enumeration en_ip = ni.getInetAddresses();//得到一个ip地址的列举 + while (en_ip.hasMoreElements()) { + ip = en_ip.nextElement(); + if (!ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) + break; + else + ip = null; + } + if (ip != null) { + break; + } + } + } catch (SocketException e) { + e.printStackTrace(); + } + return ip; + } + + private static String callCmd(String cmd, String filter) { + String result = ""; + String line = ""; + try { + Process proc = Runtime.getRuntime().exec(cmd); + InputStreamReader is = new InputStreamReader(proc.getInputStream()); + BufferedReader br = new BufferedReader(is); + + // ִ������cmd��ֻȡ����к���filter����һ�� + while ((line = br.readLine()) != null + && line.contains(filter) == false) { + // result += line; + Log.i("test", "line: " + line); + } + + result = line; + Log.i("test", "result: " + result); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + private static String getMacForHisense() { + String path = "/sys/class/net/eth0/address"; + File file = new File(path); + if (file.exists()) { + BufferedReader buf; + try { + buf = new BufferedReader(new FileReader(file)); + String mac = buf.readLine(); + if (mac != null) { + return mac; + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return ""; + } + + /** + * 获取设备拨号运营商 + * + * @return ["中国电信CTCC":3]["中国联通CUCC:2]["中国移动CMCC":1]["other":0]["无sim卡":-1] + */ + public static String getSubscriptionOperatorType() { + //int opeType = -1; + // No sim + if (!hasSim()) { + return null; + } + + TelephonyManager tm = (TelephonyManager) App.getInstance().getSystemService(Context.TELEPHONY_SERVICE); + String operator = tm.getSimOperator(); + String operator2 = tm.getSimOperatorName(); + /* // 中国联通 + if ("46001".equals(operator) || "46006".equals(operator) || "46009".equals(operator)) { + opeType = 2; + // 中国移动 + } else if ("46000".equals(operator) || "46002".equals(operator) || "46004".equals(operator) || "46007".equals(operator)) { + opeType = 1; + // 中国电信 + } else if ("46003".equals(operator) || "46005".equals(operator) || "46011".equals(operator)) { + opeType = 3; + } else { + opeType = 0; + }*/ + return operator; + } + + /** + * 判断是否有Sim卡 + * + * @return + */ + public static boolean hasSim() { + TelephonyManager tm = (TelephonyManager) App.getInstance().getSystemService(Context.TELEPHONY_SERVICE); + if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) { + return true; + } else { + return false; + } + } +} diff --git a/android/app/src/main/java/com/hissai/draw/utils/NetWork.java b/android/app/src/main/java/com/hissai/draw/utils/NetWork.java new file mode 100644 index 0000000..2b0142e --- /dev/null +++ b/android/app/src/main/java/com/hissai/draw/utils/NetWork.java @@ -0,0 +1,89 @@ +package com.hissai.draw.utils; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class NetWork { + + + //读取文件 + public static Properties getNetConfigProperties(Context activity) { + Properties props = new Properties(); + InputStream in; + try { + in = activity.getAssets().open("holybladeCloud.properties"); + props.load(in); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + return props; + } + + //获取配置 + public static void getConfigs(Context context) { + Properties con = getNetConfigProperties(context); + if (Configs.serverURL.equals("")) { + Configs.serverURL = con.getProperty("ServerURL"); + } + Configs.bossId = con.getProperty("BossId"); + Configs.appId = con.getProperty("AppId"); + + // 获取版本号 + PackageManager packageManager = context.getPackageManager(); + // getPackageName()是你当前类的包名,0代表是获取版本信息 + PackageInfo packInfo = null; + try { + packInfo = packageManager.getPackageInfo(context.getPackageName(), 0); + Configs.versionName = packInfo.versionName; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + } + + //同意协议 初始化 获取设备信息 + public static void getInit(Context context) { + Configs.deviceId = AppUtil.getDeviceId(context); + String brand = android.os.Build.BRAND; + String model = android.os.Build.MODEL; + Configs.deviceModel = brand + ":" + model; + Configs.systemVersion = "android:" + android.os.Build.VERSION.RELEASE; + Configs.cpu = getCpuName(); + + } + + + //获取cpu名称 + public static String getCpuName() { + String cpuName = ""; + try { + FileReader fr = new FileReader("/proc/cpuinfo"); + BufferedReader br = new BufferedReader(fr); + String text; + while ((text = br.readLine()) != null) { + String[] array = text.split(":\\s+", 2); + for (int i = 0; i < array.length; i++) { + //LogUtil.d("cpuName = "+ i + "="+array[i]); + cpuName = array[i]; + } + if (array[0].contains("Hardware") || array[0].contains("hardware")) + break; + } + return cpuName; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return ""; + } + +} diff --git a/android/app/src/main/java/com/hissai/draw/utils/ThreadUtil.java b/android/app/src/main/java/com/hissai/draw/utils/ThreadUtil.java new file mode 100644 index 0000000..40d4b1f --- /dev/null +++ b/android/app/src/main/java/com/hissai/draw/utils/ThreadUtil.java @@ -0,0 +1,61 @@ +package com.hissai.draw.utils; + +import android.os.Handler; +import android.os.Looper; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * 线程工具,用于执行线程等 + */ +public final class ThreadUtil { + public static final ThreadUtil INST = new ThreadUtil(); + + private ExecutorService executors; + + private ThreadUtil() { + } + + /** + * 在线程中执行 + * + * @param runnable 要执行的runnable + */ + public void excute(Runnable runnable) { + ExecutorService executorService = getExecutorService(); + if (executorService != null) { + // 优先使用线程池,提高效率 + executorService.execute(runnable); + } else { + // 线程池获取失败,则直接使用线程 + new Thread(runnable).start(); + } + } + + /** + * 在主线程中执行 + * + * @param runnable 要执行的runnable + */ + public void excuteInMainThread(Runnable runnable) { + new Handler(Looper.getMainLooper()).post(runnable); + } + + /** + * 获取缓存线程池 + * + * @return 缓存线程池服务 + */ + private ExecutorService getExecutorService() { + if (executors == null) { + try { + executors = Executors.newCachedThreadPool(); + } catch (Exception e) { + + } + } + + return executors; + } +} diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..5076a6f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..ba5bcf8 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ba5bcf8 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..ba5bcf8 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..ba5bcf8 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/kpy.png b/android/app/src/main/res/mipmap-xxhdpi/kpy.png new file mode 100644 index 0000000..dbe32f1 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/kpy.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..ba5bcf8 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..dd49500 --- /dev/null +++ b/android/app/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + + #C4C4C4 + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..6ab9a2d --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..5f2ad63 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,33 @@ +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + google() + mavenCentral() + maven { url "https://jitpack.io" } + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.2.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + maven { url "https://jitpack.io" } + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..cb24abd --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/assets/images/ad_free_bg.png b/assets/images/ad_free_bg.png new file mode 100644 index 0000000..4ec4097 Binary files /dev/null and b/assets/images/ad_free_bg.png differ diff --git a/assets/images/btn_cirilibao.webp b/assets/images/btn_cirilibao.webp new file mode 100644 index 0000000..95386e2 Binary files /dev/null and b/assets/images/btn_cirilibao.webp differ diff --git a/assets/images/create.png b/assets/images/create.png new file mode 100644 index 0000000..d08d584 Binary files /dev/null and b/assets/images/create.png differ diff --git a/assets/images/create_r.png b/assets/images/create_r.png new file mode 100644 index 0000000..ca9a535 Binary files /dev/null and b/assets/images/create_r.png differ diff --git a/assets/images/cuo.png b/assets/images/cuo.png new file mode 100644 index 0000000..7906b2c Binary files /dev/null and b/assets/images/cuo.png differ diff --git a/assets/images/cuo2.png b/assets/images/cuo2.png new file mode 100644 index 0000000..5c41cfb Binary files /dev/null and b/assets/images/cuo2.png differ diff --git a/assets/images/gallery.png b/assets/images/gallery.png new file mode 100644 index 0000000..98cb35c Binary files /dev/null and b/assets/images/gallery.png differ diff --git a/assets/images/gallery_r.png b/assets/images/gallery_r.png new file mode 100644 index 0000000..8507ee9 Binary files /dev/null and b/assets/images/gallery_r.png differ diff --git a/assets/images/google_login.png b/assets/images/google_login.png new file mode 100644 index 0000000..78b8539 Binary files /dev/null and b/assets/images/google_login.png differ diff --git a/assets/images/google_logo.png b/assets/images/google_logo.png new file mode 100644 index 0000000..5d13bb8 Binary files /dev/null and b/assets/images/google_logo.png differ diff --git a/assets/images/head.png b/assets/images/head.png new file mode 100644 index 0000000..5d3b5fc Binary files /dev/null and b/assets/images/head.png differ diff --git a/assets/images/ic_ad.png b/assets/images/ic_ad.png new file mode 100644 index 0000000..13d75ea Binary files /dev/null and b/assets/images/ic_ad.png differ diff --git a/assets/images/ic_bg.png b/assets/images/ic_bg.png new file mode 100644 index 0000000..2dfdda1 Binary files /dev/null and b/assets/images/ic_bg.png differ diff --git a/assets/images/ic_check.png b/assets/images/ic_check.png new file mode 100644 index 0000000..0c32e33 Binary files /dev/null and b/assets/images/ic_check.png differ diff --git a/assets/images/ic_close.png b/assets/images/ic_close.png new file mode 100644 index 0000000..a829905 Binary files /dev/null and b/assets/images/ic_close.png differ diff --git a/assets/images/ic_collect.png b/assets/images/ic_collect.png new file mode 100644 index 0000000..bde1221 Binary files /dev/null and b/assets/images/ic_collect.png differ diff --git a/assets/images/ic_collect_s.png b/assets/images/ic_collect_s.png new file mode 100644 index 0000000..39b156c Binary files /dev/null and b/assets/images/ic_collect_s.png differ diff --git a/assets/images/ic_count.png b/assets/images/ic_count.png new file mode 100644 index 0000000..8111cce Binary files /dev/null and b/assets/images/ic_count.png differ diff --git a/assets/images/ic_download.png b/assets/images/ic_download.png new file mode 100644 index 0000000..be8fcb5 Binary files /dev/null and b/assets/images/ic_download.png differ diff --git a/assets/images/ic_follow.png b/assets/images/ic_follow.png new file mode 100644 index 0000000..629171f Binary files /dev/null and b/assets/images/ic_follow.png differ diff --git a/assets/images/ic_jump.png b/assets/images/ic_jump.png new file mode 100644 index 0000000..cdbb959 Binary files /dev/null and b/assets/images/ic_jump.png differ diff --git a/assets/images/ic_like.png b/assets/images/ic_like.png new file mode 100644 index 0000000..ac00064 Binary files /dev/null and b/assets/images/ic_like.png differ diff --git a/assets/images/ic_like_in.png b/assets/images/ic_like_in.png new file mode 100644 index 0000000..1e575d1 Binary files /dev/null and b/assets/images/ic_like_in.png differ diff --git a/assets/images/ic_loading.webp b/assets/images/ic_loading.webp new file mode 100644 index 0000000..7a822eb Binary files /dev/null and b/assets/images/ic_loading.webp differ diff --git a/assets/images/ic_mall.png b/assets/images/ic_mall.png new file mode 100644 index 0000000..b40243c Binary files /dev/null and b/assets/images/ic_mall.png differ diff --git a/assets/images/ic_message.png b/assets/images/ic_message.png new file mode 100644 index 0000000..33c78f4 Binary files /dev/null and b/assets/images/ic_message.png differ diff --git a/assets/images/ic_message_collect.png b/assets/images/ic_message_collect.png new file mode 100644 index 0000000..d4a1a22 Binary files /dev/null and b/assets/images/ic_message_collect.png differ diff --git a/assets/images/ic_message_notice.png b/assets/images/ic_message_notice.png new file mode 100644 index 0000000..c2b7bca Binary files /dev/null and b/assets/images/ic_message_notice.png differ diff --git a/assets/images/ic_no_collect.png b/assets/images/ic_no_collect.png new file mode 100644 index 0000000..18acdbb Binary files /dev/null and b/assets/images/ic_no_collect.png differ diff --git a/assets/images/ic_no_content.png b/assets/images/ic_no_content.png new file mode 100644 index 0000000..b88d84b Binary files /dev/null and b/assets/images/ic_no_content.png differ diff --git a/assets/images/ic_open.png b/assets/images/ic_open.png new file mode 100644 index 0000000..6188836 Binary files /dev/null and b/assets/images/ic_open.png differ diff --git a/assets/images/ic_portfolio.webp b/assets/images/ic_portfolio.webp new file mode 100644 index 0000000..7c9f231 Binary files /dev/null and b/assets/images/ic_portfolio.webp differ diff --git a/assets/images/ic_random.png b/assets/images/ic_random.png new file mode 100644 index 0000000..4b09e4f Binary files /dev/null and b/assets/images/ic_random.png differ diff --git a/assets/images/ic_return.png b/assets/images/ic_return.png new file mode 100644 index 0000000..5fd089d Binary files /dev/null and b/assets/images/ic_return.png differ diff --git a/assets/images/ic_same_style.png b/assets/images/ic_same_style.png new file mode 100644 index 0000000..ca2248b Binary files /dev/null and b/assets/images/ic_same_style.png differ diff --git a/assets/images/ic_search.png b/assets/images/ic_search.png new file mode 100644 index 0000000..b3eafc4 Binary files /dev/null and b/assets/images/ic_search.png differ diff --git a/assets/images/ic_setting.png b/assets/images/ic_setting.png new file mode 100644 index 0000000..dee8f49 Binary files /dev/null and b/assets/images/ic_setting.png differ diff --git a/assets/images/ic_share.png b/assets/images/ic_share.png new file mode 100644 index 0000000..7c5277f Binary files /dev/null and b/assets/images/ic_share.png differ diff --git a/assets/images/ic_size_select.png b/assets/images/ic_size_select.png new file mode 100644 index 0000000..1aa373c Binary files /dev/null and b/assets/images/ic_size_select.png differ diff --git a/assets/images/ic_sort.png b/assets/images/ic_sort.png new file mode 100644 index 0000000..85e0d13 Binary files /dev/null and b/assets/images/ic_sort.png differ diff --git a/assets/images/ic_style_s.png b/assets/images/ic_style_s.png new file mode 100644 index 0000000..c520f51 Binary files /dev/null and b/assets/images/ic_style_s.png differ diff --git a/assets/images/ic_tip.png b/assets/images/ic_tip.png new file mode 100644 index 0000000..0478f90 Binary files /dev/null and b/assets/images/ic_tip.png differ diff --git a/assets/images/ic_title.png b/assets/images/ic_title.png new file mode 100644 index 0000000..7a056e5 Binary files /dev/null and b/assets/images/ic_title.png differ diff --git a/assets/images/ic_topping.png b/assets/images/ic_topping.png new file mode 100644 index 0000000..4c2fb0c Binary files /dev/null and b/assets/images/ic_topping.png differ diff --git a/assets/images/ic_upload.png b/assets/images/ic_upload.png new file mode 100644 index 0000000..6253505 Binary files /dev/null and b/assets/images/ic_upload.png differ diff --git a/assets/images/ic_works.png b/assets/images/ic_works.png new file mode 100644 index 0000000..91cc56f Binary files /dev/null and b/assets/images/ic_works.png differ diff --git a/assets/images/ic_works_f.png b/assets/images/ic_works_f.png new file mode 100644 index 0000000..e89618f Binary files /dev/null and b/assets/images/ic_works_f.png differ diff --git a/assets/images/icon.png b/assets/images/icon.png new file mode 100644 index 0000000..6350e4a Binary files /dev/null and b/assets/images/icon.png differ diff --git a/assets/images/img_11.png b/assets/images/img_11.png new file mode 100644 index 0000000..d09616b Binary files /dev/null and b/assets/images/img_11.png differ diff --git a/assets/images/img_11_no.png b/assets/images/img_11_no.png new file mode 100644 index 0000000..d0c02e4 Binary files /dev/null and b/assets/images/img_11_no.png differ diff --git a/assets/images/img_169.png b/assets/images/img_169.png new file mode 100644 index 0000000..04303a6 Binary files /dev/null and b/assets/images/img_169.png differ diff --git a/assets/images/img_169_no.png b/assets/images/img_169_no.png new file mode 100644 index 0000000..ebb9803 Binary files /dev/null and b/assets/images/img_169_no.png differ diff --git a/assets/images/img_34.png b/assets/images/img_34.png new file mode 100644 index 0000000..6a8d524 Binary files /dev/null and b/assets/images/img_34.png differ diff --git a/assets/images/img_34_no.png b/assets/images/img_34_no.png new file mode 100644 index 0000000..6205fd2 Binary files /dev/null and b/assets/images/img_34_no.png differ diff --git a/assets/images/img_43.png b/assets/images/img_43.png new file mode 100644 index 0000000..44ec09c Binary files /dev/null and b/assets/images/img_43.png differ diff --git a/assets/images/img_43_no.png b/assets/images/img_43_no.png new file mode 100644 index 0000000..fbd5aa8 Binary files /dev/null and b/assets/images/img_43_no.png differ diff --git a/assets/images/img_916.png b/assets/images/img_916.png new file mode 100644 index 0000000..d45cbf4 Binary files /dev/null and b/assets/images/img_916.png differ diff --git a/assets/images/img_916_no.png b/assets/images/img_916_no.png new file mode 100644 index 0000000..0d626e9 Binary files /dev/null and b/assets/images/img_916_no.png differ diff --git a/assets/images/img_delete.png b/assets/images/img_delete.png new file mode 100644 index 0000000..9c51523 Binary files /dev/null and b/assets/images/img_delete.png differ diff --git a/assets/images/jia.png b/assets/images/jia.png new file mode 100644 index 0000000..0f00559 Binary files /dev/null and b/assets/images/jia.png differ diff --git a/assets/images/jia_w.png b/assets/images/jia_w.png new file mode 100644 index 0000000..dd4c14c Binary files /dev/null and b/assets/images/jia_w.png differ diff --git a/assets/images/kpy.png b/assets/images/kpy.png new file mode 100644 index 0000000..dbe32f1 Binary files /dev/null and b/assets/images/kpy.png differ diff --git a/assets/images/kuang.png b/assets/images/kuang.png new file mode 100644 index 0000000..8279ad4 Binary files /dev/null and b/assets/images/kuang.png differ diff --git a/assets/images/login_bg.png b/assets/images/login_bg.png new file mode 100644 index 0000000..29fc05b Binary files /dev/null and b/assets/images/login_bg.png differ diff --git a/assets/images/login_logo.png b/assets/images/login_logo.png new file mode 100644 index 0000000..67a37d9 Binary files /dev/null and b/assets/images/login_logo.png differ diff --git a/assets/images/login_phone.png b/assets/images/login_phone.png new file mode 100644 index 0000000..a20857b Binary files /dev/null and b/assets/images/login_phone.png differ diff --git a/assets/images/me.png b/assets/images/me.png new file mode 100644 index 0000000..0d76c73 Binary files /dev/null and b/assets/images/me.png differ diff --git a/assets/images/me_r.png b/assets/images/me_r.png new file mode 100644 index 0000000..c0b8a0d Binary files /dev/null and b/assets/images/me_r.png differ diff --git a/assets/images/share_logo.png b/assets/images/share_logo.png new file mode 100644 index 0000000..ff45355 Binary files /dev/null and b/assets/images/share_logo.png differ diff --git a/assets/images/shop_bg.png b/assets/images/shop_bg.png new file mode 100644 index 0000000..969d99d Binary files /dev/null and b/assets/images/shop_bg.png differ diff --git a/assets/images/shop_logo.png b/assets/images/shop_logo.png new file mode 100644 index 0000000..45cd3ea Binary files /dev/null and b/assets/images/shop_logo.png differ diff --git a/assets/images/shop_star.png b/assets/images/shop_star.png new file mode 100644 index 0000000..7acb939 Binary files /dev/null and b/assets/images/shop_star.png differ diff --git a/assets/images/upbg.webp b/assets/images/upbg.webp new file mode 100644 index 0000000..6cdc28a Binary files /dev/null and b/assets/images/upbg.webp differ diff --git a/assets/images/view_ad.png b/assets/images/view_ad.png new file mode 100644 index 0000000..409c15f Binary files /dev/null and b/assets/images/view_ad.png differ diff --git a/assets/images/zhankai.png b/assets/images/zhankai.png new file mode 100644 index 0000000..eaf18de Binary files /dev/null and b/assets/images/zhankai.png differ diff --git a/ios/.symlinks/plugins/device_info b/ios/.symlinks/plugins/device_info new file mode 100644 index 0000000..bae2e42 --- /dev/null +++ b/ios/.symlinks/plugins/device_info @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.3/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/flutter_native_image b/ios/.symlinks/plugins/flutter_native_image new file mode 100644 index 0000000..1792d31 --- /dev/null +++ b/ios/.symlinks/plugins/flutter_native_image @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_native_image-0.0.6+1/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/fluttertoast b/ios/.symlinks/plugins/fluttertoast new file mode 100644 index 0000000..60dcb4e --- /dev/null +++ b/ios/.symlinks/plugins/fluttertoast @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/fluttertoast-8.2.1/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/image_cropper b/ios/.symlinks/plugins/image_cropper new file mode 100644 index 0000000..99eb7d9 --- /dev/null +++ b/ios/.symlinks/plugins/image_cropper @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/image_cropper-3.0.3/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/image_gallery_saver b/ios/.symlinks/plugins/image_gallery_saver new file mode 100644 index 0000000..9805c0e --- /dev/null +++ b/ios/.symlinks/plugins/image_gallery_saver @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/image_gallery_saver-1.7.1/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/image_picker_ios b/ios/.symlinks/plugins/image_picker_ios new file mode 100644 index 0000000..a74813e --- /dev/null +++ b/ios/.symlinks/plugins/image_picker_ios @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/image_picker_ios-0.8.7+3/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/path_provider_foundation b/ios/.symlinks/plugins/path_provider_foundation new file mode 100644 index 0000000..6cce734 --- /dev/null +++ b/ios/.symlinks/plugins/path_provider_foundation @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_foundation-2.2.2/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/permission_handler_apple b/ios/.symlinks/plugins/permission_handler_apple new file mode 100644 index 0000000..d0d8808 --- /dev/null +++ b/ios/.symlinks/plugins/permission_handler_apple @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler_apple-9.0.8/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/shared_preferences_foundation b/ios/.symlinks/plugins/shared_preferences_foundation new file mode 100644 index 0000000..ecb10a8 --- /dev/null +++ b/ios/.symlinks/plugins/shared_preferences_foundation @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_foundation-2.2.1/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/sign_in_with_apple b/ios/.symlinks/plugins/sign_in_with_apple new file mode 100644 index 0000000..6251f93 --- /dev/null +++ b/ios/.symlinks/plugins/sign_in_with_apple @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/sign_in_with_apple-4.3.0/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/sqflite b/ios/.symlinks/plugins/sqflite new file mode 100644 index 0000000..9f718e9 --- /dev/null +++ b/ios/.symlinks/plugins/sqflite @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-2.2.7/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/url_launcher_ios b/ios/.symlinks/plugins/url_launcher_ios new file mode 100644 index 0000000..2258bdb --- /dev/null +++ b/ios/.symlinks/plugins/url_launcher_ios @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_ios-6.1.4/ \ No newline at end of file diff --git a/ios/.symlinks/plugins/webview_flutter_wkwebview b/ios/.symlinks/plugins/webview_flutter_wkwebview new file mode 100644 index 0000000..8b4278f --- /dev/null +++ b/ios/.symlinks/plugins/webview_flutter_wkwebview @@ -0,0 +1 @@ +/Users/wuyangguan/Desktop/Flutter-Development/flutter/.pub-cache/hosted/pub.dartlang.org/webview_flutter_wkwebview-2.9.5/ \ No newline at end of file diff --git a/ios/Flutter/Generated.xcconfig b/ios/Flutter/Generated.xcconfig new file mode 100644 index 0000000..5785570 --- /dev/null +++ b/ios/Flutter/Generated.xcconfig @@ -0,0 +1,14 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=D:\flutter_windows_3.3.1-stable\flutter +FLUTTER_APPLICATION_PATH=D:\git_code\ai_drawing +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_TARGET=lib\main.dart +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=1.1.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 diff --git a/ios/Flutter/flutter_export_environment.sh b/ios/Flutter/flutter_export_environment.sh new file mode 100644 index 0000000..4970922 --- /dev/null +++ b/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=D:\flutter_windows_3.3.1-stable\flutter" +export "FLUTTER_APPLICATION_PATH=D:\git_code\ai_drawing" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_TARGET=lib\main.dart" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=1.1.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" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..d207307 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,38 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '11.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Runner/GeneratedPluginRegistrant.h b/ios/Runner/GeneratedPluginRegistrant.h new file mode 100644 index 0000000..7a89092 --- /dev/null +++ b/ios/Runner/GeneratedPluginRegistrant.h @@ -0,0 +1,19 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GeneratedPluginRegistrant_h +#define GeneratedPluginRegistrant_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GeneratedPluginRegistrant : NSObject ++ (void)registerWithRegistry:(NSObject*)registry; +@end + +NS_ASSUME_NONNULL_END +#endif /* GeneratedPluginRegistrant_h */ diff --git a/ios/Runner/GeneratedPluginRegistrant.m b/ios/Runner/GeneratedPluginRegistrant.m new file mode 100644 index 0000000..1b6d6d4 --- /dev/null +++ b/ios/Runner/GeneratedPluginRegistrant.m @@ -0,0 +1,126 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#import "GeneratedPluginRegistrant.h" + +#if __has_include() +#import +#else +@import connectivity_plus; +#endif + +#if __has_include() +#import +#else +@import device_info; +#endif + +#if __has_include() +#import +#else +@import flutter_native_image; +#endif + +#if __has_include() +#import +#else +@import fluttertoast; +#endif + +#if __has_include() +#import +#else +@import image_cropper; +#endif + +#if __has_include() +#import +#else +@import image_gallery_saver; +#endif + +#if __has_include() +#import +#else +@import image_picker_ios; +#endif + +#if __has_include() +#import +#else +@import ironsource_mediation; +#endif + +#if __has_include() +#import +#else +@import path_provider_foundation; +#endif + +#if __has_include() +#import +#else +@import permission_handler_apple; +#endif + +#if __has_include() +#import +#else +@import sensors_analytics_flutter_plugin; +#endif + +#if __has_include() +#import +#else +@import share_plus; +#endif + +#if __has_include() +#import +#else +@import shared_preferences_foundation; +#endif + +#if __has_include() +#import +#else +@import sqflite; +#endif + +#if __has_include() +#import +#else +@import url_launcher_ios; +#endif + +#if __has_include() +#import +#else +@import webview_flutter_wkwebview; +#endif + +@implementation GeneratedPluginRegistrant + ++ (void)registerWithRegistry:(NSObject*)registry { + [ConnectivityPlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"ConnectivityPlusPlugin"]]; + [FLTDeviceInfoPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTDeviceInfoPlugin"]]; + [FlutterNativeImagePlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterNativeImagePlugin"]]; + [FluttertoastPlugin registerWithRegistrar:[registry registrarForPlugin:@"FluttertoastPlugin"]]; + [FLTImageCropperPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImageCropperPlugin"]]; + [ImageGallerySaverPlugin registerWithRegistrar:[registry registrarForPlugin:@"ImageGallerySaverPlugin"]]; + [FLTImagePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImagePickerPlugin"]]; + [IronSourceMediationPlugin registerWithRegistrar:[registry registrarForPlugin:@"IronSourceMediationPlugin"]]; + [PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]]; + [PermissionHandlerPlugin registerWithRegistrar:[registry registrarForPlugin:@"PermissionHandlerPlugin"]]; + [SensorsAnalyticsFlutterPlugin registerWithRegistrar:[registry registrarForPlugin:@"SensorsAnalyticsFlutterPlugin"]]; + [FLTSharePlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTSharePlusPlugin"]]; + [SharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"SharedPreferencesPlugin"]]; + [SqflitePlugin registerWithRegistrar:[registry registrarForPlugin:@"SqflitePlugin"]]; + [FLTURLLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTURLLauncherPlugin"]]; + [FLTWebViewFlutterPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTWebViewFlutterPlugin"]]; +} + +@end diff --git a/lib/bean/ad_free_bean.dart b/lib/bean/ad_free_bean.dart new file mode 100644 index 0000000..cf4db83 --- /dev/null +++ b/lib/bean/ad_free_bean.dart @@ -0,0 +1,16 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'ad_free_bean.g.dart'; + +@JsonSerializable() +class AdFreeBean { + String? BackgroundImage; + String? BtnImage; + String? BtnAction; + + AdFreeBean(this.BackgroundImage, this.BtnImage, this.BtnAction); + + factory AdFreeBean.fromJson(Map json) => _$AdFreeBeanFromJson(json); + + Map toJson() => _$AdFreeBeanToJson(this); +} diff --git a/lib/bean/ad_free_bean.g.dart b/lib/bean/ad_free_bean.g.dart new file mode 100644 index 0000000..958e19c --- /dev/null +++ b/lib/bean/ad_free_bean.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ad_free_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +AdFreeBean _$AdFreeBeanFromJson(Map json) { + return AdFreeBean( + json['BackgroundImage'] as String?, + json['BtnImage'] as String?, + json['BtnAction'] as String?, + ); +} + +Map _$AdFreeBeanToJson(AdFreeBean instance) => + { + 'BackgroundImage': instance.BackgroundImage, + 'BtnImage': instance.BtnImage, + 'BtnAction': instance.BtnAction, + }; diff --git a/lib/bean/app_config_bean.dart b/lib/bean/app_config_bean.dart new file mode 100644 index 0000000..4b331eb --- /dev/null +++ b/lib/bean/app_config_bean.dart @@ -0,0 +1,26 @@ +import 'package:json_annotation/json_annotation.dart'; + +import 'ad_free_bean.dart'; + +part 'app_config_bean.g.dart'; + +@JsonSerializable() +class AppConfigBean { + int? SharingRewards; + AdFreeBean? AdFree; + String? MallInletImage; + int? InvitationCodeNumber; + int? InviteeNumber; + bool? UserPageAd; + bool? UserPageShoppingMall; + bool? UserPageOfficialAccount; + bool? IsCheckRemark; + bool? IsShowUserPageEquityBtn; + + AppConfigBean(this.SharingRewards, this.AdFree, this.MallInletImage, this.InvitationCodeNumber, this.InviteeNumber, this.UserPageAd, + this.UserPageShoppingMall, this.UserPageOfficialAccount, this.IsCheckRemark, this.IsShowUserPageEquityBtn); + + factory AppConfigBean.fromJson(Map json) => _$AppConfigBeanFromJson(json); + + Map toJson() => _$AppConfigBeanToJson(this); +} diff --git a/lib/bean/app_config_bean.g.dart b/lib/bean/app_config_bean.g.dart new file mode 100644 index 0000000..00a8024 --- /dev/null +++ b/lib/bean/app_config_bean.g.dart @@ -0,0 +1,38 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'app_config_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +AppConfigBean _$AppConfigBeanFromJson(Map json) { + return AppConfigBean( + json['SharingRewards'] as int?, + json['AdFree'] == null + ? null + : AdFreeBean.fromJson(json['AdFree'] as Map), + json['MallInletImage'] as String?, + json['InvitationCodeNumber'] as int?, + json['InviteeNumber'] as int?, + json['UserPageAd'] as bool?, + json['UserPageShoppingMall'] as bool?, + json['UserPageOfficialAccount'] as bool?, + json['IsCheckRemark'] as bool?, + json['IsShowUserPageEquityBtn'] as bool?, + ); +} + +Map _$AppConfigBeanToJson(AppConfigBean instance) => + { + 'SharingRewards': instance.SharingRewards, + 'AdFree': instance.AdFree, + 'MallInletImage': instance.MallInletImage, + 'InvitationCodeNumber': instance.InvitationCodeNumber, + 'InviteeNumber': instance.InviteeNumber, + 'UserPageAd': instance.UserPageAd, + 'UserPageShoppingMall': instance.UserPageShoppingMall, + 'UserPageOfficialAccount': instance.UserPageOfficialAccount, + 'IsCheckRemark': instance.IsCheckRemark, + 'IsShowUserPageEquityBtn': instance.IsShowUserPageEquityBtn, + }; diff --git a/lib/bean/art_detail_bean.dart b/lib/bean/art_detail_bean.dart new file mode 100644 index 0000000..f13c50a --- /dev/null +++ b/lib/bean/art_detail_bean.dart @@ -0,0 +1,30 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'art_detail_bean.g.dart'; + +@JsonSerializable() +class ArtDetailBean { + int? Id; + int? UserId; + String? TaskId; + int? TaskLevel; + String? TaskResult; + String? Title; + int? TemplateId; + String? CreateTime; + int? Status; + String? Prompt; + String? UserNickName; + String? UserIocn; + bool? IsUserDrawGallery; + bool? IsMyCollect; + int? SizeTemplateId; + int? DrawState; + + ArtDetailBean(this.Id, this.UserId, this.TaskId, this.TaskLevel, this.TaskResult, this.Title, this.TemplateId, this.CreateTime, this.Status, + this.Prompt, this.UserNickName, this.UserIocn, this.IsUserDrawGallery, this.IsMyCollect, this.SizeTemplateId, this.DrawState); + + factory ArtDetailBean.fromJson(Map json) => _$ArtDetailBeanFromJson(json); + + Map toJson() => _$ArtDetailBeanToJson(this); +} diff --git a/lib/bean/art_detail_bean.g.dart b/lib/bean/art_detail_bean.g.dart new file mode 100644 index 0000000..1c94e1f --- /dev/null +++ b/lib/bean/art_detail_bean.g.dart @@ -0,0 +1,48 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'art_detail_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ArtDetailBean _$ArtDetailBeanFromJson(Map json) { + return ArtDetailBean( + json['Id'] as int?, + json['UserId'] as int?, + json['TaskId'] as String?, + json['TaskLevel'] as int?, + json['TaskResult'] as String?, + json['Title'] as String?, + json['TemplateId'] as int?, + json['CreateTime'] as String?, + json['Status'] as int?, + json['Prompt'] as String?, + json['UserNickName'] as String?, + json['UserIocn'] as String?, + json['IsUserDrawGallery'] as bool?, + json['IsMyCollect'] as bool?, + json['SizeTemplateId'] as int?, + json['DrawState'] as int?, + ); +} + +Map _$ArtDetailBeanToJson(ArtDetailBean instance) => + { + 'Id': instance.Id, + 'UserId': instance.UserId, + 'TaskId': instance.TaskId, + 'TaskLevel': instance.TaskLevel, + 'TaskResult': instance.TaskResult, + 'Title': instance.Title, + 'TemplateId': instance.TemplateId, + 'CreateTime': instance.CreateTime, + 'Status': instance.Status, + 'Prompt': instance.Prompt, + 'UserNickName': instance.UserNickName, + 'UserIocn': instance.UserIocn, + 'IsUserDrawGallery': instance.IsUserDrawGallery, + 'IsMyCollect': instance.IsMyCollect, + 'SizeTemplateId': instance.SizeTemplateId, + 'DrawState': instance.DrawState, + }; diff --git a/lib/bean/create_order_bean.dart b/lib/bean/create_order_bean.dart new file mode 100644 index 0000000..feb2ccd --- /dev/null +++ b/lib/bean/create_order_bean.dart @@ -0,0 +1,15 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'create_order_bean.g.dart'; + +@JsonSerializable() +class CreateOrderBean { + String? OrderCode; + String? OldToken; + + CreateOrderBean(this.OrderCode, this.OldToken); + + factory CreateOrderBean.fromJson(Map json) => _$CreateOrderBeanFromJson(json); + + Map toJson() => _$CreateOrderBeanToJson(this); +} diff --git a/lib/bean/create_order_bean.g.dart b/lib/bean/create_order_bean.g.dart new file mode 100644 index 0000000..df5cab1 --- /dev/null +++ b/lib/bean/create_order_bean.g.dart @@ -0,0 +1,20 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'create_order_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +CreateOrderBean _$CreateOrderBeanFromJson(Map json) { + return CreateOrderBean( + json['OrderCode'] as String?, + json['OldToken'] as String?, + ); +} + +Map _$CreateOrderBeanToJson(CreateOrderBean instance) => + { + 'OrderCode': instance.OrderCode, + 'OldToken': instance.OldToken, + }; diff --git a/lib/bean/draw_template_bean.dart b/lib/bean/draw_template_bean.dart new file mode 100644 index 0000000..d9382f2 --- /dev/null +++ b/lib/bean/draw_template_bean.dart @@ -0,0 +1,18 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'draw_template_bean.g.dart'; + +@JsonSerializable() +class DrawTemplateBean { + int? Id; + String? Title; + String? ImageSmall; + int? Type; + double? Charging; + + DrawTemplateBean(this.Id, this.Title, this.ImageSmall, this.Type, this.Charging); + + factory DrawTemplateBean.fromJson(Map json) => _$DrawTemplateBeanFromJson(json); + + Map toJson() => _$DrawTemplateBeanToJson(this); +} diff --git a/lib/bean/draw_template_bean.g.dart b/lib/bean/draw_template_bean.g.dart new file mode 100644 index 0000000..b48431e --- /dev/null +++ b/lib/bean/draw_template_bean.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'draw_template_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +DrawTemplateBean _$DrawTemplateBeanFromJson(Map json) { + return DrawTemplateBean( + json['Id'] as int?, + json['Title'] as String?, + json['ImageSmall'] as String?, + json['Type'] as int?, + (json['Charging'] as num?)?.toDouble(), + ); +} + +Map _$DrawTemplateBeanToJson(DrawTemplateBean instance) => + { + 'Id': instance.Id, + 'Title': instance.Title, + 'ImageSmall': instance.ImageSmall, + 'Type': instance.Type, + 'Charging': instance.Charging, + }; diff --git a/lib/bean/equity_advert_bean.dart b/lib/bean/equity_advert_bean.dart new file mode 100644 index 0000000..40a0fc6 --- /dev/null +++ b/lib/bean/equity_advert_bean.dart @@ -0,0 +1,17 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'equity_advert_bean.g.dart'; + +@JsonSerializable() +class EquityAdvertBean { + bool? IsDisplay; + int? WatchNum; + int? TotalNum; + + + EquityAdvertBean(this.IsDisplay, this.WatchNum, this.TotalNum); + + factory EquityAdvertBean.fromJson(Map json) => _$EquityAdvertBeanFromJson(json); + + Map toJson() => _$EquityAdvertBeanToJson(this); +} diff --git a/lib/bean/equity_advert_bean.g.dart b/lib/bean/equity_advert_bean.g.dart new file mode 100644 index 0000000..3f81719 --- /dev/null +++ b/lib/bean/equity_advert_bean.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'equity_advert_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +EquityAdvertBean _$EquityAdvertBeanFromJson(Map json) { + return EquityAdvertBean( + json['IsDisplay'] as bool?, + json['WatchNum'] as int?, + json['TotalNum'] as int?, + ); +} + +Map _$EquityAdvertBeanToJson(EquityAdvertBean instance) => + { + 'IsDisplay': instance.IsDisplay, + 'WatchNum': instance.WatchNum, + 'TotalNum': instance.TotalNum, + }; diff --git a/lib/bean/equity_bean.dart b/lib/bean/equity_bean.dart new file mode 100644 index 0000000..5c2762d --- /dev/null +++ b/lib/bean/equity_bean.dart @@ -0,0 +1,20 @@ +import 'package:json_annotation/json_annotation.dart'; + +import 'equity_advert_bean.dart'; +import 'equity_product_bean.dart'; + +part 'equity_bean.g.dart'; + +@JsonSerializable() +class EquityBean { + + EquityAdvertBean? ObjAdvert; + EquityProductBean? ObjProduct; + + + EquityBean(this.ObjAdvert, this.ObjProduct); + + factory EquityBean.fromJson(Map json) => _$EquityBeanFromJson(json); + + Map toJson() => _$EquityBeanToJson(this); +} diff --git a/lib/bean/equity_bean.g.dart b/lib/bean/equity_bean.g.dart new file mode 100644 index 0000000..30d6ec6 --- /dev/null +++ b/lib/bean/equity_bean.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'equity_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +EquityBean _$EquityBeanFromJson(Map json) { + return EquityBean( + json['ObjAdvert'] == null + ? null + : EquityAdvertBean.fromJson(json['ObjAdvert'] as Map), + json['ObjProduct'] == null + ? null + : EquityProductBean.fromJson( + json['ObjProduct'] as Map), + ); +} + +Map _$EquityBeanToJson(EquityBean instance) => + { + 'ObjAdvert': instance.ObjAdvert, + 'ObjProduct': instance.ObjProduct, + }; diff --git a/lib/bean/equity_product_bean.dart b/lib/bean/equity_product_bean.dart new file mode 100644 index 0000000..43ebca7 --- /dev/null +++ b/lib/bean/equity_product_bean.dart @@ -0,0 +1,20 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'equity_product_bean.g.dart'; + +@JsonSerializable() +class EquityProductBean { + String? ProductId; + String? ProductName; + int? ProductNum; + int? ContinuedDay; + double? Price; + double? OriginalPrice; + String? ImageUrl; + + EquityProductBean(this.ProductId, this.ProductName, this.ProductNum, this.ContinuedDay, this.Price, this.OriginalPrice, this.ImageUrl); + + factory EquityProductBean.fromJson(Map json) => _$EquityProductBeanFromJson(json); + + Map toJson() => _$EquityProductBeanToJson(this); +} diff --git a/lib/bean/equity_product_bean.g.dart b/lib/bean/equity_product_bean.g.dart new file mode 100644 index 0000000..cc19b08 --- /dev/null +++ b/lib/bean/equity_product_bean.g.dart @@ -0,0 +1,30 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'equity_product_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +EquityProductBean _$EquityProductBeanFromJson(Map json) { + return EquityProductBean( + json['ProductId'] as String?, + json['ProductName'] as String?, + json['ProductNum'] as int?, + json['ContinuedDay'] as int?, + (json['Price'] as num?)?.toDouble(), + (json['OriginalPrice'] as num?)?.toDouble(), + json['ImageUrl'] as String?, + ); +} + +Map _$EquityProductBeanToJson(EquityProductBean instance) => + { + 'ProductId': instance.ProductId, + 'ProductName': instance.ProductName, + 'ProductNum': instance.ProductNum, + 'ContinuedDay': instance.ContinuedDay, + 'Price': instance.Price, + 'OriginalPrice': instance.OriginalPrice, + 'ImageUrl': instance.ImageUrl, + }; diff --git a/lib/bean/gallery_label_bean.dart b/lib/bean/gallery_label_bean.dart new file mode 100644 index 0000000..5cbf630 --- /dev/null +++ b/lib/bean/gallery_label_bean.dart @@ -0,0 +1,16 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'gallery_label_bean.g.dart'; + +@JsonSerializable() +class GalleryLabelBean { + int? LabelId; + String? LabelName; + bool? IsDefault; + + GalleryLabelBean(this.LabelId, this.LabelName, this.IsDefault); + + factory GalleryLabelBean.fromJson(Map json) => _$GalleryLabelBeanFromJson(json); + + Map toJson() => _$GalleryLabelBeanToJson(this); +} diff --git a/lib/bean/gallery_label_bean.g.dart b/lib/bean/gallery_label_bean.g.dart new file mode 100644 index 0000000..fdd003c --- /dev/null +++ b/lib/bean/gallery_label_bean.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'gallery_label_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +GalleryLabelBean _$GalleryLabelBeanFromJson(Map json) { + return GalleryLabelBean( + json['LabelId'] as int?, + json['LabelName'] as String?, + json['IsDefault'] as bool?, + ); +} + +Map _$GalleryLabelBeanToJson(GalleryLabelBean instance) => + { + 'LabelId': instance.LabelId, + 'LabelName': instance.LabelName, + 'IsDefault': instance.IsDefault, + }; diff --git a/lib/bean/gallery_work_label_bean.dart b/lib/bean/gallery_work_label_bean.dart new file mode 100644 index 0000000..aaed102 --- /dev/null +++ b/lib/bean/gallery_work_label_bean.dart @@ -0,0 +1,16 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'gallery_work_label_bean.g.dart'; + +@JsonSerializable() +class GalleryWorkLabelBean { + int? LabelId; + String? LabelName; + int? LabelOrderId; + + GalleryWorkLabelBean(this.LabelId, this.LabelName, this.LabelOrderId); + + factory GalleryWorkLabelBean.fromJson(Map json) => _$GalleryWorkLabelBeanFromJson(json); + + Map toJson() => _$GalleryWorkLabelBeanToJson(this); +} diff --git a/lib/bean/gallery_work_label_bean.g.dart b/lib/bean/gallery_work_label_bean.g.dart new file mode 100644 index 0000000..32af8f9 --- /dev/null +++ b/lib/bean/gallery_work_label_bean.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'gallery_work_label_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +GalleryWorkLabelBean _$GalleryWorkLabelBeanFromJson(Map json) { + return GalleryWorkLabelBean( + json['LabelId'] as int?, + json['LabelName'] as String?, + json['LabelOrderId'] as int?, + ); +} + +Map _$GalleryWorkLabelBeanToJson( + GalleryWorkLabelBean instance) => + { + 'LabelId': instance.LabelId, + 'LabelName': instance.LabelName, + 'LabelOrderId': instance.LabelOrderId, + }; diff --git a/lib/bean/gallery_work_list_bean.dart b/lib/bean/gallery_work_list_bean.dart new file mode 100644 index 0000000..403c871 --- /dev/null +++ b/lib/bean/gallery_work_list_bean.dart @@ -0,0 +1,28 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'gallery_work_list_bean.g.dart'; + +@JsonSerializable() +class GalleryWorkListBean { + String? TaskId; + int? DrawId; + String? ImageUrl; + String? Title; + int? WorksID; + String? UserNickName; + int? UserId; + String? UserIocn; + bool? IsCollect; + int? LikeNum; + String? FavoriteDateTime; + int? Status; + int? IsWorks; + int? IsTalent; + + GalleryWorkListBean(this.TaskId, this.DrawId, this.ImageUrl, this.Title, this.WorksID, this.UserNickName, this.UserId, this.UserIocn, + this.IsCollect, this.LikeNum, this.FavoriteDateTime, this.Status, this.IsWorks, this.IsTalent); + + factory GalleryWorkListBean.fromJson(Map json) => _$GalleryWorkListBeanFromJson(json); + + Map toJson() => _$GalleryWorkListBeanToJson(this); +} diff --git a/lib/bean/gallery_work_list_bean.g.dart b/lib/bean/gallery_work_list_bean.g.dart new file mode 100644 index 0000000..a5380bf --- /dev/null +++ b/lib/bean/gallery_work_list_bean.g.dart @@ -0,0 +1,45 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'gallery_work_list_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +GalleryWorkListBean _$GalleryWorkListBeanFromJson(Map json) { + return GalleryWorkListBean( + json['TaskId'] as String?, + json['DrawId'] as int?, + json['ImageUrl'] as String?, + json['Title'] as String?, + json['WorksID'] as int?, + json['UserNickName'] as String?, + json['UserId'] as int?, + json['UserIocn'] as String?, + json['IsCollect'] as bool?, + json['LikeNum'] as int?, + json['FavoriteDateTime'] as String?, + json['Status'] as int?, + json['IsWorks'] as int?, + json['IsTalent'] as int?, + ); +} + +Map _$GalleryWorkListBeanToJson( + GalleryWorkListBean instance) => + { + 'TaskId': instance.TaskId, + 'DrawId': instance.DrawId, + 'ImageUrl': instance.ImageUrl, + 'Title': instance.Title, + 'WorksID': instance.WorksID, + 'UserNickName': instance.UserNickName, + 'UserId': instance.UserId, + 'UserIocn': instance.UserIocn, + 'IsCollect': instance.IsCollect, + 'LikeNum': instance.LikeNum, + 'FavoriteDateTime': instance.FavoriteDateTime, + 'Status': instance.Status, + 'IsWorks': instance.IsWorks, + 'IsTalent': instance.IsTalent, + }; diff --git a/lib/bean/levitating_ball_bean.dart b/lib/bean/levitating_ball_bean.dart new file mode 100644 index 0000000..62903fc --- /dev/null +++ b/lib/bean/levitating_ball_bean.dart @@ -0,0 +1,20 @@ +import 'package:json_annotation/json_annotation.dart'; + +import 'levitating_ball_pop_bean.dart'; + +part 'levitating_ball_bean.g.dart'; + +@JsonSerializable() +class LevitatingBallBean { + String? name; + int? ResType; + String? ResId; + String? ImageUrl; + LevitatingBallPopBean? Popup; + + LevitatingBallBean(this.name, this.ResType, this.ResId, this.ImageUrl, this.Popup); + + factory LevitatingBallBean.fromJson(Map json) => _$LevitatingBallBeanFromJson(json); + + Map toJson() => _$LevitatingBallBeanToJson(this); +} diff --git a/lib/bean/levitating_ball_bean.g.dart b/lib/bean/levitating_ball_bean.g.dart new file mode 100644 index 0000000..99d97be --- /dev/null +++ b/lib/bean/levitating_ball_bean.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'levitating_ball_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LevitatingBallBean _$LevitatingBallBeanFromJson(Map json) { + return LevitatingBallBean( + json['name'] as String?, + json['ResType'] as int?, + json['ResId'] as String?, + json['ImageUrl'] as String?, + json['Popup'] == null + ? null + : LevitatingBallPopBean.fromJson(json['Popup'] as Map), + ); +} + +Map _$LevitatingBallBeanToJson(LevitatingBallBean instance) => + { + 'name': instance.name, + 'ResType': instance.ResType, + 'ResId': instance.ResId, + 'ImageUrl': instance.ImageUrl, + 'Popup': instance.Popup, + }; diff --git a/lib/bean/levitating_ball_pop_bean.dart b/lib/bean/levitating_ball_pop_bean.dart new file mode 100644 index 0000000..7728ca4 --- /dev/null +++ b/lib/bean/levitating_ball_pop_bean.dart @@ -0,0 +1,21 @@ +import 'package:aiplot/bean/pic_info_bean.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'levitating_ball_pop_bean.g.dart'; + +@JsonSerializable() +class LevitatingBallPopBean { + String? Image; + int? PopoutType; + String? Text; + PicInfoBean? BgPicInfo; + PicInfoBean? BtOKInfo; + PicInfoBean? BtCloseInfo; + PicInfoBean? ContentInfo; + + LevitatingBallPopBean(this.Image, this.PopoutType, this.Text, this.BgPicInfo, this.BtOKInfo, this.BtCloseInfo, this.ContentInfo); + + factory LevitatingBallPopBean.fromJson(Map json) => _$LevitatingBallPopBeanFromJson(json); + + Map toJson() => _$LevitatingBallPopBeanToJson(this); +} diff --git a/lib/bean/levitating_ball_pop_bean.g.dart b/lib/bean/levitating_ball_pop_bean.g.dart new file mode 100644 index 0000000..735bd61 --- /dev/null +++ b/lib/bean/levitating_ball_pop_bean.g.dart @@ -0,0 +1,40 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'levitating_ball_pop_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LevitatingBallPopBean _$LevitatingBallPopBeanFromJson( + Map json) { + return LevitatingBallPopBean( + json['Image'] as String?, + json['PopoutType'] as int?, + json['Text'] as String?, + json['BgPicInfo'] == null + ? null + : PicInfoBean.fromJson(json['BgPicInfo'] as Map), + json['BtOKInfo'] == null + ? null + : PicInfoBean.fromJson(json['BtOKInfo'] as Map), + json['BtCloseInfo'] == null + ? null + : PicInfoBean.fromJson(json['BtCloseInfo'] as Map), + json['ContentInfo'] == null + ? null + : PicInfoBean.fromJson(json['ContentInfo'] as Map), + ); +} + +Map _$LevitatingBallPopBeanToJson( + LevitatingBallPopBean instance) => + { + 'Image': instance.Image, + 'PopoutType': instance.PopoutType, + 'Text': instance.Text, + 'BgPicInfo': instance.BgPicInfo, + 'BtOKInfo': instance.BtOKInfo, + 'BtCloseInfo': instance.BtCloseInfo, + 'ContentInfo': instance.ContentInfo, + }; diff --git a/lib/bean/login_bean.dart b/lib/bean/login_bean.dart new file mode 100644 index 0000000..ebf6b6f --- /dev/null +++ b/lib/bean/login_bean.dart @@ -0,0 +1,17 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'login_bean.g.dart'; + +@JsonSerializable() +class LoginBean { + int? UserId; + String? UserName; + String? Token; + + + LoginBean(this.UserId, this.UserName, this.Token); + + factory LoginBean.fromJson(Map json) => _$LoginBeanFromJson(json); + + Map toJson() => _$LoginBeanToJson(this); +} diff --git a/lib/bean/login_bean.g.dart b/lib/bean/login_bean.g.dart new file mode 100644 index 0000000..320859a --- /dev/null +++ b/lib/bean/login_bean.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'login_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LoginBean _$LoginBeanFromJson(Map json) { + return LoginBean( + json['UserId'] as int?, + json['UserName'] as String?, + json['Token'] as String?, + ); +} + +Map _$LoginBeanToJson(LoginBean instance) => { + 'UserId': instance.UserId, + 'UserName': instance.UserName, + 'Token': instance.Token, + }; diff --git a/lib/bean/me_bean.dart b/lib/bean/me_bean.dart new file mode 100644 index 0000000..eac0709 --- /dev/null +++ b/lib/bean/me_bean.dart @@ -0,0 +1,21 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'me_bean.g.dart'; + +@JsonSerializable() +class MeBean { + int? Id; + String? TaskId; + String? OutputUri; + String? CreatTime; + String? UpdateTime; + String? InputParams; + String? Title; + bool? IsCheck; + + MeBean(this.Id, this.TaskId, this.OutputUri, this.CreatTime, this.UpdateTime, this.InputParams, this.Title, this.IsCheck); + + factory MeBean.fromJson(Map json) => _$MeBeanFromJson(json); + + Map toJson() => _$MeBeanToJson(this); +} diff --git a/lib/bean/me_bean.g.dart b/lib/bean/me_bean.g.dart new file mode 100644 index 0000000..144a6fa --- /dev/null +++ b/lib/bean/me_bean.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'me_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +MeBean _$MeBeanFromJson(Map json) { + return MeBean( + json['Id'] as int?, + json['TaskId'] as String?, + json['OutputUri'] as String?, + json['CreatTime'] as String?, + json['UpdateTime'] as String?, + json['InputParams'] as String?, + json['Title'] as String?, + json['IsCheck'] as bool?, + ); +} + +Map _$MeBeanToJson(MeBean instance) => { + 'Id': instance.Id, + 'TaskId': instance.TaskId, + 'OutputUri': instance.OutputUri, + 'CreatTime': instance.CreatTime, + 'UpdateTime': instance.UpdateTime, + 'InputParams': instance.InputParams, + 'Title': instance.Title, + 'IsCheck': instance.IsCheck, + }; diff --git a/lib/bean/pic_info_bean.dart b/lib/bean/pic_info_bean.dart new file mode 100644 index 0000000..df6b713 --- /dev/null +++ b/lib/bean/pic_info_bean.dart @@ -0,0 +1,18 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'pic_info_bean.g.dart'; + +@JsonSerializable() +class PicInfoBean { + String? Pic; + dynamic PosX; + dynamic PosY; + dynamic W; + dynamic H; + + PicInfoBean(this.Pic, this.PosX, this.PosY, this.W, this.H); + + factory PicInfoBean.fromJson(Map json) => _$PicInfoBeanFromJson(json); + + Map toJson() => _$PicInfoBeanToJson(this); +} diff --git a/lib/bean/pic_info_bean.g.dart b/lib/bean/pic_info_bean.g.dart new file mode 100644 index 0000000..7111648 --- /dev/null +++ b/lib/bean/pic_info_bean.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'pic_info_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PicInfoBean _$PicInfoBeanFromJson(Map json) { + return PicInfoBean( + json['Pic'] as String?, + json['PosX'], + json['PosY'], + json['W'], + json['H'], + ); +} + +Map _$PicInfoBeanToJson(PicInfoBean instance) => + { + 'Pic': instance.Pic, + 'PosX': instance.PosX, + 'PosY': instance.PosY, + 'W': instance.W, + 'H': instance.H, + }; diff --git a/lib/bean/popout_bean.dart b/lib/bean/popout_bean.dart new file mode 100644 index 0000000..f242e5f --- /dev/null +++ b/lib/bean/popout_bean.dart @@ -0,0 +1,23 @@ +import 'package:aiplot/bean/pic_info_bean.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'popout_bean.g.dart'; + +@JsonSerializable() +class PopoutBean { + int? PopoutType; + String? PopoutId; + String? Image; + String? Text; + int? AdId; + PicInfoBean? BgPicInfo; + PicInfoBean? BtOKInfo; + PicInfoBean? BtCloseInfo; + PicInfoBean? ContentInfo; + + PopoutBean(this.PopoutType, this.PopoutId, this.Image, this.Text, this.AdId, this.BgPicInfo, this.BtOKInfo, this.BtCloseInfo, this.ContentInfo); + + factory PopoutBean.fromJson(Map json) => _$PopoutBeanFromJson(json); + + Map toJson() => _$PopoutBeanToJson(this); +} diff --git a/lib/bean/popout_bean.g.dart b/lib/bean/popout_bean.g.dart new file mode 100644 index 0000000..7a8bfdd --- /dev/null +++ b/lib/bean/popout_bean.g.dart @@ -0,0 +1,42 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'popout_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PopoutBean _$PopoutBeanFromJson(Map json) { + return PopoutBean( + json['PopoutType'] as int?, + json['PopoutId'] as String?, + json['Image'] as String?, + json['Text'] as String?, + json['AdId'] as int?, + json['BgPicInfo'] == null + ? null + : PicInfoBean.fromJson(json['BgPicInfo'] as Map), + json['BtOKInfo'] == null + ? null + : PicInfoBean.fromJson(json['BtOKInfo'] as Map), + json['BtCloseInfo'] == null + ? null + : PicInfoBean.fromJson(json['BtCloseInfo'] as Map), + json['ContentInfo'] == null + ? null + : PicInfoBean.fromJson(json['ContentInfo'] as Map), + ); +} + +Map _$PopoutBeanToJson(PopoutBean instance) => + { + 'PopoutType': instance.PopoutType, + 'PopoutId': instance.PopoutId, + 'Image': instance.Image, + 'Text': instance.Text, + 'AdId': instance.AdId, + 'BgPicInfo': instance.BgPicInfo, + 'BtOKInfo': instance.BtOKInfo, + 'BtCloseInfo': instance.BtCloseInfo, + 'ContentInfo': instance.ContentInfo, + }; diff --git a/lib/bean/product_bean.dart b/lib/bean/product_bean.dart new file mode 100644 index 0000000..b8e3eca --- /dev/null +++ b/lib/bean/product_bean.dart @@ -0,0 +1,20 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'product_bean.g.dart'; + +@JsonSerializable() +class ProductBean { + String? ProductId; + String? ProductName; + int? ProductNum; + int? ContinuedDay; + double? Price; + double? OriginalPrice; + String? ImageUrl; + + ProductBean(this.ProductId, this.ProductName, this.ProductNum, this.ContinuedDay, this.Price, this.OriginalPrice, this.ImageUrl); + + factory ProductBean.fromJson(Map json) => _$ProductBeanFromJson(json); + + Map toJson() => _$ProductBeanToJson(this); +} diff --git a/lib/bean/product_bean.g.dart b/lib/bean/product_bean.g.dart new file mode 100644 index 0000000..740594f --- /dev/null +++ b/lib/bean/product_bean.g.dart @@ -0,0 +1,30 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'product_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ProductBean _$ProductBeanFromJson(Map json) { + return ProductBean( + json['ProductId'] as String?, + json['ProductName'] as String?, + json['ProductNum'] as int?, + json['ContinuedDay'] as int?, + (json['Price'] as num?)?.toDouble(), + (json['OriginalPrice'] as num?)?.toDouble(), + json['ImageUrl'] as String?, + ); +} + +Map _$ProductBeanToJson(ProductBean instance) => + { + 'ProductId': instance.ProductId, + 'ProductName': instance.ProductName, + 'ProductNum': instance.ProductNum, + 'ContinuedDay': instance.ContinuedDay, + 'Price': instance.Price, + 'OriginalPrice': instance.OriginalPrice, + 'ImageUrl': instance.ImageUrl, + }; diff --git a/lib/bean/progress_bean.dart b/lib/bean/progress_bean.dart new file mode 100644 index 0000000..6879bce --- /dev/null +++ b/lib/bean/progress_bean.dart @@ -0,0 +1,19 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'progress_bean.g.dart'; + +@JsonSerializable() +class ProgressBean { + String? TaskId; + String? CreateTime; + String? UpdateTime; + String? ServerUri; + int? TaskPercent; + String? TaskResponse; + + ProgressBean(this.TaskId, this.CreateTime, this.UpdateTime, this.ServerUri, this.TaskPercent, this.TaskResponse); + + factory ProgressBean.fromJson(Map json) => _$ProgressBeanFromJson(json); + + Map toJson() => _$ProgressBeanToJson(this); +} diff --git a/lib/bean/progress_bean.g.dart b/lib/bean/progress_bean.g.dart new file mode 100644 index 0000000..8d3620d --- /dev/null +++ b/lib/bean/progress_bean.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'progress_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ProgressBean _$ProgressBeanFromJson(Map json) { + return ProgressBean( + json['TaskId'] as String?, + json['CreateTime'] as String?, + json['UpdateTime'] as String?, + json['ServerUri'] as String?, + json['TaskPercent'] as int?, + json['TaskResponse'] as String?, + ); +} + +Map _$ProgressBeanToJson(ProgressBean instance) => + { + 'TaskId': instance.TaskId, + 'CreateTime': instance.CreateTime, + 'UpdateTime': instance.UpdateTime, + 'ServerUri': instance.ServerUri, + 'TaskPercent': instance.TaskPercent, + 'TaskResponse': instance.TaskResponse, + }; diff --git a/lib/bean/recommender_bean.dart b/lib/bean/recommender_bean.dart new file mode 100644 index 0000000..49eb846 --- /dev/null +++ b/lib/bean/recommender_bean.dart @@ -0,0 +1,18 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'recommender_bean.g.dart'; + +@JsonSerializable() +class RecommenderBean { + int? UserId; + String? NickName; + String? UserIconUrl; + int? UserFollow; + String? CreateTime; + + RecommenderBean(this.UserId, this.NickName, this.UserIconUrl, this.UserFollow, this.CreateTime); + + factory RecommenderBean.fromJson(Map json) => _$RecommenderBeanFromJson(json); + + Map toJson() => _$RecommenderBeanToJson(this); +} diff --git a/lib/bean/recommender_bean.g.dart b/lib/bean/recommender_bean.g.dart new file mode 100644 index 0000000..17ac4c0 --- /dev/null +++ b/lib/bean/recommender_bean.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'recommender_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +RecommenderBean _$RecommenderBeanFromJson(Map json) { + return RecommenderBean( + json['UserId'] as int?, + json['NickName'] as String?, + json['UserIconUrl'] as String?, + json['UserFollow'] as int?, + json['CreateTime'] as String?, + ); +} + +Map _$RecommenderBeanToJson(RecommenderBean instance) => + { + 'UserId': instance.UserId, + 'NickName': instance.NickName, + 'UserIconUrl': instance.UserIconUrl, + 'UserFollow': instance.UserFollow, + 'CreateTime': instance.CreateTime, + }; diff --git a/lib/bean/server_bean.dart b/lib/bean/server_bean.dart new file mode 100644 index 0000000..10dc95d --- /dev/null +++ b/lib/bean/server_bean.dart @@ -0,0 +1,15 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'server_bean.g.dart'; + +@JsonSerializable() +class ServerBean { + String? HissAiApiUrl; + String? HissAiPayUrl; + + ServerBean(this.HissAiApiUrl,this.HissAiPayUrl); + + factory ServerBean.fromJson(Map json) => _$ServerBeanFromJson(json); + + Map toJson() => _$ServerBeanToJson(this); +} diff --git a/lib/bean/server_bean.g.dart b/lib/bean/server_bean.g.dart new file mode 100644 index 0000000..b7848a6 --- /dev/null +++ b/lib/bean/server_bean.g.dart @@ -0,0 +1,20 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'server_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ServerBean _$ServerBeanFromJson(Map json) { + return ServerBean( + json['HissAiApiUrl'] as String?, + json['HissAiPayUrl'] as String?, + ); +} + +Map _$ServerBeanToJson(ServerBean instance) => + { + 'HissAiApiUrl': instance.HissAiApiUrl, + 'HissAiPayUrl': instance.HissAiPayUrl, + }; diff --git a/lib/bean/text_to_image_bean.dart b/lib/bean/text_to_image_bean.dart new file mode 100644 index 0000000..be9dee8 --- /dev/null +++ b/lib/bean/text_to_image_bean.dart @@ -0,0 +1,19 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'text_to_image_bean.g.dart'; + +@JsonSerializable() +class TextToImageBean { + int? SeqId; + String? TaskId; + int? TaskLevel; + int? Status; + int? TaskPercent; + String? TaskResult; + + TextToImageBean(this.SeqId, this.TaskId, this.TaskLevel, this.Status, this.TaskPercent, this.TaskResult); + + factory TextToImageBean.fromJson(Map json) => _$TextToImageBeanFromJson(json); + + Map toJson() => _$TextToImageBeanToJson(this); +} diff --git a/lib/bean/text_to_image_bean.g.dart b/lib/bean/text_to_image_bean.g.dart new file mode 100644 index 0000000..e45374c --- /dev/null +++ b/lib/bean/text_to_image_bean.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'text_to_image_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +TextToImageBean _$TextToImageBeanFromJson(Map json) { + return TextToImageBean( + json['SeqId'] as int?, + json['TaskId'] as String?, + json['TaskLevel'] as int?, + json['Status'] as int?, + json['TaskPercent'] as int?, + json['TaskResult'] as String?, + ); +} + +Map _$TextToImageBeanToJson(TextToImageBean instance) => + { + 'SeqId': instance.SeqId, + 'TaskId': instance.TaskId, + 'TaskLevel': instance.TaskLevel, + 'Status': instance.Status, + 'TaskPercent': instance.TaskPercent, + 'TaskResult': instance.TaskResult, + }; diff --git a/lib/bean/user_ad_num_bean.dart b/lib/bean/user_ad_num_bean.dart new file mode 100644 index 0000000..efdebf3 --- /dev/null +++ b/lib/bean/user_ad_num_bean.dart @@ -0,0 +1,17 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'user_ad_num_bean.g.dart'; + +@JsonSerializable() +class UserAdNumBean { + int? UsedRewardCount; + int? TotalRewardCount; + String? BackgroundImage; + + + UserAdNumBean(this.UsedRewardCount, this.TotalRewardCount, this.BackgroundImage); + + factory UserAdNumBean.fromJson(Map json) => _$UserAdNumBeanFromJson(json); + + Map toJson() => _$UserAdNumBeanToJson(this); +} diff --git a/lib/bean/user_ad_num_bean.g.dart b/lib/bean/user_ad_num_bean.g.dart new file mode 100644 index 0000000..66de49f --- /dev/null +++ b/lib/bean/user_ad_num_bean.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_ad_num_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserAdNumBean _$UserAdNumBeanFromJson(Map json) { + return UserAdNumBean( + json['UsedRewardCount'] as int?, + json['TotalRewardCount'] as int?, + json['BackgroundImage'] as String?, + ); +} + +Map _$UserAdNumBeanToJson(UserAdNumBean instance) => + { + 'UsedRewardCount': instance.UsedRewardCount, + 'TotalRewardCount': instance.TotalRewardCount, + 'BackgroundImage': instance.BackgroundImage, + }; diff --git a/lib/bean/user_bean.dart b/lib/bean/user_bean.dart new file mode 100644 index 0000000..cd3e501 --- /dev/null +++ b/lib/bean/user_bean.dart @@ -0,0 +1,16 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'user_bean.g.dart'; + +@JsonSerializable() +class UserBean { + String? userId; + String? token; + String? userToken; + + UserBean(this.userId, this.token, this.userToken); + + factory UserBean.fromJson(Map json) => _$UserBeanFromJson(json); + + Map toJson() => _$UserBeanToJson(this); +} diff --git a/lib/bean/user_bean.g.dart b/lib/bean/user_bean.g.dart new file mode 100644 index 0000000..d4811fb --- /dev/null +++ b/lib/bean/user_bean.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserBean _$UserBeanFromJson(Map json) { + return UserBean( + json['userId'] as String?, + json['token'] as String?, + json['userToken'] as String?, + ); +} + +Map _$UserBeanToJson(UserBean instance) => { + 'userId': instance.userId, + 'token': instance.token, + 'userToken': instance.userToken, + }; diff --git a/lib/bean/user_center_bean.dart b/lib/bean/user_center_bean.dart new file mode 100644 index 0000000..6c34a08 --- /dev/null +++ b/lib/bean/user_center_bean.dart @@ -0,0 +1,24 @@ +import 'package:aiplot/bean/works_list_bean.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'user_center_bean.g.dart'; + +@JsonSerializable() +class UserCenterBean { + String? UserIconUrl; + int? UserId; + String? NickName; + int? LikeNum; + int? TalentId; + List? WorksList; + int? IsTalentUser; + bool? IsFollow; + int? FansNum; + + UserCenterBean( + this.UserIconUrl, this.UserId, this.NickName, this.LikeNum, this.TalentId, this.WorksList, this.IsTalentUser, this.IsFollow, this.FansNum); + + factory UserCenterBean.fromJson(Map json) => _$UserCenterBeanFromJson(json); + + Map toJson() => _$UserCenterBeanToJson(this); +} diff --git a/lib/bean/user_center_bean.g.dart b/lib/bean/user_center_bean.g.dart new file mode 100644 index 0000000..0d73937 --- /dev/null +++ b/lib/bean/user_center_bean.g.dart @@ -0,0 +1,36 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_center_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserCenterBean _$UserCenterBeanFromJson(Map json) { + return UserCenterBean( + json['UserIconUrl'] as String?, + json['UserId'] as int?, + json['NickName'] as String?, + json['LikeNum'] as int?, + json['TalentId'] as int?, + (json['WorksList'] as List?) + ?.map((e) => WorksListBean.fromJson(e as Map)) + .toList(), + json['IsTalentUser'] as int?, + json['IsFollow'] as bool?, + json['FansNum'] as int?, + ); +} + +Map _$UserCenterBeanToJson(UserCenterBean instance) => + { + 'UserIconUrl': instance.UserIconUrl, + 'UserId': instance.UserId, + 'NickName': instance.NickName, + 'LikeNum': instance.LikeNum, + 'TalentId': instance.TalentId, + 'WorksList': instance.WorksList, + 'IsTalentUser': instance.IsTalentUser, + 'IsFollow': instance.IsFollow, + 'FansNum': instance.FansNum, + }; diff --git a/lib/bean/user_draw_bean.dart b/lib/bean/user_draw_bean.dart new file mode 100644 index 0000000..ba3f35f --- /dev/null +++ b/lib/bean/user_draw_bean.dart @@ -0,0 +1,25 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'user_draw_bean.g.dart'; + +@JsonSerializable() +class UserDrawBean { + String? TaskId; + int? DrawId; + String? ImageUrl; + String? Title; + String? UserNickName; + String? UserIocn; + bool? IsCollect; + int? CollectNumber; + String? FavoriteDateTime; + int? Status; + bool? IsCheck; + + UserDrawBean(this.TaskId, this.DrawId, this.ImageUrl, this.Title, this.UserNickName, this.UserIocn, this.IsCollect, this.CollectNumber, + this.FavoriteDateTime,this.Status,this.IsCheck); + + factory UserDrawBean.fromJson(Map json) => _$UserDrawBeanFromJson(json); + + Map toJson() => _$UserDrawBeanToJson(this); +} diff --git a/lib/bean/user_draw_bean.g.dart b/lib/bean/user_draw_bean.g.dart new file mode 100644 index 0000000..514ebb7 --- /dev/null +++ b/lib/bean/user_draw_bean.g.dart @@ -0,0 +1,38 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_draw_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserDrawBean _$UserDrawBeanFromJson(Map json) { + return UserDrawBean( + json['TaskId'] as String?, + json['DrawId'] as int?, + json['ImageUrl'] as String?, + json['Title'] as String?, + json['UserNickName'] as String?, + json['UserIocn'] as String?, + json['IsCollect'] as bool?, + json['CollectNumber'] as int?, + json['FavoriteDateTime'] as String?, + json['Status'] as int?, + json['IsCheck'] as bool?, + ); +} + +Map _$UserDrawBeanToJson(UserDrawBean instance) => + { + 'TaskId': instance.TaskId, + 'DrawId': instance.DrawId, + 'ImageUrl': instance.ImageUrl, + 'Title': instance.Title, + 'UserNickName': instance.UserNickName, + 'UserIocn': instance.UserIocn, + 'IsCollect': instance.IsCollect, + 'CollectNumber': instance.CollectNumber, + 'FavoriteDateTime': instance.FavoriteDateTime, + 'Status': instance.Status, + 'IsCheck': instance.IsCheck, + }; diff --git a/lib/bean/user_info_bean.dart b/lib/bean/user_info_bean.dart new file mode 100644 index 0000000..31f8922 --- /dev/null +++ b/lib/bean/user_info_bean.dart @@ -0,0 +1,27 @@ +import 'package:aiplot/bean/user_ad_num_bean.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'user_info_bean.g.dart'; + +@JsonSerializable() +class UserInfoBean { + int? UserId; + String? NickName; + String? UserIconUrl; + double? Currency; + double? TemporaryCurrency; + double? AllCurrency; + int? VipType; + int? CollectNumber; + int? SaveImageNumber; + UserAdNumBean? UserAdLog; + String? InvitationCode; + String? InvitationCodeImageUrl; + + UserInfoBean(this.UserId, this.NickName, this.UserIconUrl, this.Currency, this.TemporaryCurrency, this.AllCurrency, this.VipType, + this.CollectNumber, this.SaveImageNumber, this.UserAdLog, this.InvitationCode, this.InvitationCodeImageUrl); + + factory UserInfoBean.fromJson(Map json) => _$UserInfoBeanFromJson(json); + + Map toJson() => _$UserInfoBeanToJson(this); +} diff --git a/lib/bean/user_info_bean.g.dart b/lib/bean/user_info_bean.g.dart new file mode 100644 index 0000000..2669605 --- /dev/null +++ b/lib/bean/user_info_bean.g.dart @@ -0,0 +1,42 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_info_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserInfoBean _$UserInfoBeanFromJson(Map json) { + return UserInfoBean( + json['UserId'] as int?, + json['NickName'] as String?, + json['UserIconUrl'] as String?, + (json['Currency'] as num?)?.toDouble(), + (json['TemporaryCurrency'] as num?)?.toDouble(), + (json['AllCurrency'] as num?)?.toDouble(), + json['VipType'] as int?, + json['CollectNumber'] as int?, + json['SaveImageNumber'] as int?, + json['UserAdLog'] == null + ? null + : UserAdNumBean.fromJson(json['UserAdLog'] as Map), + json['InvitationCode'] as String?, + json['InvitationCodeImageUrl'] as String?, + ); +} + +Map _$UserInfoBeanToJson(UserInfoBean instance) => + { + 'UserId': instance.UserId, + 'NickName': instance.NickName, + 'UserIconUrl': instance.UserIconUrl, + 'Currency': instance.Currency, + 'TemporaryCurrency': instance.TemporaryCurrency, + 'AllCurrency': instance.AllCurrency, + 'VipType': instance.VipType, + 'CollectNumber': instance.CollectNumber, + 'SaveImageNumber': instance.SaveImageNumber, + 'UserAdLog': instance.UserAdLog, + 'InvitationCode': instance.InvitationCode, + 'InvitationCodeImageUrl': instance.InvitationCodeImageUrl, + }; diff --git a/lib/bean/works_detail_bean.dart b/lib/bean/works_detail_bean.dart new file mode 100644 index 0000000..b71eb0c --- /dev/null +++ b/lib/bean/works_detail_bean.dart @@ -0,0 +1,71 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'works_detail_bean.g.dart'; + +@JsonSerializable() +class WorksDetailBean { + int? DrawId; + int? Id; + int? UserId; + int? AppId; + String? TaskId; + int? TaskLevel; + String? TaskResult; + String? TaskResultWatermark; + String? TaskResultResize; + String? Title; + int? TemplateId; + int? TemplateLabelId; + int? FollowDrawId; + String? CreateTime; + int? Status; + String? Prompt; + String? UserNickName; + String? UserIocn; + bool? IsUserDrawGallery; + bool? IsMyCollect; + int? SizeTemplateId; + int? DrawState; + int? LikeNum; + bool? IsMyLike; + bool? IsFollow; + bool? IsTalentWork; + bool? IsCurrentImgDetails; + int? ConsumeCurrency; + String? DrawLabel; + + WorksDetailBean( + this.DrawId, + this.Id, + this.UserId, + this.AppId, + this.TaskId, + this.TaskLevel, + this.TaskResult, + this.TaskResultWatermark, + this.TaskResultResize, + this.Title, + this.TemplateId, + this.TemplateLabelId, + this.FollowDrawId, + this.CreateTime, + this.Status, + this.Prompt, + this.UserNickName, + this.UserIocn, + this.IsUserDrawGallery, + this.IsMyCollect, + this.SizeTemplateId, + this.DrawState, + this.LikeNum, + this.IsMyLike, + this.IsFollow, + this.IsTalentWork, + this.IsCurrentImgDetails, + this.ConsumeCurrency, + this.DrawLabel); + + factory WorksDetailBean.fromJson(Map json) => _$WorksDetailBeanFromJson(json); + + Map toJson() => _$WorksDetailBeanToJson(this); +} diff --git a/lib/bean/works_detail_bean.g.dart b/lib/bean/works_detail_bean.g.dart new file mode 100644 index 0000000..ea779e8 --- /dev/null +++ b/lib/bean/works_detail_bean.g.dart @@ -0,0 +1,74 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'works_detail_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WorksDetailBean _$WorksDetailBeanFromJson(Map json) { + return WorksDetailBean( + json['DrawId'] as int?, + json['Id'] as int?, + json['UserId'] as int?, + json['AppId'] as int?, + json['TaskId'] as String?, + json['TaskLevel'] as int?, + json['TaskResult'] as String?, + json['TaskResultWatermark'] as String?, + json['TaskResultResize'] as String?, + json['Title'] as String?, + json['TemplateId'] as int?, + json['TemplateLabelId'] as int?, + json['FollowDrawId'] as int?, + json['CreateTime'] as String?, + json['Status'] as int?, + json['Prompt'] as String?, + json['UserNickName'] as String?, + json['UserIocn'] as String?, + json['IsUserDrawGallery'] as bool?, + json['IsMyCollect'] as bool?, + json['SizeTemplateId'] as int?, + json['DrawState'] as int?, + json['LikeNum'] as int?, + json['IsMyLike'] as bool?, + json['IsFollow'] as bool?, + json['IsTalentWork'] as bool?, + json['IsCurrentImgDetails'] as bool?, + json['ConsumeCurrency'] as int?, + json['DrawLabel'] as String?, + ); +} + +Map _$WorksDetailBeanToJson(WorksDetailBean instance) => + { + 'DrawId': instance.DrawId, + 'Id': instance.Id, + 'UserId': instance.UserId, + 'AppId': instance.AppId, + 'TaskId': instance.TaskId, + 'TaskLevel': instance.TaskLevel, + 'TaskResult': instance.TaskResult, + 'TaskResultWatermark': instance.TaskResultWatermark, + 'TaskResultResize': instance.TaskResultResize, + 'Title': instance.Title, + 'TemplateId': instance.TemplateId, + 'TemplateLabelId': instance.TemplateLabelId, + 'FollowDrawId': instance.FollowDrawId, + 'CreateTime': instance.CreateTime, + 'Status': instance.Status, + 'Prompt': instance.Prompt, + 'UserNickName': instance.UserNickName, + 'UserIocn': instance.UserIocn, + 'IsUserDrawGallery': instance.IsUserDrawGallery, + 'IsMyCollect': instance.IsMyCollect, + 'SizeTemplateId': instance.SizeTemplateId, + 'DrawState': instance.DrawState, + 'LikeNum': instance.LikeNum, + 'IsMyLike': instance.IsMyLike, + 'IsFollow': instance.IsFollow, + 'IsTalentWork': instance.IsTalentWork, + 'IsCurrentImgDetails': instance.IsCurrentImgDetails, + 'ConsumeCurrency': instance.ConsumeCurrency, + 'DrawLabel': instance.DrawLabel, + }; diff --git a/lib/bean/works_info_bean.dart b/lib/bean/works_info_bean.dart new file mode 100644 index 0000000..250a2a3 --- /dev/null +++ b/lib/bean/works_info_bean.dart @@ -0,0 +1,61 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'works_info_bean.g.dart'; + +@JsonSerializable() +class WorksInfoBean { + int Id; + int DrawId; + int WorksId; + int UserId; + int AppId; + String BossId; + String TaskId; + String TaskResult; + String TaskResultWatermark; + String TaskResultResize; + String Title; + int TemplateId; + int TemplateLabelId; + String CreateTime; + int Status; + String Prompt; + String UserNickName; + String UserIocn; + bool IsMyLike; + int SizeTemplateId; + int LikeNum; + bool IsGalleyWork; + bool IsTalentWork; + bool IsFollow; + + WorksInfoBean( + this.Id, + this.DrawId, + this.WorksId, + this.UserId, + this.AppId, + this.BossId, + this.TaskId, + this.TaskResult, + this.TaskResultWatermark, + this.TaskResultResize, + this.Title, + this.TemplateId, + this.TemplateLabelId, + this.CreateTime, + this.Status, + this.Prompt, + this.UserNickName, + this.UserIocn, + this.IsMyLike, + this.SizeTemplateId, + this.LikeNum, + this.IsGalleyWork, + this.IsTalentWork, + this.IsFollow); + + factory WorksInfoBean.fromJson(Map json) => _$WorksInfoBeanFromJson(json); + + Map toJson() => _$WorksInfoBeanToJson(this); +} diff --git a/lib/bean/works_info_bean.g.dart b/lib/bean/works_info_bean.g.dart new file mode 100644 index 0000000..ee8d0e3 --- /dev/null +++ b/lib/bean/works_info_bean.g.dart @@ -0,0 +1,64 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'works_info_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WorksInfoBean _$WorksInfoBeanFromJson(Map json) { + return WorksInfoBean( + json['Id'] as int, + json['DrawId'] as int, + json['WorksId'] as int, + json['UserId'] as int, + json['AppId'] as int, + json['BossId'] as String, + json['TaskId'] as String, + json['TaskResult'] as String, + json['TaskResultWatermark'] as String, + json['TaskResultResize'] as String, + json['Title'] as String, + json['TemplateId'] as int, + json['TemplateLabelId'] as int, + json['CreateTime'] as String, + json['Status'] as int, + json['Prompt'] as String, + json['UserNickName'] as String, + json['UserIocn'] as String, + json['IsMyLike'] as bool, + json['SizeTemplateId'] as int, + json['LikeNum'] as int, + json['IsGalleyWork'] as bool, + json['IsTalentWork'] as bool, + json['IsFollow'] as bool, + ); +} + +Map _$WorksInfoBeanToJson(WorksInfoBean instance) => + { + 'Id': instance.Id, + 'DrawId': instance.DrawId, + 'WorksId': instance.WorksId, + 'UserId': instance.UserId, + 'AppId': instance.AppId, + 'BossId': instance.BossId, + 'TaskId': instance.TaskId, + 'TaskResult': instance.TaskResult, + 'TaskResultWatermark': instance.TaskResultWatermark, + 'TaskResultResize': instance.TaskResultResize, + 'Title': instance.Title, + 'TemplateId': instance.TemplateId, + 'TemplateLabelId': instance.TemplateLabelId, + 'CreateTime': instance.CreateTime, + 'Status': instance.Status, + 'Prompt': instance.Prompt, + 'UserNickName': instance.UserNickName, + 'UserIocn': instance.UserIocn, + 'IsMyLike': instance.IsMyLike, + 'SizeTemplateId': instance.SizeTemplateId, + 'LikeNum': instance.LikeNum, + 'IsGalleyWork': instance.IsGalleyWork, + 'IsTalentWork': instance.IsTalentWork, + 'IsFollow': instance.IsFollow, + }; diff --git a/lib/bean/works_list_bean.dart b/lib/bean/works_list_bean.dart new file mode 100644 index 0000000..ebea46e --- /dev/null +++ b/lib/bean/works_list_bean.dart @@ -0,0 +1,16 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'works_list_bean.g.dart'; + +@JsonSerializable() +class WorksListBean { + int? WorkId; + String? WorkName; + bool? IsSelect; + + WorksListBean(this.WorkId, this.WorkName, this.IsSelect); + + factory WorksListBean.fromJson(Map json) => _$WorksListBeanFromJson(json); + + Map toJson() => _$WorksListBeanToJson(this); +} diff --git a/lib/bean/works_list_bean.g.dart b/lib/bean/works_list_bean.g.dart new file mode 100644 index 0000000..59c175f --- /dev/null +++ b/lib/bean/works_list_bean.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'works_list_bean.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +WorksListBean _$WorksListBeanFromJson(Map json) { + return WorksListBean( + json['WorkId'] as int?, + json['WorkName'] as String?, + json['IsSelect'] as bool?, + ); +} + +Map _$WorksListBeanToJson(WorksListBean instance) => + { + 'WorkId': instance.WorkId, + 'WorkName': instance.WorkName, + 'IsSelect': instance.IsSelect, + }; diff --git a/lib/common/EventBusUtil.dart b/lib/common/EventBusUtil.dart new file mode 100644 index 0000000..b3e6311 --- /dev/null +++ b/lib/common/EventBusUtil.dart @@ -0,0 +1,73 @@ +import 'dart:async'; + +import 'package:event_bus/event_bus.dart'; + +class EventBusUtil { + static EventBus? _eventBus; + + //获取单例 + static EventBus getInstance() { + _eventBus ??= EventBus(); + return _eventBus!; + } + + //返回某事件的订阅者 + static StreamSubscription listen(Function(T event) onData) { + _eventBus ??= EventBus(); + //内部流属于广播模式,可以有多个订阅者 + return _eventBus!.on().listen(onData); + } + + //发送事件 + static void fire(T e) { + _eventBus ??= EventBus(); + _eventBus!.fire(e); + } +} + +abstract class Event {} + +class LoginEvent extends Event { + static int eventIn = 1; + static int eventOut = 0; + final int status; + + LoginEvent(this.status); +} + +class OrderStatusEvent extends Event {} + +class PushStatusEvent extends Event {} + +//导航切换 +class TabBarEvent extends Event { + final int Tab; + + TabBarEvent(this.Tab); +} + +class PhoneLoginBackEvent extends Event { + PhoneLoginBackEvent(); +} + +//导航跳转 +class TabBarJumpEvent extends Event { + int index; + + TabBarJumpEvent(this.index); +} + +//画同款 +class CopyDrawingEvent extends Event { + CopyDrawingEvent(); +} + +//登录完成 +class LoginSuccess extends Event { + LoginSuccess(); +} + +//刷新用户信息 +class RefreshUserdata extends Event { + RefreshUserdata(); +} diff --git a/lib/common/Global.dart b/lib/common/Global.dart new file mode 100644 index 0000000..b379b61 --- /dev/null +++ b/lib/common/Global.dart @@ -0,0 +1,55 @@ + +import 'dart:io'; + +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; + +import '../network/NetworkConfig.dart'; + +const int Environment_Dev = 1; +const int Environment_Pre = 2; +const int Environment_Online = 3; + +class Global { + factory Global() => _getInstance(); + + static Global get instance => _getInstance(); + static Global? _instance; + + Global._internal() { + // 初始化 + } + + static Global _getInstance() { + if (_instance == null) { + _instance = new Global._internal(); + } + return _instance!; + } + + static const method = MethodChannel('samples.flutter.dev/battery'); + + static bool get isRelease => bool.fromEnvironment("dart.vm.product"); + static String? flatform_name; + + static Future initialize() async { + if (!NetworkConfig.isTest) { + NetworkConfig.BASE_URLS = NetworkConfig.BASE_URLS_AI; + } + + if (Platform.isIOS) { + //ios相关代码 + flatform_name = 'iOS'; + } else if (Platform.isAndroid) { + //android相关代码 + flatform_name = 'Android'; + } + WidgetsFlutterBinding.ensureInitialized(); //不加这个强制横/竖屏会报错 + SystemChrome.setPreferredOrientations([ + // 强制竖屏 + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown + ]); + Global a = Global.instance; + } +} diff --git a/lib/common/TabUnderLine.dart b/lib/common/TabUnderLine.dart new file mode 100644 index 0000000..cc5c074 --- /dev/null +++ b/lib/common/TabUnderLine.dart @@ -0,0 +1,179 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +// 默认高度从46改为40 +const double _kTabHeight = 50.0; +const double _kTextAndIconTabHeight = 72.0; + +class RoundUnderlineTabIndicator extends Decoration { + /// Create an underline style selected tab indicator. + /// + /// The [borderSide] and [insets] arguments must not be null. + const RoundUnderlineTabIndicator({ + this.borderSide = const BorderSide(width: 2.0, color: Colors.white), + this.insets = EdgeInsets.zero, + }) : assert(borderSide != null), + assert(insets != null); + + /// The color and weight of the horizontal line drawn below the selected tab. + final BorderSide borderSide; + + /// Locates the selected tab's underline relative to the tab's boundary. + /// + /// The [TabBar.indicatorSize] property can be used to define the + /// tab indicator's bounds in terms of its (centered) tab widget with + /// [TabIndicatorSize.label], or the entire tab with [TabIndicatorSize.tab]. + final EdgeInsetsGeometry insets; + + @override + Decoration? lerpFrom(Decoration? a, double t) { + if (a is UnderlineTabIndicator) { + return UnderlineTabIndicator( + borderSide: BorderSide.lerp(a.borderSide, borderSide, t), + insets: EdgeInsetsGeometry.lerp(a.insets, insets, t)!, + ); + } + return super.lerpFrom(a, t); + } + + @override + Decoration? lerpTo(Decoration? b, double t) { + if (b is UnderlineTabIndicator) { + return UnderlineTabIndicator( + borderSide: BorderSide.lerp(borderSide, b.borderSide, t), + insets: EdgeInsetsGeometry.lerp(insets, b.insets, t)!, + ); + } + return super.lerpTo(b, t); + } + + @override + _UnderlinePainter createBoxPainter([ VoidCallback? onChanged ]) { + return _UnderlinePainter(this, onChanged!); + } +} + +class _UnderlinePainter extends BoxPainter { + _UnderlinePainter(this.decoration, VoidCallback onChanged) + : assert(decoration != null), + super(onChanged); + + final RoundUnderlineTabIndicator decoration; + + BorderSide get borderSide => decoration.borderSide; + EdgeInsetsGeometry get insets => decoration.insets; + + Rect _indicatorRectFor(Rect rect, TextDirection textDirection) { + assert(rect != null); + assert(textDirection != null); + final Rect indicator = insets.resolve(textDirection).deflateRect(rect); +// return Rect.fromLTWH( +// indicator.left, +// indicator.bottom - borderSide.width, +// indicator.width, +// borderSide.width, +// ); + //希望的宽度 + double wantWidth = 17; + //取中间坐标 + double cw = (indicator.left + indicator.right) / 2; + return Rect.fromLTWH(cw - wantWidth / 2, + indicator.bottom - borderSide.width, wantWidth, borderSide.width); + } + + @override + void paint(Canvas canvas, Offset offset, ImageConfiguration? configuration) { + assert(configuration != null); + assert(configuration!.size != null); + final Rect rect = offset & configuration!.size!; + final TextDirection? textDirection = configuration.textDirection; + final Rect indicator = _indicatorRectFor(rect!, textDirection!).deflate(borderSide.width / 2.0); +// final Paint paint = borderSide.toPaint()..strokeCap = StrokeCap.square; + // 改为圆角 + final Paint paint = borderSide.toPaint()..strokeCap = StrokeCap.round; + canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint); + } +} + + + + + + +class VgTab extends StatelessWidget { + /// Creates a material design [TabBar] tab. + /// + /// At least one of [text], [icon], and [child] must be non-null. The [text] + /// and [child] arguments must not be used at the same time. + const VgTab({ + Key? key, + this.text, + this.icon, + this.child, + }) : assert(text != null || child != null || icon != null), + assert(!(text != null && null != child)), // TODO(goderbauer): https://github.com/dart-lang/sdk/issues/34180 + super(key: key); + + /// The text to display as the tab's label. + /// + /// Must not be used in combination with [child]. + final String? text; + + /// The widget to be used as the tab's label. + /// + /// Usually a [Text] widget, possibly wrapped in a [Semantics] widget. + /// + /// Must not be used in combination with [text]. + final Widget? child; + + /// An icon to display as the tab's label. + final Widget? icon; + + Widget _buildLabelText() { + return child ?? Text(text!, softWrap: false, overflow: TextOverflow.fade); + } + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMaterial(context)); + + double height; + Widget? label; + if (icon == null) { + height = _kTabHeight; + label = _buildLabelText(); + } else if (text == null && child == null) { + height = _kTabHeight; + label = icon; + } else { + height = _kTextAndIconTabHeight; + label = Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + child: icon, + margin: const EdgeInsets.only(bottom: 10.0), + ), + _buildLabelText(), + ], + ); + } + + return SizedBox( + height: height, + width: 30, + child: Center( + child: label, + widthFactor: 1.0, + ), + ); + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(StringProperty('text', text, defaultValue: null)); + properties.add(DiagnosticsProperty('icon', icon, defaultValue: null)); + } +} \ No newline at end of file diff --git a/lib/common/app_util.dart b/lib/common/app_util.dart new file mode 100644 index 0000000..071bf45 --- /dev/null +++ b/lib/common/app_util.dart @@ -0,0 +1,218 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; + +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_cache_manager/flutter_cache_manager.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:http/http.dart' as http; +import 'package:image_cropper/image_cropper.dart'; +import 'package:image_gallery_saver/image_gallery_saver.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:mime/mime.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class AppUtil { + /// 默认为下载网络图片,如需下载资源图片,需要指定 [isAsset] 为 `true`。 + static Future saveImage(String imageUrl, {bool isAsset = false}) async { + try { + if (imageUrl == null) throw '保存失败,图片不存在!'; + + print(NetworkConfig.systemVersion); + + /// 权限检测 + PermissionStatus storageStatus; + + ///android13及以上版本 "storage" 已废除 图片 视频 音频权限需要分别申请 + if (int.parse(NetworkConfig.systemVersion) >= 13) { + storageStatus = await Permission.photos.status; + } else { + storageStatus = await Permission.storage.status; + } + + if (storageStatus != PermissionStatus.granted) { + if (int.parse(NetworkConfig.systemVersion) >= 13) { + storageStatus = await Permission.photos.request(); + } else { + storageStatus = await Permission.storage.request(); + } + if (storageStatus != PermissionStatus.granted) { + throw '无法存储图片,请先授权!'; + } + } + + /// 保存的图片数据 + Uint8List imageBytes; + + if (isAsset == true) { + /// 保存资源图片 + ByteData bytes = await rootBundle.load(imageUrl); + imageBytes = bytes.buffer.asUint8List(); + } else { + Map map = {}; + + /// 保存网络图片 + CachedNetworkImage image = CachedNetworkImage(imageUrl: imageUrl); + BaseCacheManager manager = image.cacheManager ?? DefaultCacheManager(); + Map headers = image.httpHeaders != null ? image.httpHeaders! : map; + File file = await manager.getSingleFile( + image.imageUrl, + headers: headers, + ); + imageBytes = await file.readAsBytes(); + } + + /// 保存图片 + final result = await ImageGallerySaver.saveImage(imageBytes, quality: 100); + + if (result == null || result == '') throw '图片保存失败'; + + EasyLoading.showToast("Successfully saved"); + } catch (e) { + print(e.toString()); + } + } + + ///保存Widget图片 + static Future saveWidgetImage(ByteData bytes) async { + try { + if (bytes == null) throw '保存失败,图片不存在!'; + + /// 权限检测 + PermissionStatus storageStatus; + + ///android13及以上版本 "storage" 已废除 图片 视频 音频权限需要分别申请 + if (int.parse(NetworkConfig.systemVersion) >= 13) { + storageStatus = await Permission.photos.status; + } else { + storageStatus = await Permission.storage.status; + } + + if (storageStatus != PermissionStatus.granted) { + if (int.parse(NetworkConfig.systemVersion) >= 13) { + storageStatus = await Permission.photos.request(); + } else { + storageStatus = await Permission.storage.request(); + } + + if (storageStatus != PermissionStatus.granted) { + throw '无法存储图片,请先授权!'; + } + } + + Uint8List imageBytes = bytes.buffer.asUint8List(); + + /// 保存图片 + final result = await ImageGallerySaver.saveImage(imageBytes, quality: 100); + + if (result == null || result == '') throw '图片保存失败'; + + EasyLoading.showToast("Successfully saved"); + } catch (e) { + print(e.toString()); + } + } + + //获取图片 + static Future getImages() async { + final pkImage = await ImagePicker().pickImage( + source: ImageSource.gallery, + ); + return pkImage!; + } + + //裁剪 + static cropImage(String path, int index) async { + double x = 1.0; + double y = 1.0; + switch (index) { + case 0: + x = 1.0; + y = 1.0; + break; + case 1: + x = 3.0; + y = 4.0; + break; + case 2: + x = 4.0; + y = 3.0; + break; + case 3: + x = 9.0; + y = 16.0; + break; + case 4: + x = 16.0; + y = 9.0; + break; + } + CroppedFile? croppedFile = await ImageCropper().cropImage( + sourcePath: path, + aspectRatioPresets: [ + CropAspectRatioPreset.square, //1:1 + ], + aspectRatio: CropAspectRatio(ratioX: x, ratioY: y), + uiSettings: [ + IOSUiSettings( + title: 'Cropper', + aspectRatioLockEnabled: true, + resetAspectRatioEnabled: false, + ), + AndroidUiSettings( + toolbarTitle: 'Cropper', + toolbarColor: Color(0xFFBE6FDF), + toolbarWidgetColor: Colors.white, + activeControlsWidgetColor: Color(0xFFBE6FDF), + initAspectRatio: CropAspectRatioPreset.square, + lockAspectRatio: true, + ), + ], + ); + return croppedFile; + } + + //解析图片转base64 + static uploadImage(XFile pickedFile) async { + var file = File(pickedFile.path); + String? type = lookupMimeType(pickedFile.path); //读取格式 + Uint8List imageBytes = await file.readAsBytes(); + String base64 = base64Encode(imageBytes); + return "data:$type;base64,$base64"; + } + + //解析图片转base64 + static uploadImage2(File pickedFile) async { + String? type = lookupMimeType(pickedFile.path); //读取格式 + Uint8List imageBytes = await pickedFile.readAsBytes(); + String base64 = base64Encode(imageBytes); + return "data:$type;base64,$base64"; + } + + // 获取文件大小 + static String getFileSizeString({int? bytes, int decimals = 0}) { + if (bytes! <= 0) return "0 Bytes"; + const suffixes = [" Bytes", "KB", "MB", "GB", "TB"]; + var i = (log(bytes) / log(1024)).floor(); + return ((bytes / pow(1024, i)).toStringAsFixed(decimals)) + suffixes[i]; + } + + // 获取文件大小(mb) + static double getFileSizeDouble({int? bytes, int decimals = 0}) { + final kb = bytes! / 1024; + final mb = kb / 1024; + print("object===$mb"); + return mb; + } + + ///网络图片转base64 + static Future networkImageToBase64(String imageUrl) async { + http.Response response = await http.get(Uri.parse(imageUrl)); + final bytes = response.bodyBytes; + print("bytes===$bytes"); + return bytes != null ? base64Encode(bytes) : null; + } +} diff --git a/lib/common/dialog_bean.dart b/lib/common/dialog_bean.dart new file mode 100644 index 0000000..cbcdc5c --- /dev/null +++ b/lib/common/dialog_bean.dart @@ -0,0 +1,105 @@ + + +import 'package:flutter/cupertino.dart'; + +typedef CreateDialogWidget = Widget Function(); + +/// @desc 弹窗数据类 +class DialogBean { + ///dialog唯一标识,通过 DialogBean 数据内容生成 Md5生成 + late String dialogId; + + ///当前 dialog,显示的视图。如果为空,则在顶层页面 + String? pageRouter; + + ///当前 pageRouter 对应的子页面 + List? innerPageRouters; + + ///优先级、用于显示弹窗前排序, + ///但对于加入的弹窗,已经显示的情况 + ///[highClear] 清除已显示的弹窗,直接显示当前弹窗,该属性慎用 + ///[high] 回收当前已显示的弹窗,再显示高优先级弹窗,该属性慎用 + DialogPriority dialogPriority; + + ///用于排序 + late int priority; + + ///弹窗内部业务 widget,每次show 时动态创建。不能直接传创建好的 widget,因为在 high回收时,调用 pop 再 show 会出现 The following NoSuchMethodError was thrown building Builder(dirty): + CreateDialogWidget? createDialogWidget; + + ///弹窗类型 + DialogType? dialogType; + + DialogBean({ + this.pageRouter, + this.innerPageRouters, + this.dialogPriority = DialogPriority.normal, + this.dialogType = DialogType.dialog, + @required this.createDialogWidget, + }) : super() { + assert(createDialogWidget!().key != null); + dialogId = (createDialogWidget!().key as ValueKey).value; + switch (dialogPriority) { + case DialogPriority.highClearAll: + priority = 30; + pageRouter = null; + break; + case DialogPriority.highClear: + priority = 20; + pageRouter = null; + break; + case DialogPriority.high: + priority = 10; + break; + case DialogPriority.normal: + priority = 1; + break; + case DialogPriority.low: + priority = 0; + break; + } + //如果内页不空,则 pageRouter不能为空 + if (innerPageRouters != null) { + assert(pageRouter != null); + } + } + + ///是否为高优先级,带清除功能的 + bool isHighClear() { + return dialogPriority == DialogPriority.highClear || + dialogPriority == DialogPriority.highClearAll; + } + + @override + String toString() { + return 'DialogBean{dialogId: $dialogId, pageRouter: $pageRouter, innerPageRouters: $innerPageRouters, priority: $priority, dialogType: $dialogType}'; + } +} + +enum DialogType { + ///弹窗 + dialog, + + ///底部弹窗 + bottomSheet, + + ///底部可滑动弹窗 + bottomScrollSheet, +} + +enum DialogPriority { + ///最高优先级,清除其它----所有弹窗(例如强制升级弹窗) + highClearAll, + + ///高优先级弹窗,清除其它弹窗不包括highClearAll(登录超时、多终端登录) + highClear, + + ///高优先级弹窗,回收normal弹窗,优先显示(指纹引导弹窗、提交请求弹窗) + high, + + ///默认弹窗,按顺序弹出 + normal, + + ///低优先级弹窗,按顺序弹出 + low, +} diff --git a/lib/common/dialog_manager.dart b/lib/common/dialog_manager.dart new file mode 100644 index 0000000..d3afde5 --- /dev/null +++ b/lib/common/dialog_manager.dart @@ -0,0 +1,309 @@ + +import 'package:flutter/material.dart'; + +import 'dialog_bean.dart'; +import 'navigator_manager.dart'; + +/// @desc 统一弹窗(包含 showDialog、showModalBottomSheet) +class DialogManager { + // 工厂模式 : 单例公开访问点 + factory DialogManager() => _getInstance()!; + +// static DialogManager get instance => _getInstance(); + + // 静态私有成员,没有初始化 + static DialogManager? _instance; + + ///弹窗数据(待显示) + late List _dialogList; + +// ///当前正在显示的弹窗 +// DialogBean showDialogBean; + + ///已显示过或正在显示的弹窗数据,还未被回调清除 + ///已经显示过的弹窗,不能用一个DialogBean + ///(因为showDialogBean在对话 pop 是会赋为空,一个正要显示,一个取消的回调过来又重新给设为空了。) + late List _hasShowDialogList; + + ///是否有系统弹窗正在显示,例如系统权限申请弹窗 + late bool isSystemDialogShowing; + + // 私有构造函数 + DialogManager._internal() { + // 初始化 + _dialogList = []; + _hasShowDialogList = []; + isSystemDialogShowing = false; + } + + // 静态、同步、私有访问点 + static DialogManager? _getInstance() { + if (_instance == null) { + _instance = DialogManager._internal(); + } + return _instance; + } + + ///高优先级,回收取消正在显示的弹窗 + static const String popRecycle = "popRecycle"; + + ///其它地方触发取消正在显示的调窗,且不自动显示下一个 + static const String popRecycleAndNotNext = "popRecycleAndNotNext"; + + ///取消弹窗,但不自动显示下一个 + static const String popNotNext = "popNotNext"; + + ///增加弹窗 + void add(DialogBean bean) { + print("dialog add ${bean.dialogId}"); + //对于 highClear 和 highClearAll则加入时要清掉其它低优先级弹窗,必须放在 show 前。假如在 add中,可能低优先级的在后台添加的 + switch (bean.dialogPriority) { + case DialogPriority.highClear: + case DialogPriority.highClearAll: + //移除其它低优先级弹窗数据,(不清除正显示的。在 show 里面再清除&& !hasShow(item.dialogId),也可以在后台处理) + _dialogList.removeWhere((item) => item.priority < bean.priority); + break; + default: + break; + } + //去掉重复弹窗(待显示的与顶层正在显示的弹窗) + + bool hasDialog = _getAllDialogBean().any((dialogBean) => bean.dialogId == dialogBean.dialogId); + + //没有重复的,且栈中没有 highClear 等优先级的弹窗,或者 clearBean小于等于bean.priority + if (!hasDialog) { + DialogBean? clearBean = _getHighClearDialogBean(); + if (clearBean == null || bean.priority >= clearBean.priority) { + _dialogList.add(bean); + } + } + //根据优先级进行排序:降序 + _dialogList.sort((a, b) => b.priority.compareTo(a.priority)); + } + + ///显示弹窗,不能返回 Future,不然在同时 show两次时重叠 DialogManager()..add()..show;DialogManager()..add()..show; + void show(BuildContext context) { + print("dialog show $_dialogList"); + //如果有系统弹窗正在显示,则不显示 + if (isSystemDialogShowing) { + return; + } + + //如果待显示数组为空 + if (_dialogList.isEmpty) { + return; + } + + //对于 highClean 和 highCleanAll则加入时要清掉其它低优先级弹窗,必须放在 show 前。假如在 add中,可能低优先级的在后台添加的 +// if (bean != null) { +// //移除其它低优先级弹窗数据 +// _dialogList.removeWhere((item) => item.priority < bean.priority); +// } + + //已经有正在显示的弹窗且是在栈顶层显示(showDialogBean != null && 不能加入此判断,在显示强升时碰到的,因为showDialogBean在对话 pop 是会赋为空。所以导致这里不准,一个正在显示,一个取消的回调过来又重新给设为空了。) + if (NavigatorManager().isTopDialog() && _hasShowDialogList.isNotEmpty) { + DialogBean? hasShowDialogBean = getShowingDialog(); + print("当前有正在显示的弹窗$hasShowDialogBean"); + DialogBean? bean; + //已有显示的弹窗,且high 弹窗在当前页显示,且已显示的弹窗优先级低于high级弹窗 + //highClear 和 highClearAll 不用管显示页面 所以不要这个判断,这里_getHighClearDialogBean取所有的(包括正在显示的) + if ((bean = _getHighClearDialogBean(beans: _dialogList)) != null && _canShow(bean) && (hasShowDialogBean!.priority < bean!.priority)) { + //如果当前加入的弹窗是 highClear,则清掉所有弹窗(包括当前正在显示的,以及未显示的) + print("清除正在显示的弹窗${bean.dialogPriority}"); + Navigator.pop(context); + } else if (((bean = _getDialogBeanByPriority(DialogPriority.high, beans: _dialogList)) != null || + (bean = _getDialogBeanByPriority(DialogPriority.normal, beans: _dialogList)) != null) && //已有显示的弹窗,且high 弹窗在当前页显示,且已显示的弹窗优先级低于high级弹窗 + _canShow(bean) && + hasShowDialogBean!.priority < bean!.priority) { + //如果当前加入的弹窗是 high,则回收当前正在显示的弹窗。 + print("回收正在显示的弹窗${bean.dialogPriority}"); + Navigator.pop(context, popRecycle); + //不能在这里把弹窗直接回收,因为在使用 pop 会调用whenComplete会清掉当前显示的弹窗。所以要到whenComplete 中去处理 + } + return; + } + //查找当前页面可显示的弹窗数据 + DialogBean showDialogBean; + try { + showDialogBean = _dialogList.firstWhere((bean) => _canShow(bean)); + _hasShowDialogList.add(showDialogBean); + //新从数组中移动,因为回调中再移动可能会出现提交成功后显示一个提示框,导致一直显示提交框,不会消失 + _dialogList.remove(showDialogBean); + print("显示的dialog =$showDialogBean"); + switch (showDialogBean.dialogType!) { + case DialogType.dialog: + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return showDialogBean.createDialogWidget!(); + }, + ).then((obj) { + _handlePopResult(context, obj); + }); + break; + case DialogType.bottomSheet: + showModalBottomSheet( + backgroundColor: Color(0x00FFFFFF), + context: context, + isDismissible: false, + enableDrag: false, + isScrollControlled: true, + builder: (BuildContext context) { + return showDialogBean.createDialogWidget!(); + }, + ).then((obj) { + _handlePopResult(context, obj); + }); + break; + case DialogType.bottomScrollSheet: + showModalBottomSheet( + backgroundColor: Color(0x00FFFFFF), + context: context, + isScrollControlled: true, + builder: (BuildContext context) { + return showDialogBean.createDialogWidget!(); + }, + ).then((obj) { + _handlePopResult(context, obj); + }); + break; + } + } catch (e) { + //没有找到可显示的弹窗 + } + + } + + void _handlePopResult(BuildContext context, dynamic obj) { + //取消第一个 + DialogBean dismissBean = _hasShowDialogList[0]; + print("消失的dialog =$dismissBean,接收回调结果:$obj"); + //取消第一个 + _hasShowDialogList.remove(dismissBean); + //如果是从 high 弹窗回收或外部手动 pop的话,则重新添加回数组 + if (obj == popRecycle || obj == popRecycleAndNotNext) { + _dialogList.add(dismissBean); + } + // widget 中可能会先 pop ,再 push,这里显示下一个时,通过顶层路由来判断,不能通过当前显示的页面来判断。 + if (obj != popRecycleAndNotNext && obj != popNotNext) { + show(context); + } + } + + ///弹窗是否正在显示 + bool isShowing(String? dialogId) { + DialogBean? dialogBean = getShowingDialog(); + if (dialogBean != null && dialogId == dialogBean.dialogId) { + return true; + } + return false; + } + + ///取得在正显示的弹窗 + DialogBean? getShowingDialog() { + if (_hasShowDialogList.isNotEmpty && NavigatorManager().isTopDialog()) { + return _hasShowDialogList[_hasShowDialogList.length - 1]; + } + return null; + } + + ///显示系统弹窗,必须与 dismiss 成对使用 + void showSystemDialog(BuildContext context) { + //回收正在显示的弹窗 + pop(context, result: popRecycleAndNotNext); + //正在显示系统弹窗 + isSystemDialogShowing = true; + } + + ///隐藏系统弹窗,必须与 show 成对使用 + void dismissSystemDialog(BuildContext context) { + //正在显示系统弹窗 + isSystemDialogShowing = false; + //系统弹窗消失,续续显示其它弹窗 + show(context); + } + + ///弹窗栈中是否此弹窗 + bool hasShow(String dialogId) { + return _dialogList.any((bean) => dialogId == bean.dialogId); + } + + ///清除已经显示的弹窗,系统权限弹窗时回收到其它弹窗 + ///[result] 默认回收弹窗,不显示下一个 + void pop(BuildContext context, {String? result}) { + if (_hasShowDialogList.isNotEmpty && NavigatorManager().isTopDialog()) { + Navigator.pop(context, result); + } + } + + ///清除已经显示的弹窗,系统权限弹窗时回收到其它弹窗 + ///[result] 默认回收弹窗,不显示下一个 + void popByDialogId(BuildContext context, String dialogId, {String? result}) { + if (isShowing(dialogId)) { + Navigator.pop(context, result); + } + } + + ///清除已经显示的弹窗或待显示的弹窗,例如登录超时打开登录时、或者退出登录 + void popAndClear(BuildContext context) { + //如果没有 highClear或 highClearAll. + DialogBean? dialogBean = _getHighClearDialogBean(); + if (dialogBean == null) { + _dialogList.clear(); + pop(context, result: popNotNext); + } + } + + ///是否可显示,未指定页面,或者指定的页面在顶层 + bool _canShow(DialogBean? dialogBean) { + if (dialogBean == null) { + return false; + } + String? pageRouter = dialogBean.pageRouter; + //指定的页面在顶层 + return isEmpty(pageRouter) || NavigatorManager().isTopRouter(pageRouter!); + } + + ///按取得 clear 其它弹窗优先级的弹窗 bean + DialogBean? _getHighClearDialogBean({List? beans}) { + DialogBean? bean = _getDialogBeanByPriority(DialogPriority.highClearAll, beans: beans); + if (bean != null) { + return bean; + } + bean = _getDialogBeanByPriority(DialogPriority.highClear, beans: beans); + if (bean != null) { + return bean; + } + return null; + } + + ///按弹窗优先级获取弹窗(默认包括待显示的及正在显示的) + DialogBean? _getDialogBeanByPriority(DialogPriority priority, {List? beans}) { + try { + return (beans ?? _getAllDialogBean()).firstWhere( + (bean) => priority == bean.dialogPriority, + ); + } catch (e) { + return null; + } + /*return (beans ?? _getAllDialogBean()).firstWhereOrNull( + (bean) => priority == bean.dialogPriority, + );*/ + } + + ///取得所有弹窗,包括待显示及正在显示的弹窗 + List _getAllDialogBean() { + List all = []; + DialogBean? showingDialogBean = getShowingDialog(); + if (getShowingDialog() != null) { + all.add(showingDialogBean!); + } + all.addAll(_dialogList); + return all; + } + + bool isEmpty(String? s) { + return s == null || s.isEmpty; + } +} diff --git a/lib/common/dialog_util.dart b/lib/common/dialog_util.dart new file mode 100644 index 0000000..a83fbc9 --- /dev/null +++ b/lib/common/dialog_util.dart @@ -0,0 +1,34 @@ +import 'dart:convert'; + +import 'package:convert/convert.dart'; +import 'package:crypto/crypto.dart'; +import 'package:flutter/material.dart'; + +/// @desc 弹窗 widget 统一创建类 +/// @time 2019-11-06 09:42 +/// @author Cheney +class DialogUtil { + ///对话框提示显示 + ///[id] 同一对话框唯一标识 + static Widget createTipWidget(BuildContext context, Widget dialog, String message, + {String? id, bool hasTips = true, bool canceled = true, String? cancelText, String? confirmText, final Function? onTap + /* OnCancelListener onCancelListener, + OnConfirmListener onConfirmListener,*/ + }) { + return WillPopScope(key: ValueKey(id ?? generateId("createTipWidget$message")), child: dialog, onWillPop: () async => canceled); + } + + ///生成对话框 id + static String generateId(String txt) { + assert(txt != null); + return generateMd5(txt); + } + + /// md5 加密 + static String generateMd5(String data) { + var content = Utf8Encoder().convert(data); + var digest = md5.convert(content); + // 这里其实就是 digest.toString() + return hex.encode(digest.bytes); + } +} diff --git a/lib/common/func.dart b/lib/common/func.dart new file mode 100644 index 0000000..c993f40 --- /dev/null +++ b/lib/common/func.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; + +class FunctionUtil { + static BuildContext? dialogContext; + + //显示中间弹窗 + static void popDialog(BuildContext context, Widget widget) { + showDialog( + context: context, + barrierDismissible: true, + builder: (BuildContext context) { + dialogContext = context; + return widget; + }); + } + + //显示底部弹窗 + static void bottomSheetDialog(BuildContext context, Widget widget) { + showModalBottomSheet( + backgroundColor: const Color(0x00FFFFFF), + context: context, + /* isDismissible: false,*/ + isScrollControlled: true, + builder: (BuildContext context) { + dialogContext = context; + return widget; + }, + ); + } + + //显示底部弹窗 + static void bottomNoSheetDialog(BuildContext context, Widget widget) { + showModalBottomSheet( + backgroundColor: Color(0x00FFFFFF), + context: context, + isDismissible: false, + isScrollControlled: true, + enableDrag: false, + builder: (BuildContext context) { + dialogContext = context; + return WillPopScope(onWillPop: () async => false, child: widget); + }); + } + + //返回上一级 + static void pop() { + Navigator.pop(dialogContext!); + } + + //push到下一级 + static Future push(BuildContext context, Widget widget) { + return Navigator.push( + context, + MaterialPageRoute( + builder: (context) => widget, + ), + ); + } +} diff --git a/lib/common/my_navigator_observers.dart b/lib/common/my_navigator_observers.dart new file mode 100644 index 0000000..b7eba2c --- /dev/null +++ b/lib/common/my_navigator_observers.dart @@ -0,0 +1,39 @@ +import 'package:common_utils/common_utils.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'navigator_manager.dart'; + +/// @desc: 导航监听 + +class MyNavigatorObserver extends NavigatorObserver { + @override + void didPush(Route route, Route? previousRoute) { + LogUtil.v("didPush router : $route | previousRoute: $previousRoute"); + NavigatorManager().addRouter(route); + } + + @override + void didPop(Route route, Route? previousRoute) { + LogUtil.v("didPop router : $route | previousRoute: $previousRoute"); + + NavigatorManager().removeRouter(route); + + } + + @override + void didRemove(Route route, Route? previousRoute) { + LogUtil.v("didRemove router : $route | previousRoute: $previousRoute"); + + NavigatorManager().removeRouter(route); + + } + + @override + void didReplace({Route? newRoute, Route? oldRoute}) { + LogUtil.v("didReplace router : $newRoute | previousRoute: $oldRoute"); + + NavigatorManager().replaceRouter(newRoute!, oldRoute!); + + } +} diff --git a/lib/common/navigator_manager.dart b/lib/common/navigator_manager.dart new file mode 100644 index 0000000..d9efd3f --- /dev/null +++ b/lib/common/navigator_manager.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; + +typedef OnInterceptor = Function(bool isInterceptor); + +/// 导航管理 +class NavigatorManager { + ///所有路由栈,包括弹窗与页面 + List? _history; + + static final NavigatorManager _instance = NavigatorManager._internal(); + + factory NavigatorManager() => _instance; + + NavigatorManager? _bus; + + NavigatorManager._internal() { + if (_bus == null) { + _history = []; + } + } + + ///通过拦截器增加 push router + void addRouter(Route route) { + _history?.add(route); + } + + ///通过拦截器移动 push router + void removeRouter(Route route) { + _history?.remove(route); + } + + ///通过拦截器移动 push router + void replaceRouter(Route newRoute, Route oldRoute) { + _history?.remove(oldRoute); + _history?.add(newRoute); + } + + List? get history => _history; + + ///是否顶层路由为页面,或者还未显示,正在压入栈 + bool isTopRouter(String routerName) { + if (_history!.isEmpty) { + return false; + } + int i = _history!.length - 1; + Route route = _history![i]; + while (route.settings == null && i >= 0) { + i--; + route = _history![i]; + } + return route.settings.name != null && route.settings.name == routerName; + } + + ///是否顶层路由为弹窗(包括showBottomSheet),或者还未显示,正在压入栈 + bool isTopDialog() { + if (_history!.isEmpty) { + return false; + } + return _history![_history!.length - 1].settings.name == null; + } +} diff --git a/lib/dialog/ad_free_dialog.dart b/lib/dialog/ad_free_dialog.dart new file mode 100644 index 0000000..53aedb2 --- /dev/null +++ b/lib/dialog/ad_free_dialog.dart @@ -0,0 +1,136 @@ +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:ironsource_mediation/ironsource_mediation.dart'; + +import '../generated/l10n.dart'; + +///删除图片提示 +class AdFreeDialog extends StatefulWidget { + Function onTap; + + AdFreeDialog({required this.onTap}); + + @override + State createState() => _AdFreeDialogState(); +} + +class _AdFreeDialogState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final w314 = size.width / 1.1464968152866; + final h343 = size.width / 1.0495626822157; + final h75 = size.width / 4.8; + final t40 = size.width / 9; + final w85 = size.width / 4.235294117647; + final h45 = size.width / 8; + final t143 = size.width / 2.5174825174825; + final w283 = size.width / 1.2720848056537; + final t235 = size.width / 1.531914893617; + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Center( + child: Stack( + alignment: Alignment.center, + children: [ + CachedNetworkImage( + fit: BoxFit.fitHeight, + width: w314, + height: h343, + imageUrl: NetworkConfig.appConfigBean!.AdFree!.BackgroundImage!, + errorWidget: (context, url, error) => Image( + fit: BoxFit.fitWidth, + width: w314, + height: h343, + image: AssetImage('assets/images/ad_free_bg.png'), + ), + ), + Positioned( + top: t143, + child: GestureDetector( + onTap: () { + Navigator.pop(context); + if (NetworkConfig.appConfigBean!.AdFree!.BtnAction == "mall") { + Navigator.pushNamed(context, "/ShopPage"); + } + }, + child: CachedNetworkImage( + fit: BoxFit.fitHeight, + width: w283, + imageUrl: NetworkConfig.appConfigBean!.AdFree!.BtnImage!, + errorWidget: (context, url, error) => const Icon(Icons.error), + ), + ), + ), + + ///看广告 + Positioned( + top: t235, + child: GestureDetector( + onTap: () { + if (NetworkConfig.usedRewardCount != NetworkConfig.totalRewardCount) { + if (NetworkConfig.isAdAvailable) { + Navigator.pop(context); + IronSource.showRewardedVideo(); + } else { + EasyLoading.showToast(S.of(context).no_advertisements); + } + } else { + EasyLoading.showToast(S.of(context).received_all); + } + }, + child: Container( + height: h75, + width: w283, + decoration: const BoxDecoration( + color: Color(0xFFF8F8FF), + borderRadius: BorderRadius.all(Radius.circular(7)), + ), + margin: const EdgeInsets.only(left: 15, right: 15), + child: Stack( + children: [ + Positioned( + top: 20, + left: 10, + child: Text( + "${S.of(context).Watch_the} (${NetworkConfig.usedRewardCount}/${NetworkConfig.totalRewardCount})", + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + ), + ), + Positioned( + top: t40, + left: 10, + child: Text( + S.of(context).Earn_paint, + style: TextStyle(fontSize: 10, color: Color(0xFF999999)), + ), + ), + Positioned( + right: 4, + top: 18, + child: Stack( + alignment: Alignment.center, + children: [ + Image(width: w85, height: h45, image: AssetImage('assets/images/view_ad.png')), + Positioned( + top: 10, + child: Text( + S.of(context).Watch, + style: TextStyle(fontSize: 14, color: Colors.white), + )) + ], + )) + ], + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/dialog/delete_img.dart b/lib/dialog/delete_img.dart new file mode 100644 index 0000000..a4ca6f8 --- /dev/null +++ b/lib/dialog/delete_img.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; + +import '../generated/l10n.dart'; + +///删除图片提示 +class DeleteImg extends StatefulWidget { + Function onTap; + + DeleteImg({required this.onTap}); + + @override + State createState() => _DeleteImgState(); +} + +class _DeleteImgState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final h260 = size.width / 1.3846153846153; //120 + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Container( + alignment: Alignment.center, + child: Container( + width: double.infinity, + margin: EdgeInsets.only(left: 16, right: 16), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(13))), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: EdgeInsets.only(top: 27), + child: Text( + S.of(context).Tip, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), + ), + ), + Container( + margin: EdgeInsets.only(top: 27), + child: Text( + S.of(context).Are_you_sure, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), + ), + ), + Container( + margin: EdgeInsets.only(top: 38, left: 23, right: 23, bottom: 36), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + // widget.onTap(0); + Navigator.pop(context); + }, + child: Container( + width: 132, + height: 37, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(0xFFEEE3FF), + borderRadius: BorderRadius.all(Radius.circular(7)), + ), + child: Text( + S.of(context).Cancel, + style: TextStyle(color: Color(0xFF8841FF)), + ), + ), + ), + GestureDetector( + onTap: () { + Navigator.pop(context); + widget.onTap(1); + }, + child: Container( + width: 132, + height: 37, + alignment: Alignment.center, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF843FFF), Color(0xFFE975FF)]), + borderRadius: BorderRadius.all(Radius.circular(7)), + ), + child: Text( + S.of(context).Sure, + style: TextStyle(color: Colors.white), + ), + ), + ), + ], + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/dialog/free_upper_limit_dialog.dart b/lib/dialog/free_upper_limit_dialog.dart new file mode 100644 index 0000000..b27ddba --- /dev/null +++ b/lib/dialog/free_upper_limit_dialog.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; + +import '../generated/l10n.dart'; + +///免费保存上限 +class FreeUpperLimitDialog extends StatefulWidget { + Function onTap; + + FreeUpperLimitDialog({Key? key, required this.onTap}) : super(key: key); + + @override + State createState() => _FreeUpperLimitDialogState(); +} + +class _FreeUpperLimitDialogState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final h20 = size.width / 18; //20 + final b25 = size.width / 14.4; //25 + final t30 = size.width / 12; //30 + final t27 = size.width / 13.33333333; //27 + final w132 = size.width / 2.7272727272; //132 + final h37 = size.width / 9.7297297297; //37 + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Container( + alignment: Alignment.center, + child: Container( + margin: EdgeInsets.only(left: 15, right: 15), + padding: EdgeInsets.only(left: h20, right: h20, bottom: b25), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(13))), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: EdgeInsets.only(top: t30), + child: Text( + S.of(context).Save_picture, + style: TextStyle(fontSize: h20), + ), + ), + Container( + margin: EdgeInsets.only(top: h20), + child: Text( + S.of(context).Free_users, + style: TextStyle(fontSize: 14), + ), + ), + Container( + margin: EdgeInsets.only(top: 10), + child: Text( + S.of(context).More_pictures, + style: TextStyle(fontSize: 14), + ), + ), + Container( + margin: EdgeInsets.only(top: t27, bottom: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Container( + width: w132, + height: h37, + alignment: Alignment.center, + decoration: BoxDecoration(color: Color(0xFFEEE3FF), borderRadius: BorderRadius.all(Radius.circular(7))), + child: Text( + S.of(context).Cancel, + style: TextStyle(color: Color(0xFF8841FF)), + ), + ), + ), + GestureDetector( + onTap: () { + Navigator.pop(context); + widget.onTap(1); + }, + child: Container( + width: w132, + height: h37, + alignment: Alignment.center, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), + borderRadius: BorderRadius.all(Radius.circular(7))), + child: Text( + S.of(context).to_pay, + style: TextStyle(color: Colors.white), + ), + ), + ), + ], + ), + ), + ], + ), + ))); + } +} diff --git a/lib/dialog/guideDialog.dart b/lib/dialog/guideDialog.dart new file mode 100644 index 0000000..d3ad3c9 --- /dev/null +++ b/lib/dialog/guideDialog.dart @@ -0,0 +1,231 @@ +import 'package:flutter/material.dart'; + +import '../generated/l10n.dart'; + +class guideDialog extends StatefulWidget { + // 点击返回index 0 1 + Function onTap; + final String name; + final List list; + final List selectList; + + guideDialog({Key? key, required this.onTap, required this.name, required this.list, required this.selectList}) : super(key: key); + + @override + _guideDialogState createState() => _guideDialogState(); +} + +class _guideDialogState extends State { + List selectList = []; + + @override + void initState() { + // TODO: implement initState + super.initState(); + if (widget.selectList != null && widget.selectList.isNotEmpty) { + selectList = widget.selectList; + } + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final h328 = size.width / 1.097561; + final h564 = size.width / 0.64; + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x1A000000), + child: Center( + // ClipRRect 创建圆角矩形 要不然发现下边button不是圆角 + child: Container( + width: h328, + height: h564, + decoration: const BoxDecoration( + color: Colors.white, + //设置四周圆角 角度 + borderRadius: BorderRadius.all(Radius.circular(6.6))), + child: Stack( + alignment: Alignment.topCenter, + children: [ + Container( + margin: const EdgeInsets.only(top: 14), + child: Text( + widget.name, + style: const TextStyle(color: Colors.black, fontSize: 18, fontWeight: FontWeight.w800), + ), + ), + Container( + margin: const EdgeInsets.only(left: 12, right: 12, top: 52, bottom: 58), + child: SingleChildScrollView( + child: Column( + children: [ + ListView.builder( + shrinkWrap: true, + itemCount: widget.list.length, + padding: const EdgeInsets.all(0), + //数据的数量 + itemBuilder: (context, index) { + return GestureDetector( + onTap: () {}, + child: Container( + margin: const EdgeInsets.only(bottom: 13), + decoration: const BoxDecoration( + color: Color(0xFFF3F3FB), + //设置四周圆角 角度 + borderRadius: BorderRadius.all(Radius.circular(6.6))), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.only(left: 13, top: 13), + alignment: Alignment.centerLeft, + child: Text( + widget.list[index]["name"].toString(), + style: const TextStyle(color: Colors.black, fontSize: 16), + ), + ), + Container( + margin: const EdgeInsets.only(left: 13, bottom: 18, top: 18), + child: Wrap( + spacing: 15.0, + //主轴间距 + runSpacing: 15, + //副轴间距 + alignment: WrapAlignment.start, + //主轴上的对齐方式 + crossAxisAlignment: WrapCrossAlignment.center, + //副轴上的对齐方式 + children: List.generate( + widget.list[index]["content"].length, + (int i) { + return _sizeItem2(index, widget.list[index]["content"][i], i); + }, + ).toList(), + ), + ), + ], + ), + )); + }, + physics: const NeverScrollableScrollPhysics(), + //类似 cellForRow 函数 + scrollDirection: Axis.vertical), + ], + ), + )), + Align( + alignment: Alignment.bottomCenter, + child: GestureDetector( + onTap: () { + if (widget.onTap != null) { + Navigator.pop(context); + widget.onTap(selectList); + } + }, + child: Container( + height: 40, + alignment: Alignment.center, + margin: const EdgeInsets.only(bottom: 11, left: 23, right: 23), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), + borderRadius: BorderRadius.all(Radius.circular(20))), + child: Text( + S.of(context).Save, + style: const TextStyle(color: Colors.white, fontSize: 16), + ), + ), + )), + Positioned( + top: 15, + right: 15, + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: const SizedBox( + width: 20, + height: 20, + child: Image( + width: 20, + height: 20, + image: AssetImage('assets/images/cuo.png'), + ), + ), + )) + ], + ), + ), + ), + ); + } + + _sizeItem2(index, String bean, i) { + bool isSelect = false; + if (selectList != null && selectList.isNotEmpty) { + for (var v in selectList) { + if (bean == v) { + isSelect = true; + } + } + } + + return Container( + child: GestureDetector( + onTap: () { + if (selectList.contains(bean)) { + selectList.remove(bean); + } else { + selectList.add(bean); + } + print(selectList); //{a: a3, 2: b3, 3: null} + setState(() {}); + }, + child: Container( + padding: const EdgeInsets.only(left: 10, right: 10, top: 1, bottom: 1), + decoration: BoxDecoration( + //设置四周圆角 角度 + borderRadius: const BorderRadius.all(Radius.circular(3.5)), + //设置四周边框 + border: Border.all(width: 1, color: Color(isSelect ? 0xFFBE75FF : 0xFF666666)), + color: Color(isSelect ? 0xFFBE75FF : 0x00FFFFFF), + ), + child: Text( + bean, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Color(isSelect ? 0xFFFFFFFF : 0xFF999999), fontSize: 12), + ), + ), + ), + ); + } +/* _sizeItem2(List list) { + return list.map((e) { + int index = list.indexOf(e); + return GestureDetector( + onTap: () { + mainBodyIndex = index; + t2 = responseData["body"][index]["content"]; + setState(() {}); + }, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: const Color(0xFFF3F3FB), + //设置四周圆角 角度 + borderRadius: const BorderRadius.all(Radius.circular(6.6)), + //设置四周边框 + border: Border.all(width: 1, color: Color(mainBodyIndex == index ? 0xFF8841FF : 0xFFFFFFFF)), + ), + child: Text( + list[index], + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Color(mainBodyIndex == index ? 0xFF8841FF : 0xFF999999), fontSize: 12), + ), + ), + ); + }).toList(); + }*/ +} diff --git a/lib/dialog/guide_theme_switch_tip.dart b/lib/dialog/guide_theme_switch_tip.dart new file mode 100644 index 0000000..8dfd358 --- /dev/null +++ b/lib/dialog/guide_theme_switch_tip.dart @@ -0,0 +1,113 @@ +import 'package:flutter/material.dart'; + +import '../generated/l10n.dart'; + +///引导模式切换主题提示 +class GuideThemeSwitchTip extends StatefulWidget { + Function onTap; + String theme; + + GuideThemeSwitchTip(this.theme, {Key? key, required this.onTap}) : super(key: key); + + @override + State createState() => _GuideThemeSwitchTipState(); +} + +class _GuideThemeSwitchTipState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final h20 = size.width / 18; //20 + final b25 = size.width / 14.4; //25 + final t30 = size.width / 12; //30 + final t27 = size.width / 13.33333333; //27 + final w132 = size.width / 2.7272727272; //132 + final h37 = size.width / 9.7297297297; //37 + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Container( + alignment: Alignment.center, + child: Container( + margin: EdgeInsets.only(left: 15, right: 15), + padding: EdgeInsets.only(left: h20, right: h20, bottom: b25), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(13))), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: EdgeInsets.only(top: t30), + child: Text( + S.of(context).switch_the_subject, + style: TextStyle(color: Colors.black, fontSize: 18), + ), + ), + Container( + margin: EdgeInsets.only(top: h20), + child: RichText( + text: TextSpan(children: [ + TextSpan( + text: S.of(context).After_confirmation, + style: TextStyle(color: Colors.black, fontSize: 13), + ), + TextSpan( + text: widget.theme, + style: TextStyle(color: Colors.black, fontSize: 13), + ), + TextSpan( + text: S.of(context).some_unshared, + style: TextStyle(color: Colors.black, fontSize: 13), + ), + ]), + ), + ), + Container( + margin: EdgeInsets.only(top: t27, bottom: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Container( + width: w132, + height: h37, + alignment: Alignment.center, + decoration: BoxDecoration(color: Color(0xFFEEE3FF), borderRadius: BorderRadius.all(Radius.circular(7))), + child: Text( + S.of(context).Cancel, + style: TextStyle(color: Color(0xFF8841FF)), + ), + ), + ), + GestureDetector( + onTap: () { + Navigator.pop(context); + widget.onTap(1); + }, + child: Container( + width: w132, + height: h37, + alignment: Alignment.center, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), + borderRadius: BorderRadius.all(Radius.circular(7))), + child: Text( + S.of(context).Cover, + style: TextStyle(color: Colors.white), + ), + ), + ), + ], + ), + ), + ], + ), + ))); + } +} diff --git a/lib/dialog/influential_prompt_dialog.dart b/lib/dialog/influential_prompt_dialog.dart new file mode 100644 index 0000000..2341581 --- /dev/null +++ b/lib/dialog/influential_prompt_dialog.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +import '../generated/l10n.dart'; + +class InfluentialPromptDialog extends StatefulWidget { + Function onTap; + String prompt; + + InfluentialPromptDialog({required this.prompt, required this.onTap}); + + @override + State createState() => _InfluentialPromptDialogState(); +} + +class _InfluentialPromptDialogState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + + + + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Container( + width: size.width, + color: const Color(0x70000000), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(top: 20, left: 14), + child: Text( + S.of(context).Painting_parameters, + style: const TextStyle(color: Color(0xFFC4C4C4)), + ), + ), + Container( + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(left: 15, right: 15, top: 13), + child: Text( + widget.prompt, + style: const TextStyle(color: Colors.white), + ), + ), + Container(height: 22), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ///复制提示词 + GestureDetector( + onTap: () { + EasyLoading.showToast(S.of(context).Already_copied); + Clipboard.setData(ClipboardData(text: widget.prompt)); + }, + child: Container( + alignment: Alignment.center, + margin: const EdgeInsets.only(left: 16), + width: 154.67, + height: 32, + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + child: Text( + S.of(context).copy_prompt_word, + style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600), + ), + ), + ), + + ///画同款 + GestureDetector( + onTap: () { + widget.onTap(); + }, + child: Container( + alignment: Alignment.center, + margin: const EdgeInsets.only(right: 16), + width: 154.67, + height: 32, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), + borderRadius: BorderRadius.all(Radius.circular(16)), + ), + child: Text( + S.of(context).Draw_the_same, + style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: Colors.white), + ), + ), + ), + ], + ), + Container(height: 22), + ], + ), + ), + ); + } +} diff --git a/lib/dialog/invitation_code_dialog.dart b/lib/dialog/invitation_code_dialog.dart new file mode 100644 index 0000000..dedec1b --- /dev/null +++ b/lib/dialog/invitation_code_dialog.dart @@ -0,0 +1,145 @@ +import 'dart:async'; +import 'dart:ui'; + +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +import '../generated/l10n.dart'; +import '../tools/me/me_info_model.dart'; + +///填写邀请码弹框 +class InvitationCodeDialog extends StatefulWidget { + InvitationCodeDialog({Key? key}) : super(key: key); + + @override + State createState() => _InvitationCodeDialogState(); +} + +class _InvitationCodeDialogState extends State { + TextEditingController _textEditingController = TextEditingController(); + String text = ""; + + void _textFieldChanged(String str) { + text = str.toUpperCase(); + _textEditingController.value = _textEditingController.value.copyWith(text: text.toUpperCase()); + } + + StreamSubscription? subscription; + final MeInfoModel _viewModel = MeInfoModel(); + + @override + void initState() { + // TODO: implement initState + super.initState(); + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + switch (code) { + case "fillInInvitationCode": + Navigator.pop(context); + String message = newData['data']; + EasyLoading.showToast(message); + break; + default: + String message = newData['data']; + EasyLoading.showToast(message); + break; + } + } + setState(() {}); + }); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Container( + alignment: Alignment.center, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: size.width, + margin: EdgeInsets.only(left: 25, right: 25), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(7))), + child: Column( + children: [ + Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(top: 22, left: 34), + child: Text( + S.of(context).Invitation_code, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + ), + Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(top: 11, left: 34, right: 34), + child: Text("${S.of(context).Fill_in} ${NetworkConfig.appConfigBean!.InviteeNumber} ${S.of(context).Painting_points}"), + ), + Container( + height: 37, + alignment: Alignment.center, + margin: const EdgeInsets.only(top: 11, left: 34, right: 34), + decoration: const BoxDecoration( + color: Color(0xFFF0F0FF), + borderRadius: BorderRadius.all(Radius.circular(7)), + ), + child: TextField( + controller: _textEditingController, + keyboardType: TextInputType.name, + cursorColor: Color(0xFF843FFF), + decoration: InputDecoration.collapsed(hintStyle: const TextStyle(fontSize: 16.0, color: Color(0xFFB5B5B5)), hintText: ''), + //文本对齐方式 + textAlign: TextAlign.center, + //最大长度,设置此项会让TextField右下角有一个输入数量的统计字符串 + //最大行数 + maxLines: 1, + //输入文本的样式 + style: const TextStyle(fontSize: 18.0, color: Color(0xFF843FFF), fontWeight: FontWeight.w500), + onChanged: _textFieldChanged, + autofocus: false, + ), + ), + GestureDetector( + onTap: () { + if (text != "") { + _viewModel.fillInInvitationCode(text); + } else { + EasyLoading.showToast(S.of(context).Please_fill_in); + } + }, + child: Container( + height: 45, + width: double.infinity, + alignment: Alignment.center, + margin: EdgeInsets.only(top: 30), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF843FFF), Color(0xFFF87DFF)]), + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(7), bottomRight: Radius.circular(7))), + child: Text( + S.of(context).Sure, + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ) + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/dialog/login_dialog.dart b/lib/dialog/login_dialog.dart new file mode 100644 index 0000000..e03e58b --- /dev/null +++ b/lib/dialog/login_dialog.dart @@ -0,0 +1,176 @@ +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +import '../generated/l10n.dart'; +import '../tools/web/CommonlyWebPage.dart'; + +class LoginDialog extends StatefulWidget { + Function onTap; //0 手机登录 1 谷歌登录 + + LoginDialog(Key key, {required this.onTap}) : super(key: key); + + @override + State createState() => LoginDialogState(); +} + +class LoginDialogState extends State { + //用来收手势监听 + final TapGestureRecognizer _tgr1 = TapGestureRecognizer(); + final TapGestureRecognizer _tgr2 = TapGestureRecognizer(); + + @override + void initState() { + // TODO: implement initState + super.initState(); + } + + @override + void dispose() { + // TODO: implement dispose + _tgr1.dispose(); + _tgr2.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final t37 = size.width / 9.729729729729; + final w97 = size.width / 3.7113402061855; + final b104 = size.width / 3.4615384615384; + final w48 = size.width / 7.5; + final w301 = size.width / 1.1960132890365; + final h56 = size.width / 6.4285714285714; + final w38 = size.width / 9.4736842105263; + final h342 = size.width / 1.0526315789473; + + return Stack( + alignment: Alignment.center, + children: [ + Positioned( + bottom: 0, + child: SizedBox( + height: h342, + child: Stack( + alignment: Alignment.center, + children: [ + Image(image: AssetImage('assets/images/login_bg.png')), + Positioned( + top: t37, + child: Image( + width: w97, + height: w97, + image: AssetImage('assets/images/login_logo.png'), + )), + + ///谷歌登录 + Positioned( + bottom: b104, + child: GestureDetector( + onTap: () { + if (NetworkConfig.isTest) { + widget.onTap(0); + } else { + widget.onTap(1); + } + }, + child: Stack( + alignment: Alignment.center, + children: [ + Image( + width: w301, + height: h56, + image: const AssetImage('assets/images/google_login.png'), + ), + Positioned( + top: 12, + child: Row( + children: [ + const Image(width: 27, height: 27, image: AssetImage('assets/images/google_logo.png')), + Container( + margin: const EdgeInsets.only(left: 5), + child: Text( + S.of(context).Google, + style: const TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ], + ), + ), + ], + ), + )), + + ///隐私协议,用户政策 + Positioned( + bottom: w38, + child: RichText( + textAlign: TextAlign.center, + text: TextSpan(children: [ + TextSpan( + style: const TextStyle( + color: Color(0xFF999999), + fontSize: 11.0, + // fontWeight: FontWeight.w800, + ), + text: S.of(context).By_continuing), + TextSpan( + style: const TextStyle( + color: Colors.black, + fontSize: 11.0, + ), + recognizer: _tgr1 + ..onTap = () { + Navigator.push( + context, + MaterialPageRoute( + //导航打开新视图 + builder: (context) => CommonlyWebPage( + url: "https://appfiles.hissai.com/hissai/UserAgreement_EN.html", + title: S.of(context).User_Agreement, + ) //打开第二个页面,并传值,传递值的名称是model + )); + }, + text: "《${S.of(context).User_Agreement}》\n", + ), + TextSpan( + style: const TextStyle( + color: Color(0xFF999999), + fontSize: 11.0, + // fontWeight: FontWeight.w800, + ), + text: S.of(context).and), + TextSpan( + style: const TextStyle( + color: Colors.black, + fontSize: 11, + ), + recognizer: _tgr2 + ..onTap = () { + Navigator.push( + context, + MaterialPageRoute( + //导航打开新视图 + builder: (context) => CommonlyWebPage( + url: "https://appfiles.hissai.com/hissai/PrivacyPolicy_EN.html", + title: S.of(context).Privacy_Policy, + ) //打开第二个页面,并传值,传递值的名称是model + )); + }, + text: "《${S.of(context).Privacy_Policy}》", + ), + ]), + ), + ) + ], + ), + )), + ], + ); + } + + void Pop() { + Navigator.pop(context); + } +} diff --git a/lib/dialog/newDialog.dart b/lib/dialog/newDialog.dart new file mode 100644 index 0000000..de5f77e --- /dev/null +++ b/lib/dialog/newDialog.dart @@ -0,0 +1,162 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; + +import '../bean/popout_bean.dart'; + +///弹框列表 +class newDialog extends StatefulWidget { + // 点击返回index 0 1 + Function onTap; + final PopoutBean popoutBean; + + newDialog({required this.onTap, required this.popoutBean}); + + @override + _newDialogState createState() => _newDialogState(); +} + +class _newDialogState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + + final dw = size.width / 1.87178287318; + final dh = size.width / 7.71373473323; + double bl = 0, bt = 0, br = 0, bb = 0; + if (widget.popoutBean.BgPicInfo != null) { + if (widget.popoutBean.BgPicInfo!.PosY < 0) { + bt = widget.popoutBean.BgPicInfo!.PosY * -1 + 0.0; + } else { + bb = widget.popoutBean.BgPicInfo!.PosY + 0.0; + } + if (widget.popoutBean.BgPicInfo!.PosX < 0) { + bl = widget.popoutBean.BgPicInfo!.PosX * -1 + 0.0; + } else { + br = widget.popoutBean.BgPicInfo!.PosX + 0.0; + } + } + + double dl = 0, dt = 0, dr = 0, db = 0; + if (widget.popoutBean.BtOKInfo != null) { + if (widget.popoutBean.BtOKInfo!.PosY < 0) { + dt = widget.popoutBean.BtOKInfo!.PosY * -1 + 0.0; + } else { + db = widget.popoutBean.BtOKInfo!.PosY + 0.0; + } + if (widget.popoutBean.BtOKInfo!.PosX < 0) { + dl = widget.popoutBean.BtOKInfo!.PosX * -1 + 0.0; + } else { + dr = widget.popoutBean.BtOKInfo!.PosX + 0.0; + } + } + double dl2 = 0, dt2 = 0, dr2 = 0, db2 = 0; + if (widget.popoutBean.BtCloseInfo != null) { + if (widget.popoutBean.BtCloseInfo!.PosY < 0) { + dt2 = widget.popoutBean.BtCloseInfo!.PosY * -1 + 0.0; + } else { + db2 = widget.popoutBean.BtCloseInfo!.PosY + 0.0; + } + if (widget.popoutBean.BtCloseInfo!.PosX < 0) { + dl2 = widget.popoutBean.BtCloseInfo!.PosX * -1 + 0.0; + } else { + dr2 = widget.popoutBean.BtCloseInfo!.PosX + 0.0; + } + } + + // String price = ""; + // NetworkConfig.productIdList.forEach((key, value) { + // if (widget.popoutBean.Text == key) { + // price = value; + // } + // }); + + return Material( + type: MaterialType.transparency, //透明类型 + color: Color(0x1A000000), + child: Center( + // ClipRRect 创建圆角矩形 要不然发现下边button不是圆角 + child: Container( + child: Stack( + alignment: Alignment.center, + children: [ + widget.popoutBean.BgPicInfo != null + ? Container( + margin: EdgeInsets.only(left: bl, top: bt, right: br, bottom: bb), + child: CachedNetworkImage( + width: widget.popoutBean.BgPicInfo!.W + 0.33, + height: widget.popoutBean.BgPicInfo!.H + 0.33, + fit: BoxFit.fill, + imageUrl: widget.popoutBean.BgPicInfo != null && widget.popoutBean.BgPicInfo!.Pic != null + ? widget.popoutBean.BgPicInfo!.Pic! + : "", + errorWidget: (context, url, error) => Icon(Icons.error), + )) + : Container(), + widget.popoutBean.BtOKInfo != null + ? Container( + margin: EdgeInsets.only(left: dl, top: dt, right: dr, bottom: db), + child: GestureDetector( + onTap: () { + // Navigator.pop(context); + if (widget.onTap != null) { + // Navigator.pop(context); + widget.onTap(widget.popoutBean.PopoutId, widget.popoutBean.PopoutType, widget.popoutBean.Text); + } + }, + child: Stack( + alignment: Alignment.center, + children: [ + CachedNetworkImage( + width: widget.popoutBean.BtOKInfo!.W + 0.33, + height: widget.popoutBean.BtOKInfo!.H + 0.33, + fit: BoxFit.fill, + imageUrl: widget.popoutBean.BtOKInfo != null && widget.popoutBean.BtOKInfo!.Pic != null + ? widget.popoutBean.BtOKInfo!.Pic! + : "", + errorWidget: (context, url, error) => Image( + height: dh, + width: dw, + fit: BoxFit.fill, + image: AssetImage('assets/images/btn_mianfeiliangqu.webp'), + ), + ), + widget.popoutBean.PopoutType == 6 + ? Positioned( + child: Text( + "S.of(context).only + price", + style: TextStyle(color: Colors.white, fontSize: 16), + )) + : Container() + ], + ), + )) + : Container(), + widget.popoutBean.BtCloseInfo != null + ? Container( + margin: EdgeInsets.only(left: dl2, top: dt2, right: dr2, bottom: db2), + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: CachedNetworkImage( + width: widget.popoutBean.BtCloseInfo!.W + 0.33, + height: widget.popoutBean.BtCloseInfo!.H + 0.33, + fit: BoxFit.fill, + imageUrl: widget.popoutBean.BtCloseInfo != null && widget.popoutBean.BtCloseInfo!.Pic != null + ? widget.popoutBean.BtCloseInfo!.Pic! + : "", + errorWidget: (context, url, error) => Image( + height: dh, + width: dw, + fit: BoxFit.fill, + image: AssetImage('assets/images/btn_mianfeiliangqu.webp'), + ), + ))) + : Container(), + ], + ), + ), + ), + ); + } +} diff --git a/lib/dialog/new_ball_dialog.dart b/lib/dialog/new_ball_dialog.dart new file mode 100644 index 0000000..401c8d5 --- /dev/null +++ b/lib/dialog/new_ball_dialog.dart @@ -0,0 +1,144 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; + +import '../bean/levitating_ball_pop_bean.dart'; + +///悬浮球弹框 +class NewBallDialog extends StatefulWidget { + // 点击返回index 0 1 + Function onTap; + final LevitatingBallPopBean popoutBean; + + NewBallDialog({required this.onTap, required this.popoutBean}); + + @override + _NewBallDialogState createState() => _NewBallDialogState(); +} + +class _NewBallDialogState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + + final dw = size.width / 1.87178287318; + final dh = size.width / 7.71373473323; + double bl = 0, bt = 0, br = 0, bb = 0; + if (widget.popoutBean.BgPicInfo != null) { + if (widget.popoutBean.BgPicInfo!.PosY < 0) { + bt = widget.popoutBean.BgPicInfo!.PosY * -1 + 0.0; + } else { + bb = widget.popoutBean.BgPicInfo!.PosY + 0.0; + } + if (widget.popoutBean.BgPicInfo!.PosX < 0) { + bl = widget.popoutBean.BgPicInfo!.PosX * -1 + 0.0; + } else { + br = widget.popoutBean.BgPicInfo!.PosX + 0.0; + } + } + + double dl = 0, dt = 0, dr = 0, db = 0; + if (widget.popoutBean.BtOKInfo != null) { + if (widget.popoutBean.BtOKInfo!.PosY < 0) { + dt = widget.popoutBean.BtOKInfo!.PosY * -1 + 0.0; + } else { + db = widget.popoutBean.BtOKInfo!.PosY + 0.0; + } + if (widget.popoutBean.BtOKInfo!.PosX < 0) { + dl = widget.popoutBean.BtOKInfo!.PosX * -1 + 0.0; + } else { + dr = widget.popoutBean.BtOKInfo!.PosX + 0.0; + } + } + double dl2 = 0, dt2 = 0, dr2 = 0, db2 = 0; + if (widget.popoutBean.BtCloseInfo != null) { + if (widget.popoutBean.BtCloseInfo!.PosY < 0) { + dt2 = widget.popoutBean.BtCloseInfo!.PosY * -1 + 0.0; + } else { + db2 = widget.popoutBean.BtCloseInfo!.PosY + 0.0; + } + if (widget.popoutBean.BtCloseInfo!.PosX < 0) { + dl2 = widget.popoutBean.BtCloseInfo!.PosX * -1 + 0.0; + } else { + dr2 = widget.popoutBean.BtCloseInfo!.PosX + 0.0; + } + } + + // String price = ""; + // NetworkConfig.productIdList.forEach((key, value) { + // if (widget.popoutBean.Text == key) { + // price = value; + // } + // }); + + return Material( + type: MaterialType.transparency, //透明类型 + color: Color(0x1A000000), + child: Center( + // ClipRRect 创建圆角矩形 要不然发现下边button不是圆角 + child: Container( + child: Stack( + alignment: Alignment.center, + children: [ + widget.popoutBean.BgPicInfo != null + ? Container( + margin: EdgeInsets.only(left: bl, top: bt, right: br, bottom: bb), + child: CachedNetworkImage( + width: widget.popoutBean.BgPicInfo!.W + 0.33, + height: widget.popoutBean.BgPicInfo!.H + 0.33, + fit: BoxFit.fill, + imageUrl: widget.popoutBean.BgPicInfo != null && widget.popoutBean.BgPicInfo!.Pic != null + ? widget.popoutBean.BgPicInfo!.Pic! + : "", + errorWidget: (context, url, error) => const Icon(Icons.error, size: 0), + )) + : Container(), + widget.popoutBean.BtOKInfo != null + ? Container( + margin: EdgeInsets.only(left: dl, top: dt, right: dr, bottom: db), + child: GestureDetector( + onTap: () { + Navigator.pop(context); + if (widget.onTap != null) { + widget.onTap(); + } + }, + child: Stack( + alignment: Alignment.center, + children: [ + CachedNetworkImage( + width: widget.popoutBean.BtOKInfo!.W + 0.33, + height: widget.popoutBean.BtOKInfo!.H + 0.33, + fit: BoxFit.fill, + imageUrl: widget.popoutBean.BtOKInfo != null && widget.popoutBean.BtOKInfo!.Pic != null + ? widget.popoutBean.BtOKInfo!.Pic! + : "", + errorWidget: (context, url, error) => const Icon(Icons.error, size: 0), + ), + ], + ), + )) + : Container(), + widget.popoutBean.BtCloseInfo != null + ? Container( + margin: EdgeInsets.only(left: dl2, top: dt2, right: dr2, bottom: db2), + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: CachedNetworkImage( + width: widget.popoutBean.BtCloseInfo!.W + 0.33, + height: widget.popoutBean.BtCloseInfo!.H + 0.33, + fit: BoxFit.fill, + imageUrl: widget.popoutBean.BtCloseInfo != null && widget.popoutBean.BtCloseInfo!.Pic != null + ? widget.popoutBean.BtCloseInfo!.Pic! + : "", + errorWidget: (context, url, error) => const Icon(Icons.error, size: 0), + ))) + : Container(), + ], + ), + ), + ), + ); + } +} diff --git a/lib/dialog/obtaining_benefits_dialog.dart b/lib/dialog/obtaining_benefits_dialog.dart new file mode 100644 index 0000000..7e2ed43 --- /dev/null +++ b/lib/dialog/obtaining_benefits_dialog.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; + +import '../bean/equity_bean.dart'; +import '../generated/l10n.dart'; + +class ObtainingBenefitsDialog extends StatefulWidget { + Function onTap; + EquityBean? equityBean; + + ObtainingBenefitsDialog({required this.onTap, required this.equityBean}); + + @override + State createState() => _ObtainingBenefitsDialogState(); +} + +class _ObtainingBenefitsDialogState extends State { + @override + Widget build(BuildContext context) { + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Container( + alignment: Alignment.center, + child: Container( + width: double.infinity, + margin: EdgeInsets.only(left: 27, right: 27), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.only(top: 18), + child: Text( + S.of(context).obtaining_benefits, + style: const TextStyle(fontSize: 20), + ), + ), + GestureDetector( + onTap: () { + if (widget.equityBean?.ObjAdvert?.WatchNum != widget.equityBean?.ObjAdvert?.TotalNum) { + Navigator.pop(context); + widget.onTap(0); + } + }, + child: Container( + width: double.infinity, + height: 48, + margin: const EdgeInsets.only(left: 21, right: 21, top: 27), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF843FFF), Color(0xFFEB76FF)])), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "${S.of(context).Full_Watch}${widget.equityBean?.ObjAdvert?.WatchNum}/${widget.equityBean?.ObjAdvert?.TotalNum})", + style: TextStyle(color: Colors.white), + ), + Text( + S.of(context).Get_saved, + style: TextStyle(fontSize: 12, color: Colors.white), + ), + ], + ), + ), + ), + GestureDetector( + onTap: () { + widget.onTap(1); + }, + child: Container( + width: double.infinity, + height: 48, + margin: const EdgeInsets.only(left: 21, right: 21, top: 12, bottom: 21), + decoration: + BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(10)), border: Border.all(color: Color(0xFF8A42FF), width: 1)), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "${S.of(context).Number_of}${widget.equityBean?.ObjProduct?.Price}", + style: TextStyle(color: Color(0xFF8B43FF)), + ), + Text( + "${widget.equityBean?.ObjProduct?.ProductNum}${S.of(context).Number_of_saved}", + style: TextStyle(fontSize: 12, color: Color(0xFF8B43FF)), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/dialog/phone_login_dialog.dart b/lib/dialog/phone_login_dialog.dart new file mode 100644 index 0000000..6442cb5 --- /dev/null +++ b/lib/dialog/phone_login_dialog.dart @@ -0,0 +1,217 @@ +import 'dart:async'; + +import 'package:aiplot/common/EventBusUtil.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +import '../tools/home/home_model.dart'; + +class PhoneLoginDialog extends StatefulWidget { + const PhoneLoginDialog({Key? key}) : super(key: key); + + @override + State createState() => _PhoneLoginDialogState(); +} + +class _PhoneLoginDialogState extends State with WidgetsBindingObserver { + bool isKeyboardShow = false; + StreamSubscription? subscription; + final HomeModel _viewModel = HomeModel(); + + //输入框内容 + String phoneNum = ""; + String verCode = ""; + + void _phone(String str) { + phoneNum = str; + } + + void _verCode(String str) { + verCode = str; + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + WidgetsBinding.instance?.addObserver(this); + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + if (code == "login") { + EventBusUtil.fire(LoginSuccess()); + Navigator.pop(context); + } + } + setState(() {}); + }); + } + + double boardShowH = 0.0; + + @override + void didChangeMetrics() { + super.didChangeMetrics(); + WidgetsBinding.instance?.addPostFrameCallback((_) { + setState(() { + if (MediaQuery.of(context).viewInsets.bottom == 0) { + //关闭键盘 + isKeyboardShow = false; + boardShowH = 0.0; + } else { + //显示键盘 + isKeyboardShow = true; + boardShowH = MediaQuery.of(context).viewInsets.bottom - 106; + } + }); + }); + } + + @override + void dispose() { + // TODO: implement dispose + WidgetsBinding.instance?.removeObserver(this); + subscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final t37 = size.width / 9.729729729729; + final w97 = size.width / 3.7113402061855; + final b104 = size.width / 1.61; + final w48 = size.width / 7.5; + + final h40 = size.width / 9; + final h77 = size.width / 4.675; + final h172 = size.width / 2.093; + final h224 = size.width / 1.6047787; + final h338 = size.width / 1.097561; + final h341 = size.width / 1.04347826; + return Container( + margin: EdgeInsets.only(bottom: isKeyboardShow ? boardShowH : 0), + height: h341, + child: Stack( + children: [ + const Image(height: double.infinity, width: double.infinity, fit: BoxFit.fill, image: AssetImage('assets/images/login_bg.png')), + Align( + alignment: Alignment.topCenter, + child: Container( + margin: EdgeInsets.only( + top: 21, + ), + child: Text( + "手机号登录", + style: TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.w800), + ), + )), + Positioned( + top: 5, + left: 15, + child: IconButton( + icon: Icon(Icons.arrow_back_ios), + onPressed: () { + Navigator.pop(context); + EventBusUtil.fire(PhoneLoginBackEvent()); + }, + )), + + ///手机号 + Align( + alignment: Alignment.bottomCenter, + child: Container( + margin: EdgeInsets.only( + bottom: h224, + ), + width: h338, + height: h40, + padding: const EdgeInsets.only(left: 15), + alignment: Alignment.center, + decoration: const BoxDecoration( + color: Color(0xFFEEEEEE), + borderRadius: BorderRadius.all(Radius.circular(25)), + ), + child: TextField( + keyboardType: TextInputType.number, + decoration: const InputDecoration( + hintText: "请输入手机号", + border: InputBorder.none, + isCollapsed: true, + ), + inputFormatters: [ + LengthLimitingTextInputFormatter(11), + ], + onChanged: _phone, + ), + ), + ), + + ///验证码 + Align( + alignment: Alignment.bottomCenter, + child: Container( + margin: EdgeInsets.only( + bottom: h172, + ), + width: h338, + height: h40, + padding: const EdgeInsets.only(left: 15), + alignment: Alignment.center, + decoration: const BoxDecoration( + color: Color(0xFFEEEEEE), + borderRadius: BorderRadius.all(Radius.circular(25)), + ), + child: TextField( + keyboardType: TextInputType.number, + decoration: const InputDecoration( + hintText: "验证码", + border: InputBorder.none, + isCollapsed: true, + ), + inputFormatters: [ + LengthLimitingTextInputFormatter(4), + ], + onChanged: _verCode, + ), + ), + ), + Positioned( + left: 16.33, + right: 16.33, + bottom: 104, + child: GestureDetector( + onTap: () { + EasyLoading.show(status: 'loading...', maskType: EasyLoadingMaskType.black); + _viewModel.userLogin(1, phoneNum, "", verCode, ""); + }, + child: Container( + width: h338, + height: h40, + alignment: Alignment.center, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color(0xFF8540FF), + Color(0xFFE472FF), + ], + ), + borderRadius: BorderRadius.all(Radius.circular(20)), + ), + child: Text( + "登录", + style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w800), + ), + ), + )) + ], + ), + ); + } +} diff --git a/lib/dialog/reference_image_tip_dialog.dart b/lib/dialog/reference_image_tip_dialog.dart new file mode 100644 index 0000000..78356b0 --- /dev/null +++ b/lib/dialog/reference_image_tip_dialog.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; + +import '../generated/l10n.dart'; + +///参考图提示 +class ReferenceImageTipDialog extends StatefulWidget { + const ReferenceImageTipDialog({Key? key}) : super(key: key); + + @override + State createState() => _ReferenceImageTipDialogState(); +} + +class _ReferenceImageTipDialogState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final h20 = size.width / 18; //20 + final t27 = size.width / 13.33333333; //27 + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Container( + alignment: Alignment.center, + child: Container( + margin: EdgeInsets.only(left: 16, right: 16), + padding: EdgeInsets.only(left: 16, right: 16, bottom: h20), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(13))), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(top: t27), + child: Text( + S.of(context).Reference_image, + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), + ), + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + S.of(context).The_reference, + style: TextStyle(fontSize: 13, color: Color(0xFF666666)), + ), + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 2), + child: Text( + S.of(context).The_smaller_the, + style: TextStyle(fontSize: 13, color: Color(0xFF666666)), + ), + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 2), + child: Text( + S.of(context).Users_are_responsible, + style: TextStyle(fontSize: 13, color: Color(0xFF666666)), + ), + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 2), + child: Text( + S.of(context).The_final_generated, + style: TextStyle(fontSize: 13, color: Color(0xFF666666)), + ), + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 2), + child: Text( + S.of(context).Using_the_reference, + style: TextStyle(fontSize: 13, color: Color(0xFF666666)), + ), + ), + ], + ), + ))); + } +} diff --git a/lib/dialog/share_dialog.dart b/lib/dialog/share_dialog.dart new file mode 100644 index 0000000..ae9df04 --- /dev/null +++ b/lib/dialog/share_dialog.dart @@ -0,0 +1,232 @@ +import 'dart:io'; +import 'dart:typed_data'; +import 'dart:ui'; + +import 'package:aiplot/common/app_util.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:share_plus/share_plus.dart'; + +import '../generated/l10n.dart'; + +///分享邀请弹框 +class ShareDialog extends StatefulWidget { + String imgUrl; + String userName; + + ShareDialog(this.imgUrl, this.userName, {Key? key}) : super(key: key); + + @override + State createState() => _ShareDialogState(); +} + +class _ShareDialogState extends State { + final _boundaryKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final l39 = size.width / 9.2307692307692; + final w74 = size.width / 4.86486486486; + final w66 = size.width / 5.454545454545; + final w60 = size.width / 6; + final w50 = size.width / 7.2; + final w135 = size.width / 2.666666666666; + final h37 = size.width / 9.729729729729; + + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Container( + alignment: Alignment.center, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: l39, right: l39), + child: Text( + S.of(context).Invite_new, + style: TextStyle(color: Colors.white), + ), + ), + + ///分享的主体 + Container( + margin: EdgeInsets.only(left: l39, right: l39, top: 10), + child: RepaintBoundary( + key: _boundaryKey, + child: Container( + width: size.width, + color: Colors.white, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 12, top: 13), + child: Image(width: w74, image: AssetImage("assets/images/share_logo.png")), + ), + Container( + margin: EdgeInsets.only(right: 12), + child: Row( + children: [ + Text( + "${S.of(context).Author}:", + style: TextStyle(fontSize: 12, color: Color(0xFF666666)), + ), + SizedBox( + width: w60, + child: Text( + "${widget.userName}", + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 12, color: Color(0xFF666666)), + ), + ), + ], + ), + ) + ], + ), + widget.imgUrl != "" + ? Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 12, top: 12, right: 12), + child: CachedNetworkImage(imageUrl: widget.imgUrl), + ) + : Container(), + SizedBox( + width: double.infinity, + height: w66, + child: Stack( + children: [ + Positioned( + left: 12, + top: 14, + child: Text( + "${S.of(context).New_users} ${NetworkConfig.appConfigBean!.InvitationCodeNumber} ${S.of(context).Painting_points}", + style: TextStyle(fontSize: 13), + )), + Positioned( + left: 12, + bottom: 12, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + child: Text( + "${S.of(context).Invitation_code} :", + style: TextStyle(fontSize: 10, color: Color(0xFF6A6A6A)), + ), + ), + Container( + margin: EdgeInsets.only(left: 9), + child: Text( + NetworkConfig.invitationCode!, + style: TextStyle(fontSize: 16, color: Color(0xFF853FFF)), + ), + ), + ], + )), + Positioned( + right: 12, + top: 10, + child: Container( + width: w50, + height: w50, + color: Color(0xFFEEEEFF), + child: CachedNetworkImage( + fit: BoxFit.fitHeight, + imageUrl: NetworkConfig.userData!.InvitationCodeImageUrl!, + ), + )), + ], + ), + ), + ], + ), + ), + ), + ), + Container( + margin: EdgeInsets.only(left: l39, right: l39, top: 9), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ///保存 + GestureDetector( + onTap: () async { + EasyLoading.show(status: 'loading...'); + final boundary = _boundaryKey.currentContext?.findRenderObject(); + if (boundary != null && boundary is RenderRepaintBoundary) { + final image = await boundary.toImage(pixelRatio: 3.0); + ByteData? byteData = await image.toByteData(format: ImageByteFormat.png); + EasyLoading.dismiss(); + AppUtil.saveWidgetImage(byteData!); + } + }, + child: Container( + width: w135, + height: h37, + alignment: Alignment.center, + color: Colors.white, + child: Text( + S.of(context).Save, + style: TextStyle(color: Color(0xFF853FFF), fontSize: 16), + ), + ), + ), + + ///分享 + GestureDetector( + onTap: () async { + EasyLoading.show(status: 'loading...'); + final boundary = _boundaryKey.currentContext?.findRenderObject(); + if (boundary != null && boundary is RenderRepaintBoundary) { + final image = await boundary.toImage(pixelRatio: 3.0); + ByteData? byteData = await image.toByteData(format: ImageByteFormat.png); + final xFile = await byteDataToXFile(ByteData.view(byteData!.buffer)); + EasyLoading.dismiss(); + await Share.shareXFiles([xFile]); + } + }, + child: Container( + width: w135, + height: h37, + alignment: Alignment.center, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF843FFF), Color(0xFFF87DFF)]), + ), + child: Text( + S.of(context).Share, + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ); + } + + Future byteDataToXFile(ByteData bytes) async { + Uint8List uint8List = bytes.buffer.asUint8List(); + Directory tempDir = await getTemporaryDirectory(); + String tempPath = tempDir.path; + File tempFile = await File('$tempPath/image.jpg').writeAsBytes(uint8List); + return XFile(tempFile.path); + } +} diff --git a/lib/dialog/tip_overwrite_not_dialog.dart b/lib/dialog/tip_overwrite_not_dialog.dart new file mode 100644 index 0000000..2030b5e --- /dev/null +++ b/lib/dialog/tip_overwrite_not_dialog.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; + +import '../generated/l10n.dart'; + +///推荐词是否覆盖内容 +class TipOverwriteNotDialog extends StatefulWidget { + Function onTap; + + TipOverwriteNotDialog({Key? key, required this.onTap}) : super(key: key); + + @override + State createState() => _TipOverwriteNotDialogState(); +} + +class _TipOverwriteNotDialogState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final h20 = size.width / 18; //20 + final b25 = size.width / 14.4; //25 + final t30 = size.width / 12; //30 + final t27 = size.width / 13.33333333; //27 + final w132 = size.width / 2.7272727272; //132 + final h37 = size.width / 9.7297297297; //37 + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: Container( + alignment: Alignment.center, + child: Container( + margin: EdgeInsets.only(left: 15, right: 15), + padding: EdgeInsets.only(left: h20, right: h20, bottom: b25), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(13))), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: EdgeInsets.only(top: t30), + child: Text( + S.of(context).Random_suggested, + textAlign: TextAlign.center, + ), + ), + Container( + margin: EdgeInsets.only(top: h20), + child: Text(S.of(context).do_you), + ), + Container( + margin: EdgeInsets.only(top: t27), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Container( + width: w132, + height: h37, + alignment: Alignment.center, + decoration: BoxDecoration(color: Color(0xFFEEE3FF), borderRadius: BorderRadius.all(Radius.circular(7))), + child: Text( + S.of(context).Cancel, + style: TextStyle(color: Color(0xFF8841FF)), + ), + ), + ), + GestureDetector( + onTap: () { + Navigator.pop(context); + widget.onTap(1); + }, + child: Container( + width: w132, + height: h37, + alignment: Alignment.center, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), + borderRadius: BorderRadius.all(Radius.circular(7))), + child: Text( + S.of(context).Cover, + style: TextStyle(color: Colors.white), + ), + ), + ), + ], + ), + ), + ], + ), + ))); + } +} diff --git a/lib/generated/intl/messages_all.dart b/lib/generated/intl/messages_all.dart new file mode 100644 index 0000000..5a784ef --- /dev/null +++ b/lib/generated/intl/messages_all.dart @@ -0,0 +1,71 @@ +// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart +// This is a library that looks up messages for specific locales by +// delegating to the appropriate library. + +// Ignore issues from commonly used lints in this file. +// ignore_for_file:implementation_imports, file_names, unnecessary_new +// ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering +// ignore_for_file:argument_type_not_assignable, invalid_assignment +// ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases +// ignore_for_file:comment_references + +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:intl/intl.dart'; +import 'package:intl/message_lookup_by_library.dart'; +import 'package:intl/src/intl_helpers.dart'; + +import 'messages_en.dart' as messages_en; +import 'messages_ja.dart' as messages_ja; +import 'messages_zh.dart' as messages_zh; + +typedef Future LibraryLoader(); +Map _deferredLibraries = { + 'en': () => new SynchronousFuture(null), + 'ja': () => new SynchronousFuture(null), + 'zh': () => new SynchronousFuture(null), +}; + +MessageLookupByLibrary? _findExact(String localeName) { + switch (localeName) { + case 'en': + return messages_en.messages; + case 'ja': + return messages_ja.messages; + case 'zh': + return messages_zh.messages; + default: + return null; + } +} + +/// User programs should call this before using [localeName] for messages. +Future initializeMessages(String localeName) { + var availableLocale = Intl.verifiedLocale( + localeName, (locale) => _deferredLibraries[locale] != null, + onFailure: (_) => null); + if (availableLocale == null) { + return new SynchronousFuture(false); + } + var lib = _deferredLibraries[availableLocale]; + lib == null ? new SynchronousFuture(false) : lib(); + initializeInternalMessageLookup(() => new CompositeMessageLookup()); + messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor); + return new SynchronousFuture(true); +} + +bool _messagesExistFor(String locale) { + try { + return _findExact(locale) != null; + } catch (e) { + return false; + } +} + +MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) { + var actualLocale = + Intl.verifiedLocale(locale, _messagesExistFor, onFailure: (_) => null); + if (actualLocale == null) return null; + return _findExact(actualLocale); +} diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart new file mode 100644 index 0000000..1c520c4 --- /dev/null +++ b/lib/generated/intl/messages_en.dart @@ -0,0 +1,277 @@ +// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart +// This is a library that provides messages for a en locale. All the +// messages from the main program should be duplicated here with the same +// function name. + +// Ignore issues from commonly used lints in this file. +// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new +// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering +// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases +// ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes +// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes + +import 'package:intl/intl.dart'; +import 'package:intl/message_lookup_by_library.dart'; + +final messages = new MessageLookup(); + +typedef String MessageIfAbsent(String messageStr, List args); + +class MessageLookup extends MessageLookupByLibrary { + String get localeName => 'en'; + + final messages = _notInlinedMessages(_notInlinedMessages); + static Map _notInlinedMessages(_) => { + "A_close": MessageLookupByLibrary.simpleMessage( + "A close-up of a pretty girl\'s face, surrounded by halo, ethereal, romantic, dreamy, delicate"), + "A_colorful": MessageLookupByLibrary.simpleMessage( + "A colorful magic castle in a crystal ball"), + "About": MessageLookupByLibrary.simpleMessage("About"), + "Account_cancellation": MessageLookupByLibrary.simpleMessage( + "Account Cancellation Request"), + "After_confirmation": MessageLookupByLibrary.simpleMessage( + "After confirmation, the subject type will be replaced with "), + "After_rain": MessageLookupByLibrary.simpleMessage( + "After rain, clear colors, sunshine, pink flowers, quiet, soft focus, chasing butterflies"), + "After_the_account_is_cancelled": MessageLookupByLibrary.simpleMessage( + "After the account is cancelled, all your data will be deleted and cannot be recovered."), + "Already_copied": + MessageLookupByLibrary.simpleMessage("Already copied"), + "Are_you_sure": MessageLookupByLibrary.simpleMessage( + "Are you sure to permanently delete this work? \nAfter deletion, it will not be able to be retrieved"), + "Artist": MessageLookupByLibrary.simpleMessage("Artist"), + "Author": MessageLookupByLibrary.simpleMessage("Author"), + "Beautiful_angel": MessageLookupByLibrary.simpleMessage( + "Beautiful angel, white wings, halo, long blonde hair, royal sister, queen temperament"), + "Brunette_princess": MessageLookupByLibrary.simpleMessage( + "Brunette princess, crown on head, gorgeous, firefly, forest background, elegant"), + "By_continuing": MessageLookupByLibrary.simpleMessage( + "By continuing, you agree to HissAi"), + "Cancel": MessageLookupByLibrary.simpleMessage("Cancel"), + "Check_in": MessageLookupByLibrary.simpleMessage( + "Check in \"Me\" after the screen is created"), + "Close": MessageLookupByLibrary.simpleMessage("Close"), + "Collected": MessageLookupByLibrary.simpleMessage("Collected"), + "Collection": MessageLookupByLibrary.simpleMessage("Collection"), + "Confirm_submission": + MessageLookupByLibrary.simpleMessage("Confirm submission"), + "Consume": MessageLookupByLibrary.simpleMessage("Cost"), + "Contact_information": + MessageLookupByLibrary.simpleMessage("Contact information"), + "Cover": MessageLookupByLibrary.simpleMessage("Cover"), + "Creation": MessageLookupByLibrary.simpleMessage("Creation"), + "Creation_ja": MessageLookupByLibrary.simpleMessage("Creation"), + "Current_progress": + MessageLookupByLibrary.simpleMessage("Current progress"), + "Date_sort": MessageLookupByLibrary.simpleMessage("date sort"), + "Delete": MessageLookupByLibrary.simpleMessage("Delete"), + "Describe_in_detail": MessageLookupByLibrary.simpleMessage( + "Describe your vision in detail"), + "Distant_mountains": MessageLookupByLibrary.simpleMessage( + "Distant mountains, sunsets, sunsets, meadows, flowers, canyons, rivers, houses"), + "Download": MessageLookupByLibrary.simpleMessage("Download"), + "Draw_another_picture": + MessageLookupByLibrary.simpleMessage("Draw again"), + "Draw_the_same": MessageLookupByLibrary.simpleMessage("Draw the same"), + "Earn_paint": MessageLookupByLibrary.simpleMessage( + "Earn 1 paint point after watching 1 AD"), + "Easy_mode": MessageLookupByLibrary.simpleMessage("Easy mode"), + "Exhibition_works": + MessageLookupByLibrary.simpleMessage("Exhibition of works"), + "Exit_login": MessageLookupByLibrary.simpleMessage("Exit login"), + "Expand": MessageLookupByLibrary.simpleMessage("Expand"), + "Expert_selection": MessageLookupByLibrary.simpleMessage("Featured"), + "Fans": MessageLookupByLibrary.simpleMessage("Fans:"), + "Favorite": MessageLookupByLibrary.simpleMessage("Favorite"), + "Feedback": MessageLookupByLibrary.simpleMessage("Feedback"), + "Fill_in": MessageLookupByLibrary.simpleMessage( + "Fill in the invitation code to send"), + "Followed": MessageLookupByLibrary.simpleMessage("Followed"), + "Free": MessageLookupByLibrary.simpleMessage("Free"), + "Free_users": MessageLookupByLibrary.simpleMessage( + "Free users can only save 10 pictures"), + "Full_Watch": + MessageLookupByLibrary.simpleMessage("Full Watch Video (Today"), + "Gallery": MessageLookupByLibrary.simpleMessage("Gallery"), + "Generate_painting": MessageLookupByLibrary.simpleMessage("Generate"), + "Generate_time": MessageLookupByLibrary.simpleMessage("Generate time"), + "Get_saved": MessageLookupByLibrary.simpleMessage( + "Get 1 saved image after watching 1 advertisement"), + "Google": MessageLookupByLibrary.simpleMessage("Google"), + "Image_scale": MessageLookupByLibrary.simpleMessage("Image scale"), + "Image_too_large": + MessageLookupByLibrary.simpleMessage("Image too large"), + "In_review": MessageLookupByLibrary.simpleMessage("In review"), + "Insufficient_drawing_points": + MessageLookupByLibrary.simpleMessage("Insufficient drawing points"), + "Invitation_code": + MessageLookupByLibrary.simpleMessage("Invitation code"), + "Invite_new": MessageLookupByLibrary.simpleMessage( + "Invite new users to fill in the invitation code, reward 10 paint points"), + "Language_switching": + MessageLookupByLibrary.simpleMessage("Language switching"), + "Least_Favorite": + MessageLookupByLibrary.simpleMessage("Least Favorite"), + "Like_sorting": MessageLookupByLibrary.simpleMessage("like sorting"), + "Liked": MessageLookupByLibrary.simpleMessage("Liked:"), + "Long_hair": MessageLookupByLibrary.simpleMessage( + "Long hair girl, sitting in the garden swing, flowers, soft colors, face close-up"), + "Mall": MessageLookupByLibrary.simpleMessage("Mall"), + "Me": MessageLookupByLibrary.simpleMessage("Me"), + "More_pictures": MessageLookupByLibrary.simpleMessage( + "More pictures can be saved after paying"), + "Most_favorite": MessageLookupByLibrary.simpleMessage("Most favorite"), + "My_Works": MessageLookupByLibrary.simpleMessage("My Works"), + "New_users": MessageLookupByLibrary.simpleMessage("New users send"), + "Newest": MessageLookupByLibrary.simpleMessage("Newest"), + "Number_collections": + MessageLookupByLibrary.simpleMessage("Number of collections"), + "Number_of": MessageLookupByLibrary.simpleMessage( + "Number of purchased images \$"), + "Number_of_saved": + MessageLookupByLibrary.simpleMessage("Number of saved images"), + "Number_works": MessageLookupByLibrary.simpleMessage("Number of works"), + "Obtained_after_review": + MessageLookupByLibrary.simpleMessage("Obtained after review"), + "Oldest": MessageLookupByLibrary.simpleMessage("Oldest"), + "Paint_points": MessageLookupByLibrary.simpleMessage( + "Paint points are used according to options \nwhen generating paintings."), + "Painting_parameters": + MessageLookupByLibrary.simpleMessage("Painting parameters:"), + "Painting_point": + MessageLookupByLibrary.simpleMessage("Painting point"), + "Painting_points": MessageLookupByLibrary.simpleMessage("paint points"), + "Painting_points_never": MessageLookupByLibrary.simpleMessage( + "Painting points never expire and can be \nused at any time."), + "Painting_style": + MessageLookupByLibrary.simpleMessage("Painting style"), + "Please_describe": MessageLookupByLibrary.simpleMessage( + "Please describe in detail the problem you are experiencing"), + "Please_enter": MessageLookupByLibrary.simpleMessage( + "Please enter your email so that we can contact you"), + "Please_fill": MessageLookupByLibrary.simpleMessage( + "Please fill in the description of the picture"), + "Please_fill_in": MessageLookupByLibrary.simpleMessage( + "Please fill in the invitation code"), + "Please_select": + MessageLookupByLibrary.simpleMessage("Please select a work"), + "Please_wait": MessageLookupByLibrary.simpleMessage( + "Please wait for the generation to end"), + "Popular": MessageLookupByLibrary.simpleMessage("Popular"), + "Press_again": + MessageLookupByLibrary.simpleMessage("Press again to exit"), + "Privacy_Policy": + MessageLookupByLibrary.simpleMessage("Privacy Policy"), + "Random_Description": + MessageLookupByLibrary.simpleMessage("Random Description"), + "Random_suggested": MessageLookupByLibrary.simpleMessage( + "Random suggested words will overwrite what has been entered"), + "Rapeseed_flowers": MessageLookupByLibrary.simpleMessage( + "Rapeseed flowers bloom as far as the eye can see, a group of butterflies flying in the flowers"), + "Recommend": MessageLookupByLibrary.simpleMessage("Recommend"), + "Recommended_influencers": + MessageLookupByLibrary.simpleMessage("Recommended influencers"), + "Reference_drawing": + MessageLookupByLibrary.simpleMessage("Reference drawing"), + "Reference_drawing_redrawing": MessageLookupByLibrary.simpleMessage( + "Reference drawing redrawing degree"), + "Reference_image": + MessageLookupByLibrary.simpleMessage("Reference image description"), + "Regenerate": MessageLookupByLibrary.simpleMessage("Regenerate"), + "Request_cancellation": MessageLookupByLibrary.simpleMessage( + "Request for Account Cancellation"), + "Resolution": MessageLookupByLibrary.simpleMessage("Resolution"), + "Save": MessageLookupByLibrary.simpleMessage("Save"), + "Save_picture": + MessageLookupByLibrary.simpleMessage("Save picture is full"), + "Search_influential": + MessageLookupByLibrary.simpleMessage("Search for influencers"), + "Selected": MessageLookupByLibrary.simpleMessage("Selected"), + "Selects": MessageLookupByLibrary.simpleMessage("Selects"), + "Settings": MessageLookupByLibrary.simpleMessage("Settings"), + "Share": MessageLookupByLibrary.simpleMessage("Share"), + "Snow_mountain": MessageLookupByLibrary.simpleMessage( + "Snow mountain, forest, lake, sea of flowers, sun"), + "Sort_by": MessageLookupByLibrary.simpleMessage("Sort by"), + "Start_account_cancellation": MessageLookupByLibrary.simpleMessage( + "You are about to start the account cancellation process."), + "Submit": MessageLookupByLibrary.simpleMessage("Submit"), + "Successfully_saved": + MessageLookupByLibrary.simpleMessage("Successfully saved"), + "Sure": MessageLookupByLibrary.simpleMessage("Sure"), + "The_final_generated": MessageLookupByLibrary.simpleMessage( + "4. The final generated image will be reviewed, and images containing sensitive content will not be displayed."), + "The_function": MessageLookupByLibrary.simpleMessage( + "The function is about to open, please stay tuned"), + "The_reference": MessageLookupByLibrary.simpleMessage( + "1. The reference image file must be less than 10M."), + "The_smaller": MessageLookupByLibrary.simpleMessage( + "The lower the value, the more like a reference image; the higher the value, the more creative"), + "The_smaller_the": MessageLookupByLibrary.simpleMessage( + "2. The smaller the redraw value of the reference image, the more similar it is to the original image."), + "The_stars": MessageLookupByLibrary.simpleMessage( + "The stars, the ocean, the beach, the cabin"), + "The_subject": MessageLookupByLibrary.simpleMessage( + "The subject you want to paint"), + "Tip": MessageLookupByLibrary.simpleMessage("Tip"), + "To_create": MessageLookupByLibrary.simpleMessage("To create"), + "Upload": MessageLookupByLibrary.simpleMessage("Upload"), + "Upload_artwork_gallery": + MessageLookupByLibrary.simpleMessage("Upload artwork to gallery"), + "Upload_gallery": MessageLookupByLibrary.simpleMessage( + "Upload your work to the gallery, allowing more users to see your work"), + "Upload_successful": + MessageLookupByLibrary.simpleMessage("Upload successful"), + "Upload_the_painting": MessageLookupByLibrary.simpleMessage( + "Upload Gallery Pass Review Reward"), + "User_Agreement": + MessageLookupByLibrary.simpleMessage("User Agreement"), + "User_details": MessageLookupByLibrary.simpleMessage("User details"), + "Users_are_responsible": MessageLookupByLibrary.simpleMessage( + "3. Users are responsible for any legal disputes caused by reference images."), + "Using_the_reference": MessageLookupByLibrary.simpleMessage( + "5. Using the reference image function will consume 1 paint point."), + "Waiting_in": MessageLookupByLibrary.simpleMessage( + "Server is full, expect to queue for 10 mins, please wait"), + "Watch": MessageLookupByLibrary.simpleMessage("Watch"), + "Watch_the": + MessageLookupByLibrary.simpleMessage("Watch the full video"), + "What_kind": MessageLookupByLibrary.simpleMessage( + "What kind of images do you want to generate?"), + "Will_refer": MessageLookupByLibrary.simpleMessage( + "AI will generate with reference to the pictures you upload"), + "all": MessageLookupByLibrary.simpleMessage("all"), + "and": MessageLookupByLibrary.simpleMessage("and"), + "collect": MessageLookupByLibrary.simpleMessage("Collect"), + "copy_it": MessageLookupByLibrary.simpleMessage("copy it"), + "copy_prompt_word": + MessageLookupByLibrary.simpleMessage("copy prompt word"), + "details": MessageLookupByLibrary.simpleMessage("Details"), + "do_you": + MessageLookupByLibrary.simpleMessage("do you want to overwrite?"), + "follow": MessageLookupByLibrary.simpleMessage("follow"), + "for_instance": MessageLookupByLibrary.simpleMessage( + "for instance\"girl, long hair, sit on the swing, garden, pastel colors, face specific\""), + "guide": MessageLookupByLibrary.simpleMessage("Guide"), + "message": MessageLookupByLibrary.simpleMessage("Message"), + "more_detailed": MessageLookupByLibrary.simpleMessage( + "The more detailed the more accurate ~"), + "no_advertisements": MessageLookupByLibrary.simpleMessage( + "There are currently no advertisements available"), + "obtaining_benefits": MessageLookupByLibrary.simpleMessage("Equity"), + "point": MessageLookupByLibrary.simpleMessage("point"), + "problems_encountered": + MessageLookupByLibrary.simpleMessage("problems encountered"), + "received_all": MessageLookupByLibrary.simpleMessage( + "received all the drawing points today"), + "search": MessageLookupByLibrary.simpleMessage("search"), + "share_to_gallery": + MessageLookupByLibrary.simpleMessage("Upload to gallery"), + "some_unshared": MessageLookupByLibrary.simpleMessage( + ",and some unshared options will be cleared."), + "switch_the_subject": MessageLookupByLibrary.simpleMessage( + "Are you sure to switch the subject type?"), + "to_pay": MessageLookupByLibrary.simpleMessage("to pay"), + "uploaded": MessageLookupByLibrary.simpleMessage("uploaded") + }; +} diff --git a/lib/generated/intl/messages_ja.dart b/lib/generated/intl/messages_ja.dart new file mode 100644 index 0000000..3c6d7b2 --- /dev/null +++ b/lib/generated/intl/messages_ja.dart @@ -0,0 +1,113 @@ +// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart +// This is a library that provides messages for a ja locale. All the +// messages from the main program should be duplicated here with the same +// function name. + +// Ignore issues from commonly used lints in this file. +// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new +// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering +// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases +// ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes +// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes + +import 'package:intl/intl.dart'; +import 'package:intl/message_lookup_by_library.dart'; + +final messages = new MessageLookup(); + +typedef String MessageIfAbsent(String messageStr, List args); + +class MessageLookup extends MessageLookupByLibrary { + String get localeName => 'ja'; + + final messages = _notInlinedMessages(_notInlinedMessages); + static Map _notInlinedMessages(_) => { + "Account_cancellation": MessageLookupByLibrary.simpleMessage( + "Account Cancellation Request"), + "After_the_account_is_cancelled": MessageLookupByLibrary.simpleMessage( + "After the account is cancelled, all your data will be deleted and cannot be recovered."), + "Artist": MessageLookupByLibrary.simpleMessage("アーティスト"), + "Confirm_submission": MessageLookupByLibrary.simpleMessage("コミットの確認"), + "Consume": MessageLookupByLibrary.simpleMessage("消費"), + "Creation": MessageLookupByLibrary.simpleMessage("作成"), + "Creation_ja": MessageLookupByLibrary.simpleMessage("の作成"), + "Date_sort": MessageLookupByLibrary.simpleMessage("日付ソート"), + "Describe_in_detail": + MessageLookupByLibrary.simpleMessage("あなたのビジョンを詳しく説明してください"), + "Earn_paint": MessageLookupByLibrary.simpleMessage( + "1 つの広告を視聴すると 1 ペイント \nポイントを獲得"), + "Easy_mode": MessageLookupByLibrary.simpleMessage("単純"), + "Exhibition_works": MessageLookupByLibrary.simpleMessage("作品の展示"), + "Expert_selection": MessageLookupByLibrary.simpleMessage("専門家の選択"), + "Fans": MessageLookupByLibrary.simpleMessage("ファン:"), + "Followed": MessageLookupByLibrary.simpleMessage("フォローしました"), + "Free": MessageLookupByLibrary.simpleMessage("無料"), + "Full_Watch": MessageLookupByLibrary.simpleMessage("ビデオを完全に見る(今日"), + "Generate_painting": MessageLookupByLibrary.simpleMessage("生成"), + "Get_saved": + MessageLookupByLibrary.simpleMessage("1回の広告を見終わったら1つのセーブ数を得る"), + "Image_scale": MessageLookupByLibrary.simpleMessage("画像比率"), + "Language_switching": MessageLookupByLibrary.simpleMessage("言語切り替え"), + "Like_sorting": MessageLookupByLibrary.simpleMessage("いいねソート"), + "Liked": MessageLookupByLibrary.simpleMessage("気に入った:"), + "Number_of": MessageLookupByLibrary.simpleMessage("購入済在庫数"), + "Number_of_saved": MessageLookupByLibrary.simpleMessage("メモリ数"), + "Obtained_after_review": + MessageLookupByLibrary.simpleMessage("レビュー後に取得"), + "Painting_parameters": + MessageLookupByLibrary.simpleMessage("ペイントパラメータ:"), + "Painting_points": MessageLookupByLibrary.simpleMessage("ペイントポイント"), + "Painting_style": MessageLookupByLibrary.simpleMessage("絵画スタイル"), + "Popular": MessageLookupByLibrary.simpleMessage("人気のある"), + "Random_Description": + MessageLookupByLibrary.simpleMessage("ランダムなおすすめワード"), + "Recommended_influencers": + MessageLookupByLibrary.simpleMessage("おすすめ達人"), + "Reference_drawing": MessageLookupByLibrary.simpleMessage("参考画像"), + "Reference_drawing_redrawing": + MessageLookupByLibrary.simpleMessage("参照マップ再描画度"), + "Reference_image": MessageLookupByLibrary.simpleMessage("参考図の説明"), + "Request_cancellation": MessageLookupByLibrary.simpleMessage( + "Request for Account Cancellation"), + "Search_influential": MessageLookupByLibrary.simpleMessage("検索の達人"), + "Start_account_cancellation": MessageLookupByLibrary.simpleMessage( + "You are about to start the account cancellation process."), + "The_final_generated": MessageLookupByLibrary.simpleMessage( + "4. 最終的に生成された画像が確認され、機密コンテンツを含む画像は表示されません。"), + "The_reference": MessageLookupByLibrary.simpleMessage( + "1. 参照画像ファイルは 10M 未満である必要があります"), + "The_smaller": MessageLookupByLibrary.simpleMessage( + "値が低いほど参照画像に類似し、値が高いほどクリエイティブになります。"), + "The_smaller_the": MessageLookupByLibrary.simpleMessage( + "2. 参照画像の再描画値が小さいほど、元の画像に近づきます。"), + "Upload": MessageLookupByLibrary.simpleMessage("送信"), + "Upload_gallery": MessageLookupByLibrary.simpleMessage( + "ギャラリーに作品をアップロードして、より多くのユーザーに作品を見てもらう"), + "Upload_successful": + MessageLookupByLibrary.simpleMessage("アップロードに成功しました"), + "Upload_the_painting": + MessageLookupByLibrary.simpleMessage("絵画がギャラリーにアップロードされ、承認されて"), + "User_details": MessageLookupByLibrary.simpleMessage("ユーザーの詳細"), + "Users_are_responsible": MessageLookupByLibrary.simpleMessage( + "3. 参考画像に起因する法的紛争については、利用者が責任を負います。"), + "Using_the_reference": MessageLookupByLibrary.simpleMessage( + "5. 参照画像機能を使用すると描画ポイントを1消費します。"), + "Watch": MessageLookupByLibrary.simpleMessage("見る"), + "Watch_the": MessageLookupByLibrary.simpleMessage("ビデオを完全に見る"), + "Will_refer": MessageLookupByLibrary.simpleMessage( + "上で説明したように、参照画像をスタイル ペイントに変換します。"), + "all": MessageLookupByLibrary.simpleMessage("全て"), + "copy_it": MessageLookupByLibrary.simpleMessage("コピーしてください"), + "copy_prompt_word": + MessageLookupByLibrary.simpleMessage("プロンプトの単語をコピーする"), + "follow": MessageLookupByLibrary.simpleMessage("フォローする"), + "for_instance": MessageLookupByLibrary.simpleMessage( + "「髪の長い女の子、庭のブランコに座る、花、パステルカラー、顔のクローズアップ」など"), + "guide": MessageLookupByLibrary.simpleMessage("ガイド"), + "more_detailed": + MessageLookupByLibrary.simpleMessage("説明が詳細であればあるほど、画像はより正確になります〜"), + "obtaining_benefits": MessageLookupByLibrary.simpleMessage("資本"), + "point": MessageLookupByLibrary.simpleMessage("ポイント"), + "search": MessageLookupByLibrary.simpleMessage("検索けんさく") + }; +} diff --git a/lib/generated/intl/messages_zh.dart b/lib/generated/intl/messages_zh.dart new file mode 100644 index 0000000..6bffd5c --- /dev/null +++ b/lib/generated/intl/messages_zh.dart @@ -0,0 +1,219 @@ +// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart +// This is a library that provides messages for a zh locale. All the +// messages from the main program should be duplicated here with the same +// function name. + +// Ignore issues from commonly used lints in this file. +// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new +// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering +// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases +// ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes +// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes + +import 'package:intl/intl.dart'; +import 'package:intl/message_lookup_by_library.dart'; + +final messages = new MessageLookup(); + +typedef String MessageIfAbsent(String messageStr, List args); + +class MessageLookup extends MessageLookupByLibrary { + String get localeName => 'zh'; + + final messages = _notInlinedMessages(_notInlinedMessages); + static Map _notInlinedMessages(_) => { + "A_close": + MessageLookupByLibrary.simpleMessage("漂亮女孩的脸特写,被光晕包围,空灵,浪漫,梦幻,精致"), + "A_colorful": MessageLookupByLibrary.simpleMessage("水晶球里的彩色魔法城堡"), + "About": MessageLookupByLibrary.simpleMessage("关于"), + "Account_cancellation": MessageLookupByLibrary.simpleMessage("账号申请注销"), + "After_confirmation": + MessageLookupByLibrary.simpleMessage("确认后主题类型将替换为"), + "After_rain": MessageLookupByLibrary.simpleMessage( + "雨后,清澈的色彩,阳光,粉色花朵,宁静,柔和的焦点,追逐的蝴蝶"), + "After_the_account_is_cancelled": + MessageLookupByLibrary.simpleMessage("账号注销后,您所有的数据都将删除,且无法找回。"), + "Already_copied": MessageLookupByLibrary.simpleMessage("描述已复制进剪切版"), + "Are_you_sure": + MessageLookupByLibrary.simpleMessage("确定永久删除这张作品吗\n删除后将不能找回"), + "Artist": MessageLookupByLibrary.simpleMessage("艺术家"), + "Author": MessageLookupByLibrary.simpleMessage("作者"), + "Beautiful_angel": MessageLookupByLibrary.simpleMessage( + "美丽的天使,白色翅膀,头顶光环,金色长发,御姐,女王气质"), + "Brunette_princess": + MessageLookupByLibrary.simpleMessage("黑发公主,头戴皇冠,华丽,萤火虫,森林背景,优雅"), + "By_continuing": MessageLookupByLibrary.simpleMessage("继续即同意HissAi的"), + "Cancel": MessageLookupByLibrary.simpleMessage("取消"), + "Check_in": MessageLookupByLibrary.simpleMessage("画面生成后在“我的”查看"), + "Close": MessageLookupByLibrary.simpleMessage("关闭"), + "Collected": MessageLookupByLibrary.simpleMessage("被收藏"), + "Collection": MessageLookupByLibrary.simpleMessage("收藏"), + "Confirm_submission": MessageLookupByLibrary.simpleMessage("确认提交"), + "Consume": MessageLookupByLibrary.simpleMessage("消耗"), + "Contact_information": MessageLookupByLibrary.simpleMessage("联系方式"), + "Cover": MessageLookupByLibrary.simpleMessage("确定"), + "Creation": MessageLookupByLibrary.simpleMessage("创作"), + "Creation_ja": MessageLookupByLibrary.simpleMessage("创作"), + "Current_progress": MessageLookupByLibrary.simpleMessage("当前进度"), + "Date_sort": MessageLookupByLibrary.simpleMessage("日期排序"), + "Delete": MessageLookupByLibrary.simpleMessage("删除"), + "Describe_in_detail": + MessageLookupByLibrary.simpleMessage("详细描述你想象中的画面"), + "Distant_mountains": + MessageLookupByLibrary.simpleMessage("远山,落日,夕阳,草地,鲜花,峡谷,河流,房屋"), + "Download": MessageLookupByLibrary.simpleMessage("下载"), + "Draw_another_picture": MessageLookupByLibrary.simpleMessage("再画一张"), + "Draw_the_same": MessageLookupByLibrary.simpleMessage("画同款"), + "Earn_paint": MessageLookupByLibrary.simpleMessage("看完1次广告获得1绘画点"), + "Easy_mode": MessageLookupByLibrary.simpleMessage("简易"), + "Exhibition_works": MessageLookupByLibrary.simpleMessage("作品展示"), + "Exit_login": MessageLookupByLibrary.simpleMessage("退出登录"), + "Expand": MessageLookupByLibrary.simpleMessage("展开"), + "Expert_selection": MessageLookupByLibrary.simpleMessage("达人精选"), + "Fans": MessageLookupByLibrary.simpleMessage("粉丝:"), + "Favorite": MessageLookupByLibrary.simpleMessage("已收藏"), + "Feedback": MessageLookupByLibrary.simpleMessage("反馈"), + "Fill_in": MessageLookupByLibrary.simpleMessage("填写邀请码送"), + "Followed": MessageLookupByLibrary.simpleMessage("已关注"), + "Free": MessageLookupByLibrary.simpleMessage("免费"), + "Free_users": MessageLookupByLibrary.simpleMessage("免费用户仅可保存10张图片"), + "Full_Watch": MessageLookupByLibrary.simpleMessage("完整观看视频(今日"), + "Gallery": MessageLookupByLibrary.simpleMessage("画廊"), + "Generate_painting": MessageLookupByLibrary.simpleMessage("生成"), + "Generate_time": MessageLookupByLibrary.simpleMessage("生成时间"), + "Get_saved": MessageLookupByLibrary.simpleMessage("看完1次广告获取1存图数"), + "Google": MessageLookupByLibrary.simpleMessage("谷歌登录"), + "Image_scale": MessageLookupByLibrary.simpleMessage("图片比例"), + "Image_too_large": MessageLookupByLibrary.simpleMessage("图片过大"), + "In_review": MessageLookupByLibrary.simpleMessage("审核中"), + "Insufficient_drawing_points": + MessageLookupByLibrary.simpleMessage("绘画点不足"), + "Invitation_code": MessageLookupByLibrary.simpleMessage("邀请码"), + "Invite_new": + MessageLookupByLibrary.simpleMessage("邀请新用户填写邀请码,奖励10绘画点"), + "Language_switching": MessageLookupByLibrary.simpleMessage("语言切换"), + "Least_Favorite": MessageLookupByLibrary.simpleMessage("收藏最少"), + "Like_sorting": MessageLookupByLibrary.simpleMessage("获赞排序"), + "Liked": MessageLookupByLibrary.simpleMessage("获赞:"), + "Long_hair": + MessageLookupByLibrary.simpleMessage("长发女孩,坐在花园的秋千上,鲜花,色彩柔和,脸部特写"), + "Mall": MessageLookupByLibrary.simpleMessage("商城"), + "Me": MessageLookupByLibrary.simpleMessage("我的"), + "More_pictures": MessageLookupByLibrary.simpleMessage("付费后可保存更多图片"), + "Most_favorite": MessageLookupByLibrary.simpleMessage("收藏最多"), + "My_Works": MessageLookupByLibrary.simpleMessage("我的作品"), + "New_users": MessageLookupByLibrary.simpleMessage("新用户注册送"), + "Newest": MessageLookupByLibrary.simpleMessage("最新"), + "Number_collections": MessageLookupByLibrary.simpleMessage("收藏数量"), + "Number_of": MessageLookupByLibrary.simpleMessage("购买存图数¥"), + "Number_of_saved": MessageLookupByLibrary.simpleMessage("存图数"), + "Number_works": MessageLookupByLibrary.simpleMessage("作品数量"), + "Obtained_after_review": + MessageLookupByLibrary.simpleMessage("通过审核后获得"), + "Oldest": MessageLookupByLibrary.simpleMessage("最早"), + "Paint_points": + MessageLookupByLibrary.simpleMessage("生成绘画时根据选项将消耗一定绘画点."), + "Painting_parameters": MessageLookupByLibrary.simpleMessage("绘画参数:"), + "Painting_point": MessageLookupByLibrary.simpleMessage("绘画点"), + "Painting_points": MessageLookupByLibrary.simpleMessage("绘画点"), + "Painting_points_never": + MessageLookupByLibrary.simpleMessage("绘画点永不过期, 可以随时使用."), + "Painting_style": MessageLookupByLibrary.simpleMessage("绘画风格"), + "Please_describe": MessageLookupByLibrary.simpleMessage("请详细描述您遇到的问题"), + "Please_enter": + MessageLookupByLibrary.simpleMessage("请输入您的邮箱,方便我们与您联系"), + "Please_fill": MessageLookupByLibrary.simpleMessage("请填写画面描述"), + "Please_fill_in": MessageLookupByLibrary.simpleMessage("请填写邀请码"), + "Please_select": MessageLookupByLibrary.simpleMessage("请选择作品"), + "Please_wait": MessageLookupByLibrary.simpleMessage("请等待生成结束"), + "Popular": MessageLookupByLibrary.simpleMessage("热门"), + "Press_again": MessageLookupByLibrary.simpleMessage("再按一次退出"), + "Privacy_Policy": MessageLookupByLibrary.simpleMessage("隐私协议"), + "Random_Description": MessageLookupByLibrary.simpleMessage("点这里试试推荐词"), + "Random_suggested": + MessageLookupByLibrary.simpleMessage("随机推荐词将覆盖已输入的内容"), + "Rapeseed_flowers": + MessageLookupByLibrary.simpleMessage("油菜花开花,一望无际,一群蝴蝶在花丛中飞舞"), + "Recommend": MessageLookupByLibrary.simpleMessage("推荐"), + "Recommended_influencers": MessageLookupByLibrary.simpleMessage("推荐达人"), + "Reference_drawing": MessageLookupByLibrary.simpleMessage("参考图"), + "Reference_drawing_redrawing": + MessageLookupByLibrary.simpleMessage("参考图重绘度"), + "Reference_image": MessageLookupByLibrary.simpleMessage("参考图说明"), + "Regenerate": MessageLookupByLibrary.simpleMessage("重新生成"), + "Request_cancellation": MessageLookupByLibrary.simpleMessage("申请注销"), + "Resolution": MessageLookupByLibrary.simpleMessage("分辨率"), + "Save": MessageLookupByLibrary.simpleMessage("保存"), + "Save_picture": MessageLookupByLibrary.simpleMessage("保存图片已达上限"), + "Search_influential": MessageLookupByLibrary.simpleMessage("搜索达人"), + "Selected": MessageLookupByLibrary.simpleMessage("已选中"), + "Selects": MessageLookupByLibrary.simpleMessage("多选"), + "Settings": MessageLookupByLibrary.simpleMessage("设置"), + "Share": MessageLookupByLibrary.simpleMessage("分享"), + "Snow_mountain": MessageLookupByLibrary.simpleMessage("雪山,森林,湖泊,花海,太阳"), + "Sort_by": MessageLookupByLibrary.simpleMessage("排序"), + "Start_account_cancellation": + MessageLookupByLibrary.simpleMessage("您即将开始账号注销流程。"), + "Submit": MessageLookupByLibrary.simpleMessage("提交"), + "Successfully_saved": MessageLookupByLibrary.simpleMessage("保存成功"), + "Sure": MessageLookupByLibrary.simpleMessage("确定"), + "The_final_generated": MessageLookupByLibrary.simpleMessage( + "4.最终的生成图会进行审核,含有敏感内容的图片将无法展示。"), + "The_function": MessageLookupByLibrary.simpleMessage("功能即将开放,敬请期待"), + "The_reference": MessageLookupByLibrary.simpleMessage("1.参考图文件需小于10M。"), + "The_smaller": + MessageLookupByLibrary.simpleMessage("数值越低,与参考图越相似;数值越高,越充满创意"), + "The_smaller_the": + MessageLookupByLibrary.simpleMessage("2.参考图重绘度值越小,与原图越相似。"), + "The_stars": MessageLookupByLibrary.simpleMessage("星空,海洋,沙滩,木屋"), + "The_subject": MessageLookupByLibrary.simpleMessage("你想绘画的主体"), + "Tip": MessageLookupByLibrary.simpleMessage("提示"), + "To_create": MessageLookupByLibrary.simpleMessage("去创作"), + "Upload": MessageLookupByLibrary.simpleMessage("上传"), + "Upload_artwork_gallery": + MessageLookupByLibrary.simpleMessage("作品上传至画廊"), + "Upload_gallery": + MessageLookupByLibrary.simpleMessage("上传作品至画廊,让更多用户看到您的作品"), + "Upload_successful": MessageLookupByLibrary.simpleMessage("上传成功"), + "Upload_the_painting": + MessageLookupByLibrary.simpleMessage("绘画上传至画廊并通过审核奖励"), + "User_Agreement": MessageLookupByLibrary.simpleMessage("用户协议"), + "User_details": MessageLookupByLibrary.simpleMessage("用户详情"), + "Users_are_responsible": + MessageLookupByLibrary.simpleMessage("3.因参考图造成的法律纠纷用户需要自行负责。"), + "Using_the_reference": + MessageLookupByLibrary.simpleMessage("5.使用参考图功能,将消耗1绘画点。"), + "Waiting_in": + MessageLookupByLibrary.simpleMessage("服务器已满,预计排队10分钟,请稍等"), + "Watch": MessageLookupByLibrary.simpleMessage("观看"), + "Watch_the": MessageLookupByLibrary.simpleMessage("完整观看视频"), + "What_kind": MessageLookupByLibrary.simpleMessage("希望生成什么种类的图片呢?"), + "Will_refer": MessageLookupByLibrary.simpleMessage("将参考图转化为上述描写的风格画作"), + "all": MessageLookupByLibrary.simpleMessage("全部"), + "and": MessageLookupByLibrary.simpleMessage("和"), + "collect": MessageLookupByLibrary.simpleMessage("收藏"), + "copy_it": MessageLookupByLibrary.simpleMessage("画同款"), + "copy_prompt_word": MessageLookupByLibrary.simpleMessage("复制提示词"), + "details": MessageLookupByLibrary.simpleMessage("详情"), + "do_you": MessageLookupByLibrary.simpleMessage("是否要覆盖?"), + "follow": MessageLookupByLibrary.simpleMessage("关注"), + "for_instance": MessageLookupByLibrary.simpleMessage( + "如“长发女孩,坐在花园的秋千上,鲜花,色彩柔和,脸部特写”"), + "guide": MessageLookupByLibrary.simpleMessage("引导模式"), + "message": MessageLookupByLibrary.simpleMessage("消息"), + "more_detailed": MessageLookupByLibrary.simpleMessage("描述越详细画面越精准哦~"), + "no_advertisements": MessageLookupByLibrary.simpleMessage("暂无广告"), + "obtaining_benefits": MessageLookupByLibrary.simpleMessage("获取权益"), + "point": MessageLookupByLibrary.simpleMessage("点"), + "problems_encountered": MessageLookupByLibrary.simpleMessage("遇到的问题"), + "received_all": MessageLookupByLibrary.simpleMessage("今天绘画点已领完"), + "search": MessageLookupByLibrary.simpleMessage("搜索"), + "share_to_gallery": MessageLookupByLibrary.simpleMessage("上传至画廊"), + "some_unshared": + MessageLookupByLibrary.simpleMessage(",某些不共用的选择项将会被清空。"), + "switch_the_subject": + MessageLookupByLibrary.simpleMessage("确认切换主题类型吗?"), + "to_pay": MessageLookupByLibrary.simpleMessage("去付费"), + "uploaded": MessageLookupByLibrary.simpleMessage("已上传") + }; +} diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart new file mode 100644 index 0000000..7c339cf --- /dev/null +++ b/lib/generated/l10n.dart @@ -0,0 +1,1690 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'intl/messages_all.dart'; + +// ************************************************************************** +// Generator: Flutter Intl IDE plugin +// Made by Localizely +// ************************************************************************** + +// ignore_for_file: non_constant_identifier_names, lines_longer_than_80_chars +// ignore_for_file: join_return_with_assignment, prefer_final_in_for_each +// ignore_for_file: avoid_redundant_argument_values, avoid_escaping_inner_quotes + +class S { + S(); + + static S? _current; + + static S get current { + assert(_current != null, + 'No instance of S was loaded. Try to initialize the S delegate before accessing S.current.'); + return _current!; + } + + static const AppLocalizationDelegate delegate = AppLocalizationDelegate(); + + static Future load(Locale locale) { + final name = (locale.countryCode?.isEmpty ?? false) + ? locale.languageCode + : locale.toString(); + final localeName = Intl.canonicalizedLocale(name); + return initializeMessages(localeName).then((_) { + Intl.defaultLocale = localeName; + final instance = S(); + S._current = instance; + + return instance; + }); + } + + static S of(BuildContext context) { + final instance = S.maybeOf(context); + assert(instance != null, + 'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?'); + return instance!; + } + + static S? maybeOf(BuildContext context) { + return Localizations.of(context, S); + } + + /// `By continuing, you agree to HissAi` + String get By_continuing { + return Intl.message( + 'By continuing, you agree to HissAi', + name: 'By_continuing', + desc: '', + args: [], + ); + } + + /// `User Agreement` + String get User_Agreement { + return Intl.message( + 'User Agreement', + name: 'User_Agreement', + desc: '', + args: [], + ); + } + + /// `and` + String get and { + return Intl.message( + 'and', + name: 'and', + desc: '', + args: [], + ); + } + + /// `Privacy Policy` + String get Privacy_Policy { + return Intl.message( + 'Privacy Policy', + name: 'Privacy_Policy', + desc: '', + args: [], + ); + } + + /// `Google` + String get Google { + return Intl.message( + 'Google', + name: 'Google', + desc: '', + args: [], + ); + } + + /// `Gallery` + String get Gallery { + return Intl.message( + 'Gallery', + name: 'Gallery', + desc: '', + args: [], + ); + } + + /// `Creation` + String get Creation { + return Intl.message( + 'Creation', + name: 'Creation', + desc: '', + args: [], + ); + } + + /// `Upload` + String get Upload { + return Intl.message( + 'Upload', + name: 'Upload', + desc: '', + args: [], + ); + } + + /// `Confirm submission` + String get Confirm_submission { + return Intl.message( + 'Confirm submission', + name: 'Confirm_submission', + desc: '', + args: [], + ); + } + + /// `Upload your work to the gallery, allowing more users to see your work` + String get Upload_gallery { + return Intl.message( + 'Upload your work to the gallery, allowing more users to see your work', + name: 'Upload_gallery', + desc: '', + args: [], + ); + } + + /// `Upload successful` + String get Upload_successful { + return Intl.message( + 'Upload successful', + name: 'Upload_successful', + desc: '', + args: [], + ); + } + + /// `Creation` + String get Creation_ja { + return Intl.message( + 'Creation', + name: 'Creation_ja', + desc: '', + args: [], + ); + } + + /// `Me` + String get Me { + return Intl.message( + 'Me', + name: 'Me', + desc: '', + args: [], + ); + } + + /// `Recommend` + String get Recommend { + return Intl.message( + 'Recommend', + name: 'Recommend', + desc: '', + args: [], + ); + } + + /// `Describe your vision in detail` + String get Describe_in_detail { + return Intl.message( + 'Describe your vision in detail', + name: 'Describe_in_detail', + desc: '', + args: [], + ); + } + + /// `for instance"girl, long hair, sit on the swing, garden, pastel colors, face specific"` + String get for_instance { + return Intl.message( + 'for instance"girl, long hair, sit on the swing, garden, pastel colors, face specific"', + name: 'for_instance', + desc: '', + args: [], + ); + } + + /// `The more detailed the more accurate ~` + String get more_detailed { + return Intl.message( + 'The more detailed the more accurate ~', + name: 'more_detailed', + desc: '', + args: [], + ); + } + + /// `Random Description` + String get Random_Description { + return Intl.message( + 'Random Description', + name: 'Random_Description', + desc: '', + args: [], + ); + } + + /// `Easy mode` + String get Easy_mode { + return Intl.message( + 'Easy mode', + name: 'Easy_mode', + desc: '', + args: [], + ); + } + + /// `Guide` + String get guide { + return Intl.message( + 'Guide', + name: 'guide', + desc: '', + args: [], + ); + } + + /// `Artist` + String get Artist { + return Intl.message( + 'Artist', + name: 'Artist', + desc: '', + args: [], + ); + } + + /// `Painting style` + String get Painting_style { + return Intl.message( + 'Painting style', + name: 'Painting_style', + desc: '', + args: [], + ); + } + + /// `Reference drawing` + String get Reference_drawing { + return Intl.message( + 'Reference drawing', + name: 'Reference_drawing', + desc: '', + args: [], + ); + } + + /// `AI will generate with reference to the pictures you upload` + String get Will_refer { + return Intl.message( + 'AI will generate with reference to the pictures you upload', + name: 'Will_refer', + desc: '', + args: [], + ); + } + + /// `Image scale` + String get Image_scale { + return Intl.message( + 'Image scale', + name: 'Image_scale', + desc: '', + args: [], + ); + } + + /// `Generate` + String get Generate_painting { + return Intl.message( + 'Generate', + name: 'Generate_painting', + desc: '', + args: [], + ); + } + + /// `Please fill in the description of the picture` + String get Please_fill { + return Intl.message( + 'Please fill in the description of the picture', + name: 'Please_fill', + desc: '', + args: [], + ); + } + + /// `Reference image description` + String get Reference_image { + return Intl.message( + 'Reference image description', + name: 'Reference_image', + desc: '', + args: [], + ); + } + + /// `Details` + String get details { + return Intl.message( + 'Details', + name: 'details', + desc: '', + args: [], + ); + } + + /// `Current progress` + String get Current_progress { + return Intl.message( + 'Current progress', + name: 'Current_progress', + desc: '', + args: [], + ); + } + + /// `Already copied` + String get Already_copied { + return Intl.message( + 'Already copied', + name: 'Already_copied', + desc: '', + args: [], + ); + } + + /// `Delete` + String get Delete { + return Intl.message( + 'Delete', + name: 'Delete', + desc: '', + args: [], + ); + } + + /// `Download` + String get Download { + return Intl.message( + 'Download', + name: 'Download', + desc: '', + args: [], + ); + } + + /// `Regenerate` + String get Regenerate { + return Intl.message( + 'Regenerate', + name: 'Regenerate', + desc: '', + args: [], + ); + } + + /// `Upload to gallery` + String get share_to_gallery { + return Intl.message( + 'Upload to gallery', + name: 'share_to_gallery', + desc: '', + args: [], + ); + } + + /// `Check in "Me" after the screen is created` + String get Check_in { + return Intl.message( + 'Check in "Me" after the screen is created', + name: 'Check_in', + desc: '', + args: [], + ); + } + + /// `Generate time` + String get Generate_time { + return Intl.message( + 'Generate time', + name: 'Generate_time', + desc: '', + args: [], + ); + } + + /// `Resolution` + String get Resolution { + return Intl.message( + 'Resolution', + name: 'Resolution', + desc: '', + args: [], + ); + } + + /// `Image too large` + String get Image_too_large { + return Intl.message( + 'Image too large', + name: 'Image_too_large', + desc: '', + args: [], + ); + } + + /// `Collect` + String get collect { + return Intl.message( + 'Collect', + name: 'collect', + desc: '', + args: [], + ); + } + + /// `Favorite` + String get Favorite { + return Intl.message( + 'Favorite', + name: 'Favorite', + desc: '', + args: [], + ); + } + + /// `Reference drawing redrawing degree` + String get Reference_drawing_redrawing { + return Intl.message( + 'Reference drawing redrawing degree', + name: 'Reference_drawing_redrawing', + desc: '', + args: [], + ); + } + + /// `Painting point` + String get Painting_point { + return Intl.message( + 'Painting point', + name: 'Painting_point', + desc: '', + args: [], + ); + } + + /// `Collected` + String get Collected { + return Intl.message( + 'Collected', + name: 'Collected', + desc: '', + args: [], + ); + } + + /// `My Works` + String get My_Works { + return Intl.message( + 'My Works', + name: 'My_Works', + desc: '', + args: [], + ); + } + + /// `Collection` + String get Collection { + return Intl.message( + 'Collection', + name: 'Collection', + desc: '', + args: [], + ); + } + + /// `Number of works` + String get Number_works { + return Intl.message( + 'Number of works', + name: 'Number_works', + desc: '', + args: [], + ); + } + + /// `Selects` + String get Selects { + return Intl.message( + 'Selects', + name: 'Selects', + desc: '', + args: [], + ); + } + + /// `Sort by` + String get Sort_by { + return Intl.message( + 'Sort by', + name: 'Sort_by', + desc: '', + args: [], + ); + } + + /// `Cancel` + String get Cancel { + return Intl.message( + 'Cancel', + name: 'Cancel', + desc: '', + args: [], + ); + } + + /// `Selected` + String get Selected { + return Intl.message( + 'Selected', + name: 'Selected', + desc: '', + args: [], + ); + } + + /// `Number of collections` + String get Number_collections { + return Intl.message( + 'Number of collections', + name: 'Number_collections', + desc: '', + args: [], + ); + } + + /// `Newest` + String get Newest { + return Intl.message( + 'Newest', + name: 'Newest', + desc: '', + args: [], + ); + } + + /// `Oldest` + String get Oldest { + return Intl.message( + 'Oldest', + name: 'Oldest', + desc: '', + args: [], + ); + } + + /// `Most favorite` + String get Most_favorite { + return Intl.message( + 'Most favorite', + name: 'Most_favorite', + desc: '', + args: [], + ); + } + + /// `Least Favorite` + String get Least_Favorite { + return Intl.message( + 'Least Favorite', + name: 'Least_Favorite', + desc: '', + args: [], + ); + } + + /// `The function is about to open, please stay tuned` + String get The_function { + return Intl.message( + 'The function is about to open, please stay tuned', + name: 'The_function', + desc: '', + args: [], + ); + } + + /// `Author` + String get Author { + return Intl.message( + 'Author', + name: 'Author', + desc: '', + args: [], + ); + } + + /// `Cost` + String get Consume { + return Intl.message( + 'Cost', + name: 'Consume', + desc: '', + args: [], + ); + } + + /// `point` + String get point { + return Intl.message( + 'point', + name: 'point', + desc: '', + args: [], + ); + } + + /// `Press again to exit` + String get Press_again { + return Intl.message( + 'Press again to exit', + name: 'Press_again', + desc: '', + args: [], + ); + } + + /// `Tip` + String get Tip { + return Intl.message( + 'Tip', + name: 'Tip', + desc: '', + args: [], + ); + } + + /// `Are you sure to permanently delete this work? \nAfter deletion, it will not be able to be retrieved` + String get Are_you_sure { + return Intl.message( + 'Are you sure to permanently delete this work? \nAfter deletion, it will not be able to be retrieved', + name: 'Are_you_sure', + desc: '', + args: [], + ); + } + + /// `Sure` + String get Sure { + return Intl.message( + 'Sure', + name: 'Sure', + desc: '', + args: [], + ); + } + + /// `Successfully saved` + String get Successfully_saved { + return Intl.message( + 'Successfully saved', + name: 'Successfully_saved', + desc: '', + args: [], + ); + } + + /// `Settings` + String get Settings { + return Intl.message( + 'Settings', + name: 'Settings', + desc: '', + args: [], + ); + } + + /// `About` + String get About { + return Intl.message( + 'About', + name: 'About', + desc: '', + args: [], + ); + } + + /// `The lower the value, the more like a reference image; the higher the value, the more creative` + String get The_smaller { + return Intl.message( + 'The lower the value, the more like a reference image; the higher the value, the more creative', + name: 'The_smaller', + desc: '', + args: [], + ); + } + + /// `Please select a work` + String get Please_select { + return Intl.message( + 'Please select a work', + name: 'Please_select', + desc: '', + args: [], + ); + } + + /// `1. The reference image file must be less than 10M.` + String get The_reference { + return Intl.message( + '1. The reference image file must be less than 10M.', + name: 'The_reference', + desc: '', + args: [], + ); + } + + /// `2. The smaller the redraw value of the reference image, the more similar it is to the original image.` + String get The_smaller_the { + return Intl.message( + '2. The smaller the redraw value of the reference image, the more similar it is to the original image.', + name: 'The_smaller_the', + desc: '', + args: [], + ); + } + + /// `3. Users are responsible for any legal disputes caused by reference images.` + String get Users_are_responsible { + return Intl.message( + '3. Users are responsible for any legal disputes caused by reference images.', + name: 'Users_are_responsible', + desc: '', + args: [], + ); + } + + /// `4. The final generated image will be reviewed, and images containing sensitive content will not be displayed.` + String get The_final_generated { + return Intl.message( + '4. The final generated image will be reviewed, and images containing sensitive content will not be displayed.', + name: 'The_final_generated', + desc: '', + args: [], + ); + } + + /// `5. Using the reference image function will consume 1 paint point.` + String get Using_the_reference { + return Intl.message( + '5. Using the reference image function will consume 1 paint point.', + name: 'Using_the_reference', + desc: '', + args: [], + ); + } + + /// `Insufficient drawing points` + String get Insufficient_drawing_points { + return Intl.message( + 'Insufficient drawing points', + name: 'Insufficient_drawing_points', + desc: '', + args: [], + ); + } + + /// `Draw again` + String get Draw_another_picture { + return Intl.message( + 'Draw again', + name: 'Draw_another_picture', + desc: '', + args: [], + ); + } + + /// `Draw the same` + String get Draw_the_same { + return Intl.message( + 'Draw the same', + name: 'Draw_the_same', + desc: '', + args: [], + ); + } + + /// `A colorful magic castle in a crystal ball` + String get A_colorful { + return Intl.message( + 'A colorful magic castle in a crystal ball', + name: 'A_colorful', + desc: '', + args: [], + ); + } + + /// `Brunette princess, crown on head, gorgeous, firefly, forest background, elegant` + String get Brunette_princess { + return Intl.message( + 'Brunette princess, crown on head, gorgeous, firefly, forest background, elegant', + name: 'Brunette_princess', + desc: '', + args: [], + ); + } + + /// `Beautiful angel, white wings, halo, long blonde hair, royal sister, queen temperament` + String get Beautiful_angel { + return Intl.message( + 'Beautiful angel, white wings, halo, long blonde hair, royal sister, queen temperament', + name: 'Beautiful_angel', + desc: '', + args: [], + ); + } + + /// `Rapeseed flowers bloom as far as the eye can see, a group of butterflies flying in the flowers` + String get Rapeseed_flowers { + return Intl.message( + 'Rapeseed flowers bloom as far as the eye can see, a group of butterflies flying in the flowers', + name: 'Rapeseed_flowers', + desc: '', + args: [], + ); + } + + /// `Long hair girl, sitting in the garden swing, flowers, soft colors, face close-up` + String get Long_hair { + return Intl.message( + 'Long hair girl, sitting in the garden swing, flowers, soft colors, face close-up', + name: 'Long_hair', + desc: '', + args: [], + ); + } + + /// `A close-up of a pretty girl's face, surrounded by halo, ethereal, romantic, dreamy, delicate` + String get A_close { + return Intl.message( + 'A close-up of a pretty girl\'s face, surrounded by halo, ethereal, romantic, dreamy, delicate', + name: 'A_close', + desc: '', + args: [], + ); + } + + /// `After rain, clear colors, sunshine, pink flowers, quiet, soft focus, chasing butterflies` + String get After_rain { + return Intl.message( + 'After rain, clear colors, sunshine, pink flowers, quiet, soft focus, chasing butterflies', + name: 'After_rain', + desc: '', + args: [], + ); + } + + /// `Distant mountains, sunsets, sunsets, meadows, flowers, canyons, rivers, houses` + String get Distant_mountains { + return Intl.message( + 'Distant mountains, sunsets, sunsets, meadows, flowers, canyons, rivers, houses', + name: 'Distant_mountains', + desc: '', + args: [], + ); + } + + /// `Snow mountain, forest, lake, sea of flowers, sun` + String get Snow_mountain { + return Intl.message( + 'Snow mountain, forest, lake, sea of flowers, sun', + name: 'Snow_mountain', + desc: '', + args: [], + ); + } + + /// `The stars, the ocean, the beach, the cabin` + String get The_stars { + return Intl.message( + 'The stars, the ocean, the beach, the cabin', + name: 'The_stars', + desc: '', + args: [], + ); + } + + /// `Random suggested words will overwrite what has been entered` + String get Random_suggested { + return Intl.message( + 'Random suggested words will overwrite what has been entered', + name: 'Random_suggested', + desc: '', + args: [], + ); + } + + /// `do you want to overwrite?` + String get do_you { + return Intl.message( + 'do you want to overwrite?', + name: 'do_you', + desc: '', + args: [], + ); + } + + /// `Cover` + String get Cover { + return Intl.message( + 'Cover', + name: 'Cover', + desc: '', + args: [], + ); + } + + /// `Save picture is full` + String get Save_picture { + return Intl.message( + 'Save picture is full', + name: 'Save_picture', + desc: '', + args: [], + ); + } + + /// `Free users can only save 10 pictures` + String get Free_users { + return Intl.message( + 'Free users can only save 10 pictures', + name: 'Free_users', + desc: '', + args: [], + ); + } + + /// `More pictures can be saved after paying` + String get More_pictures { + return Intl.message( + 'More pictures can be saved after paying', + name: 'More_pictures', + desc: '', + args: [], + ); + } + + /// `to pay` + String get to_pay { + return Intl.message( + 'to pay', + name: 'to_pay', + desc: '', + args: [], + ); + } + + /// `Mall` + String get Mall { + return Intl.message( + 'Mall', + name: 'Mall', + desc: '', + args: [], + ); + } + + /// `Message` + String get message { + return Intl.message( + 'Message', + name: 'message', + desc: '', + args: [], + ); + } + + /// `Are you sure to switch the subject type?` + String get switch_the_subject { + return Intl.message( + 'Are you sure to switch the subject type?', + name: 'switch_the_subject', + desc: '', + args: [], + ); + } + + /// `After confirmation, the subject type will be replaced with ` + String get After_confirmation { + return Intl.message( + 'After confirmation, the subject type will be replaced with ', + name: 'After_confirmation', + desc: '', + args: [], + ); + } + + /// `,and some unshared options will be cleared.` + String get some_unshared { + return Intl.message( + ',and some unshared options will be cleared.', + name: 'some_unshared', + desc: '', + args: [], + ); + } + + /// `The subject you want to paint` + String get The_subject { + return Intl.message( + 'The subject you want to paint', + name: 'The_subject', + desc: '', + args: [], + ); + } + + /// `What kind of images do you want to generate?` + String get What_kind { + return Intl.message( + 'What kind of images do you want to generate?', + name: 'What_kind', + desc: '', + args: [], + ); + } + + /// `Exit login` + String get Exit_login { + return Intl.message( + 'Exit login', + name: 'Exit_login', + desc: '', + args: [], + ); + } + + /// `Expand` + String get Expand { + return Intl.message( + 'Expand', + name: 'Expand', + desc: '', + args: [], + ); + } + + /// `Close` + String get Close { + return Intl.message( + 'Close', + name: 'Close', + desc: '', + args: [], + ); + } + + /// `Save` + String get Save { + return Intl.message( + 'Save', + name: 'Save', + desc: '', + args: [], + ); + } + + /// `Feedback` + String get Feedback { + return Intl.message( + 'Feedback', + name: 'Feedback', + desc: '', + args: [], + ); + } + + /// `problems encountered` + String get problems_encountered { + return Intl.message( + 'problems encountered', + name: 'problems_encountered', + desc: '', + args: [], + ); + } + + /// `Please describe in detail the problem you are experiencing` + String get Please_describe { + return Intl.message( + 'Please describe in detail the problem you are experiencing', + name: 'Please_describe', + desc: '', + args: [], + ); + } + + /// `Contact information` + String get Contact_information { + return Intl.message( + 'Contact information', + name: 'Contact_information', + desc: '', + args: [], + ); + } + + /// `Please enter your email so that we can contact you` + String get Please_enter { + return Intl.message( + 'Please enter your email so that we can contact you', + name: 'Please_enter', + desc: '', + args: [], + ); + } + + /// `Submit` + String get Submit { + return Intl.message( + 'Submit', + name: 'Submit', + desc: '', + args: [], + ); + } + + /// `Watch the full video` + String get Watch_the { + return Intl.message( + 'Watch the full video', + name: 'Watch_the', + desc: '', + args: [], + ); + } + + /// `Earn 1 paint point after watching 1 AD` + String get Earn_paint { + return Intl.message( + 'Earn 1 paint point after watching 1 AD', + name: 'Earn_paint', + desc: '', + args: [], + ); + } + + /// `Watch` + String get Watch { + return Intl.message( + 'Watch', + name: 'Watch', + desc: '', + args: [], + ); + } + + /// `Free` + String get Free { + return Intl.message( + 'Free', + name: 'Free', + desc: '', + args: [], + ); + } + + /// `There are currently no advertisements available` + String get no_advertisements { + return Intl.message( + 'There are currently no advertisements available', + name: 'no_advertisements', + desc: '', + args: [], + ); + } + + /// `received all the drawing points today` + String get received_all { + return Intl.message( + 'received all the drawing points today', + name: 'received_all', + desc: '', + args: [], + ); + } + + /// `Share` + String get Share { + return Intl.message( + 'Share', + name: 'Share', + desc: '', + args: [], + ); + } + + /// `Upload Gallery Pass Review Reward` + String get Upload_the_painting { + return Intl.message( + 'Upload Gallery Pass Review Reward', + name: 'Upload_the_painting', + desc: '', + args: [], + ); + } + + /// `paint points` + String get Painting_points { + return Intl.message( + 'paint points', + name: 'Painting_points', + desc: '', + args: [], + ); + } + + /// `Obtained after review` + String get Obtained_after_review { + return Intl.message( + 'Obtained after review', + name: 'Obtained_after_review', + desc: '', + args: [], + ); + } + + /// `Upload artwork to gallery` + String get Upload_artwork_gallery { + return Intl.message( + 'Upload artwork to gallery', + name: 'Upload_artwork_gallery', + desc: '', + args: [], + ); + } + + /// `To create` + String get To_create { + return Intl.message( + 'To create', + name: 'To_create', + desc: '', + args: [], + ); + } + + /// `Invitation code` + String get Invitation_code { + return Intl.message( + 'Invitation code', + name: 'Invitation_code', + desc: '', + args: [], + ); + } + + /// `In review` + String get In_review { + return Intl.message( + 'In review', + name: 'In_review', + desc: '', + args: [], + ); + } + + /// `Fill in the invitation code to send` + String get Fill_in { + return Intl.message( + 'Fill in the invitation code to send', + name: 'Fill_in', + desc: '', + args: [], + ); + } + + /// `New users send` + String get New_users { + return Intl.message( + 'New users send', + name: 'New_users', + desc: '', + args: [], + ); + } + + /// `Invite new users to fill in the invitation code, reward 10 paint points` + String get Invite_new { + return Intl.message( + 'Invite new users to fill in the invitation code, reward 10 paint points', + name: 'Invite_new', + desc: '', + args: [], + ); + } + + /// `Please fill in the invitation code` + String get Please_fill_in { + return Intl.message( + 'Please fill in the invitation code', + name: 'Please_fill_in', + desc: '', + args: [], + ); + } + + /// `Please wait for the generation to end` + String get Please_wait { + return Intl.message( + 'Please wait for the generation to end', + name: 'Please_wait', + desc: '', + args: [], + ); + } + + /// `uploaded` + String get uploaded { + return Intl.message( + 'uploaded', + name: 'uploaded', + desc: '', + args: [], + ); + } + + /// `Server is full, expect to queue for 10 mins, please wait` + String get Waiting_in { + return Intl.message( + 'Server is full, expect to queue for 10 mins, please wait', + name: 'Waiting_in', + desc: '', + args: [], + ); + } + + /// `Language switching` + String get Language_switching { + return Intl.message( + 'Language switching', + name: 'Language_switching', + desc: '', + args: [], + ); + } + + /// `You are about to start the account cancellation process.` + String get Start_account_cancellation { + return Intl.message( + 'You are about to start the account cancellation process.', + name: 'Start_account_cancellation', + desc: '', + args: [], + ); + } + + /// `After the account is cancelled, all your data will be deleted and cannot be recovered.` + String get After_the_account_is_cancelled { + return Intl.message( + 'After the account is cancelled, all your data will be deleted and cannot be recovered.', + name: 'After_the_account_is_cancelled', + desc: '', + args: [], + ); + } + + /// `Account Cancellation Request` + String get Account_cancellation { + return Intl.message( + 'Account Cancellation Request', + name: 'Account_cancellation', + desc: '', + args: [], + ); + } + + /// `Request for Account Cancellation` + String get Request_cancellation { + return Intl.message( + 'Request for Account Cancellation', + name: 'Request_cancellation', + desc: '', + args: [], + ); + } + + /// `Paint points are used according to options \nwhen generating paintings.` + String get Paint_points { + return Intl.message( + 'Paint points are used according to options \nwhen generating paintings.', + name: 'Paint_points', + desc: '', + args: [], + ); + } + + /// `Painting points never expire and can be \nused at any time.` + String get Painting_points_never { + return Intl.message( + 'Painting points never expire and can be \nused at any time.', + name: 'Painting_points_never', + desc: '', + args: [], + ); + } + + /// `Equity` + String get obtaining_benefits { + return Intl.message( + 'Equity', + name: 'obtaining_benefits', + desc: '', + args: [], + ); + } + + /// `Get 1 saved image after watching 1 advertisement` + String get Get_saved { + return Intl.message( + 'Get 1 saved image after watching 1 advertisement', + name: 'Get_saved', + desc: '', + args: [], + ); + } + + /// `Full Watch Video (Today` + String get Full_Watch { + return Intl.message( + 'Full Watch Video (Today', + name: 'Full_Watch', + desc: '', + args: [], + ); + } + + /// `Number of purchased images $` + String get Number_of { + return Intl.message( + 'Number of purchased images \$', + name: 'Number_of', + desc: '', + args: [], + ); + } + + /// `Number of saved images` + String get Number_of_saved { + return Intl.message( + 'Number of saved images', + name: 'Number_of_saved', + desc: '', + args: [], + ); + } + + /// `Search for influencers` + String get Search_influential { + return Intl.message( + 'Search for influencers', + name: 'Search_influential', + desc: '', + args: [], + ); + } + + /// `search` + String get search { + return Intl.message( + 'search', + name: 'search', + desc: '', + args: [], + ); + } + + /// `Recommended influencers` + String get Recommended_influencers { + return Intl.message( + 'Recommended influencers', + name: 'Recommended_influencers', + desc: '', + args: [], + ); + } + + /// `Exhibition of works` + String get Exhibition_works { + return Intl.message( + 'Exhibition of works', + name: 'Exhibition_works', + desc: '', + args: [], + ); + } + + /// `copy prompt word` + String get copy_prompt_word { + return Intl.message( + 'copy prompt word', + name: 'copy_prompt_word', + desc: '', + args: [], + ); + } + + /// `Painting parameters:` + String get Painting_parameters { + return Intl.message( + 'Painting parameters:', + name: 'Painting_parameters', + desc: '', + args: [], + ); + } + + /// `follow` + String get follow { + return Intl.message( + 'follow', + name: 'follow', + desc: '', + args: [], + ); + } + + /// `Followed` + String get Followed { + return Intl.message( + 'Followed', + name: 'Followed', + desc: '', + args: [], + ); + } + + /// `Featured` + String get Expert_selection { + return Intl.message( + 'Featured', + name: 'Expert_selection', + desc: '', + args: [], + ); + } + + /// `Popular` + String get Popular { + return Intl.message( + 'Popular', + name: 'Popular', + desc: '', + args: [], + ); + } + + /// `all` + String get all { + return Intl.message( + 'all', + name: 'all', + desc: '', + args: [], + ); + } + + /// `User details` + String get User_details { + return Intl.message( + 'User details', + name: 'User_details', + desc: '', + args: [], + ); + } + + /// `Liked:` + String get Liked { + return Intl.message( + 'Liked:', + name: 'Liked', + desc: '', + args: [], + ); + } + + /// `Fans:` + String get Fans { + return Intl.message( + 'Fans:', + name: 'Fans', + desc: '', + args: [], + ); + } + + /// `date sort` + String get Date_sort { + return Intl.message( + 'date sort', + name: 'Date_sort', + desc: '', + args: [], + ); + } + + /// `like sorting` + String get Like_sorting { + return Intl.message( + 'like sorting', + name: 'Like_sorting', + desc: '', + args: [], + ); + } + + /// `copy it` + String get copy_it { + return Intl.message( + 'copy it', + name: 'copy_it', + desc: '', + args: [], + ); + } +} + +class AppLocalizationDelegate extends LocalizationsDelegate { + const AppLocalizationDelegate(); + + List get supportedLocales { + return const [ + Locale.fromSubtags(languageCode: 'en'), + Locale.fromSubtags(languageCode: 'ja'), + Locale.fromSubtags(languageCode: 'zh'), + ]; + } + + @override + bool isSupported(Locale locale) => _isSupported(locale); + @override + Future load(Locale locale) => S.load(locale); + @override + bool shouldReload(AppLocalizationDelegate old) => false; + + bool _isSupported(Locale locale) { + for (var supportedLocale in supportedLocales) { + if (supportedLocale.languageCode == locale.languageCode) { + return true; + } + } + return false; + } +} diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb new file mode 100644 index 0000000..6af3fa6 --- /dev/null +++ b/lib/l10n/intl_en.arb @@ -0,0 +1,163 @@ +{ + "By_continuing": "By continuing, you agree to HissAi", + "User_Agreement": "User Agreement", + "and": "and", + "Privacy_Policy": "Privacy Policy", + "Google": "Google", + "Gallery": "Gallery", + "Creation": "Creation", + "Upload": "Upload", + "Confirm_submission": "Confirm submission", + "Upload_gallery": "Upload your work to the gallery, allowing more users to see your work", + "Upload_successful": "Upload successful", + "Creation_ja": "Creation", + "Me": "Me", + "Recommend": "Recommend", + "Describe_in_detail": "Describe your vision in detail", + "for_instance": "for instance\"girl, long hair, sit on the swing, garden, pastel colors, face specific\"", + "more_detailed": "The more detailed the more accurate ~", + "Random_Description": "Random Description", + "Easy_mode": "Easy mode", + "guide": "Guide", + "Artist": "Artist", + "Painting_style": "Painting style", + "Reference_drawing": "Reference drawing", + "Will_refer": "AI will generate with reference to the pictures you upload", + "Image_scale": "Image scale", + "Generate_painting": "Generate", + "Please_fill": "Please fill in the description of the picture", + "Reference_image": "Reference image description", + "details": "Details", + "Current_progress": "Current progress", + "Already_copied": "Already copied", + "Delete": "Delete", + "Download": "Download", + "Regenerate": "Regenerate", + "share_to_gallery": "Upload to gallery", + "Check_in": "Check in \"Me\" after the screen is created", + "Generate_time": "Generate time", + "Resolution": "Resolution", + "Image_too_large": "Image too large", + "collect": "Collect", + "Favorite": "Favorite", + "Reference_drawing_redrawing": "Reference drawing redrawing degree", + "Painting_point": "Painting point", + "Collected": "Collected", + "My_Works": "My Works", + "Collection": "Collection", + "Number_works": "Number of works", + "Selects": "Selects", + "Sort_by": "Sort by", + "Cancel": "Cancel", + "Selected": "Selected", + "Number_collections": "Number of collections", + "Newest": "Newest", + "Oldest": "Oldest", + "Most_favorite": "Most favorite", + "Least_Favorite": "Least Favorite", + "The_function": "The function is about to open, please stay tuned", + "Author": "Author", + "Consume": "Cost", + "point": "point", + "Press_again": "Press again to exit", + "Tip": "Tip", + "Are_you_sure": "Are you sure to permanently delete this work? \nAfter deletion, it will not be able to be retrieved", + "Sure": "Sure", + "Successfully_saved": "Successfully saved", + "Settings": "Settings", + "About": "About", + "The_smaller": "The lower the value, the more like a reference image; the higher the value, the more creative", + "Please_select": "Please select a work", + "The_reference": "1. The reference image file must be less than 10M.", + "The_smaller_the": "2. The smaller the redraw value of the reference image, the more similar it is to the original image.", + "Users_are_responsible": "3. Users are responsible for any legal disputes caused by reference images.", + "The_final_generated": "4. The final generated image will be reviewed, and images containing sensitive content will not be displayed.", + "Using_the_reference": "5. Using the reference image function will consume 1 paint point.", + "Insufficient_drawing_points": "Insufficient drawing points", + "Draw_another_picture": "Draw again", + "Draw_the_same": "Draw the same", + "A_colorful": "A colorful magic castle in a crystal ball", + "Brunette_princess": "Brunette princess, crown on head, gorgeous, firefly, forest background, elegant", + "Beautiful_angel": "Beautiful angel, white wings, halo, long blonde hair, royal sister, queen temperament", + "Rapeseed_flowers": "Rapeseed flowers bloom as far as the eye can see, a group of butterflies flying in the flowers", + "Long_hair": "Long hair girl, sitting in the garden swing, flowers, soft colors, face close-up", + "A_close": "A close-up of a pretty girl's face, surrounded by halo, ethereal, romantic, dreamy, delicate", + "After_rain": "After rain, clear colors, sunshine, pink flowers, quiet, soft focus, chasing butterflies", + "Distant_mountains": "Distant mountains, sunsets, sunsets, meadows, flowers, canyons, rivers, houses", + "Snow_mountain": "Snow mountain, forest, lake, sea of flowers, sun", + "The_stars": "The stars, the ocean, the beach, the cabin", + "Random_suggested": "Random suggested words will overwrite what has been entered", + "do_you": "do you want to overwrite?", + "Cover": "Cover", + "Save_picture": "Save picture is full", + "Free_users": "Free users can only save 10 pictures", + "More_pictures": "More pictures can be saved after paying", + "to_pay": "to pay", + "Mall": "Mall", + "message": "Message", + "switch_the_subject": "Are you sure to switch the subject type?", + "After_confirmation": "After confirmation, the subject type will be replaced with ", + "some_unshared": ",and some unshared options will be cleared.", + "The_subject": "The subject you want to paint", + "What_kind": "What kind of images do you want to generate?", + "Exit_login": "Exit login", + "Expand": "Expand", + "Close": "Close", + "Save": "Save", + "Feedback": "Feedback", + "problems_encountered": "problems encountered", + "Please_describe": "Please describe in detail the problem you are experiencing", + "Contact_information": "Contact information", + "Please_enter": "Please enter your email so that we can contact you", + "Submit": "Submit", + "Watch_the": "Watch the full video", + "Earn_paint": "Earn 1 paint point after watching 1 AD", + "Watch": "Watch", + "Free": "Free", + "no_advertisements": "There are currently no advertisements available", + "received_all": "received all the drawing points today", + "Share": "Share", + "Upload_the_painting": "Upload Gallery Pass Review Reward", + "Painting_points": "paint points", + "Obtained_after_review": "Obtained after review", + "Upload_artwork_gallery": "Upload artwork to gallery", + "To_create": "To create", + "Invitation_code": "Invitation code", + "In_review": "In review", + "Fill_in": "Fill in the invitation code to send", + "New_users": "New users send", + "Invite_new": "Invite new users to fill in the invitation code, reward 10 paint points", + "Please_fill_in": "Please fill in the invitation code", + "Please_wait": "Please wait for the generation to end", + "uploaded": "uploaded", + "Waiting_in": "Server is full, expect to queue for 10 mins, please wait", + "Language_switching": "Language switching", + "Start_account_cancellation" : "You are about to start the account cancellation process.", + "After_the_account_is_cancelled" : "After the account is cancelled, all your data will be deleted and cannot be recovered.", + "Account_cancellation" : "Account Cancellation Request", + "Request_cancellation": "Request for Account Cancellation", + "Paint_points": "Paint points are used according to options \nwhen generating paintings.", + "Painting_points_never": "Painting points never expire and can be \nused at any time.", + "obtaining_benefits": "Equity", + "Get_saved": "Get 1 saved image after watching 1 advertisement", + "Full_Watch": "Full Watch Video (Today", + "Number_of": "Number of purchased images $", + "Number_of_saved": "Number of saved images", + "Search_influential": "Search for influencers", + "search": "search", + "Recommended_influencers": "Recommended influencers", + "Exhibition_works": "Exhibition of works", + "copy_prompt_word": "copy prompt word", + "Painting_parameters": "Painting parameters:", + "follow": "follow", + "Followed": "Followed", + "Expert_selection": "Featured", + "Popular": "Popular", + "all": "all", + "User_details": "User details", + "Liked": "Liked:", + "Fans": "Fans:", + "Date_sort": "date sort", + "Like_sorting": "like sorting", + "copy_it": "copy it" +} \ No newline at end of file diff --git a/lib/l10n/intl_ja.arb b/lib/l10n/intl_ja.arb new file mode 100644 index 0000000..5861ef3 --- /dev/null +++ b/lib/l10n/intl_ja.arb @@ -0,0 +1,64 @@ +{ + "Creation": "作成", + "Upload": "送信", + "Confirm_submission": "コミットの確認", + "Upload_gallery": "ギャラリーに作品をアップロードして、より多くのユーザーに作品を見てもらう", + "Upload_successful": "アップロードに成功しました", + "Creation_ja": "の作成", + "Describe_in_detail": "あなたのビジョンを詳しく説明してください", + "for_instance": "「髪の長い女の子、庭のブランコに座る、花、パステルカラー、顔のクローズアップ」など", + "more_detailed": "説明が詳細であればあるほど、画像はより正確になります〜", + "Random_Description": "ランダムなおすすめワード", + "Easy_mode": "単純", + "guide": "ガイド", + "Artist": "アーティスト", + "Painting_style": "絵画スタイル", + "Reference_drawing": "参考画像", + "Image_scale": "画像比率", + "Reference_image": "参考図の説明", + "The_reference": "1. 参照画像ファイルは 10M 未満である必要があります", + "The_smaller_the": "2. 参照画像の再描画値が小さいほど、元の画像に近づきます。", + "Users_are_responsible": "3. 参考画像に起因する法的紛争については、利用者が責任を負います。", + "The_final_generated": "4. 最終的に生成された画像が確認され、機密コンテンツを含む画像は表示されません。", + "Using_the_reference": "5. 参照画像機能を使用すると描画ポイントを1消費します。", + "Will_refer": "上で説明したように、参照画像をスタイル ペイントに変換します。", + "Reference_drawing_redrawing": "参照マップ再描画度", + "The_smaller": "値が低いほど参照画像に類似し、値が高いほどクリエイティブになります。", + "Generate_painting": "生成", + "Consume": "消費", + "point": "ポイント", + "Upload_the_painting": "絵画がギャラリーにアップロードされ、承認されて", + "Painting_points": "ペイントポイント", + "Free": "無料", + "Watch_the": "ビデオを完全に見る", + "Earn_paint": "1 つの広告を視聴すると 1 ペイント \nポイントを獲得", + "Watch": "見る", + "Obtained_after_review": "レビュー後に取得", + "Language_switching": "言語切り替え", + "Start_account_cancellation" : "You are about to start the account cancellation process.", + "After_the_account_is_cancelled" : "After the account is cancelled, all your data will be deleted and cannot be recovered.", + "Account_cancellation" : "Account Cancellation Request", + "Request_cancellation": "Request for Account Cancellation", + "obtaining_benefits": "資本", + "Get_saved": "1回の広告を見終わったら1つのセーブ数を得る", + "Full_Watch": "ビデオを完全に見る(今日", + "Number_of": "購入済在庫数", + "Number_of_saved": "メモリ数", + "Search_influential": "検索の達人", + "search": "検索けんさく", + "Recommended_influencers": "おすすめ達人", + "Exhibition_works": "作品の展示", + "copy_prompt_word": "プロンプトの単語をコピーする", + "Painting_parameters": "ペイントパラメータ:", + "follow": "フォローする", + "Followed": "フォローしました", + "Expert_selection": "専門家の選択", + "Popular": "人気のある", + "all": "全て", + "User_details": "ユーザーの詳細", + "Liked": "気に入った:", + "Fans": "ファン:", + "Date_sort": "日付ソート", + "Like_sorting": "いいねソート", + "copy_it": "コピーしてください" +} \ No newline at end of file diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb new file mode 100644 index 0000000..51dfde0 --- /dev/null +++ b/lib/l10n/intl_zh.arb @@ -0,0 +1,163 @@ +{ + "By_continuing": "继续即同意HissAi的", + "User_Agreement": "用户协议", + "and": "和", + "Privacy_Policy": "隐私协议", + "Google": "谷歌登录", + "Gallery": "画廊", + "Creation": "创作", + "Upload": "上传", + "Confirm_submission": "确认提交", + "Upload_successful": "上传成功", + "Upload_gallery": "上传作品至画廊,让更多用户看到您的作品", + "Creation_ja": "创作", + "Me": "我的", + "Recommend": "推荐", + "Describe_in_detail": "详细描述你想象中的画面", + "for_instance": "如“长发女孩,坐在花园的秋千上,鲜花,色彩柔和,脸部特写”", + "more_detailed": "描述越详细画面越精准哦~", + "Random_Description": "点这里试试推荐词", + "Easy_mode": "简易", + "guide": "引导模式", + "Artist": "艺术家", + "Painting_style": "绘画风格", + "Reference_drawing": "参考图", + "Will_refer": "将参考图转化为上述描写的风格画作", + "Image_scale": "图片比例", + "Generate_painting": "生成", + "Please_fill": "请填写画面描述", + "Reference_image": "参考图说明", + "details": "详情", + "Current_progress": "当前进度", + "Already_copied": "描述已复制进剪切版", + "Delete": "删除", + "Download": "下载", + "Regenerate": "重新生成", + "share_to_gallery": "上传至画廊", + "Check_in": "画面生成后在“我的”查看", + "Generate_time": "生成时间", + "Resolution": "分辨率", + "Image_too_large": "图片过大", + "collect": "收藏", + "Favorite": "已收藏", + "Reference_drawing_redrawing": "参考图重绘度", + "Painting_point": "绘画点", + "Collected": "被收藏", + "My_Works": "我的作品", + "Collection": "收藏", + "Number_works": "作品数量", + "Selects": "多选", + "Sort_by": "排序", + "Cancel": "取消", + "Selected": "已选中", + "Number_collections": "收藏数量", + "Newest": "最新", + "Oldest": "最早", + "Most_favorite": "收藏最多", + "Least_Favorite": "收藏最少", + "The_function": "功能即将开放,敬请期待", + "Author": "作者", + "Consume": "消耗", + "point": "点", + "Press_again": "再按一次退出", + "Tip": "提示", + "Are_you_sure": "确定永久删除这张作品吗\n删除后将不能找回", + "Sure": "确定", + "Successfully_saved": "保存成功", + "Settings": "设置", + "About": "关于", + "The_smaller": "数值越低,与参考图越相似;数值越高,越充满创意", + "Please_select": "请选择作品", + "The_reference": "1.参考图文件需小于10M。", + "The_smaller_the": "2.参考图重绘度值越小,与原图越相似。", + "Users_are_responsible": "3.因参考图造成的法律纠纷用户需要自行负责。", + "The_final_generated": "4.最终的生成图会进行审核,含有敏感内容的图片将无法展示。", + "Using_the_reference": "5.使用参考图功能,将消耗1绘画点。", + "Insufficient_drawing_points": "绘画点不足", + "Draw_another_picture": "再画一张", + "Draw_the_same": "画同款", + "A_colorful": "水晶球里的彩色魔法城堡", + "Brunette_princess": "黑发公主,头戴皇冠,华丽,萤火虫,森林背景,优雅", + "Beautiful_angel": "美丽的天使,白色翅膀,头顶光环,金色长发,御姐,女王气质", + "Rapeseed_flowers": "油菜花开花,一望无际,一群蝴蝶在花丛中飞舞", + "Long_hair": "长发女孩,坐在花园的秋千上,鲜花,色彩柔和,脸部特写", + "A_close": "漂亮女孩的脸特写,被光晕包围,空灵,浪漫,梦幻,精致", + "After_rain": "雨后,清澈的色彩,阳光,粉色花朵,宁静,柔和的焦点,追逐的蝴蝶", + "Distant_mountains": "远山,落日,夕阳,草地,鲜花,峡谷,河流,房屋", + "Snow_mountain": "雪山,森林,湖泊,花海,太阳", + "The_stars": "星空,海洋,沙滩,木屋", + "Random_suggested": "随机推荐词将覆盖已输入的内容", + "do_you": "是否要覆盖?", + "Cover": "确定", + "Save_picture": "保存图片已达上限", + "Free_users": "免费用户仅可保存10张图片", + "More_pictures": "付费后可保存更多图片", + "to_pay": "去付费", + "Mall": "商城", + "message": "消息", + "switch_the_subject": "确认切换主题类型吗?", + "After_confirmation": "确认后主题类型将替换为", + "some_unshared": ",某些不共用的选择项将会被清空。", + "The_subject": "你想绘画的主体", + "What_kind": "希望生成什么种类的图片呢?", + "Exit_login": "退出登录", + "Expand": "展开", + "Close": "关闭", + "Save": "保存", + "Feedback": "反馈", + "problems_encountered": "遇到的问题", + "Please_describe": "请详细描述您遇到的问题", + "Contact_information": "联系方式", + "Please_enter": "请输入您的邮箱,方便我们与您联系", + "Submit": "提交", + "Watch_the": "完整观看视频", + "Earn_paint": "看完1次广告获得1绘画点", + "Watch": "观看", + "Free": "免费", + "no_advertisements": "暂无广告", + "received_all": "今天绘画点已领完", + "Share": "分享", + "Upload_the_painting": "绘画上传至画廊并通过审核奖励", + "Painting_points": "绘画点", + "Obtained_after_review": "通过审核后获得", + "Upload_artwork_gallery": "作品上传至画廊", + "To_create": "去创作", + "Invitation_code": "邀请码", + "In_review": "审核中", + "Fill_in": "填写邀请码送", + "New_users": "新用户注册送", + "Invite_new": "邀请新用户填写邀请码,奖励10绘画点", + "Please_fill_in": "请填写邀请码", + "Please_wait": "请等待生成结束", + "uploaded": "已上传", + "Waiting_in": "服务器已满,预计排队10分钟,请稍等", + "Language_switching": "语言切换", + "Start_account_cancellation": "您即将开始账号注销流程。", + "Account_cancellation": "账号申请注销", + "Request_cancellation": "申请注销", + "After_the_account_is_cancelled": "账号注销后,您所有的数据都将删除,且无法找回。", + "Paint_points": "生成绘画时根据选项将消耗一定绘画点.", + "Painting_points_never": "绘画点永不过期, 可以随时使用.", + "obtaining_benefits": "获取权益", + "Get_saved": "看完1次广告获取1存图数", + "Full_Watch": "完整观看视频(今日", + "Number_of": "购买存图数¥", + "Number_of_saved": "存图数", + "Search_influential": "搜索达人", + "search": "搜索", + "Recommended_influencers": "推荐达人", + "Exhibition_works": "作品展示", + "copy_prompt_word": "复制提示词", + "Painting_parameters": "绘画参数:", + "follow": "关注", + "Followed": "已关注", + "Expert_selection": "达人精选", + "Popular": "热门", + "all": "全部", + "User_details": "用户详情", + "Liked": "获赞:", + "Fans": "粉丝:", + "Date_sort": "日期排序", + "Like_sorting": "获赞排序", + "copy_it": "画同款" +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..629f7cd --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,132 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/tools/home/home_page.dart'; +import 'package:aiplot/tools/me/about_page.dart'; +import 'package:aiplot/tools/me/feedback_page.dart'; +import 'package:aiplot/tools/me/setting_page.dart'; +import 'package:aiplot/tools/message/message_page.dart'; +import 'package:aiplot/tools/shop/shop_page.dart'; +import 'package:aiplot/tools/start_page.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:ironsource_mediation/ironsource_mediation.dart'; +import 'package:sensors_analytics_flutter_plugin/sensors_analytics_flutter_plugin.dart'; + +import 'common/Global.dart'; +import 'common/my_navigator_observers.dart'; +import 'generated/l10n.dart'; + +Future main() async { + await runZonedGuarded(() async { + WidgetsFlutterBinding.ensureInitialized(); + Global.initialize().then((e) { + new Global(); + runApp(CloudApp()); + if (Platform.isAndroid) { + // 以下两行 设置android状态栏为透明的沉浸。写在组件渲染之后,是为了在渲染后进行set赋值,覆盖状态栏,写在渲染之前MaterialApp组件会覆盖掉这个值。 + SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(statusBarColor: Colors.transparent); + SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); + } + }); + }, (error, stackTrace) {}); +} + +class CloudApp extends StatefulWidget { + @override + _CloudAppState createState() => _CloudAppState(); +} + +class _CloudAppState extends State with IronSourceInitializationListener { + // 注册方法,等待被原生通过invokeMethod唤起 接收原生数据 + Future nativeCallHandler(MethodCall methodCall) async { + switch (methodCall.method) { + case "AreaCode": //时区选择 + + final AreaCode = await methodCall.arguments["AreaCode"]; + final AreaName = await methodCall.arguments["AreaName"]; + // EventBusUtil.fire(LoginAreaCodeEvent(AreaCode, AreaName)); + break; + } + } + + @override + void initState() { + Global.method.setMethodCallHandler(nativeCallHandler); + + //神策初始化 + SensorsAnalyticsFlutterPlugin.init( + serverUrl: "https://sj.datasink.sensorsdata.cn/sa?project=production&token=8749cbadc8e370e7", + autoTrackTypes: { + SAAutoTrackType.APP_START, + SAAutoTrackType.APP_VIEW_SCREEN, + SAAutoTrackType.APP_CLICK, + SAAutoTrackType.APP_END + }, + enableLog: false, + visualized: VisualizedConfig(autoTrack: true, properties: true), + android: AndroidConfig(maxCacheSize: 32 * 1024 * 1024, jellybean: true, subProcessFlush: true), + ios: IOSConfig(maxCacheSize: 10000)); + + // 公共属性 + SensorsAnalyticsFlutterPlugin.registerSuperProperties({ + "S_Key_system_APPnames": "HissAi", + "Platform_type": Platform.isAndroid ? "Android" : "iOS", + "AppId": NetworkConfig.AppId, + }); + + //is广告初始化 + IronSource.setFlutterVersion("3.3.1"); + IronSource.init(appKey: "19ff4f345"); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + navigatorObservers: [MyNavigatorObserver()], + title: 'AI', + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + S.delegate + ], + supportedLocales: const [ + Locale("en"), + Locale("zh"), + Locale("ja"), + ], + + home: StartPage(), + + //注册路由 + routes: { + '/HomePage': (BuildContext context) => HomePage(), + '/SettingPage': (BuildContext context) => SettingPage(), + '/ShopPage': (BuildContext context) => ShopPage(), + '/AboutPage': (BuildContext context) => AboutPage(), + '/MessagePage': (BuildContext context) => MessagePage(), + '/FeedbackPage': (BuildContext context) => FeedbackPage(), + }, + + debugShowMaterialGrid: false, + //显示网格 + debugShowCheckedModeBanner: false, + //去掉右上角的debug + builder: EasyLoading.init(), + ); + } + + @override + void onInitializationComplete() { + // TODO: implement onInitializationComplete + //is sdk 初始化完成 + debugPrint("ironSource SDK is initialized"); + print("ironSource SDK is initialized"); + } +} diff --git a/lib/network/BaseEntity.dart b/lib/network/BaseEntity.dart new file mode 100644 index 0000000..af31442 --- /dev/null +++ b/lib/network/BaseEntity.dart @@ -0,0 +1,38 @@ +import 'dart:convert'; + +class BaseEntity { + int? code; + int? result; + String? message; + dynamic data; + + // 构造函数 + BaseEntity({this.code, this.result, this.message, this.data}); + + // 数据解析 + factory BaseEntity.fromJson(json) { + Map responseData = jsonDecode(json); + int code = responseData["Code"]; + int result = responseData["Result"]; + String message = responseData["Message"]; //错误描述 + dynamic data = responseData["Data"]; + return BaseEntity(code: code, result: result, message: message, data: data); + } + + // 数据解析 + factory BaseEntity.PlayfromJson(json) { + Map responseData = json; + int code = responseData["Code"]; + // int result = responseData["Result"]; + String message = responseData["Message"]; //错误描述 + dynamic data = responseData["Data"]; + return BaseEntity(code: code, result: 0, message: message, data: data); + } +} + +class ErrorEntity { + int? code; + String? message; + + ErrorEntity({this.code, this.message}); +} diff --git a/lib/network/DioLogInterceptor.dart b/lib/network/DioLogInterceptor.dart new file mode 100644 index 0000000..308488d --- /dev/null +++ b/lib/network/DioLogInterceptor.dart @@ -0,0 +1,134 @@ +import 'package:dio/dio.dart'; + +///日志拦截器 +class DioLogInterceptor extends Interceptor { + ///请求前 + @override + void onRequest(RequestOptions options, RequestInterceptorHandler handler) { + String requestStr = "\n 请求 - URL:${/*options.baseUrl + */ options.uri}" + " 时间 - :${DateTime.now().millisecondsSinceEpoch}\n"; + //requestStr += "- HEADER:\n${options.headers.mapToStructureString()}\n"; + final data = options.data; + if (data != null) { + if (data is Map) + requestStr += "- BODY:\n${data.mapToStructureString()}\n"; + else if (data is FormData) { + final formDataMap = Map() + ..addEntries(data.fields) + ..addEntries(data.files); + requestStr += "- BODY:\n${formDataMap.mapToStructureString()}\n"; + } else + requestStr += "- BODY:\n${data.toString()}\n"; + } + print(requestStr); + + handler.next(options); + } + + ///出错前 + @override + void onError(DioError err, ErrorInterceptorHandler handler) { + String errorStr = "\n==================== 响应 ====================\n" + "- URL:\n${err.requestOptions.path}\n" + "- METHOD: ${err.requestOptions.method}\n"; + + /* errorStr += + "- HEADER:\n${err.response.headers.map.mapToStructureString()}\n";*/ + if (err.response != null && err.response!.data != null) { + print('╔ ${err.type.toString()}'); + errorStr += "- ERROR:\n${_parseResponse(err.response!)}\n"; + } else { + errorStr += "- ERRORTYPE: ${err.type}\n"; + errorStr += "- MSG: ${err.message}\n"; + } + print(errorStr); + + handler.next(err); + } + + ///响应前 + @override + void onResponse(Response response, ResponseInterceptorHandler handler) { + String responseStr = "\n 响应 - URL:${response.requestOptions.uri}" + " 时间 - :${DateTime.now().millisecondsSinceEpoch}\n"; + + /* responseStr += "- HEADER:\n{"; + response.headers.forEach( + (key, list) => responseStr += "\n " + "\"$key\" : \"$list\","); + responseStr += "\n}\n";*/ + //responseStr += "- STATUS: ${response.statusCode}\n"; + + if (response.data != null) { + responseStr += "- BODY:\n ${_parseResponse(response)}"; + } + printWrapped(responseStr); + + handler.next(response); + } + + void printWrapped(String text) { + final pattern = new RegExp('.{1,800}'); // 800 is the size of each chunk + pattern.allMatches(text).forEach((match) => print(match.group(0))); + } + + String _parseResponse(Response response) { + String responseStr = ""; + var data = response.data; + if (data is Map) + responseStr += data.mapToStructureString(); + else if (data is List) + responseStr += data.listToStructureString(); + else + responseStr += response.data.toString(); + + return responseStr; + } +} + +///Map拓展,MAp转字符串输出 +extension Map2StringEx on Map { + String mapToStructureString({int indentation = 2}) { + String result = ""; + String indentationStr = " " * indentation; + if (true) { + result += " {"; + this.forEach((key, value) { + if (value is Map) { + var temp = value.mapToStructureString(indentation: indentation + 2); + result += "$indentationStr" + "\"$key\":$temp,"; + } else if (value is List) { + result += "$indentationStr" + "\"$key\":${value.listToStructureString(indentation: indentation + 2)},"; + } else { + result += "$indentationStr" + "\"$key\":\"$value\","; + } + }); + result = result.substring(0, result.length - 1); + result += indentation == 2 ? "}" : "\n${" " * (indentation - 1)}}"; + } + + return result; + } +} + +///List拓展,List转字符串输出 +extension List2StringEx on List { + String listToStructureString({int indentation = 2}) { + String result = ""; + String indentationStr = " " * indentation; + if (true) { + result += "$indentationStr["; + this.forEach((value) { + if (value is Map) { + var temp = value.mapToStructureString(indentation: indentation + 2); + result += "\n$indentationStr" + "\"$temp\","; + } else if (value is List) { + result += value.listToStructureString(indentation: indentation + 2); + } else { + result += "\n$indentationStr" + "\"$value\","; + } + }); + result = result.substring(0, result.length - 1); + result += "\n$indentationStr]"; + } + + return result; + } +} diff --git a/lib/network/NetworkConfig.dart b/lib/network/NetworkConfig.dart new file mode 100644 index 0000000..0a7e446 --- /dev/null +++ b/lib/network/NetworkConfig.dart @@ -0,0 +1,99 @@ +import '../bean/app_config_bean.dart'; +import '../bean/user_info_bean.dart'; +import '../bean/works_info_bean.dart'; + +class NetworkConfig { + static String ServerDomain_Online = BASE_URLS[SELECT_INDEX]; + static String deviceID = ""; //设备ID + static String systemVersion = ""; //设备ID + + /// 选择哪个域名做请求 + static int SELECT_INDEX = 0; + + static List BASE_URLS = [ + "http://127.0.0.1:7860/", + "http://127.0.0.1:7860/", + "http://127.0.0.1:7860/", + ]; + + static List BASE_URLS_AI = [ + "http://127.0.0.1:7860/", + ]; + + static String payCenter = "https://test.moguyouxi.cn:8400/HissAI4.PayCenter/"; //支付 + + static bool isTest = true; + + static String token = ""; + static String userToken = ""; //用户登录验签 + static String AppId = "1001"; + static String BossId = ""; + static String userId = ""; + static String userName = ""; + static String Version = "1.1.9"; + static String Language = "en"; + + static String CPU = ""; + static String imsi = ""; + static String ip = ""; + static String timeZone = ""; //时区 + static int statusHeight = 0; //状态栏高度 + static String allCurrency = "0"; //用户点数 + static double currency = 0.0; //用户点数 + static String saveImageNumber = "10"; //用户作品上限 + + static String prompt = ""; //提示词 + static int templateId = 1; //风格id + static int sizeTemplateId = 0; //尺寸id + static int followId = 0; //跟随的作品id + static String followUrl = ""; //跟随的作品的图片 + + static bool isImitate = false; //是否是画同款状态 + static bool isAdAvailable = false; //广告是否可用 + static AppConfigBean? appConfigBean; //app配置信息 + static int? usedRewardCount = 0; //已看广告数 + static int? totalRewardCount = 0; //看广告上限 + static String? invitationCode = "ABC"; //邀请码 + static UserInfoBean? userData; + static List workList = []; //达人详情列表 + + static const String getServerList = "AppConfig/GetAppServerList"; //获取地址 + static const String getAppConfig = "AppConfig/GetAppConfig"; //获取配置信息 + static const String userLogin = "Account/Login"; //登录 + static const String getUserData = "Account/GetUserData"; //获取用户信息 + static const String txt2Img = "AiDraw/Txt2Img"; //文字生成 + static const String img2Img = "AiDraw/Img2Img"; //图片生成 + static const String uploadImg = "Upload/UploadImg"; //审核模式上传图片 + + static const String getProgress = "AiDraw/GetProgress"; //获取任务进度 + static const String getArtDetail = "AiDraw/GetArtDetail"; //图片详情 + static const String getPopoutList = "AppConfig/GetPopoutList"; //获取弹窗列表 + static const String getDrawTemplateList = "AiDraw/GetDrawTemplateList"; //获取模板列表 + static const String getProductList = "Product/GetProductList"; //获取商品列表 + static String createOrder = "${payCenter}Google/CreateOrder"; //生成订单 + static String completeOrder = "${payCenter}Google/CompleteOrder"; //完成订单 + static String getGalleryList = "AiDraw/GetGalleryList"; //获取画廊列表 + static String userDrawGallery = "AiDraw/UserDrawGallery"; //分享画廊 + static String getUserDrawList = "AiDraw/GetUserDrawList"; //我的作品 + static String getMyFavoriteList = "AiDraw/GetMyFavoriteList"; //我的收藏 + static String userDrawCollect = "AiDraw/UserDrawCollect"; //收藏 + static String delMyDrawCollect = "AiDraw/DelMyDrawCollect"; //删除我的作品 + static String getUserMessage = "Message/GetUserMessage"; //消息 + static String getLevitatingBall = "Home/GetLevitatingBall"; //悬浮球 + static String receiveAwardNewUserPackage = "Home/ReceiveAwardNewUserPackage"; //悬浮球领取奖励 + static String submitUserFeedback = "Account/SubmitUserFeedback"; //反馈 + static String getGalleryLableList = "AppConfig/GetGalleryLableList"; //画廊标签 + static String getNewUserPackage = "Home/GetNewUserPackage"; //新用户弹框 + static String lookAdReward = "Ad/LookAdReward"; //观看广告 + static String fillInInvitationCode = "Home/FillInInvitationCode"; //填写邀请码 + static String getQuanYi = "Home/GetQuanYi"; //审核下权益信息 + static String getRecommenderList = "AiDraw/GetRecommenderList"; //画廊推荐达人 + static String getGalleryWorkLabel = "AiDraw/GetGalleryWorkLabel"; //画廊标签列表 + static String getWorksListByLabel = "AiDraw/GetWorksListByLabel"; //画廊标签列表 + static String getWorksDetailList = "AiDraw/GetWorksDetailList"; //获取作品详情列表 + static String userFollow = "Account/Follow"; //关注 + static String getUserPersonalCenter = "AiDraw/GetUserPersonalCenter"; //达人个人中心 + static String getWorksInfo = "AiDraw/GetWorksInfo"; //获取达人个人作品信息 + static String getUserHomePageByPw = "AiDraw/GetUserHomePageByPw"; //搜索达人 + +} diff --git a/lib/network/RequestCenter.dart b/lib/network/RequestCenter.dart new file mode 100644 index 0000000..65c8916 --- /dev/null +++ b/lib/network/RequestCenter.dart @@ -0,0 +1,467 @@ +import 'dart:convert'; + +import 'package:crypto/crypto.dart'; +import 'package:dio/dio.dart'; + +import 'BaseEntity.dart'; +import 'DioLogInterceptor.dart'; +import 'NetworkConfig.dart'; + +enum RequestMethod { + Post, + Get, +} + +const RequestMethodValues = { + RequestMethod.Get: "GET", + RequestMethod.Post: "POST", +}; + +class RequestCenter { + factory RequestCenter() => _getInstance(); + + static RequestCenter get instance => _getInstance(); + static RequestCenter? _instance; + + static String signKey = "5159d59637fe1b79ba789e87443e8282"; + + Dio? _dio, _dioLog; + + RequestCenter._internal() { + setup(); + } + + static RequestCenter _getInstance() { + _instance ??= RequestCenter._internal(); + //域名不一致,重新初始化 + if (_instance!._dio != null && NetworkConfig.ServerDomain_Online != _instance!._dio!.options.baseUrl) { + _instance!._dio!.options.baseUrl = NetworkConfig.ServerDomain_Online; + } + return _instance!; + } + + void setup() { + // 初始化 + if (null == _dio) { + _dio = Dio(BaseOptions( + baseUrl: NetworkConfig.ServerDomain_Online, + sendTimeout: const Duration(seconds: 10), + receiveTimeout: const Duration(seconds: 20), + connectTimeout: const Duration(seconds: 20), + contentType: Headers.jsonContentType, + responseType: ResponseType.json)); + _dio!.interceptors.add(DioLogInterceptor()); + /* _dio.interceptors.add(new ResponseInterceptors());*/ + _dioLog = Dio(BaseOptions( + sendTimeout: const Duration(seconds: 10), + receiveTimeout: const Duration(seconds: 20), + connectTimeout: const Duration(seconds: 20), + contentType: Headers.jsonContentType, + responseType: ResponseType.json)); + _dioLog!.interceptors.add(DioLogInterceptor()); + + // if (NetworkConfig.isAgent) { + // (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { + // client.findProxy = (uri) { + // return "PROXY 192.168.1.231:8888"; + // }; + // //抓Https包设置 + // client.badCertificateCallback = (X509Certificate cert, String host, int port) => true; + // }; + // } + } + } + + //首页第一个接口 + Future request0(path, Map parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error, + {RequestMethod? method}) async { + Map headers = { + "AppId": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "userId": NetworkConfig.userId, + "Version": NetworkConfig.Version, + "Language": NetworkConfig.Language + }; + parmeters.addAll(headers); + Map parmetersSign = sign(parmeters); + try { + FormData formData = FormData.fromMap(parmetersSign); + Dio dio = Dio(BaseOptions( + sendTimeout: const Duration(seconds: 10), + receiveTimeout: const Duration(seconds: 10), + connectTimeout: const Duration(seconds: 15), + )); + dio.interceptors.add(new DioLogInterceptor()); + Response response = await dio.post(path, data: formData); + if (response != null && response.statusCode == 200) { + BaseEntity entity = BaseEntity.fromJson(response.data); + success(entity); + return entity; + } else { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } catch (e) { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } + + //特殊处理网络请求默认为post + Future request1(path, Map parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error, + {RequestMethod? method}) async { + Map headers = { + "AppId": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "userId": NetworkConfig.userId, + "Version": NetworkConfig.Version, + "Language": NetworkConfig.Language + }; + parmeters.addAll(headers); + Map parmetersSign = sign(parmeters); + try { + /*由于服务器是表单结构*/ + FormData formData = FormData.fromMap(parmetersSign); + Response response = await _dio!.post(path, data: formData); + if (response != null && response.statusCode == 200) { + BaseEntity entity = BaseEntity.fromJson(response.data); + success(entity); + return entity; + } else { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } catch (e) { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } + + Future requestLog( + path, Map parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error, + {RequestMethod? method}) async { + Map headers = { + "AppId": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "userId": NetworkConfig.userId, + "Version": NetworkConfig.Version, + "Language": NetworkConfig.Language + }; + parmeters.addAll(headers); + Map parmetersSign = sign(parmeters); + try { + /*由于服务器是表单结构*/ + FormData formData = FormData.fromMap(parmetersSign); + Response response = await _dioLog!.post(path, data: formData); + if (response != null && response.statusCode == 200) { + BaseEntity entity = BaseEntity.fromJson(response.data); + success(entity); + return entity; + } else { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } catch (e) { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } + + // 网络请求默认为post + Future request(path, Map parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error, + {RequestMethod? method}) async { + Map headers = { + "AppId": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "userId": NetworkConfig.userId, + "Version": NetworkConfig.Version, + "Language": NetworkConfig.Language + }; + parmeters.addAll(headers); + //签名加密 + Map parmetersSign = sign(parmeters); + try { + FormData formData = FormData.fromMap(parmetersSign); + Response response = await _dio!.post(path, data: formData); + if (response != null && response.statusCode == 200) { + BaseEntity entity = BaseEntity.fromJson(response.data); + success(entity); + return entity; + } else { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } catch (e) { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } + + Future request2(path, Map parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error, + {RequestMethod? method}) async { + Map headers = { + "AppId": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "Version": NetworkConfig.Version, + "Language": NetworkConfig.Language + }; + parmeters.addAll(headers); + //签名加密 + Map parmetersSign = sign(parmeters); + try { + FormData formData = FormData.fromMap(parmetersSign); + Response response = await _dio!.post(path, data: formData); + if (response != null && response.statusCode == 200) { + BaseEntity entity = BaseEntity.fromJson(response.data); + success(entity); + + return entity; + } else { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } catch (e) { + if (e == DioError) { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + } else { + print("Network Anomaly" + e.toString()); + error(ErrorEntity(code: -1, message: "Network Anomaly")); + } + return null; + } + } + + // 网络请求默认为post + Future cleanRequest(path, Map parmeters, {RequestMethod? method}) async { + Map headers = { + "AppID": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "Version": NetworkConfig.Version, + "Language": "en", + "UserId": NetworkConfig.userId, + "Language": NetworkConfig.Language + }; + + parmeters.addAll(headers); + + Map parmetersSign = sign(parmeters); + + FormData formData = FormData.fromMap(parmetersSign); + + Response response = await _dio!.post(path, data: formData); + + if (response != null && response.statusCode == 200) { + return response; + } else { + return null; + } + } + + // 网络请求默认为post + Future requestPay( + path, Map parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error, + {RequestMethod? method}) async { + Map headers = { + "AppId": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "userId": NetworkConfig.userId, + "Version": NetworkConfig.Version, + "Language": NetworkConfig.Language + }; + parmeters.addAll(headers); + Map parmetersSign = sign(parmeters); + try { + FormData formData = FormData.fromMap(parmetersSign); + Response response = await _dio!.post(path, data: formData); + if (response != null && response.statusCode == 200) { + BaseEntity entity = BaseEntity.fromJson(response.data); + success(entity); + return entity; + } else { + error(ErrorEntity(code: -1, message: "未知错误")); + return null; + } + } catch (e) { + ErrorEntity(code: -1, message: "未知错误"); + return null; + } + } + + // 网络请求默认为post + Future requestPlay( + path, Map parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error, + {RequestMethod? method}) async { + Map headers = { + "AppId": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "UserId": NetworkConfig.userId, + "Version": NetworkConfig.Version, + "Language": NetworkConfig.Language + }; + parmeters.addAll(headers); + Map parmetersSign = sign(parmeters); + try { + FormData formData = FormData.fromMap(parmetersSign); + print("Authorization==${NetworkConfig.token}"); + //用户验签 + _dio!.options.headers = {"Authorization": NetworkConfig.token}; + Response response = await _dio!.post(path, data: formData); + if (response != null && response.statusCode == 200) { + BaseEntity entity = BaseEntity.PlayfromJson(response.data); + success(entity); + return entity; + } else { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } catch (e) { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } + + // 网络请求默认为post (网页) + Future requestWeb( + path, Map parmeters, Function(BaseEntity dataEntity) success, Function(ErrorEntity errorEntity) error, + {RequestMethod? method}) async { + Map headers = { + "AppId": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "UserId": NetworkConfig.userId, + "Version": NetworkConfig.Version, + "Language": NetworkConfig.Language + }; + parmeters.addAll(headers); + //签名加密 + Map parmetersSign = sign(parmeters); + try { + /*由于服务器是表单结构*/ + FormData formData = FormData.fromMap(parmetersSign); + Response response = await _dio!.post(path, data: formData); + if (response != null && response.statusCode == 200) { + BaseEntity entity = BaseEntity.fromJson(response.data); + Map parmeters = { + "AppId": NetworkConfig.AppId, + /*"BossId": NetworkConfig.BossId,*/ + "UserId": NetworkConfig.userId, + "Token": entity.message + }; + Map p1 = sign(parmeters); + parmeters.addAll(p1); + //data 信息添加用户信息 + entity.data = gettoken(parmeters); + success(entity); + + return entity; + } else { + error(ErrorEntity(code: -1, message: "Network Anomaly")); + return null; + } + } catch (e) { + ErrorEntity(code: -1, message: "Network Anomaly"); + return null; + } + } + + // 捕获异常的错误信息 + ErrorEntity _getErrorMsg(DioError error) { + switch (error.type) { + case DioErrorType.cancel: + { + return ErrorEntity(code: -1, message: "请求取消"); + } + break; + case DioErrorType.connectionTimeout: + { + return ErrorEntity(code: -1, message: "连接超时"); + } + break; + case DioErrorType.sendTimeout: + { + return ErrorEntity(code: -1, message: "请求超时"); + } + break; + case DioErrorType.receiveTimeout: + { + return ErrorEntity(code: -1, message: "响应超时"); + } + break; + case DioErrorType.badResponse: + { + try { + int errCode = error.response!.statusCode!; + String errorMsg = error.response!.statusMessage!; + return ErrorEntity(code: errCode, message: errorMsg); + } on Exception catch (_) { + return ErrorEntity(code: -1, message: "Network Anomaly"); + } + } + break; + default: + { + return ErrorEntity(code: -1, message: "Network Anomaly"); + } + } + } + + Map sign(Map parmeters) { + List keys = parmeters.keys.toList(); + // key排序 + keys.sort((a, b) { + List al = a.codeUnits; + List bl = b.codeUnits; + for (int i = 0; i < al.length; i++) { + if (bl.length <= i) return 1; + if (al[i] > bl[i]) { + return 1; + } else if (al[i] < bl[i]) return -1; + } + return 0; + }); + Map treeMap = Map(); + keys.forEach((element) { + treeMap[element] = parmeters[element]; + }); + String data = ""; + for (dynamic str in treeMap.values) { + if (str != null) { + data = data + str.toString(); + } + } + treeMap["sign"] = generateMd5(data + NetworkConfig.userToken); + return treeMap; + } + + String gettoken(Map parmeters) { + List keys = parmeters.keys.toList(); + // key排序 + keys.sort((a, b) { + List al = a.codeUnits; + List bl = b.codeUnits; + for (int i = 0; i < al.length; i++) { + if (bl.length <= i) return 1; + if (al[i] > bl[i]) { + return 1; + } else if (al[i] < bl[i]) return -1; + } + return 0; + }); + Map treeMap = Map(); + keys.forEach((element) { + treeMap[element] = parmeters[element]; + }); + String data = ""; + treeMap.forEach((key, value) { + if (data == "") { + data = key + "=" + value.toString(); + } else { + data = data + "&" + key + "=" + value.toString(); + } + }); + return data; + } + + String generateMd5(String data) { + return md5.convert(utf8.encode(data)).toString(); + } +} diff --git a/lib/tools/create/create_model.dart b/lib/tools/create/create_model.dart new file mode 100644 index 0000000..3de5162 --- /dev/null +++ b/lib/tools/create/create_model.dart @@ -0,0 +1,204 @@ +import 'dart:async'; + +import 'package:aiplot/bean/draw_template_bean.dart'; + +import '../../bean/text_to_image_bean.dart'; +import '../../bean/user_draw_bean.dart'; +import '../../bean/user_info_bean.dart'; +import '../../network/BaseEntity.dart'; +import '../../network/NetworkConfig.dart'; +import '../../network/RequestCenter.dart'; + +class CreateModel { + StreamController streamController = StreamController.broadcast(); + + CreateModel() { + setup(); + } + + void setup() { + //初始化 + } + + //获取模板列表 + Future getDrawTemplateList() async { + RequestCenter.instance.requestPlay(NetworkConfig.getDrawTemplateList, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => DrawTemplateBean.fromJson(e as Map)).toList(); + streamController.sink.add({ + 'code': "getDrawTemplateList", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + Future getUserData() async { + RequestCenter.instance.requestPlay(NetworkConfig.getUserData, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + UserInfoBean data = UserInfoBean.fromJson(json); + NetworkConfig.userData = data; + double num = data.AllCurrency!; + NetworkConfig.allCurrency = num.truncate().toString(); + NetworkConfig.currency = num; + NetworkConfig.usedRewardCount = data.UserAdLog!.UsedRewardCount; + NetworkConfig.totalRewardCount = data.UserAdLog!.TotalRewardCount; + NetworkConfig.invitationCode = data.InvitationCode; + + streamController.sink.add({ + 'code': "getUserData", //有数据 + 'data': data, + }); + } else {} + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //图片描述 + Future txt2Img(String prompt, int templateId, int sizeTemplateId, int followId) async { + RequestCenter.instance.requestPlay(NetworkConfig.txt2Img, { + "Prompt": prompt, + "TemplateId": templateId, + "SizeTemplateId": sizeTemplateId, + "FollowId": followId, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + TextToImageBean data = TextToImageBean.fromJson(json); + streamController.sink.add({ + 'code': "txt2Img", //有数据 + 'data': data, + }); + } else if (dataEntity.code == -5) { + //免费生成到上限 + streamController.sink.add({ + 'code': "upperLimit", + 'data': dataEntity.message, + }); + } else if (dataEntity.code == -6) { + //绘画点不足 + streamController.sink.add({ + 'code': "InsufficientPoints", + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //图片描述(与文生图数据结构相同) + Future img2Img(String prompt, String initImg, int templateId, int sizeTemplateId, double denoisingStrength, int followId) async { + RequestCenter.instance.requestPlay(NetworkConfig.img2Img, { + "Prompt": prompt, + "InitImg": initImg, + "TemplateId": templateId, + "SizeTemplateId": sizeTemplateId, + "DenoisingStrength": denoisingStrength, + "FollowId": followId, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + TextToImageBean data = TextToImageBean.fromJson(json); + streamController.sink.add({ + 'code': "txt2Img", //有数据 + 'data': data, + }); + } else if (dataEntity.code == -5) { + //免费生成到上限 + streamController.sink.add({ + 'code': "upperLimit", //有数据 + 'data': dataEntity.message, + }); + } else if (dataEntity.code == -6) { + //绘画点不足 + streamController.sink.add({ + 'code': "InsufficientPoints", + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //审核模式上传图片 + Future uploadImg(String initImg) async { + RequestCenter.instance.requestPlay(NetworkConfig.uploadImg, { + "ImgBase64": initImg, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0 && dataEntity.data != null) { + //Map json = dataEntity.data; + streamController.sink.add({ + 'code': "uploadOk", //有数据 + 'data': "", + }); + } else { + streamController.sink.add({ + 'code': "uploadErr", //有数据 + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //获取画廊 + Future getGalleryList() async { + RequestCenter.instance.requestPlay(NetworkConfig.getGalleryList, {"index": 1, "size": 30, "DrawLabele": 0}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => UserDrawBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "bannerGallery", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } +} diff --git a/lib/tools/create/create_page.dart b/lib/tools/create/create_page.dart new file mode 100644 index 0000000..700d86f --- /dev/null +++ b/lib/tools/create/create_page.dart @@ -0,0 +1,1545 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:math'; + +import 'package:aiplot/common/EventBusUtil.dart'; +import 'package:aiplot/common/app_util.dart'; +import 'package:aiplot/dialog/ad_free_dialog.dart'; +import 'package:aiplot/dialog/free_upper_limit_dialog.dart'; +import 'package:aiplot/dialog/guide_theme_switch_tip.dart'; +import 'package:aiplot/dialog/reference_image_tip_dialog.dart'; +import 'package:aiplot/dialog/tip_overwrite_not_dialog.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/tools/create/create_model.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_native_image/flutter_native_image.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:image_cropper/image_cropper.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:sensors_analytics_flutter_plugin/sensors_analytics_flutter_plugin.dart'; + +import '../../bean/draw_template_bean.dart'; +import '../../bean/text_to_image_bean.dart'; +import '../../bean/user_draw_bean.dart'; +import '../../common/Global.dart'; +import '../../common/dialog_bean.dart'; +import '../../common/dialog_manager.dart'; +import '../../common/dialog_util.dart'; +import '../../common/func.dart'; +import '../../dialog/guideDialog.dart'; +import '../../dialog/login_dialog.dart'; +import '../../dialog/phone_login_dialog.dart'; +import '../../generated/l10n.dart'; +import '../drawdetails/draw_details_page.dart'; +import '../start_model.dart'; +import 'guidance_label.dart'; + +///创作页 +class CreatePage extends StatefulWidget { + const CreatePage({Key? key}) : super(key: key); + + @override + State createState() => _CreatePageState(); +} + +class _CreatePageState extends State with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { + @override + bool get wantKeepAlive => true; + + StreamSubscription? subscription; + final CreateModel _viewModel = CreateModel(); + TextToImageBean? textToImageBean; + final StartModel _startModel = StartModel(); + + StreamSubscription? _tabBarEvent; + StreamSubscription? _copyDrawingEvent; + StreamSubscription? _refreshUserdata; + + bool isEntered = false; + + //输入框内容 + String promptText = ""; + + void _textFieldChanged(String str) { + if (str != "") { + isEntered = true; + } else { + isEntered = false; + } + promptText = str; + } + + final TextEditingController _textController = TextEditingController(text: ''); + final ScrollController _gridController = ScrollController(); + + String initImg = ""; //参考图 + final FocusNode _commentFocus = FocusNode(); //输入框焦点 + int currentIndex = 0; //当前风格下标 + int currentSizeIndex = 0; //当前尺寸下标 + + //尺寸 + List sizeList = [ + AssetImage('assets/images/img_11.png'), + AssetImage('assets/images/img_34.png'), + AssetImage('assets/images/img_43.png'), + AssetImage('assets/images/img_916.png'), + AssetImage('assets/images/img_169.png'), + ]; + List sizeListNo = [ + AssetImage('assets/images/img_11_no.png'), + AssetImage('assets/images/img_34_no.png'), + AssetImage('assets/images/img_43_no.png'), + AssetImage('assets/images/img_916_no.png'), + AssetImage('assets/images/img_169_no.png'), + ]; + + //风格列表 + List templateList = []; + + //顶部banner数据 + List bannerGalleryList = []; + final ScrollController _bannerController = ScrollController(); + + //滑动条数值 + double sliderValue = 4.0; + double repaintValue = 0.4; //重绘度 + CroppedFile? selectImage; //选择的相册图 + String copyImgUrl = ""; //画同款图片 + + double countP = 0.0; //消耗点数 + String cueWord = ""; + + //选中类型 + int selectType = 0; + int mainBodyIndex = 0; //当前主体下标 + //风格列表 + List t1 = []; + + //选择前 + List t2 = []; + + //选择后 + List t3 = []; + + //选择的选项集合 + Map> selectList1 = {}; + + //引导词 + String introducer = ""; + + /// 动画控制器 + AnimationController? _controller; + + /// 非线性动画 + Animation? _curveAnimation; + + Map? responseData; + + GlobalKey loginDialogKey = GlobalKey(); //登录弹框key + + Timer? timer; + + @override + void initState() { + // TODO: implement initState + super.initState(); + + if (Platform.isIOS) { + subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { + // Got a new connectivity status! + if (result == ConnectivityResult.mobile || result == ConnectivityResult.wifi) { + setState(() { + _viewModel.getDrawTemplateList(); + _viewModel.getUserData(); + _viewModel.getGalleryList(); + _startModel.getAppConfig(); + }); + } + }); + } + + //引导模式数据 + if (NetworkConfig.Language != "zh") { + responseData = GuidanceLabel.responseDataEn; + } else { + responseData = GuidanceLabel.responseDataZh; + } + + //banner滑动监听 到底部时跳到第一位 + _bannerController.addListener(() { + if (_bannerController.offset >= _bannerController.position.maxScrollExtent && !_bannerController.position.outOfRange) { + _bannerController.jumpTo(0.0); + } + }); + + //设置定时器 自动滑动 + timer = Timer.periodic(Duration(milliseconds: 100), (Timer t) { + if (_bannerController.hasClients) { + _bannerController.animateTo( + _bannerController.offset + 15, + duration: const Duration(milliseconds: 500), + curve: Curves.easeOut, + ); + } + }); + + ///动画 + _controller = AnimationController( + duration: const Duration(seconds: 1), + vsync: this, + ); + _curveAnimation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: _controller!, curve: Curves.easeInOut)); + + ///eventbus + //刷新用户信息 + _tabBarEvent = EventBusUtil.listen((event) { + _commentFocus.unfocus(); + if (event.Tab == 1) { + _viewModel.getUserData(); + } + }); + + _refreshUserdata = EventBusUtil.listen((event) { + _commentFocus.unfocus(); + _viewModel.getUserData(); + }); + + //画同款 + _copyDrawingEvent = EventBusUtil.listen((event) { + _textController.text = NetworkConfig.prompt; + promptText = NetworkConfig.prompt; + copyImgUrl = NetworkConfig.followUrl; + selectImage = null; + selectList1 = {}; + introducer = ""; + for (int i = 0; i < templateList.length; i++) { + if (NetworkConfig.templateId == templateList[i].Id) { + currentIndex = i; + + ///滑动到选中的风格 + double offsetX = (currentIndex / 2) * 86; + _gridController.animateTo( + offsetX, + duration: Duration(milliseconds: 500), + curve: Curves.decelerate, + ); + } + } + currentSizeIndex = NetworkConfig.sizeTemplateId; + + print("object${NetworkConfig.prompt}"); + print("object${NetworkConfig.templateId}"); + print("object${NetworkConfig.sizeTemplateId}"); + + setState(() {}); + }); + + ///网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + switch (code) { + case "getDrawTemplateList": //风格列表 + EasyLoading.dismiss(); + templateList = newData['data']; + if (NetworkConfig.isImitate) { + _textController.text = NetworkConfig.prompt; + promptText = NetworkConfig.prompt; + for (int i = 0; i < templateList.length; i++) { + if (NetworkConfig.templateId == templateList[i].Id) { + currentIndex = i; + } + } + currentSizeIndex = NetworkConfig.sizeTemplateId; + } + break; + case "txt2Img": //上传生成信息 + EasyLoading.dismiss(); + textToImageBean = newData['data']; + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DrawDetailsPage( + true, + taskId: textToImageBean!.TaskId!, + isMyWork: true, + describeText: cueWord, + ), + )); + break; + case "upperLimit": //免费保存上限 + EasyLoading.dismiss(); + FunctionUtil.popDialog(context, FreeUpperLimitDialog( + onTap: (index) { + if (index == 1) { + Navigator.pushNamed(context, "/ShopPage"); + } + }, + )); + break; + case "InsufficientPoints": //绘画点不足 + Fluttertoast.showToast( + msg: newData['data'], + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 1, + backgroundColor: Colors.black, + textColor: Colors.white, + fontSize: 16.0); + Navigator.pushNamed(context, "/ShopPage"); + break; + case "bannerGallery": + bannerGalleryList = newData['data']; + break; + case "getUserData": + break; + default: + String message = newData['data']; + EasyLoading.showToast(message); + break; + } + } + setState(() {}); + }); + getData(); + } + + ///获取数据 + Future getData() async { + for (var name in responseData!["body"]) { + t1.add(name["name"]); + } + t2 = responseData!["body"][0]["content"]; + for (int i = 0; i < t2.length; i++) { + selectList1[i] = []; + } + EasyLoading.show(status: 'loading...'); + _viewModel.getDrawTemplateList(); + _viewModel.getUserData(); + _viewModel.getGalleryList(); + } + + //生成图片 0:文生图 1:图生图 + Future _createPic(int type, String prompt, int templateId, int sizeTemplateId) async { + if (type == 0) { + _viewModel.txt2Img(prompt, templateId, sizeTemplateId, 0); + } else { + _viewModel.img2Img(prompt, initImg, templateId, sizeTemplateId, double.parse(repaintValue.toStringAsFixed(1)), 0); + } + _viewModel.getUserData(); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + _tabBarEvent?.cancel(); + timer?.cancel(); + _refreshUserdata?.cancel(); + _copyDrawingEvent?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final w100 = size.width / 3.6; //100 + final h32 = size.width / 11.25; //32 + final h70 = size.width / 5.1428571428571; //301 + final h40 = size.width / 9; //40 + final w193 = size.width / 1.8652849740932; //57 + final h186 = size.width / 1.9354838709677; //186 + final w86 = size.width / 4.1860465116279; //86 + final w124 = size.width / 2.9032258064516; //86 + + if (templateList.isNotEmpty && templateList[currentIndex].Charging != null) { + countP = templateList[currentIndex].Charging! + (selectImage != null || copyImgUrl != "" ? 1 : 0); + } + + //推荐词 + List recommendList = [ + S.of(context).A_colorful, + S.of(context).Brunette_princess, + S.of(context).Beautiful_angel, + S.of(context).Rapeseed_flowers, + S.of(context).Long_hair, + S.of(context).A_close, + S.of(context).After_rain, + S.of(context).Distant_mountains, + S.of(context).Snow_mountain, + S.of(context).The_stars, + ]; + + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.only(right: 10), + child: const Image( + width: 23, + height: 23, + image: AssetImage('assets/images/ic_title.png'), + ), + ), + Text( + "AI${S.of(context).Creation_ja}", + style: const TextStyle(color: Colors.black, fontSize: 20), + ), + ], + ), + centerTitle: true, + ), + body: Stack( + alignment: Alignment.center, + children: [ + SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ///顶部banner + bannerGalleryList != null && bannerGalleryList.isNotEmpty + ? GestureDetector( + onTap: () { + EventBusUtil.fire(TabBarJumpEvent(0)); + }, + child: Container( + height: 182, + width: size.width, + margin: EdgeInsets.only(top: 10), + child: ListView.builder( + controller: _bannerController, + itemCount: bannerGalleryList.length, + itemBuilder: (BuildContext context, int index) { + return _bannerItem(bannerGalleryList[index], index); + }, + physics: NeverScrollableScrollPhysics(), + scrollDirection: Axis.horizontal), + ), + ) + : Container(), + + Container( + margin: const EdgeInsets.only(left: 15, top: 26), + alignment: Alignment.centerLeft, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "*${S.of(context).Describe_in_detail}", + style: TextStyle(color: Colors.black, fontSize: NetworkConfig.Language == "ja" ? 12 : 16), + ), + + ///点数 + GestureDetector( + onTap: () { + if (NetworkConfig.userId == "") { + showLoginDialog(); + } else { + Navigator.pushNamed(context, "/ShopPage"); + } + }, + child: Container( + height: 18, + margin: const EdgeInsets.only(right: 15), + padding: const EdgeInsets.only(left: 5, right: 5), + decoration: BoxDecoration(borderRadius: const BorderRadius.all(Radius.circular(9))), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Image( + width: 15, + height: 15, + image: AssetImage('assets/images/ic_count.png'), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text( + "×${NetworkConfig.allCurrency}", + style: const TextStyle(color: Color(0xFF8841FF), fontSize: 12), + ), + ), + ], + ), + ), + ) + ], + ), + ), + + ///输入框 描述 + Container( + alignment: Alignment.center, + margin: const EdgeInsets.only(top: 13, left: 15, right: 15), + padding: const EdgeInsets.only(left: 9, top: 13, right: 9), + decoration: const BoxDecoration( + //背景 + color: Color(0xFFF3F3FB), + //设置四周圆角 角度 + borderRadius: BorderRadius.all(Radius.circular(6.6)), + //设置四周边框 + ), + child: TextField( + controller: _textController, + keyboardType: TextInputType.name, + focusNode: _commentFocus, + decoration: InputDecoration.collapsed( + hintText: '${S.of(context).for_instance}\n\n${S.of(context).more_detailed}', + hintStyle: const TextStyle(fontSize: 16.0, color: Color(0xFFB5B5B5))), + textAlign: TextAlign.left, + //文本对齐方式 + //最大长度,设置此项会让TextField右下角有一个输入数量的统计字符串 + maxLines: 7, + //最大行数 + style: const TextStyle(fontSize: 16.0, color: Colors.black), + //输入文本的样式 + onChanged: _textFieldChanged, + autofocus: false, + maxLength: 500, + // inputFormatters: [ + // /* FilteringTextInputFormatter.allow(RegExp('[0-9]')),*/ + // //只能输入汉字或者字母或数字 + // LengthLimitingTextInputFormatter(500), + // //最大长度 + // ], + ), + ), + + ///随机提示词 推荐 + Container( + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(top: 7, left: 15), + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + _startOrStopRotation(); + _commentFocus.unfocus(); + var indexNet = Random().nextInt(10); + if (isEntered) { + FunctionUtil.popDialog(context, TipOverwriteNotDialog( + onTap: (index) { + if (index == 1) { + NetworkConfig.prompt = recommendList[indexNet]; + _textController.text = recommendList[indexNet]; + promptText = recommendList[indexNet]; + isEntered = false; + } + }, + )); + } else { + NetworkConfig.prompt = recommendList[indexNet]; + _textController.text = recommendList[indexNet]; + promptText = recommendList[indexNet]; + } + }, + child: SizedBox( + width: 180, + height: 40, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + S.of(context).Random_Description, + style: TextStyle( + color: const Color(0xFFBB71E0), + fontSize: NetworkConfig.Language == "ja" ? 12 : 14, + ), + ), + Container( + margin: const EdgeInsets.only(left: 5, top: 1), + child: RotationTransition( + turns: _curveAnimation!, + child: const Image( + width: 15, + height: 15, + image: AssetImage('assets/images/ic_random.png'), + ), + ), + ) + ], + ), + ), + ), + ), + + ///类型 + Container( + margin: const EdgeInsets.only(left: 15, top: 20, right: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ///简易 + GestureDetector( + onTap: () { + setState(() { + selectType = 0; + }); + }, + child: Container( + width: w100, + height: h32, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(selectType == 0 ? 0xFFBB70E0 : 0xFFF3F3FB), borderRadius: const BorderRadius.all(Radius.circular(5))), + child: Text( + S.of(context).Easy_mode, + style: TextStyle(color: Color(selectType == 0 ? 0xFFFFFFFF : 0xFF999999)), + ), + ), + ), + + ///引导模式 + GestureDetector( + onTap: () { + setState(() { + selectType = 1; + }); + }, + child: Container( + width: w100, + height: h32, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(selectType == 1 ? 0xFFBB70E0 : 0xFFF3F3FB), borderRadius: const BorderRadius.all(Radius.circular(5))), + child: Text( + S.of(context).guide, + style: TextStyle(color: Color(selectType == 1 ? 0xFFFFFFFF : 0xFF999999)), + ), + ), + ), + + ///艺术家 + GestureDetector( + onTap: () { + EasyLoading.showToast(S.of(context).The_function); + }, + child: Stack( + children: [ + Container( + width: w100, + height: h32, + alignment: Alignment.center, + decoration: const BoxDecoration(color: Color(0xFFF3F3FB), borderRadius: BorderRadius.all(Radius.circular(5))), + child: Text( + S.of(context).Artist, + style: const TextStyle(color: Color(0xFF999999)), + ), + ), + Positioned( + right: 0, + child: Container( + width: 30, + height: 11, + color: Colors.red, + alignment: Alignment.center, + child: const Text( + "VIP", + style: TextStyle(color: Colors.white, fontSize: 10), + ), + )), + ], + ), + ), + ], + ), + ), + + ///0 简易风格 1 引导模式 + selectType == 1 + ? Column( + children: [ + Container( + margin: const EdgeInsets.only(left: 15, top: 23), + alignment: Alignment.centerLeft, + child: Text( + S.of(context).The_subject, + style: const TextStyle(color: Colors.black, fontSize: 16), + ), + ), + + ///主体 + Container( + margin: const EdgeInsets.only(top: 13), + child: GridView.count( + shrinkWrap: true, + primary: false, + //水平子Widget之间间距 + crossAxisSpacing: 10, + //垂直子Widget之间间距 + mainAxisSpacing: 10, + //GridView内边距 + padding: const EdgeInsets.only(left: 16, right: 16), + //一行的Widget数量 + crossAxisCount: 4, + //子Widget宽高比例 + childAspectRatio: 2.7, + //子Widget列表 + children: _sizeItem2(t1), + //类似 cellForRow 函数 + scrollDirection: Axis.vertical), + ), + + ///内容 + Container( + child: ListView.builder( + shrinkWrap: true, + itemCount: t2.length, + itemExtent: 100, + padding: const EdgeInsets.all(0), + //数据的数量 + itemBuilder: (context, index) { + return GestureDetector( + onTap: () {}, + child: Column( + children: [ + Container( + margin: const EdgeInsets.only(left: 15, top: 23), + alignment: Alignment.centerLeft, + child: Text( + t2[index]["name"].toString(), + style: const TextStyle(color: Colors.black, fontSize: 16), + ), + ), + _sizeItem3(index), + ], + )); + }, + physics: const NeverScrollableScrollPhysics(), + //类似 cellForRow 函数 + scrollDirection: Axis.vertical), + ), + ], + ) + : Container(), + + ///绘画风格 + Container( + margin: const EdgeInsets.only(left: 15, top: 30), + alignment: Alignment.centerLeft, + child: Text( + S.of(context).Painting_style, + style: const TextStyle(color: Colors.black, fontSize: 16), + ), + ), + Container( + margin: const EdgeInsets.only(top: 11), + child: SizedBox( + height: h186, + width: MediaQuery.of(context).size.width, + child: GridView.count( + controller: _gridController, + shrinkWrap: true, + //水平子Widget之间间距 + crossAxisSpacing: 10.0, + //垂直子Widget之间间距 + mainAxisSpacing: 10.0, + //GridView内边距 + padding: const EdgeInsets.only(left: 15, right: 15), + //一行的Widget数量 + crossAxisCount: 2, + //子Widget宽高比例 + childAspectRatio: 1.0, + //子Widget列表 + children: _item(templateList, w86), + //类似 cellForRow 函数 + scrollDirection: Axis.horizontal)), + ), + + ///尺寸 + Container( + margin: const EdgeInsets.only(left: 15, top: 23), + alignment: Alignment.centerLeft, + child: Text( + S.of(context).Image_scale, + style: const TextStyle(color: Colors.black, fontSize: 16), + ), + ), + Container( + margin: const EdgeInsets.only(top: 11), + child: GridView.count( + shrinkWrap: true, + primary: false, + //水平子Widget之间间距 + crossAxisSpacing: 5, + //垂直子Widget之间间距 + mainAxisSpacing: 10, + //GridView内边距 + padding: const EdgeInsets.only(left: 16, right: 16), + //一行的Widget数量 + crossAxisCount: 3, + //子Widget宽高比例 + childAspectRatio: 3.2, + //子Widget列表 + children: _sizeItem(sizeList, sizeListNo), + //类似 cellForRow 函数 + scrollDirection: Axis.vertical), + ), + + ///参考图 + Container( + margin: const EdgeInsets.only(left: 15, top: 30, right: 15), + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + S.of(context).Reference_drawing, + style: const TextStyle(color: Colors.black, fontSize: 16), + ), + //说明弹框 + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + FunctionUtil.popDialog(context, ReferenceImageTipDialog()); + }, + child: Container( + padding: EdgeInsets.all(10), + child: const Image( + width: 20, + height: 20, + image: AssetImage('assets/images/ic_tip.png'), + ), + ), + ) + ], + ), + ), + + ///相册图(选取相册图片) + Container( + alignment: Alignment.centerLeft, + child: Stack( + children: [ + GestureDetector( + onTap: () async { + XFile img = await AppUtil.getImages(); + selectImage = await AppUtil.cropImage(img.path, currentSizeIndex); + + setState(() {}); + }, + child: Container( + height: w86, + margin: const EdgeInsets.only(left: 15, top: 10), + padding: const EdgeInsets.only(right: 20), + + ///画廊画同款 + child: copyImgUrl != "" + ? CachedNetworkImage( + fit: BoxFit.cover, + imageUrl: copyImgUrl, + errorWidget: (context, url, error) => const Icon(Icons.error), + ) + + ///相册选择图片 + : selectImage != null + ? Image.file( + File(selectImage!.path), + fit: BoxFit.cover, + ) + : const Image( + image: AssetImage('assets/images/ic_upload.png'), + ), + ), + ), + Positioned( + right: 0, + child: selectImage != null || copyImgUrl != "" + ? GestureDetector( + onTap: () { + selectImage = null; + copyImgUrl = ""; + initImg = ""; + setState(() {}); + }, + child: const Image( + width: 15, + height: 15, + image: AssetImage('assets/images/img_delete.png'), + ), + ) + : Container()) + ], + ), + ), + + Container( + margin: const EdgeInsets.only(left: 15, top: 11), + alignment: Alignment.centerLeft, + child: Text( + S.of(context).Will_refer, + style: const TextStyle(color: Color(0xFF999999), fontSize: 12), + ), + ), + Container( + margin: const EdgeInsets.only(left: 15, top: 22), + alignment: Alignment.centerLeft, + child: Text( + S.of(context).Reference_drawing_redrawing, + style: const TextStyle(color: Colors.black, fontSize: 16), + ), + ), + + ///滑动条 重绘度 + Container( + margin: const EdgeInsets.only(top: 15), + alignment: Alignment.centerLeft, + child: Row( + children: [ + Flexible( + flex: 9, + child: SliderTheme( + data: SliderTheme.of(context).copyWith( + trackHeight: 4.0, + ), + child: Slider( + value: sliderValue, + activeColor: const Color(0xFF8841FF), + inactiveColor: const Color(0xFFD1D1D1), + min: 1, + max: 10, + onChanged: (value) { + setState(() { + sliderValue = value; + repaintValue = sliderValue * 0.1; + }); + }, + ), + )), + Flexible( + flex: 1, + child: Text( + sliderValue.toStringAsFixed(0), + style: const TextStyle(color: Color(0xFF555555)), + ), + ), + ], + )), + Container( + margin: const EdgeInsets.only(left: 15, top: 11, bottom: 100), + alignment: Alignment.centerLeft, + child: Text( + S.of(context).The_smaller, + style: TextStyle(color: Color(0xFF999999), fontSize: 12), + ), + ), + ], + ), + ), + Positioned( + bottom: 0, + child: Container( + color: Colors.white, + width: size.width, + height: 80, + alignment: Alignment.topCenter, + padding: EdgeInsets.only(left: 15, right: 15, top: 10), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ///生成绘画 + GestureDetector( + onTap: () async { + _generateImages(); + }, + child: Container( + width: w193, + height: h40, + alignment: Alignment.center, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), + borderRadius: BorderRadius.all(Radius.circular(20))), + //显示消耗点 + child: templateList.isNotEmpty + ? Text( + "${S.of(context).Generate_painting}(${S.of(context).Consume} ${countP.truncate()} ${S.of(context).point})", + style: const TextStyle(color: Colors.white, fontSize: 16), + ) + : Text( + S.of(context).Generate_painting, + style: const TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ), + + ///免费 + GestureDetector( + onTap: () async { + if (NetworkConfig.userId != "") { + if (NetworkConfig.appConfigBean != null && NetworkConfig.appConfigBean!.AdFree != null) { + FunctionUtil.popDialog( + context, + AdFreeDialog( + onTap: (index) {}, + )); + } + } else { + showLoginDialog(); + } + }, + child: Container( + width: w124, + height: h40, + alignment: Alignment.center, + decoration: const BoxDecoration(color: Color(0xFFF3F3FB), borderRadius: BorderRadius.all(Radius.circular(20))), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Image(width: 22, image: AssetImage('assets/images/ic_ad.png')), + Container( + margin: EdgeInsets.only(left: 8), + child: Text( + S.of(context).Free, + style: const TextStyle(color: Color(0xFF666666), fontSize: 16), + ), + ), + ], + ), + ), + ), + ], + ), + NetworkConfig.appConfigBean != null && NetworkConfig.appConfigBean!.SharingRewards != null + ? Container( + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(top: 5), + child: Text( + "${S.of(context).Upload_the_painting} ${NetworkConfig.appConfigBean!.SharingRewards} ${S.of(context).Painting_points}", + style: TextStyle(color: Color(0xFF999999), fontSize: NetworkConfig.Language == "ja" ? 8 : 12), + ), + ) + : Container(), + ], + ), + ), + ), + ], + ), + ); + } + + ///生成图片 + _generateImages() async { + EasyLoading.show(status: 'loading...'); + if (NetworkConfig.userId != "") { + if (promptText != "" || introducer != "") { + _commentFocus.unfocus(); + //合并提示词 + cueWord = "$promptText${selectType == 0 ? "" : introducer}${selectType == 0 ? "" : ","}${selectType == 0 ? "" : t1[mainBodyIndex]}"; + if (cueWord.startsWith(",")) { + cueWord = cueWord.substring(1); + } + if (selectImage != null || copyImgUrl != "") { + if (copyImgUrl == "") { + //处理图片 + initImg = await _compressPictures(); + } else { + initImg = (await AppUtil.networkImageToBase64(copyImgUrl))!; + } + + ///图生图 + _createPic(1, cueWord, templateList[currentIndex].Id!, currentSizeIndex); + //埋点 + SensorsAnalyticsFlutterPlugin.track('AidrawStart', {'AidrawMode': '图生图', 'AidrawCZMode': selectType == 0 ? '简易模式' : '引导模式'}); + } else { + ///文生图 + _createPic(0, cueWord, templateList[currentIndex].Id!, currentSizeIndex); + //埋点 + SensorsAnalyticsFlutterPlugin.track('AidrawStart', {'AidrawMode': '文生图', 'AidrawCZMode': selectType == 0 ? '简易模式' : '引导模式'}); + } + NetworkConfig.prompt = cueWord; + } else { + EasyLoading.showToast(S.of(context).Please_fill); + } + } else { + showLoginDialog(); + } + } + + //动画 + void _startOrStopRotation() { + setState(() { + if (_controller!.isAnimating) { + _controller!.stop(); + } + _controller!.forward(from: 0.0); + }); + } + + _bannerItem(UserDrawBean data, int index) { + return Container( + margin: EdgeInsets.only(left: 10), + child: ClipRRect( + borderRadius: BorderRadius.circular(7), + child: CachedNetworkImage( + imageUrl: data.ImageUrl!, + fit: BoxFit.fitHeight, + )), + // child: Image(image: list[index]), + ); + } + + //风格 + _item(List list, double w86) { + return list.map((e) { + int index = list.indexOf(e); + return GestureDetector( + onTap: () { + currentIndex = index; + NetworkConfig.templateId = list[index].Id!; + setState(() {}); + }, + child: Container( + alignment: Alignment.center, + child: Stack( + alignment: Alignment.center, + children: [ + CachedNetworkImage(imageUrl: list[index].ImageSmall!), + currentIndex == index ? const Image(image: AssetImage('assets/images/ic_style_s.png')) : Container(), + Positioned( + bottom: 1, + child: Container( + width: w86, + height: 20, + alignment: Alignment.center, + decoration: const BoxDecoration( + color: Color(0x4D000000), borderRadius: BorderRadius.only(bottomLeft: Radius.circular(5), bottomRight: Radius.circular(5))), + child: Text( + list[index].Title!, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Colors.white, fontSize: 12), + ), + )), + ], + ), + ), + ); + }).toList(); + } + + //尺寸 + _sizeItem(List list, List listNo) { + return list.map((e) { + int index = list.indexOf(e); + return GestureDetector( + onTap: () { + if (selectImage == null && copyImgUrl == "") { + currentSizeIndex = index; + NetworkConfig.sizeTemplateId = currentSizeIndex; + setState(() {}); + } + }, + child: Container( + alignment: Alignment.center, + child: Stack( + alignment: Alignment.center, + children: [ + Image( + image: selectImage == null && copyImgUrl == "" + ? list[index] + : currentSizeIndex == index + ? list[index] + : listNo[index]), + currentSizeIndex == index ? const Image(fit: BoxFit.fill, image: AssetImage('assets/images/ic_size_select.png')) : Container(), + ], + ), + ), + ); + }).toList(); + } + + //主体切换 + _sizeItem2(List list) { + return list.map((e) { + int index = list.indexOf(e); + return GestureDetector( + onTap: () { + if (introducer != "") { + //进行弹窗提示,以下为弹窗中点切换时处理 + FunctionUtil.popDialog( + context, + GuideThemeSwitchTip( + t1[index], + onTap: (indexTip) { + if (indexTip == 1) { + mainBodyIndex = index; + t2 = responseData!["body"][index]["content"]; + selectList1 = {}; + for (int i = 0; i < t2.length; i++) { + selectList1[i] = []; + } + introducer = ""; + setState(() {}); + } + }, + )); + } else { + mainBodyIndex = index; + t2 = responseData!["body"][index]["content"]; + } + + setState(() {}); + }, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: const Color(0xFFF3F3FB), + //设置四周圆角 角度 + borderRadius: const BorderRadius.all(Radius.circular(6.6)), + //设置四周边框 + border: Border.all(width: 1, color: Color(mainBodyIndex == index ? 0xFF8841FF : 0xFFFFFFFF)), + ), + child: Text( + list[index], + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Color(mainBodyIndex == index ? 0xFF8841FF : 0xFF999999), fontSize: 12), + ), + ), + ); + }).toList(); + } + + _sizeItem3(int i) { + return GestureDetector( + onTap: () { + _commentFocus.unfocus(); + DialogManager() + ..add(DialogBean( + createDialogWidget: () => DialogUtil.createTipWidget( + context, + guideDialog( + name: t2[i]["name"], + list: t2[i]["content"], + selectList: selectList1 != null && selectList1.isNotEmpty ? selectList1[i]! : [], + onTap: (selectList) { + selectList1[i] = selectList; + introducer = ""; + selectList1.forEach((key, value) { + if (value != null && value.isNotEmpty) { + for (var v in value) { + introducer = introducer + "," + v; + } + } + }); + print(introducer); + setState(() {}); + }, + ), + "guideDialog$i", + canceled: false))) + ..show(context); + }, + child: Container( + margin: const EdgeInsets.only(left: 15, right: 15, top: 13), + padding: const EdgeInsets.only( + left: 15, + right: 15, + ), + height: 40, + decoration: const BoxDecoration( + color: Color(0xFFF3F3FB), + //设置四周圆角 角度 + borderRadius: BorderRadius.all(Radius.circular(6.6)), + ), + child: Stack( + children: [ + selectList1 != null && selectList1.isNotEmpty && selectList1[i] != null && selectList1[i]!.isNotEmpty + ? Container( + height: 40, + margin: const EdgeInsets.only( + right: 40, + ), + child: SingleChildScrollView( + physics: BouncingScrollPhysics(), + scrollDirection: Axis.horizontal, + child: Row( + children: selectList1[i]! + .map((data) => Container( + margin: const EdgeInsets.only( + right: 10, + ), + child: GestureDetector( + onTap: () { + setState(() { + selectList1[i]!.remove(data); + introducer = ""; + selectList1.forEach((key, value) { + if (value != null && value.isNotEmpty) { + for (var v in value) { + introducer = introducer + v; + } + } + }); + print(introducer); + setState(() {}); + }); + }, + child: Container( + padding: const EdgeInsets.only(left: 5, right: 5, top: 1, bottom: 1), + decoration: BoxDecoration( + //设置四周圆角 角度 + borderRadius: const BorderRadius.all(Radius.circular(3.5)), + //设置四周边框 + border: Border.all(width: 1, color: const Color(0xFF8841FF)), + ), + child: Row( + children: [ + Text( + data, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Color(0xFF8841FF), fontSize: 12), + ), + Container( + margin: const EdgeInsets.only( + left: 9, + ), + child: Image(width: 13, height: 13, image: AssetImage('assets/images/cuo2.png'))) + ], + ), + ), + ), + )) + .toList()), + ), + ) + : Align( + alignment: Alignment.centerLeft, + child: Text( + S.of(context).What_kind, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Color(0xFF999999), fontSize: 12), + ), + ), + Align( + alignment: Alignment.centerRight, + child: Image(width: 16, height: 16, image: AssetImage('assets/images/zhankai.png')), + ) + ], + ), + ), + ); + } + + //处理图片 + _compressPictures() async { + String img = ""; + //1,取方向,判断原图方向横竖 + // 2,同方向取宽高中最大值,匹配已选择的画面比例宽高值。反方向小值 + + //1:1 512*512 3:4 512*704 4:3 704*512 9:16 512*910 16:9 910*512 + File file = File(selectImage!.path); + File? compressedFile; + ImageProperties properties = await FlutterNativeImage.getImageProperties(file.path); + //判断当前方向 + int isDirection = 0; //0 正方形 1 横向长方形 2 纵向长方形 + if (properties.width == properties.height) { + isDirection = 0; + } else if (properties.width! > properties.height!) { + isDirection = 1; + } else if (properties.width! < properties.height!) { + isDirection = 2; + } + //下标选择方向 + if (currentSizeIndex == 0) { + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 512, targetHeight: (properties.height! * 512 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 512 / properties.height!).round(), targetHeight: 512); + } else { + compressedFile = file; + } + } + } else if (currentSizeIndex == 1) { + //下标方向为纵向 + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + //横向 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 512, targetHeight: (properties.height! * 512 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + //纵向 + if (properties.height! > 704) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 704 / properties.height!).round(), targetHeight: 704); + } else { + compressedFile = file; + } + } + } else if (currentSizeIndex == 2) { + //下标方向为横向 + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + //横向 + if (properties.width! > 704) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 704, targetHeight: (properties.height! * 704 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + //纵向 + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 512 / properties.height!).round(), targetHeight: 512); + } else { + compressedFile = file; + } + } + } else if (currentSizeIndex == 3) { + //下标方向为纵向 + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + //横向 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 512, targetHeight: (properties.height! * 512 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + //纵向 + if (properties.height! > 910) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 910 / properties.height!).round(), targetHeight: 910); + } else { + compressedFile = file; + } + } + } else if (currentSizeIndex == 4) { + //下标方向为横向 + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + //横向 + if (properties.width! > 910) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 910, targetHeight: (properties.height! * 910 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + //纵向 + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 512 / properties.height!).round(), targetHeight: 512); + } else { + compressedFile = file; + } + } + } + + ImageProperties properties2 = await FlutterNativeImage.getImageProperties(compressedFile!.path); + print("ImageProperties===" + properties2.width.toString() + "*" + properties2.height.toString()); + + ///判断图片大小 + double size = AppUtil.getFileSizeDouble(bytes: compressedFile.lengthSync()); + //取整 大于10m直接抛弃 + var s = size.ceil(); + if (s > 10) { + EasyLoading.showToast(S.of(context).Image_too_large); + } else { + //取整 大于1m直接压缩,小于1m使用原图 + if (s > 1) { + //图片压缩,压缩算法为 (10-s)*10,m越大调整后百分比越小 + int percentage = (10 - s) * 10; + File compressedFile2 = await FlutterNativeImage.compressImage(compressedFile.path, quality: 80, percentage: percentage); + //AppUtil.getFileSizeDouble(bytes: compressedFile2.lengthSync()); + img = await AppUtil.uploadImage2(compressedFile2); + } else { + //不压 + img = await AppUtil.uploadImage2(compressedFile); + } + } + return img; + } + + //弹出登录 + showLoginDialog() { + DialogManager() + ..add(DialogBean( + dialogPriority: DialogPriority.highClear, + createDialogWidget: () => DialogUtil.createTipWidget( + context, + LoginDialog( + loginDialogKey, + onTap: (index) { + switch (index) { + case 0: + if (loginDialogKey.currentState != null) { + loginDialogKey.currentState!.Pop(); + } + FunctionUtil.bottomSheetDialog(context, const PhoneLoginDialog()); + break; + case 1: //谷歌登录 + Map map = {"googleLogin": "googleLogin"}; + invokeNativeMethod("googleLogin", map); + break; + } + }, + ), + "LoginDialog", + canceled: true))) + ..show(context); + } + + // 获取原生的值 + invokeNativeMethod(String method, Map map) async { + dynamic args; + try { + args = await Global.method.invokeMethod(method, map); + } on PlatformException catch (e) {} + } +} diff --git a/lib/tools/create/guidance_label.dart b/lib/tools/create/guidance_label.dart new file mode 100644 index 0000000..8cd039d --- /dev/null +++ b/lib/tools/create/guidance_label.dart @@ -0,0 +1,4131 @@ +///引导模式数据 +class GuidanceLabel { + static Map responseDataEn = { + "body": [ + { + "name": "Girl", + "content": [ + { + "name": "Hair", + "content": [ + { + "name": "Hair Length", + "max": 1, + "content": [ + "short hair", + "Medium Hair", + "Over the shoulder hair", + "Ultra Short Hair", + "long hair", + "Extra Long Hair", + "Long and short" + ] + }, + { + "name": "Hairstyle", + "max": 1, + "content": [ + "curls", + "Wavy Curl", + "Multiple hairs", + "Divided main cut", + "Two Bun Heads", + "single braid", + "Single ponytail", + "straight hair", + "Princess Roll", + "Stupid hair", + "Sister Cut", + "Baozitou", + "braid", + "Double Braid", + "Double tail" + ] + }, + { + "name": "Bangs", + "max": 1, + "content": [ + "No bangs", + "braid bangs", + "side fringe", + "Forked bangs", + "Asymmetric bangs", + "bangs", + "long bangs", + "Qi bangs", + "Side Swept Bangs", + "Cross bangs" + ] + }, + { + "name": "Hair Color", + "max": 1, + "content": [ + "Gradient Hair", + "Inner colored hair", + "Alternate Color Hair", + "multicolored hair", + "Dual Tone Hair", + "Hair Highlights", + "Colored Hair" + ] + }, + { + "name": "Effect", + "max": 2, + "content": ["Messy Hair", "hair sparkle", "hair drooping", "wet hair", "hair fluttering"] + }, + { + "name": "Hair Pose", + "max": 2, + "content": [ + "hair behind the ears", + "hair covering eyes", + "hair backwards", + "hair between the eyes", + "hair covering chest", + "hair between the chest", + "let your hair go", + "tie up your hair" + ] + } + ] + }, + { + "name": "Face", + "content": [ + { + "name": "eyes", + "max": 1, + "content": [ + "Diamond Eyes", + "Cute Big Eyes", + "Beautiful and detailed eyes", + "Big watery eyes", + "Bright and big eyes", + "Glowing Big Eyes", + "close your eyes", + "half-closed eyes", + "Empty Eyes", + "Starry Eyes" + ] + }, + { + "name": "Face", + "max": 1, + "content": [ + "thick eyebrows", + "thick eyelashes", + "freckle", + "Innocent Face", + "red lips", + "big lips", + "eye shadow", + "red cheeks", + "There are scars on the face", + "little lips" + ] + }, + { + "name": "Mood", + "max": 1, + "content": [ + "Smile", + "giggle", + "toothy grin", + "laugh", + "laughing out loud", + "bad smile", + "excited", + "charming smile", + "proud", + "shy", + "serious", + "blush", + "boring", + "Poker face", + "sad", + "cry", + "Melancholy", + "nervous", + "Puzzled", + "angry", + "frown", + "disdain", + "contempt", + "disgust", + "surprise", + "Fear", + "horror", + "panic", + "despair" + ] + } + ] + }, + { + "name": "Body", + "content": [ + { + "name": "body", + "max": 1, + "content": ["Skinny", "Exquisite body portrayal", "full", "Perfect body"] + }, + { + "name": "chest", + "max": 1, + "content": ["poor chest", "small chest", "middle chest", "big boobs"] + }, + { + "name": "pose", + "max": 1, + "content": [ + "sit", + "kneel", + "climb", + "Jump", + "stand", + "lie", + "Walk", + "Tilt head", + "turn back", + "sleep", + "Lotus position", + "duck sitting", + "kneeling", + "leg hug", + "Akimbo", + "Princess hug", + "battle state" + ] + } + ] + }, + { + "name": "Apparel", + "content": [ + { + "name": "Suit", + "max": 1, + "content": [ + "Sailor suit", + "School Uniform", + "Workplace Uniform", + "Suit", + "tooling", + "Sportswear", + "pajamas", + "bathrobe", + "kimono", + "sling bikini", + "Strap Bikini", + "Tether Bikini", + "Cow Bikini", + "swimsuit", + "one-piece swimsuit", + "Competitive Swimsuit", + "Dead Reservoir Water", + "lingerie", + "cheongsam", + "Casual Wear", + "Tights", + "Strapless Bodysuit", + "volleyball uniform", + "dressing gown", + "Japanese Wedding Dress", + "Hanfu", + "Tuxedo" + ] + }, + { + "name": "Dress", + "max": 1, + "content": [ + "Transparent Dress", + "Dress Dress", + "Breastless Dress", + "dress without sleeve", + "Wedding dress", + "Sailor Dress", + "Sweater Dress", + "evening dress", + "Chiffon Dress", + "Cross Neck Dress", + "Tulle Dress", + "Summer Dress", + "Tight Dress", + "Ballerina", + "Lotus Skirt", + "slip dress" + ] + }, + { + "name": "Theme", + "max": 1, + "content": [ + "Japanese clothing", + "American Clothing", + "British clothing", + "Chinese clothing", + "European clothing", + "Western clothing", + "Gothic Costume", + "Witch Costume", + "Lolita Costume", + "Nun Costume", + "Police Costume", + "Convenience Store Workwear", + "Magic Girl Costume", + "Maid Outfit", + "military uniform", + "Doll Costume", + "ghost outfit", + "Mummy Dress", + "Vampire Outfit", + "Halloween Costume", + "Christmas costumes" + ] + }, + { + "name": "hat", + "max": 1, + "content": [ + "hat", + "straw hat", + "Sailor Hat", + "Berets", + "top hat", + "hood", + "Nurse Hat", + "Wizard Hat", + "East Golden Cap", + "Pumpkin Hat", + "Dome Hat", + "Newsboy Hat", + "Fisherman's hat", + "Christmas hat", + "cap", + "fedora", + "baseball cap", + "Knitted hat" + ] + }, + { + "name": "tops", + "max": 1, + "content": [ + "T-shirt", + "collared shirt", + "shirt", + "jacket", + "sweater", + "Dress Shirt", + "Rib Sweater", + "Sweater Jacket", + "turtleneck sweater", + "Wool Cardigan", + "Hoodie", + "robe", + "apron", + "Vest", + "Sports Vest", + "Sleeve and Shoulder Separation", + "sleeveless tops", + "Small Cape", + "camisole", + "baseball uniform", + "lab coat", + "cloak", + "coat", + "fur coat", + "Winter Coat", + "Trench Coat", + "Parke", + "tube top", + "Alan Sweater", + "Tunic Coat", + "Small Shawl", + "bra", + "corset" + ] + }, + { + "name": "Bottom", + "max": 1, + "content": [ + "shorts", + "Bike Shorts", + "High Waist Shorts", + "hot pants", + "Dolphin Shorts", + "Denim shorts", + "Bloomers", + "yoga pants", + "Multilayer Skirt", + "Plaid skirt", + "Pleated Skirt", + "mini skirt", + "Pencil Skirt", + "cupcake dress", + "bikini pants", + "Bib short" + ] + }, + { + "name": "socks", + "max": 1, + "content": [ + "no socks", + "bare feet", + "Knee socks", + "sock", + "Japanese Thick Soled Socks", + "Pile of socks", + "Stockings", + "garter", + "fishnet stockings", + "Pantyhose", + "leggings pantyhose" + ] + }, + { + "name": "shoes", + "max": 1, + "content": [ + "no shoes", + "boots", + "Loafers", + "barefoot", + "shoe", + "slim high heel", + "High heel", + "lace-up boots", + "Strap Heels", + "Mary Jane Shoes", + "Ladies student shoes", + "slippers", + "clogs", + "sports shoes", + "sandals", + "leather shoes", + "ballet shoes" + ] + }, + { + "name": "Installation effect", + "max": 1, + "content": [ + "Shoulders", + "Grid pattern", + "horizontal stripes", + "polka dot pattern", + "ruffle", + "lace", + "waistless", + "Backless", + "soaked", + "Girdle", + "Fine fabric feel", + "Absolute Territory" + ] + } + ] + }, + { + "name": "Accessories", + "content": [ + { + "name": "Headwear", + "max": 1, + "content": ["veil", "Maid's Tiara", "crown", "bridal tiara", "halo", "Triple Crown", "wreath", "Antenna Headgear"] + }, + { + "name": "Hair Accessories", + "max": 1, + "content": [ + "ribbon", + "hairpin", + "issuing card", + "Hair band", + "hair ring", + "Flower", + "hair knot", + "hairpin set", + "hair accessories", + "Bat Hair Accessories", + "Food Theme Hair Accessories", + "Pumpkin Hair Accessory", + "Wings Hair Accessories", + "Leaves Hair Accessories", + "Heart Hair Accessory", + "Star Hair Accessories", + "Butterfly Hair Accessories", + "Frog Hair Accessories", + "Crescent Hair Ornament", + "Feather Headdress", + "Musical note hair ornament", + "Carrot Hair Accessory", + "Snowflake Hair Accessories", + "Skull Headdress", + "clover hair ornament" + ] + }, + { + "name": "Earrings", + "max": 1, + "content": ["earrings", "Beaded Earrings", "earphone", "Pearl ear-rings", "Crystal Earrings", "earring", "Ear Muffs"] + }, + { + "name": "Face", + "max": 1, + "content": [ + "Glasses", + "thick glasses", + "goggles", + "sunglasses", + "Rimless Glasses", + "Blindfold", + "Cyclops", + "Face mask", + "Medical masks", + "Tengu Mask", + "Fox Mask", + "forehead", + "Carmina Sunglasses" + ] + }, + { + "name": "Necklace", + "max": 1, + "content": ["jewelry", "necklace", "scarf", "neck strap", "collar", "bow tie", "tie", "Cross Bangs", "bell", "pendant"] + }, + { + "name": "hand", + "max": 1, + "content": [ + "Gloves", + "Elbow Gloves", + "Lace Gloves", + "mitts", + "Wedding Gloves", + "Latex Gloves", + "Boxing gloves", + "Bracelet", + "Emerald Bracelet", + "wristband", + "Wrist Jewelry", + "arm ring", + "watch" + ] + }, + { + "name": "Other", + "max": 1, + "content": [ + "tassel", + "sash", + "butterfly", + "belt", + "thigh strap", + "leg ring", + "badge", + "brooch", + "Tattoo", + "amulet", + "Elizabeth Circle" + ] + } + ] + }, + { + "name": "Non-Human Element", + "content": [ + { + "name": "ear", + "max": 1, + "content": [ + "Beast Ear Lolita Mode", + "bat ears", + "dog ears", + "Beast Ears", + "Plush Animal Ears", + "cat ear", + "rabbit ears", + "Fox ears", + "pointed ears", + "raccoon ears", + "wolf ears", + "drop ears", + "mouse ears", + "Mal" + ] + }, + { + "name": "corner", + "max": 1, + "content": ["horn", "Dragon Horn", "Devil Horns", "ghost horn", "Goat horns", "antlers"] + }, + { + "name": "wings", + "max": 1, + "content": [ + "wing", + "Angel Wings", + "Butterfly wings", + "Bat Wings", + "Devil Wings", + "Fairy Wings", + "Dragon Wings", + "Sun Gear Wings", + "Ice Crystal Texture Wings", + "Split Wings", + "High Wings", + "Low Wings", + "Mini Wings", + "Fake Wings" + ] + }, + { + "name": "tail", + "max": 1, + "content": ["Tail", "cat tail", "Fox Tail", "rabbit tail", "dog tail", "Dragon Tail", "Ponytail", "Devil Tail"] + } + ] + }, + { + "name": "Object", + "content": [ + { + "name": "Stationery", + "max": 2, + "content": ["book", "notebook", "letter", "paper", "Pen", "pencil", "Sketchbook", "Score", "calendar", "Bag", "bag"] + }, + { + "name": "food", + "max": 2, + "content": [ + "food", + "apple", + "lemon", + "vegetable", + "fruit", + "Grape", + "acorn", + "cake", + "Taiyaki", + "biscuit", + "Steamed bun", + "wine", + "ice cream", + "Wagashi", + "Tuanzi", + "Lollipop", + "candy", + "Tea" + ] + }, + { + "name": "Instrument", + "max": 2, + "content": ["microphone", "Guitar", "violin", "piano"] + }, + { + "name": "Vehicle", + "max": 2, + "content": ["car", "vessel", "airplane", "train", "subway", "airship"] + }, + { + "name": "animal", + "max": 2, + "content": [ + "animal", + "squirrel", + "Pigeon", + "Seagull", + "cat", + "dog", + "bird", + "swallow", + "starfish", + "Butterflys", + "dragonfly", + "goldfish", + "bee", + "fish" + ] + }, + { + "name": "Plant", + "max": 2, + "content": [ + "plant", + "flower Plant", + "lotus", + "daisy", + "Potted plants", + "Rose", + "Water Lily", + "Dandelion", + "Hydrangea", + "tulip", + "lily", + "Vine", + "ivy", + "shrub", + "Tree", + "bamboo", + "Cherry blossoms", + "Palm tree", + "pumpkin", + "maple", + "Leaves", + "coconut tree", + "pine", + "Falling leaves", + "Ginkgo biloba", + "Maple Leaf", + "petal", + "fly" + ] + }, + { + "name": "Natural Object", + "max": 2, + "content": [ + "stone", + "water", + "sand", + "Sky", + "Blue sky and white clouds", + "sun", + "moon", + "Sunset", + "full moon", + "new moon", + "Star", + "Blood Moon", + "meteor", + "starry", + "aurora", + "nebula", + "cumulonimbus mane", + "bald cumulonimbus", + "fireworks", + "Messy clouds", + "Skyline", + "rain", + "storm", + "rainbow", + "wind", + "breeze", + "tornado", + "Snow", + "avalanche", + "snowflake", + "ice", + "Frost", + "cloud", + "ice crystals", + "fog", + "Galaxy" + ] + }, + { + "name": "Other", + "max": 2, + "content": ["umbrella", "Sun umbrella", "bouquet", "Origami", "Paper Umbrella", "cane", "doll", "Paper Crane", "Magic Circle"] + } + ] + }, + { + "name": "Environment", + "content": [ + { + "name": "Building", + "max": 2, + "content": [ + "Cityscape", + "National Style City", + "skyscraper", + "Prosperous City", + "Kowloon City", + "Cyberpunk City", + "classroom", + "Art room", + "stadium", + "dormitory", + "temple", + "church", + "library", + "spa", + "Torii", + "Cafe", + "Restaurant", + "museum", + "shop", + "street", + "indoor", + "bridge", + "fountain", + "palace", + "Ferris wheel", + "castle", + "lighthouse", + "the way", + "bus stop", + "sidewalk", + "balcony", + "roof", + "garden", + "Airport", + "pool", + "pier", + "town", + "corridor", + "Fantasy City", + "amusement park", + "Cinema", + "campus", + "Hospital" + ] + }, + { + "name": "Natural", + "max": 2, + "content": [ + "lake", + "beach", + "Mountains", + "flowers", + "desert", + "rural", + "flower field", + "underwater", + "Fall", + "farm", + "the Alps", + "cave", + "stream", + "wetlands", + "river", + "sea", + "forest", + "grassland", + "outdoor", + "Reed Prairie", + "Prosperous Meadow", + "islands", + "lawn", + "Snows", + "pond", + "hill", + "jungle", + "canyon" + ] + }, + { + "name": "Weather", + "max": 1, + "content": ["cloudy day", "partly cloudy", "sunny", "snow day", "rain day", "foggy day"] + } + ] + }, + { + "name": "Time", + "content": [ + { + "name": "period", + "max": 1, + "content": ["dawn", "noon", "dusk", "daytime", "early morning", "Morning", "afternoon", "night", "night"] + }, + { + "name": "season", + "max": 1, + "content": ["spring", "summer", "autumn", "winter"] + }, + { + "name": "Holiday", + "max": 1, + "content": [ + "Valentine's Day", + "Halloween", + "Spring Festival", + "Mid-Autumn Festival", + "Girl's Day", + "Tokyo Kanda Festival", + "new year", + "Thanksgiving Day", + "Christmas", + "Dragon Boat Festival", + "Sakura Festival", + "Kyoto Gion Festival", + "Osaka Tenjin Festival" + ] + } + ] + }, + { + "name": "Painting Type", + "content": [ + { + "name": "Special Effects", + "max": 1, + "content": ["High Contrast", "Colorful", "chromatic aberration", "sharp", "High Saturation", "Contour deepening", "HDR"] + }, + { + "name": "Quality", + "max": 4, + "content": [ + "Masterpiece", + "high resolution", + "Super High Resolution", + "extremely detailed", + "Excellent Details", + "high quality", + "Outstanding Theater of the World", + "Extreme High Resolution", + "Complicated Details" + ] + }, + { + "name": "painting style", + "max": 1, + "content": [ + "Paper film", + "80's", + "pencil style", + "Ink", + "watercolor", + "sketch", + "Line Draft", + "Voxel Painting", + "Ukiyo-e", + "Plane Shading", + "grayscale", + "Famous painting spoof", + "Paper Art", + "retro", + "the 90s", + "Colored lead painting", + "realistic", + "Charcoal Sketch", + "Pixel Art", + "Cyberpunk", + "Flat coating", + "Monotone", + "role play" + ] + }, + { + "name": "form", + "max": 1, + "content": [ + "Light Novel Illustration", + "Game CG", + "8K wallpaper", + "comic book", + "Anime Screenshot", + "Official Map", + "Stand drawing", + "Pillow", + "Doujinshi", + "poster", + "Tarot Style", + "game Master", + "illustration", + "Original painting", + "Very detailed CG", + "8K ultra-detailed CG wallpaper", + "Four-frame comics", + "Character Setting Diagram", + "Magazine", + "P station style", + "Soviet Poster", + "Card style" + ] + } + ] + }, + { + "name": "Composition", + "content": [ + { + "name": "Viewpoint", + "max": 1, + "content": [ + "TV View", + "bust", + "Focus View", + "Back view", + "Side View", + "Looking Up Perspective", + "Dynamic Perspective", + "Full body portrait", + "subjective perspective", + "Looking into the distance", + "Tilt View", + "Overview Perspective" + ] + }, + { + "name": "distance", + "max": 1, + "content": ["Vision", "close view", "Fisheye", "Isometric", "panoramic", "Middle Scene", "close up", "Depth of Field", "perspective"] + } + ] + }, + { + "name": "Light", + "content": [ + { + "name": "Light Source", + "max": 2, + "content": [ + "Sunlight", + "morning light", + "Dappled Sunlight", + "Dynamic Angle Light Axis", + "Real Light", + "Gap Light", + "moonlight", + "Studio Lighting", + "Angel Light" + ] + }, + { + "name": "direction", + "max": 2, + "content": ["Backlight", "rim light", "Split Lighting", "top light", "Accent Lighting"] + }, + { + "name": "property", + "max": 2, + "content": [ + "Weak light source", + "Soft Light", + "cold light", + "overexposure", + "Ambient Light", + "Strong Light Source", + "warm light", + "color light source", + "Volume Light" + ] + }, + { + "name": "Quality", + "max": 2, + "content": ["Movie Light", "Detailed Glow", "Excellent Glow", "Golden Hour Lighting"] + }, + { + "name": "Light Effect", + "max": 2, + "content": ["Light Leak", "Color Refraction", "Tindal Light", "flash", "ray tracing", "reflective", "lens flare", "Fluorescence"] + }, + { + "name": "Particle", + "max": 2, + "content": ["Glowing Particles", "Illuminating Particles"] + }, + { + "name": "Shadow", + "max": 2, + "content": [ + "Tree Shadow", + "Shadow Cast", + "Best Shade", + "Strong shades of black", + "True Shadows", + "Dramatic Shadows", + "Shadow Tactics App", + "Beautiful detailed shadows" + ] + } + ] + } + ] + }, + { + "name": "Boy", + "content": [ + { + "name": "Role", + "content": [ + { + "name": "Hairstyle", + "max": 1, + "content": [ + "long hair", + "Mohawk head", + "Wool Roll", + "Messy Hair", + "short hair", + "back head", + "hedgehog head", + "Refreshing hairstyle", + "hair backwards" + ] + }, + { + "name": "eyes", + "max": 1, + "content": [ + "Diamond Eyes", + "Cute Big Eyes", + "Beautiful and detailed eyes", + "Big watery eyes", + "Bright and big eyes", + "Glowing Big Eyes", + "close your eyes", + "half-closed eyes", + "Empty Eyes", + "Starry Eyes" + ] + }, + { + "name": "Face", + "max": 1, + "content": [ + "thick eyebrows", + "thick eyelashes", + "freckle", + "Innocent Face", + "red lips", + "big lips", + "eye shadow", + "red cheeks", + "There are scars on the face", + "little lips" + ] + }, + { + "name": "Mood", + "max": 1, + "content": [ + "Smile", + "giggle", + "toothy grin", + "laugh", + "laughing out loud", + "bad smile", + "excited", + "charming smile", + "proud", + "shy", + "serious", + "blush", + "boring", + "Poker face", + "sad", + "cry", + "Melancholy", + "nervous", + "Puzzled", + "angry", + "frown", + "disdain", + "contempt", + "disgust", + "surprise", + "Fear", + "horror", + "panic", + "despair" + ] + }, + { + "name": "pose", + "max": 1, + "content": [ + "sit", + "kneel", + "climb", + "Jump", + "stand", + "lie", + "Walk", + "Tilt head", + "turn back", + "sleep", + "Lotus position", + "duck sitting", + "kneeling", + "leg hug", + "Akimbo", + "Princess hug", + "battle state" + ] + } + ] + }, + { + "name": "Apparel", + "content": [ + { + "name": "Suit", + "max": 1, + "content": [ + "Sailor suit", + "School Uniform", + "Workplace Uniform", + "Suit", + "tooling", + "Sportswear", + "pajamas", + "bathrobe", + "kimono", + "swimsuit", + "Competitive Swimsuit", + "Casual Wear", + "Tights", + "volleyball uniform", + "dressing gown", + "Hanfu", + "Tuxedo" + ] + }, + { + "name": "Theme", + "max": 1, + "content": [ + "Japanese clothing", + "American Clothing", + "British clothing", + "Chinese clothing", + "European clothing", + "Western clothing", + "Gothic Costume", + "Vampire Outfit", + "Halloween Costume", + "Christmas costumes", + "Police Costume", + "Convenience Store Workwear", + "Magic Girl Costume", + "Maid Outfit", + "military uniform", + "Doll Costume", + "ghost outfit", + "Mummy Dress" + ] + }, + { + "name": "hat", + "max": 1, + "content": [ + "hat", + "straw hat", + "Sailor Hat", + "Berets", + "top hat", + "hood", + "Nurse Hat", + "Wizard Hat", + "East Golden Cap", + "Pumpkin Hat", + "Dome Hat", + "Newsboy Hat", + "Fisherman's hat", + "Christmas hat", + "cap", + "fedora", + "baseball cap", + "Knitted hat" + ] + }, + { + "name": "tops", + "max": 1, + "content": [ + "T-shirt", + "collared shirt", + "shirt", + "jacket", + "sweater", + "Dress Shirt", + "Rib Sweater", + "Sweater Jacket", + "turtleneck sweater", + "Wool Cardigan", + "Hoodie", + "robe", + "cloak", + "apron", + "Vest", + "Sports Vest", + "Sleeve and Shoulder Separation", + "sleeveless tops", + "Small Cape", + "baseball uniform", + "lab coat", + "cloak", + "coat", + "fur coat", + "Winter Coat", + "Trench Coat", + "Parke", + "Alan Sweater", + "Tunic Coat", + "Little Shawl" + ] + }, + { + "name": "Bottom", + "max": 1, + "content": ["shorts", "Bike Shorts", "High Waist Shorts", "hot pants", "Dolphin Shorts", "Denim shorts", "Bloomers", "Bib short"] + }, + { + "name": "socks", + "max": 1, + "content": [ + "no socks", + "bare feet", + "Knee socks", + "sock", + "Japanese Thick Soled Socks", + "Pile of socks", + "Stockings", + "garter", + "fishnet stockings", + "Pantyhose", + "leggings pantyhose" + ] + }, + { + "name": "shoes", + "max": 1, + "content": [ + "no shoes", + "boots", + "Loafers", + "barefoot", + "shoe", + "slippers", + "clogs", + "sports shoes", + "lace-up boots", + "sandals", + "leather shoes" + ] + }, + { + "name": "Installation effect", + "max": 1, + "content": [ + "Shoulders", + "Grid pattern", + "horizontal stripes", + "polka dot pattern", + "ruffle", + "lace", + "waistless", + "Backless", + "soaked", + "Girdle", + "Fine fabric feel" + ] + } + ] + }, + { + "name": "Accessories", + "content": [ + { + "name": "Headwear", + "max": 1, + "content": [ + "veil", + "Maid's Tiara", + "crown", + "bridal tiara", + "halo", + "Triple Crown", + "wreath", + "Antenna Headgear", + ] + }, + { + "name": "Hair Accessories", + "max": 1, + "content": [ + "ribbon", + "hairpin", + "issuing card", + "Hair band", + "hair ring", + "Flower", + "hair knot", + "hairpin set", + "hair accessories", + "Bat Hair Accessories", + "Food Theme Hair Accessories", + "Pumpkin Hair Accessory", + "Wings Hair Accessories", + "Leaves Hair Accessories", + "Heart Hair Accessory", + "Star Hair Accessories", + "Butterfly Hair Accessories", + "Frog Hair Accessories", + "Crescent Hair Ornament", + "Feather Headdress", + "Musical note hair ornament", + "Carrot Hair Accessory", + "Snowflake Hair Accessories", + "Skull Headdress", + "clover hair ornament" + ] + }, + { + "name": "Earrings", + "max": 1, + "content": ["earrings", "Beaded Earrings", "earphone", "Pearl ear-rings", "Crystal Earrings", "earring", "Ear Muffs"] + }, + { + "name": "Face", + "max": 1, + "content": [ + "Glasses", + "thick glasses", + "goggles", + "sunglasses", + "Rimless Glasses", + "Blindfold", + "Cyclops", + "Face mask", + "Medical masks", + "Tengu Mask", + "Fox Mask", + "forehead", + "Carmina Sunglasses" + ] + }, + { + "name": "Necklace", + "max": 1, + "content": ["jewelry", "necklace", "scarf", "neck strap", "collar", "bow tie", "tie", "Cross Bangs", "bell", "pendant"] + }, + { + "name": "hand", + "max": 1, + "content": [ + "Gloves", + "Elbow Gloves", + "Lace Gloves", + "mitts", + "Wedding Gloves", + "Latex Gloves", + "Boxing gloves", + "Bracelet", + "Emerald Bracelet", + "wristband", + "Wrist Jewelry", + "arm ring", + "watch" + ] + }, + { + "name": "Other", + "max": 1, + "content": [ + "tassel", + "sash", + "butterfly", + "belt", + "thigh strap", + "leg ring", + "badge", + "brooch", + "Tattoo", + "amulet", + "Elizabeth Circle" + ] + } + ] + }, + { + "name": "Non-Human Element", + "content": [ + { + "name": "ear", + "max": 1, + "content": [ + "Beast Ear Lolita Mode", + "bat ears", + "dog ears", + "Beast Ears", + "Plush Animal Ears", + "cat ear", + "rabbit ears", + "Fox ears", + "pointed ears", + "raccoon ears", + "wolf ears", + "drop ears", + "mouse ears", + "Mal" + ] + }, + { + "name": "corner", + "max": 1, + "content": ["horn", "Dragon Horn", "Devil Horns", "ghost horn", "Goat horns", "antlers"] + }, + { + "name": "wings", + "max": 1, + "content": [ + "wing", + "Angel Wings", + "Butterfly wings", + "Bat Wings", + "Devil Wings", + "Fairy Wings", + "Dragon Wings", + "Sun Gear Wings", + "Ice Crystal Texture Wings", + "Split Wings", + "High Wings", + "Low Wings", + "Mini Wings", + "Fake Wings" + ] + }, + { + "name": "tail", + "max": 1, + "content": ["Tail", "cat tail", "Fox Tail", "rabbit tail", "dog tail", "Dragon Tail", "Ponytail", "Devil Tail"] + } + ] + }, + { + "name": "Object", + "content": [ + { + "name": "Stationery", + "max": 2, + "content": ["book", "notebook", "letter", "paper", "Pen", "pencil", "Sketchbook", "Score", "calendar", "Bag", "bag"] + }, + { + "name": "food", + "max": 2, + "content": [ + "food", + "apple", + "lemon", + "vegetable", + "fruit", + "Grape", + "acorn", + "cake", + "Taiyaki", + "biscuit", + "Steamed bun", + "wine", + "ice cream", + "Wagashi", + "Tuanzi", + "Lollipop", + "candy", + "Tea" + ] + }, + { + "name": "Instrument", + "max": 2, + "content": ["microphone", "Guitar", "violin", "piano"] + }, + { + "name": "Vehicle", + "max": 2, + "content": ["car", "vessel", "airplane", "train", "subway", "airship"] + }, + { + "name": "animal", + "max": 2, + "content": [ + "animal", + "squirrel", + "Pigeon", + "Seagull", + "cat", + "dog", + "bird", + "swallow", + "starfish", + "Butterflys", + "dragonfly", + "goldfish", + "bee", + "fish" + ] + }, + { + "name": "Plant", + "max": 2, + "content": [ + "plant", + "flower Plant", + "lotus", + "daisy", + "Potted plants", + "Rose", + "Water Lily", + "Dandelion", + "Hydrangea", + "tulip", + "lily", + "Vine", + "ivy", + "shrub", + "Tree", + "bamboo", + "Cherry blossoms", + "Palm tree", + "pumpkin", + "maple", + "Leaves", + "coconut tree", + "pine", + "Falling leaves", + "Ginkgo biloba", + "Maple Leaf", + "petal", + "fly" + ] + }, + { + "name": "Natural Object", + "max": 2, + "content": [ + "stone", + "water", + "sand", + "Sky", + "Blue sky and white clouds", + "sun", + "moon", + "Sunset", + "full moon", + "new moon", + "Star", + "Blood Moon", + "meteor", + "starry", + "aurora", + "nebula", + "cumulonimbus mane", + "bald cumulonimbus", + "fireworks", + "Messy clouds", + "Skyline", + "rain", + "storm", + "rainbow", + "wind", + "breeze", + "tornado", + "Snow", + "avalanche", + "snowflake", + "ice", + "Frost", + "cloud", + "ice crystals", + "fog", + "Galaxy" + ] + }, + { + "name": "Other", + "max": 2, + "content": ["umbrella", "Sun umbrella", "bouquet", "Origami", "Paper Umbrella", "cane", "doll", "Paper Crane", "Magic Circle"] + } + ] + }, + { + "name": "Environment", + "content": [ + { + "name": "Building", + "max": 2, + "content": [ + "Cityscape", + "National Style City", + "skyscraper", + "Prosperous City", + "Kowloon City", + "Cyberpunk City", + "classroom", + "Art room", + "stadium", + "dormitory", + "temple", + "church", + "library", + "spa", + "Torii", + "Cafe", + "Restaurant", + "museum", + "shop", + "street", + "indoor", + "bridge", + "fountain", + "palace", + "Ferris wheel", + "castle", + "lighthouse", + "the way", + "bus stop", + "sidewalk", + "balcony", + "roof", + "garden", + "Airport", + "pool", + "pier", + "town", + "corridor", + "Fantasy City", + "amusement park", + "Cinema", + "campus", + "Hospital" + ] + }, + { + "name": "Natural", + "max": 2, + "content": [ + "lake", + "beach", + "Mountains", + "flowers", + "desert", + "rural", + "flower field", + "underwater", + "Fall", + "farm", + "the Alps", + "cave", + "stream", + "wetlands", + "river", + "sea", + "forest", + "grassland", + "outdoor", + "Reed Prairie", + "Prosperous Meadow", + "islands", + "lawn", + "Snows", + "pond", + "hill", + "jungle", + "canyon" + ] + }, + { + "name": "Weather", + "max": 1, + "content": ["cloudy day", "partly cloudy", "sunny", "snow day", "rain day", "foggy day"] + } + ] + }, + { + "name": "Time", + "content": [ + { + "name": "period", + "max": 1, + "content": ["dawn", "noon", "dusk", "daytime", "early morning", "Morning", "afternoon", "night", "night"] + }, + { + "name": "season", + "max": 1, + "content": ["spring", "summer", "autumn", "winter"] + }, + { + "name": "Holiday", + "max": 1, + "content": [ + "Valentine's Day", + "Halloween", + "Spring Festival", + "Mid-Autumn Festival", + "Girl's Day", + "Tokyo Kanda Festival", + "new year", + "Thanksgiving Day", + "Christmas", + "Dragon Boat Festival", + "Sakura Festival", + "Kyoto Gion Festival", + "Osaka Tenjin Festival" + ] + } + ] + }, + { + "name": "Painting Type", + "content": [ + { + "name": "Special Effects", + "max": 1, + "content": ["High Contrast", "Colorful", "chromatic aberration", "sharp", "High Saturation", "Contour deepening", "HDR"] + }, + { + "name": "Quality", + "max": 4, + "content": [ + "Masterpiece", + "high resolution", + "Super High Resolution", + "extremely detailed", + "Excellent Details", + "high quality", + "Outstanding Theater of the World", + "Extreme High Resolution", + "Complicated Details" + ] + }, + { + "name": "painting style", + "max": 1, + "content": [ + "Paper film", + "80's", + "pencil style", + "Ink", + "watercolor", + "sketch", + "Line Draft", + "Voxel Painting", + "Ukiyo-e", + "Plane Shading", + "grayscale", + "Famous painting spoof", + "Paper Art", + "retro", + "the 90s", + "Colored lead painting", + "realistic", + "Charcoal Sketch", + "Pixel Art", + "Cyberpunk", + "Flat coating", + "Monotone", + "role play" + ] + }, + { + "name": "form", + "max": 1, + "content": [ + "Light Novel Illustration", + "Game CG", + "8K wallpaper", + "comic book", + "Anime Screenshot", + "Official Map", + "Stand drawing", + "Pillow", + "Doujinshi", + "poster", + "Tarot Style", + "game Master", + "illustration", + "Original painting", + "Very detailed CG", + "8K ultra-detailed CG wallpaper", + "Four-frame comics", + "Character Setting Diagram", + "Magazine", + "P station style", + "Soviet Poster", + "Card style" + ] + } + ] + }, + { + "name": "Composition", + "content": [ + { + "name": "Viewpoint", + "max": 1, + "content": [ + "TV View", + "bust", + "Focus View", + "Back view", + "Side View", + "Looking Up Perspective", + "Dynamic Perspective", + "Full body portrait", + "subjective perspective", + "Looking into the distance", + "Tilt View", + "Overview Perspective" + ] + }, + { + "name": "distance", + "max": 1, + "content": ["Vision", "close view", "Fisheye", "Isometric", "panoramic", "Middle Scene", "close up", "Depth of Field", "perspective"] + } + ] + }, + { + "name": "Light", + "content": [ + { + "name": "Light Source", + "max": 2, + "content": [ + "Sunlight", + "morning light", + "Dappled Sunlight", + "Dynamic Angle Light Axis", + "Real Light", + "Gap Light", + "moonlight", + "Studio Lighting", + "Angel Light" + ] + }, + { + "name": "direction", + "max": 2, + "content": ["Backlight", "rim light", "Split Lighting", "top light", "Accent Lighting"] + }, + { + "name": "property", + "max": 2, + "content": [ + "Weak light source", + "Soft Light", + "cold light", + "overexposure", + "Ambient Light", + "Strong Light Source", + "warm light", + "color light source", + "Volume Light" + ] + }, + { + "name": "Quality", + "max": 2, + "content": ["Movie Light", "Detailed Glow", "Excellent Glow", "Golden Hour Lighting"] + }, + { + "name": "Light Effect", + "max": 2, + "content": ["Light Leak", "Color Refraction", "Tindal Light", "flash", "ray tracing", "reflective", "lens flare", "Fluorescence"] + }, + { + "name": "Particle", + "max": 2, + "content": ["Glowing Particles", "Illuminating Particles"] + }, + { + "name": "Shadow", + "max": 2, + "content": [ + "Tree Shadow", + "Shadow Cast", + "Best Shade", + "Strong shades of black", + "True Shadows", + "Dramatic Shadows", + "Shadow Tactics App", + "Beautiful detailed shadows" + ] + } + ] + } + ] + }, + { + "name": "Scenery", + "content": [ + { + "name": "Object", + "content": [ + { + "name": "Stationery", + "max": 2, + "content": ["book", "notebook", "letter", "paper", "Pen", "pencil", "Sketchbook", "Score", "calendar", "Bag", "bag"] + }, + { + "name": "food", + "max": 2, + "content": [ + "food", + "apple", + "lemon", + "vegetable", + "fruit", + "Grape", + "acorn", + "cake", + "Taiyaki", + "biscuit", + "Steamed bun", + "wine", + "ice cream", + "Wagashi", + "Tuanzi", + "Lollipop", + "candy", + "Tea" + ] + }, + { + "name": "Instrument", + "max": 2, + "content": ["microphone", "Guitar", "violin", "piano"] + }, + { + "name": "Vehicle", + "max": 2, + "content": ["car", "vessel", "airplane", "train", "subway", "airship"] + }, + { + "name": "animal", + "max": 2, + "content": [ + "animal", + "squirrel", + "Pigeon", + "Seagull", + "cat", + "dog", + "bird", + "swallow", + "starfish", + "Butterflys", + "dragonfly", + "goldfish", + "bee", + "fish" + ] + }, + { + "name": "Plant", + "max": 2, + "content": [ + "plant", + "flower Plant", + "lotus", + "daisy", + "Potted plants", + "Rose", + "Water Lily", + "Dandelion", + "Hydrangea", + "tulip", + "lily", + "Vine", + "ivy", + "shrub", + "Tree", + "bamboo", + "Cherry blossoms", + "Palm tree", + "pumpkin", + "maple", + "Leaves", + "coconut tree", + "pine", + "Falling leaves", + "Ginkgo biloba", + "Maple Leaf", + "petal", + "fly" + ] + }, + { + "name": "Natural Object", + "max": 2, + "content": [ + "stone", + "water", + "sand", + "Sky", + "Blue sky and white clouds", + "sun", + "moon", + "Sunset", + "full moon", + "new moon", + "Star", + "Blood Moon", + "meteor", + "starry", + "aurora", + "nebula", + "cumulonimbus mane", + "bald cumulonimbus", + "fireworks", + "Messy clouds", + "Skyline", + "rain", + "storm", + "rainbow", + "wind", + "breeze", + "tornado", + "Snow", + "avalanche", + "snowflake", + "ice", + "Frost", + "cloud", + "ice crystals", + "fog", + "Galaxy" + ] + }, + { + "name": "Other", + "max": 2, + "content": ["umbrella", "Sun umbrella", "bouquet", "Origami", "Paper Umbrella", "cane", "doll", "Paper Crane", "Magic Circle"] + } + ] + }, + { + "name": "Environment", + "content": [ + { + "name": "Building", + "max": 2, + "content": [ + "Cityscape", + "National Style City", + "skyscraper", + "Prosperous City", + "Kowloon City", + "Cyberpunk City", + "classroom", + "Art room", + "stadium", + "dormitory", + "temple", + "church", + "library", + "spa", + "Torii", + "Cafe", + "Restaurant", + "museum", + "shop", + "street", + "indoor", + "bridge", + "fountain", + "palace", + "Ferris wheel", + "castle", + "lighthouse", + "the way", + "bus stop", + "sidewalk", + "balcony", + "roof", + "garden", + "Airport", + "pool", + "pier", + "town", + "corridor", + "Fantasy City", + "amusement park", + "Cinema", + "campus", + "Hospital" + ] + }, + { + "name": "Natural", + "max": 2, + "content": [ + "lake", + "beach", + "Mountains", + "flowers", + "desert", + "rural", + "flower field", + "underwater", + "Fall", + "farm", + "the Alps", + "cave", + "stream", + "wetlands", + "river", + "sea", + "forest", + "grassland", + "outdoor", + "Reed Prairie", + "Prosperous Meadow", + "islands", + "lawn", + "Snows", + "pond", + "hill", + "jungle", + "canyon" + ] + }, + { + "name": "Weather", + "max": 1, + "content": ["cloudy day", "partly cloudy", "sunny", "snow day", "rain day", "foggy day"] + } + ] + }, + { + "name": "Time", + "content": [ + { + "name": "period", + "max": 1, + "content": ["dawn", "noon", "dusk", "daytime", "early morning", "Morning", "afternoon", "night", "night"] + }, + { + "name": "season", + "max": 1, + "content": ["spring", "summer", "autumn", "winter"] + }, + { + "name": "Holiday", + "max": 1, + "content": [ + "Valentine's Day", + "Halloween", + "Spring Festival", + "Mid-Autumn Festival", + "Girl's Day", + "Tokyo Kanda Festival", + "new year", + "Thanksgiving Day", + "Christmas", + "Dragon Boat Festival", + "Sakura Festival", + "Kyoto Gion Festival", + "Osaka Tenjin Festival" + ] + } + ] + }, + { + "name": "Painting Type", + "content": [ + { + "name": "Special Effects", + "max": 1, + "content": ["High Contrast", "Colorful", "chromatic aberration", "sharp", "High Saturation", "Contour deepening", "HDR"] + }, + { + "name": "Quality", + "max": 4, + "content": [ + "Masterpiece", + "high resolution", + "Super High Resolution", + "extremely detailed", + "Excellent Details", + "high quality", + "Outstanding Theater of the World", + "Extreme High Resolution", + "Complicated Details" + ] + }, + { + "name": "painting style", + "max": 1, + "content": [ + "Paper film", + "80's", + "pencil style", + "Ink", + "watercolor", + "sketch", + "Line Draft", + "Voxel Painting", + "Ukiyo-e", + "Plane Shading", + "grayscale", + "Famous painting spoof", + "Paper Art", + "retro", + "the 90s", + "Colored lead painting", + "realistic", + "Charcoal Sketch", + "Pixel Art", + "Cyberpunk", + "Flat coating", + "Monotone", + "role play" + ] + }, + { + "name": "form", + "max": 1, + "content": [ + "Light Novel Illustration", + "Game CG", + "8K wallpaper", + "comic book", + "Anime Screenshot", + "Official Map", + "Stand drawing", + "Pillow", + "Doujinshi", + "poster", + "Tarot Style", + "game Master", + "illustration", + "Original painting", + "Very detailed CG", + "8K ultra-detailed CG wallpaper", + "Four-frame comics", + "Character Setting Diagram", + "Magazine", + "P station style", + "Soviet Poster", + "Card style" + ] + } + ] + }, + { + "name": "Composition", + "content": [ + { + "name": "Viewpoint", + "max": 1, + "content": [ + "TV View", + "bust", + "Focus View", + "Back view", + "Side View", + "Looking Up Perspective", + "Dynamic Perspective", + "Full body portrait", + "subjective perspective", + "Looking into the distance", + "Tilt View", + "Overview Perspective" + ] + }, + { + "name": "distance", + "max": 1, + "content": ["Vision", "close view", "Fisheye", "Isometric", "panoramic", "Middle Scene", "close up", "Depth of Field", "perspective"] + } + ] + }, + { + "name": "Light", + "content": [ + { + "name": "Light Source", + "max": 2, + "content": [ + "Sunlight", + "morning light", + "Dappled Sunlight", + "Dynamic Angle Light Axis", + "Real Light", + "Gap Light", + "moonlight", + "Studio Lighting", + "Angel Light" + ] + }, + { + "name": "direction", + "max": 2, + "content": ["Backlight", "rim light", "Split Lighting", "top light", "Accent Lighting"] + }, + { + "name": "property", + "max": 2, + "content": [ + "Weak light source", + "Soft Light", + "cold light", + "overexposure", + "Ambient Light", + "Strong Light Source", + "warm light", + "color light source", + "Volume Light" + ] + }, + { + "name": "Quality", + "max": 2, + "content": ["Movie Light", "Detailed Glow", "Excellent Glow", "Golden Hour Lighting"] + }, + { + "name": "Light Effect", + "max": 2, + "content": ["Light Leak", "Color Refraction", "Tindal Light", "flash", "ray tracing", "reflective", "lens flare", "Fluorescence"] + }, + { + "name": "Particle", + "max": 2, + "content": ["Glowing Particles", "Illuminating Particles"] + }, + { + "name": "Shadow", + "max": 2, + "content": [ + "Tree Shadow", + "Shadow Cast", + "Best Shade", + "Strong shades of black", + "True Shadows", + "Dramatic Shadows", + "Shadow Tactics App", + "Beautiful detailed shadows" + ] + } + ] + } + ] + } + ] + }; + + static Map responseDataZh = { + "body": [ + { + "name": "女生", + "content": [ + { + "name": "头发", + "content": [ + { + "name": "发长", + "max": 1, + "content": ["短发", "中等发", "过肩长发", "超短发", "长发", "超长发", "有长有短"] + }, + { + "name": "发型", + "max": 1, + "content": ["卷发", "波浪卷", "多根呆毛", "分主切", "俩包子头", "单辫子", "单马尾", "直发", "公主卷", "呆毛", "妹妹切", "包子头", "辫子", "双辫子", "双马尾"] + }, + { + "name": "刘海", + "max": 1, + "content": ["无刘海", "辫子刘海", "斜刘海", "分叉刘海", "不对称刘海", "刘海", "长刘海", "齐刘海", "侧扫刘海", "交叉刘海"] + }, + { + "name": "发色", + "max": 1, + "content": ["渐变色头发", "内层彩色头发", "交替色头发", "多色头发", "双色调头发", "挑染头发", "分色头发"] + }, + { + "name": "发效", + "max": 2, + "content": ["凌乱头发", "头发闪闪", "头发下垂", "湿头发", "头发飘舞"] + }, + { + "name": "头发姿态", + "max": 2, + "content": ["头发在耳朵后面", "头发遮住眼睛", "头发向后", "头发在眼睛之间", "头发盖住胸部", "头发在胸部之间", "散开头发", "扎起头发"] + } + ] + }, + { + "name": "脸部", + "content": [ + { + "name": "眼睛", + "max": 1, + "content": ["钻石般耀眼的眼睛", "可爱大眼睛", "美丽细致的眼睛", "水汪汪的大眼睛", "明亮大眼睛", "发光大眼睛", "闭上眼睛", "半闭眼睛", "空洞的眼睛", "星空眼"] + }, + { + "name": "脸部", + "max": 1, + "content": ["粗眉毛", "粗睫毛", "雀斑", "无辜的脸", "红嘴唇", "大嘴唇", "眼影", "红脸颊", "脸上有疤", "小嘴唇"] + }, + { + "name": "情绪", + "max": 1, + "content": [ + "微笑", + "傻笑", + "露齿笑", + "笑", + "大笑", + "坏笑", + "兴奋", + "迷人的笑", + "得意", + "害羞", + "严肃", + "腼腆", + "脸红", + "无聊", + "面无表情", + "悲伤", + "哭泣", + "忧郁", + "紧张", + "困惑", + "生气", + "皱眉", + "鄙夷", + "恼怒", + "蔑视", + "厌恶", + "惊讶", + "害怕", + "惊骇", + "惊慌", + "绝望" + ] + } + ] + }, + { + "name": "身体", + "content": [ + { + "name": "身材", + "max": 1, + "content": ["骨感", "精致的身材刻画", "完美身材"] + }, + { + "name": "胸部", + "max": 1, + "content": ["贫胸", "小胸", "中胸"] + }, + { + "name": "姿势", + "max": 1, + "content": ["坐", "跪", "爬", "跳", "站", "趴", "躺", "走", "歪头", "回头", "睡觉", "莲花坐", "鸭子坐", "跪坐", "抱腿", "叉腰", "公主抱", "战斗态"] + } + ] + }, + { + "name": "服饰", + "content": [ + { + "name": "套装", + "max": 1, + "content": [ + "水手服", + "学校制服", + "职场制服", + "西装", + "工装", + "运动服", + "睡衣", + "浴衣", + "和服", + "吊索比基尼", + "系带比基尼", + "系绳比基尼", + "奶牛比基尼", + "泳装", + "连体泳衣", + "竞技泳衣", + "死库水", + "女用贴身内衣裤", + "旗袍", + "休闲服", + "紧身衣", + "无肩带紧身连衣裤", + "排球服", + "晨衣", + "日式嫁衣", + "汉服", + "燕尾服" + ] + }, + { + "name": "连衣裙", + "max": 1, + "content": [ + "透明长裙", + "礼服长裙", + "露胸连衣裙", + "无袖连衣裙", + "婚纱", + "水手连衣裙", + "毛衣连衣裙", + "晚礼服", + "雪纺连衣裙", + "绕颈连衣裙", + "薄纱连衣裙", + "夏日长裙", + "紧身连衣裙", + "芭蕾舞裙", + "莲蓬裙", + "吊带裙" + ] + }, + { + "name": "主题", + "max": 1, + "content": [ + "日式服装", + "美式服装", + "英式服装", + "中式服装", + "欧式服装", + "西式服装", + "哥特服装", + "巫女服装", + "洛丽塔服装", + "修女服装", + "警察服装", + "便利店工作服", + "魔法少女服装", + "女仆装", + "军装", + "玩偶装", + "鬼魂装", + "木乃伊装", + "吸血鬼装", + "万圣节装", + "圣诞装" + ] + }, + { + "name": "帽子", + "max": 1, + "content": ["帽子", "草帽", "水手帽", "贝雷帽", "礼帽", "兜帽", "护士帽", "巫师帽", "东金帽", "南瓜帽", "圆顶帽", "报童帽", "渔夫帽", "圣诞帽", "鸭舌帽", "软呢帽", "棒球帽", "针织帽"] + }, + { + "name": "上装", + "max": 1, + "content": [ + "T恤", + "有领衬衫", + "衬衫", + "夹克", + "毛衣", + "礼服衬衫", + "罗纹毛衣", + "毛衣夹克", + "高领毛衣", + "羊毛开衫", + "卫衣", + "长袍", + "斗篷", + "围裙", + "背心", + "短上衣", + "运动背心", + "袖肩分离", + "无袖上衣", + "小披风", + "吊带背心", + "棒球服", + "实验袍", + "披风", + "大衣", + "毛皮衣", + "风衣", + "冬装大衣", + "战壕风衣", + "派克大衣", + "抹胸", + "阿兰毛衣", + "束腰大衣", + "小披肩", + "胸罩", + "胸衣" + ] + }, + { + "name": "下装", + "max": 1, + "content": [ + "短裤", + "自行车短裤", + "高腰短裤", + "热裤", + "海豚短裤", + "牛仔短裤", + "灯笼裤", + "瑜伽裤", + "多层裙子", + "格子裙", + "荷叶裙", + "百褶裙", + "迷你裙", + "铅笔裙", + "蛋糕裙", + "比基尼裤", + "吊带裤" + ] + }, + { + "name": "袜子", + "max": 1, + "content": ["不穿袜子", "裸足", "过膝袜", "袜子", "短袜", "日式厚底短袜", "堆堆袜", "长筒袜", "吊带袜", "渔网袜", "连裤袜", "裤袜", "丝袜", "连体袜", "绑腿连裤袜"] + }, + { + "name": "鞋子", + "max": 1, + "content": [ + "不穿鞋", + "靴子", + "乐福鞋", + "赤脚", + "鞋子", + "长筒靴", + "细高跟", + "高跟鞋", + "系带靴", + "束带高跟鞋", + "玛丽珍鞋", + "女士学生鞋", + "拖鞋", + "木屐", + "运动鞋", + "凉鞋", + "皮鞋", + "芭蕾舞鞋" + ] + }, + { + "name": "装效", + "max": 1, + "content": ["露肩", "格子纹", "横条纹", "波点纹", "褶边", "花边", "露腰", "露背", "浸湿", "束腰", "精细面料感", "绝对领域"] + } + ] + }, + { + "name": "配饰", + "content": [ + { + "name": "头饰", + "max": 1, + "content": ["面纱", "女仆头饰", "皇冠", "新娘头饰", "光环", "三重冕", "花环", "天线头饰", "簪子"] + }, + { + "name": "发饰", + "max": 1, + "content": [ + "缎带发饰", + "发夹", + "发卡", + "发束", + "发箍", + "发簪", + "发环", + "发花", + "发结", + "发簪套", + "发饰", + "蝙蝠发饰", + "食物主题发饰", + "南瓜发饰", + "翅膀发饰", + "树叶发饰", + "心形发饰", + "星星发饰", + "蝴蝶发饰", + "青蛙发饰", + "月牙发饰", + "羽毛头饰", + "音符发饰", + "胡萝卜发饰", + "雪花发饰", + "骷髅头饰", + "三叶草发饰" + ] + }, + { + "name": "耳饰", + "max": 1, + "content": ["耳环", "珠状耳环", "耳机", "珍珠耳环", "水晶耳环", "耳坠", "耳扣", "耳钉", "御寒耳罩"] + }, + { + "name": "面部", + "max": 1, + "content": ["眼镜", "厚眼镜", "风镜", "太阳镜", "无框眼镜", "眼罩", "独眼眼罩", "口罩", "医用口罩", "天狗面具", "狐狸面具", "护额", "卡米纳墨镜"] + }, + { + "name": "颈饰", + "max": 1, + "content": ["首饰", "项链", "围巾", "领巾", "颈带", "项圈", "领结", "领带", "交叉刘海", "铃铛", "吊坠"] + }, + { + "name": "手部", + "max": 1, + "content": ["手套", "肘部手套", "蕾丝手套", "露指手套", "婚礼手套", "乳胶手套", "拳击手套", "手链", "翡翠手镯", "腕带", "腕饰", "臂环", "手表"] + }, + { + "name": "其他", + "max": 1, + "content": ["流苏", "丝带", "饰带", "蝴蝶结", "缎带", "腰带", "大腿带", "腿环", "徽章", "胸针", "纹身", "护身符", "伊丽莎白圈"] + } + ] + }, + { + "name": "非人元素", + "content": [ + { + "name": "耳", + "max": 1, + "content": ["兽耳萝莉模式", "蝙蝠耳", "狗耳", "兽耳", "毛绒兽耳", "猫耳", "兔耳", "狐狸耳", "尖耳", "浣熊耳", "狼耳", "垂耳", "老鼠耳朵", "马耳"] + }, + { + "name": "角", + "max": 1, + "content": ["角", "龙角", "恶魔角", "鬼角", "山羊角", "鹿角"] + }, + { + "name": "翅膀", + "max": 1, + "content": ["翅膀", "天使翅膀", "蝴蝶翅膀", "蝙蝠翅膀", "恶魔翅膀", "妖精翅膀", "龙族翅膀", "太阳齿轮翅膀", "冰晶纹理翅膀", "分离式翅膀", "高位翅膀", "低位翅膀", "迷你翅膀", "假翅膀"] + }, + { + "name": "尾巴", + "max": 1, + "content": ["尾巴", "猫尾", "狐狸尾", "兔尾", "狗尾", "龙尾", "马尾", "恶魔尾"] + } + ] + }, + { + "name": "客体", + "content": [ + { + "name": "文具", + "max": 2, + "content": ["书本", "笔记本", "信", "纸张", "笔", "铅笔", "素描本", "乐谱", "日历", "包", "书包"] + }, + { + "name": "食物", + "max": 2, + "content": ["食物", "苹果", "柠檬", "蔬菜", "水果", "葡萄", "橡子", "蛋糕", "鲷鱼烧", "饼干", "馒头", "红酒", "冰淇淋", "和果子", "团子", "棒棒糖", "糖果", "茶"] + }, + { + "name": "乐器", + "max": 2, + "content": ["麦克风", "吉他", "小提琴", "钢琴"] + }, + { + "name": "交通工具", + "max": 2, + "content": ["汽车", "船只", "飞机", "火车", "地铁", "飞艇"] + }, + { + "name": "动物", + "max": 2, + "content": ["动物", "松鼠", "鸽子", "海鸥", "猫", "狗", "鸟", "燕子", "海星", "蝴蝶", "蜻蜓", "金鱼", "蜜蜂", "鱼"] + }, + { + "name": "植物", + "max": 2, + "content": [ + "植物", + "花植物", + "莲花", + "雏菊", + "盆栽植物", + "玫瑰", + "睡莲", + "蒲公英", + "紫阳花", + "郁金香", + "百合", + "藤类", + "常春藤", + "灌木", + "树", + "竹子", + "樱花", + "棕榈树", + "南瓜", + "枫树", + "椰子树", + "松树", + "树叶", + "落叶", + "银杏叶", + "枫叶", + "花瓣", + "飞花" + ] + }, + { + "name": "自然物", + "max": 2, + "content": [ + "石", + "水", + "沙", + "鲜花", + "天空", + "蓝天白云", + "太阳", + "月亮", + "落日", + "满月", + "新月", + "星星", + "血月", + "流星", + "繁星", + "极光", + "星云", + "鬃积雨云", + "秃积雨云", + "烟花", + "杂乱无章的云", + "天际线", + "雨", + "暴风雨", + "彩虹", + "风", + "微风", + "龙卷风", + "雪", + "雪崩", + "雪花", + "冰", + "霜", + "云", + "冰晶", + "雾", + "银河" + ] + }, + { + "name": "其他", + "max": 2, + "content": ["伞", "太阳伞", "花束", "折纸", "油纸伞", "手杖", "玩偶", "纸鹤", "魔法阵"] + } + ] + }, + { + "name": "环境", + "content": [ + { + "name": "建筑", + "max": 2, + "content": [ + "城市风光", + "国风城市", + "摩天楼", + "繁华都市", + "九龙城", + "赛博朋克城市", + "教室", + "美术室", + "体育馆", + "宿舍", + "寺庙", + "教堂", + "图书馆", + "温泉", + "鸟居", + "咖啡厅", + "饭店", + "博物馆", + "商店", + "街道", + "室内", + "桥", + "喷泉", + "宫殿", + "摩天轮", + "城堡", + "灯塔", + "道路", + "公交车站", + "人行道", + "阳台", + "屋顶", + "花园", + "公园", + "机场", + "泳池", + "码头", + "小镇", + "走廊", + "奇幻城市", + "游乐园", + "电影院", + "校园", + "医院" + ] + }, + { + "name": "自然", + "max": 2, + "content": [ + "湖泊", + "沙滩", + "山脉", + "花", + "沙漠", + "田园", + "花田", + "水下", + "瀑布", + "农场", + "阿尔卑斯山脉", + "洞穴", + "溪流", + "湿地", + "河流", + "大海", + "森林", + "草地", + "室外", + "芦苇草原", + "繁华草甸", + "岛屿", + "草坪", + "雪地", + "池塘", + "山丘", + "丛林", + "峡谷" + ] + }, + { + "name": "天气", + "max": 1, + "content": ["阴天", "多云", "晴天", "雪天", "雨天", "雾天"] + } + ] + }, + { + "name": "时间", + "content": [ + { + "name": "时段", + "max": 1, + "content": ["黎明", "中午", "黄昏", "白天", "凌晨", "早上", "下午", "晚上", "夜晚"] + }, + { + "name": "季节", + "max": 1, + "content": ["春季", "夏季", "秋季", "冬季"] + }, + { + "name": "节日", + "max": 1, + "content": ["情人节", "万圣节", "春节", "中秋节", "女儿节", "东京神田祭", "新年", "感恩节", "圣诞节", "端午节", "樱花祭", "京都祇园祭", "大阪天神祭"] + } + ] + }, + { + "name": "画种", + "content": [ + { + "name": "特效", + "max": 1, + "content": ["高对比度", "色彩斑斓", "色差", "锐化", "高饱和度", "轮廓加深", "HDR"] + }, + { + "name": "质量", + "max": 4, + "content": ["大师之作", "高分辨率", "超高分辨率", "极其详细", "优良细节", "高质量", "世界杰出剧院", "极高分辨率", "复杂细节"] + }, + { + "name": "画风", + "max": 1, + "content": [ + "纸膜", + "80年代", + "铅笔画风", + "水墨", + "水彩", + "素描", + "线稿", + "体素画", + "浮世绘", + "平面着色", + "灰度", + "名画恶搞", + "纸艺", + "复古", + "90年代", + "彩铅绘", + "写实", + "炭笔素描", + "像素画", + "赛博朋克", + "平涂", + "单色调", + "角色扮演" + ] + }, + { + "name": "形式", + "max": 1, + "content": [ + "轻小说插画", + "游戏CG", + "8K壁纸", + "漫画书", + "动漫截图", + "官方图", + "立绘", + "抱枕", + "同人志风", + "海报", + "塔罗牌风格", + "游戏王", + "插画", + "原画", + "非常详细的CG", + "8K超详细的CG壁纸", + "四格漫画", + "角色设定图", + "杂志", + "P站风格", + "苏维埃海报", + "卡牌风" + ] + } + ] + }, + { + "name": "构图", + "content": [ + { + "name": "视角", + "max": 1, + "content": ["电视视角", "半身像", "焦点视角", "背后视角", "侧视视角", "仰视视角", "动态视角", "全身像", "主观视角", "眺望远方", "倾斜视角", "俯视视角"] + }, + { + "name": "距离", + "max": 1, + "content": ["远景", "近景", "鱼眼", "等距", "全景", "中景", "特写", "景深", "透视"] + } + ] + }, + { + "name": "灯光", + "content": [ + { + "name": "光源", + "max": 2, + "content": ["阳光", "晨光", "斑驳的阳光", "动态角度灯轴", "真实光源", "云隙光", "月光", "工作室光照", "天使圣光"] + }, + { + "name": "方向", + "max": 2, + "content": ["背光", "轮廓光", "分割照明", "顶光", "逆光", "重点照明"] + }, + { + "name": "属性", + "max": 2, + "content": ["弱光源", "柔光", "冷光", "过曝光", "气氛光", "强光源", "暧光", "彩色光源", "体积光"] + }, + { + "name": "品质", + "max": 2, + "content": ["电影光", "详细的辉光", "优良的发光", "黄金时段照明"] + }, + { + "name": "光效", + "max": 2, + "content": ["光线泄露", "彩色折射", "丁达尔光", "闪光", "光线追踪", "反光", "镜头光晕", "荧光"] + }, + { + "name": "粒子", + "max": 2, + "content": ["发光粒子", "照明粒子"] + }, + { + "name": "阴影", + "max": 2, + "content": ["树影", "投影阴影", "最佳阴影", "强烈的黑色阴影", "真实阴影", "戏剧阴影", "阴影战术应用", "美丽的详细阴影"] + } + ] + } + ] + }, + { + "name": "男生", + "content": [ + { + "name": "角色", + "content": [ + { + "name": "发型", + "max": 1, + "content": ["长发", "莫西干头", "羊毛卷", "凌乱头发", "短发", "背头", "刺猬头", "清爽发型", "头发向后"] + }, + { + "name": "眼睛", + "max": 1, + "content": ["钻石般耀眼的眼睛", "可爱大眼睛", "美丽细致的眼睛", "水汪汪的大眼睛", "明亮大眼睛", "发光大眼睛", "闭上眼睛", "半闭眼睛", "空洞的眼睛", "星空眼"] + }, + { + "name": "脸部", + "max": 1, + "content": ["粗眉毛", "粗睫毛", "雀斑", "无辜的脸", "红嘴唇", "大嘴唇", "眼影", "红脸颊", "脸上有疤", "小嘴唇"] + }, + { + "name": "情绪", + "max": 1, + "content": [ + "微笑", + "傻笑", + "露齿笑", + "笑", + "大笑", + "坏笑", + "兴奋", + "迷人的笑", + "得意", + "害羞", + "严肃", + "腼腆", + "脸红", + "无聊", + "面无表情", + "悲伤", + "哭泣", + "忧郁", + "紧张", + "困惑", + "生气", + "皱眉", + "鄙夷", + "恼怒", + "蔑视", + "厌恶", + "惊讶", + "害怕", + "惊骇", + "惊慌", + "绝望" + ] + }, + { + "name": "姿势", + "max": 1, + "content": ["坐", "跪", "爬", "跳", "站", "趴", "躺", "走", "歪头", "回头", "睡觉", "莲花坐", "鸭子坐", "跪坐", "抱腿", "叉腰", "公主抱", "战斗态"] + } + ] + }, + { + "name": "服饰", + "content": [ + { + "name": "套装", + "max": 1, + "content": ["水手服", "学校制服", "职场制服", "西装", "工装", "运动服", "睡衣", "浴衣", "和服", "泳装", "竞技泳衣", "休闲服", "紧身衣", "排球服", "晨衣", "汉服", "燕尾服"] + }, + { + "name": "主题", + "max": 1, + "content": [ + "日式服装", + "美式服装", + "英式服装", + "中式服装", + "欧式服装", + "西式服装", + "哥特服装", + "吸血鬼装", + "万圣节装", + "圣诞装", + "警察服装", + "便利店工作服", + "魔法少女服装", + "女仆装", + "军装", + "玩偶装", + "鬼魂装", + "木乃伊装" + ] + }, + { + "name": "帽子", + "max": 1, + "content": ["帽子", "草帽", "水手帽", "贝雷帽", "礼帽", "兜帽", "护士帽", "巫师帽", "东金帽", "南瓜帽", "圆顶帽", "报童帽", "渔夫帽", "圣诞帽", "鸭舌帽", "软呢帽", "棒球帽", "针织帽"] + }, + { + "name": "上装", + "max": 1, + "content": [ + "T恤", + "有领衬衫", + "衬衫", + "夹克", + "毛衣", + "礼服衬衫", + "罗纹毛衣", + "毛衣夹克", + "高领毛衣", + "羊毛开衫", + "卫衣", + "长袍", + "斗篷", + "围裙", + "背心", + "短上衣", + "运动背心", + "袖肩分离", + "无袖上衣", + "小披风", + "棒球服", + "实验袍", + "披风", + "大衣", + "毛皮衣", + "风衣", + "冬装大衣", + "战壕风衣", + "派克大衣", + "阿兰毛衣", + "束腰大衣", + "小披肩" + ] + }, + { + "name": "下装", + "max": 1, + "content": ["短裤", "自行车短裤", "高腰短裤", "热裤", "海豚短裤", "牛仔短裤", "灯笼裤", "吊带裤"] + }, + { + "name": "袜子", + "max": 1, + "content": ["不穿袜子", "裸足", "过膝袜", "袜子", "短袜", "日式厚底短袜", "堆堆袜", "长筒袜", "吊带袜", "渔网袜", "连裤袜", "裤袜", "丝袜", "连体袜", "绑腿连裤袜"] + }, + { + "name": "鞋子", + "max": 1, + "content": ["不穿鞋", "靴子", "乐福鞋", "赤脚", "鞋子", "拖鞋", "木屐", "运动鞋", "系带靴", "凉鞋", "皮鞋"] + }, + { + "name": "装效", + "max": 1, + "content": ["露肩", "格子纹", "横条纹", "波点纹", "褶边", "花边", "露腰", "露背", "浸湿", "束腰", "精细面料感"] + } + ] + }, + { + "name": "配饰", + "content": [ + { + "name": "头饰", + "max": 1, + "content": ["面纱", "女仆头饰", "皇冠", "新娘头饰", "光环", "三重冕", "花环", "天线头饰", "簪子"] + }, + { + "name": "发饰", + "max": 1, + "content": [ + "缎带发饰", + "发夹", + "发卡", + "发束", + "发箍", + "发簪", + "发环", + "发花", + "发结", + "发簪套", + "发饰", + "蝙蝠发饰", + "食物主题发饰", + "南瓜发饰", + "翅膀发饰", + "树叶发饰", + "心形发饰", + "星星发饰", + "蝴蝶发饰", + "青蛙发饰", + "月牙发饰", + "羽毛头饰", + "音符发饰", + "胡萝卜发饰", + "雪花发饰", + "骷髅头饰", + "三叶草发饰" + ] + }, + { + "name": "耳饰", + "max": 1, + "content": ["耳环", "珠状耳环", "耳机", "珍珠耳环", "水晶耳环", "耳坠", "耳扣", "耳钉", "御寒耳罩"] + }, + { + "name": "面部", + "max": 1, + "content": ["眼镜", "厚眼镜", "风镜", "太阳镜", "无框眼镜", "眼罩", "独眼眼罩", "口罩", "医用口罩", "天狗面具", "狐狸面具", "护额", "卡米纳墨镜"] + }, + { + "name": "颈饰", + "max": 1, + "content": ["首饰", "项链", "围巾", "领巾", "颈带", "项圈", "领结", "领带", "交叉刘海", "铃铛", "吊坠"] + }, + { + "name": "手部", + "max": 1, + "content": ["手套", "肘部手套", "蕾丝手套", "露指手套", "婚礼手套", "乳胶手套", "拳击手套", "手链", "翡翠手镯", "腕带", "腕饰", "臂环", "手表"] + }, + { + "name": "其他", + "max": 1, + "content": ["流苏", "丝带", "饰带", "蝴蝶结", "缎带", "腰带", "大腿带", "腿环", "徽章", "胸针", "纹身", "护身符", "伊丽莎白圈"] + } + ] + }, + { + "name": "非人元素", + "content": [ + { + "name": "耳", + "max": 1, + "content": ["兽耳萝莉模式", "蝙蝠耳", "狗耳", "兽耳", "毛绒兽耳", "猫耳", "兔耳", "狐狸耳", "尖耳", "浣熊耳", "狼耳", "垂耳", "老鼠耳朵", "马耳"] + }, + { + "name": "角", + "max": 1, + "content": ["角", "龙角", "恶魔角", "鬼角", "山羊角", "鹿角"] + }, + { + "name": "翅膀", + "max": 1, + "content": ["翅膀", "天使翅膀", "蝴蝶翅膀", "蝙蝠翅膀", "恶魔翅膀", "妖精翅膀", "龙族翅膀", "太阳齿轮翅膀", "冰晶纹理翅膀", "分离式翅膀", "高位翅膀", "低位翅膀", "迷你翅膀", "假翅膀"] + }, + { + "name": "尾巴", + "max": 1, + "content": ["尾巴", "猫尾", "狐狸尾", "兔尾", "狗尾", "龙尾", "马尾", "恶魔尾"] + } + ] + }, + { + "name": "客体", + "content": [ + { + "name": "文具", + "max": 2, + "content": ["书本", "笔记本", "信", "纸张", "笔", "铅笔", "素描本", "乐谱", "日历", "包", "书包"] + }, + { + "name": "食物", + "max": 2, + "content": ["食物", "苹果", "柠檬", "蔬菜", "水果", "葡萄", "橡子", "蛋糕", "鲷鱼烧", "饼干", "馒头", "红酒", "冰淇淋", "和果子", "团子", "棒棒糖", "糖果", "茶"] + }, + { + "name": "乐器", + "max": 2, + "content": ["麦克风", "吉他", "小提琴", "钢琴"] + }, + { + "name": "交通工具", + "max": 2, + "content": ["汽车", "船只", "飞机", "火车", "地铁", "飞艇"] + }, + { + "name": "动物", + "max": 2, + "content": ["动物", "松鼠", "鸽子", "海鸥", "猫", "狗", "鸟", "燕子", "海星", "蝴蝶", "蜻蜓", "金鱼", "蜜蜂", "鱼"] + }, + { + "name": "植物", + "max": 2, + "content": [ + "植物", + "花植物", + "莲花", + "雏菊", + "盆栽植物", + "玫瑰", + "睡莲", + "蒲公英", + "紫阳花", + "郁金香", + "百合", + "藤类", + "常春藤", + "灌木", + "树", + "竹子", + "樱花", + "棕榈树", + "南瓜", + "枫树", + "椰子树", + "松树", + "树叶", + "落叶", + "银杏叶", + "枫叶", + "花瓣", + "飞花" + ] + }, + { + "name": "自然物", + "max": 2, + "content": [ + "石", + "水", + "沙", + "天空", + "蓝天白云", + "太阳", + "月亮", + "落日", + "满月", + "新月", + "星星", + "血月", + "流星", + "繁星", + "极光", + "星云", + "鬃积雨云", + "秃积雨云", + "烟花", + "杂乱无章的云", + "天际线", + "雨", + "暴风雨", + "彩虹", + "风", + "微风", + "龙卷风", + "雪", + "雪崩", + "雪花", + "冰", + "霜", + "云", + "冰晶", + "雾", + "银河" + ] + }, + { + "name": "其他", + "max": 2, + "content": ["伞", "太阳伞", "花束", "折纸", "油纸伞", "手杖", "玩偶", "纸鹤", "魔法阵"] + } + ] + }, + { + "name": "环境", + "content": [ + { + "name": "建筑", + "max": 2, + "content": [ + "城市风光", + "国风城市", + "摩天楼", + "繁华都市", + "九龙城", + "赛博朋克城市", + "教室", + "美术室", + "体育馆", + "宿舍", + "寺庙", + "教堂", + "图书馆", + "温泉", + "鸟居", + "咖啡厅", + "饭店", + "博物馆", + "商店", + "街道", + "室内", + "桥", + "喷泉", + "宫殿", + "摩天轮", + "城堡", + "灯塔", + "道路", + "公交车站", + "人行道", + "阳台", + "屋顶", + "花园", + "公园", + "机场", + "泳池", + "码头", + "小镇", + "走廊", + "奇幻城市", + "游乐园", + "电影院", + "校园", + "医院" + ] + }, + { + "name": "自然", + "max": 2, + "content": [ + "湖泊", + "沙滩", + "山脉", + "花", + "沙漠", + "田园", + "花田", + "水下", + "瀑布", + "农场", + "阿尔卑斯山脉", + "洞穴", + "溪流", + "湿地", + "河流", + "大海", + "森林", + "草地", + "室外", + "芦苇草原", + "繁华草甸", + "岛屿", + "草坪", + "雪地", + "池塘", + "山丘", + "丛林", + "峡谷" + ] + }, + { + "name": "天气", + "max": 1, + "content": ["阴天", "多云", "晴天", "雪天", "雨天", "雾天"] + } + ] + }, + { + "name": "时间", + "content": [ + { + "name": "时段", + "max": 1, + "content": ["黎明", "中午", "黄昏", "白天", "凌晨", "早上", "下午", "晚上", "夜晚"] + }, + { + "name": "季节", + "max": 1, + "content": ["春季", "夏季", "秋季", "冬季"] + }, + { + "name": "节日", + "max": 1, + "content": ["情人节", "万圣节", "春节", "中秋节", "女儿节", "东京神田祭", "新年", "感恩节", "圣诞节", "端午节", "樱花祭", "京都祇园祭", "大阪天神祭"] + } + ] + }, + { + "name": "画种", + "content": [ + { + "name": "特效", + "max": 1, + "content": ["高对比度", "色彩斑斓", "色差", "锐化", "高饱和度", "轮廓加深", "HDR"] + }, + { + "name": "质量", + "max": 4, + "content": ["大师之作", "高分辨率", "超高分辨率", "极其详细", "优良细节", "高质量", "世界杰出剧院", "极高分辨率", "复杂细节"] + }, + { + "name": "画风", + "max": 1, + "content": [ + "纸膜", + "80年代", + "铅笔画风", + "水墨", + "水彩", + "素描", + "线稿", + "体素画", + "浮世绘", + "平面着色", + "灰度", + "名画恶搞", + "纸艺", + "复古", + "90年代", + "彩铅绘", + "写实", + "炭笔素描", + "像素画", + "赛博朋克", + "平涂", + "单色调", + "角色扮演" + ] + }, + { + "name": "形式", + "max": 1, + "content": [ + "轻小说插画", + "游戏CG", + "8K壁纸", + "漫画书", + "动漫截图", + "官方图", + "立绘", + "抱枕", + "同人志风", + "海报", + "塔罗牌风格", + "游戏王", + "插画", + "原画", + "非常详细的CG", + "8K超详细的CG壁纸", + "四格漫画", + "角色设定图", + "杂志", + "P站风格", + "苏维埃海报", + "卡牌风" + ] + } + ] + }, + { + "name": "构图", + "content": [ + { + "name": "视角", + "max": 1, + "content": ["电视视角", "半身像", "焦点视角", "背后视角", "侧视视角", "仰视视角", "动态视角", "全身像", "主观视角", "眺望远方", "倾斜视角", "俯视视角"] + }, + { + "name": "距离", + "max": 1, + "content": ["远景", "近景", "鱼眼", "等距", "全景", "中景", "特写", "景深", "透视"] + } + ] + }, + { + "name": "灯光", + "content": [ + { + "name": "光源", + "max": 2, + "content": ["阳光", "晨光", "斑驳的阳光", "动态角度灯轴", "真实光源", "云隙光", "月光", "工作室光照", "天使圣光"] + }, + { + "name": "方向", + "max": 2, + "content": ["背光", "轮廓光", "分割照明", "顶光", "逆光", "重点照明"] + }, + { + "name": "属性", + "max": 2, + "content": ["弱光源", "柔光", "冷光", "过曝光", "气氛光", "强光源", "暧光", "彩色光源", "体积光"] + }, + { + "name": "品质", + "max": 2, + "content": ["电影光", "详细的辉光", "优良的发光", "黄金时段照明"] + }, + { + "name": "光效", + "max": 2, + "content": ["光线泄露", "彩色折射", "丁达尔光", "闪光", "光线追踪", "反光", "镜头光晕", "荧光"] + }, + { + "name": "粒子", + "max": 2, + "content": ["发光粒子", "照明粒子"] + }, + { + "name": "阴影", + "max": 2, + "content": ["树影", "投影阴影", "最佳阴影", "强烈的黑色阴影", "真实阴影", "戏剧阴影", "阴影战术应用", "美丽的详细阴影"] + } + ] + } + ] + }, + { + "name": "景物", + "content": [ + { + "name": "客体", + "content": [ + { + "name": "文具", + "max": 2, + "content": ["书本", "笔记本", "信", "纸张", "笔", "铅笔", "素描本", "乐谱", "日历", "包", "书包"] + }, + { + "name": "食物", + "max": 2, + "content": ["食物", "苹果", "柠檬", "蔬菜", "水果", "葡萄", "橡子", "蛋糕", "鲷鱼烧", "饼干", "馒头", "红酒", "冰淇淋", "和果子", "团子", "棒棒糖", "糖果", "茶"] + }, + { + "name": "乐器", + "max": 2, + "content": ["麦克风", "吉他", "小提琴", "钢琴"] + }, + { + "name": "交通工具", + "max": 2, + "content": ["汽车", "船只", "飞机", "火车", "地铁", "飞艇"] + }, + { + "name": "动物", + "max": 2, + "content": ["动物", "松鼠", "鸽子", "海鸥", "猫", "狗", "鸟", "燕子", "海星", "蝴蝶", "蜻蜓", "金鱼", "蜜蜂", "鱼"] + }, + { + "name": "植物", + "max": 2, + "content": [ + "植物", + "花植物", + "莲花", + "雏菊", + "盆栽植物", + "玫瑰", + "睡莲", + "蒲公英", + "紫阳花", + "郁金香", + "百合", + "藤类", + "常春藤", + "灌木", + "树", + "竹子", + "樱花", + "棕榈树", + "南瓜", + "枫树", + "树叶", + "椰子树", + "松树", + "落叶", + "银杏叶", + "枫叶", + "花瓣", + "飞花" + ] + }, + { + "name": "自然物", + "max": 2, + "content": [ + "石", + "水", + "沙", + "天空", + "蓝天白云", + "太阳", + "月亮", + "落日", + "满月", + "新月", + "星星", + "血月", + "流星", + "繁星", + "极光", + "星云", + "鬃积雨云", + "秃积雨云", + "烟花", + "杂乱无章的云", + "天际线", + "雨", + "暴风雨", + "彩虹", + "风", + "微风", + "龙卷风", + "雪", + "雪崩", + "雪花", + "冰", + "霜", + "云", + "冰晶", + "雾", + "银河" + ] + }, + { + "name": "其他", + "max": 2, + "content": ["伞", "太阳伞", "花束", "折纸", "油纸伞", "手杖", "玩偶", "纸鹤", "魔法阵"] + } + ] + }, + { + "name": "环境", + "content": [ + { + "name": "建筑", + "max": 2, + "content": [ + "城市风光", + "国风城市", + "摩天楼", + "繁华都市", + "九龙城", + "赛博朋克城市", + "教室", + "美术室", + "体育馆", + "宿舍", + "寺庙", + "教堂", + "图书馆", + "温泉", + "鸟居", + "咖啡厅", + "饭店", + "博物馆", + "商店", + "街道", + "室内", + "桥", + "喷泉", + "宫殿", + "摩天轮", + "城堡", + "灯塔", + "道路", + "公交车站", + "人行道", + "阳台", + "屋顶", + "花园", + "公园", + "机场", + "泳池", + "码头", + "小镇", + "走廊", + "奇幻城市", + "游乐园", + "电影院", + "校园", + "医院" + ] + }, + { + "name": "自然", + "max": 2, + "content": [ + "湖泊", + "沙滩", + "山脉", + "花", + "沙漠", + "田园", + "花田", + "水下", + "瀑布", + "农场", + "阿尔卑斯山脉", + "洞穴", + "溪流", + "湿地", + "河流", + "大海", + "森林", + "草地", + "室外", + "芦苇草原", + "繁华草甸", + "岛屿", + "草坪", + "雪地", + "池塘", + "山丘", + "丛林", + "峡谷" + ] + }, + { + "name": "天气", + "max": 1, + "content": ["阴天", "多云", "晴天", "雪天", "雨天", "雾天"] + } + ] + }, + { + "name": "时间", + "content": [ + { + "name": "时段", + "max": 1, + "content": ["黎明", "中午", "黄昏", "白天", "凌晨", "早上", "下午", "晚上", "夜晚"] + }, + { + "name": "季节", + "max": 1, + "content": ["春季", "夏季", "秋季", "冬季"] + }, + { + "name": "节日", + "max": 1, + "content": ["情人节", "万圣节", "春节", "中秋节", "女儿节", "东京神田祭", "新年", "感恩节", "圣诞节", "端午节", "樱花祭", "京都祇园祭", "大阪天神祭"] + } + ] + }, + { + "name": "画种", + "content": [ + { + "name": "特效", + "max": 1, + "content": ["高对比度", "色彩斑斓", "色差", "锐化", "高饱和度", "轮廓加深", "HDR"] + }, + { + "name": "质量", + "max": 4, + "content": ["大师之作", "高分辨率", "超高分辨率", "极其详细", "优良细节", "高质量", "世界杰出剧院", "极高分辨率", "复杂细节"] + }, + { + "name": "画风", + "max": 1, + "content": [ + "纸膜", + "80年代", + "铅笔画风", + "水墨", + "水彩", + "素描", + "线稿", + "体素画", + "浮世绘", + "平面着色", + "灰度", + "名画恶搞", + "纸艺", + "复古", + "90年代", + "彩铅绘", + "写实", + "炭笔素描", + "像素画", + "赛博朋克", + "平涂", + "单色调", + "角色扮演" + ] + }, + { + "name": "形式", + "max": 1, + "content": [ + "轻小说插画", + "游戏CG", + "8K壁纸", + "漫画书", + "动漫截图", + "官方图", + "立绘", + "抱枕", + "同人志风", + "海报", + "塔罗牌风格", + "游戏王", + "插画", + "原画", + "非常详细的CG", + "8K超详细的CG壁纸", + "四格漫画", + "角色设定图", + "杂志", + "P站风格", + "苏维埃海报", + "卡牌风" + ] + } + ] + }, + { + "name": "构图", + "content": [ + { + "name": "视角", + "max": 1, + "content": ["电视视角", "半身像", "焦点视角", "背后视角", "侧视视角", "仰视视角", "动态视角", "全身像", "主观视角", "眺望远方", "倾斜视角", "俯视视角"] + }, + { + "name": "距离", + "max": 1, + "content": ["远景", "近景", "鱼眼", "等距", "全景", "中景", "特写", "景深", "透视"] + } + ] + }, + { + "name": "灯光", + "content": [ + { + "name": "光源", + "max": 2, + "content": ["阳光", "晨光", "斑驳的阳光", "动态角度灯轴", "真实光源", "云隙光", "月光", "工作室光照", "天使圣光"] + }, + { + "name": "方向", + "max": 2, + "content": ["背光", "轮廓光", "分割照明", "顶光", "逆光", "重点照明"] + }, + { + "name": "属性", + "max": 2, + "content": ["弱光源", "柔光", "冷光", "过曝光", "气氛光", "强光源", "暧光", "彩色光源", "体积光"] + }, + { + "name": "品质", + "max": 2, + "content": ["电影光", "详细的辉光", "优良的发光", "黄金时段照明"] + }, + { + "name": "光效", + "max": 2, + "content": ["光线泄露", "彩色折射", "丁达尔光", "闪光", "光线追踪", "反光", "镜头光晕", "荧光"] + }, + { + "name": "粒子", + "max": 2, + "content": ["发光粒子", "照明粒子"] + }, + { + "name": "阴影", + "max": 2, + "content": ["树影", "投影阴影", "最佳阴影", "强烈的黑色阴影", "真实阴影", "戏剧阴影", "阴影战术应用", "美丽的详细阴影"] + } + ] + } + ] + } + ] + }; +} diff --git a/lib/tools/drawdetails/draw_details_model.dart b/lib/tools/drawdetails/draw_details_model.dart new file mode 100644 index 0000000..9c14c0d --- /dev/null +++ b/lib/tools/drawdetails/draw_details_model.dart @@ -0,0 +1,246 @@ +import 'dart:async'; + +import 'package:aiplot/bean/text_to_image_bean.dart'; + +import '../../bean/art_detail_bean.dart'; +import '../../bean/user_center_bean.dart'; +import '../../bean/works_detail_bean.dart'; +import '../../bean/works_info_bean.dart'; +import '../../network/BaseEntity.dart'; +import '../../network/NetworkConfig.dart'; +import '../../network/RequestCenter.dart'; + +class DrawDetailsModel { + StreamController streamController = StreamController.broadcast(); + + DrawDetailsModel() { + setup(); + } + + void setup() { + //初始化 + } + + //任务进度 + Future getProgress(String taskId) async { + RequestCenter.instance.requestPlay(NetworkConfig.getProgress, {"TaskId": taskId}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + TextToImageBean data = TextToImageBean.fromJson(json); + streamController.sink.add({ + 'code': "getProgress", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //图片详情 + Future getArtDetail(String drawId) async { + RequestCenter.instance.requestPlay(NetworkConfig.getArtDetail, { + "DrawId": drawId, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + ArtDetailBean data = ArtDetailBean.fromJson(json); + streamController.sink.add({ + 'code': "getArtDetail", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //分享画廊 + Future userDrawGallery(bool isUpdate, String drawId) async { + RequestCenter.instance.requestPlay(NetworkConfig.userDrawGallery, {"IsUpdate": isUpdate, "DrawId": drawId}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + // Map json = dataEntity.data; + // ArtDetailBean data = ArtDetailBean.fromJson(json); + streamController.sink.add({ + 'code': "userDrawGallery", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //收藏 + Future userDrawCollect(bool isCollect, String drawId) async { + RequestCenter.instance.requestPlay(NetworkConfig.userDrawCollect, { + "IsCollect": isCollect, + "DrawId": drawId, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + // List data = (dataEntity.data as List).map((e) => UserDrawBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "userDrawCollect", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //删除 + Future delMyDrawCollect(String drawId) async { + RequestCenter.instance.requestPlay(NetworkConfig.delMyDrawCollect, {"DrawIds": drawId}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "delMyDrawCollect", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //获取作品详情列表 + Future getWorksDetailList(String drawId) async { + RequestCenter.instance.requestPlay(NetworkConfig.getWorksDetailList, {"drawId": drawId}, (BaseEntity dataEntity) { + List data = (dataEntity.data as List).map((e) => WorksDetailBean.fromJson(e as Map)).toList(); + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "getWorksDetailList", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //关注 + Future userFollow(String followUserId) async { + RequestCenter.instance.requestPlay(NetworkConfig.userFollow, {"followUserId": followUserId}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "userFollow", //有数据 + 'data': dataEntity.data, + 'message': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //达人个人中心 + Future getUserPersonalCenter(String workUserId, String worksID) async { + RequestCenter.instance.requestPlay(NetworkConfig.getUserPersonalCenter, { + "workUserId": workUserId, + "worksID": worksID, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + UserCenterBean data = UserCenterBean.fromJson(json); + streamController.sink.add({ + 'code': "getUserPersonalCenter", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //获取达人作品 + Future getWorksInfo(String workUserId, String workId, String sortType) async { + RequestCenter.instance.requestPlay(NetworkConfig.getWorksInfo, { + "workUserId": workUserId, + "workId": workId, + "sortType": sortType, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => WorksInfoBean.fromJson(e as Map)).toList(); + streamController.sink.add({ + 'code': "getWorksInfo", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } +} diff --git a/lib/tools/drawdetails/draw_details_page.dart b/lib/tools/drawdetails/draw_details_page.dart new file mode 100644 index 0000000..278baef --- /dev/null +++ b/lib/tools/drawdetails/draw_details_page.dart @@ -0,0 +1,658 @@ + +import 'dart:async'; +import 'dart:convert'; + +import 'package:aiplot/common/EventBusUtil.dart'; +import 'package:aiplot/dialog/delete_img.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/tools/drawdetails/draw_details_model.dart'; +import 'package:aiplot/tools/drawdetails/picture_details_page.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:expandable_text/expandable_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:sensors_analytics_flutter_plugin/sensors_analytics_flutter_plugin.dart'; + +import '../../bean/art_detail_bean.dart'; +import '../../bean/text_to_image_bean.dart'; +import '../../common/app_util.dart'; +import '../../common/func.dart'; +import '../../dialog/share_dialog.dart'; +import '../../generated/l10n.dart'; + +///绘制详情页 +class DrawDetailsPage extends StatefulWidget { + String? taskId; + String? drawId; + String? describeText = ""; //描述文字 + bool isCreate = false; //是否是新生成作品 + bool isMyWork; //是否是我的作品 + bool isCollect = false; //是否已收藏 + int status; //作品状态 + + DrawDetailsPage(this.isCreate, {Key? key, this.taskId, this.drawId, this.describeText, this.isMyWork = false, this.status = 3}) : super(key: key); + + @override + State createState() => _DrawDetailsPageState(); +} + +class _DrawDetailsPageState extends State { + StreamSubscription? subscription; + final DrawDetailsModel _viewModel = DrawDetailsModel(); + Timer? timer; + double pace = 0.0; //进度条 + ArtDetailBean? artDetailBean; + TextToImageBean? textToImageBean; + bool isShare = false; //是否分享画廊 + String imageUrl = ""; //展示的图片 + String resolutionRatio = "512*512"; //分辨率 + int drawState = 0; //审核状态 0 未审核,1审核中 + + @override + void initState() { + // TODO: implement initState + super.initState(); + + NetworkConfig.isImitate = false; + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + switch (code) { + case "getProgress": //进度 + textToImageBean = newData['data']; + pace = textToImageBean!.TaskPercent! * 0.01; + imageUrl = textToImageBean!.TaskResult!; + widget.drawId = textToImageBean!.SeqId.toString(); + if (textToImageBean!.TaskResult != "") { + timer?.cancel(); + } + break; + case "getArtDetail": //详情 + artDetailBean = newData['data']; + widget.drawId = artDetailBean!.Id.toString(); + widget.describeText = artDetailBean!.Prompt; + widget.isCollect = artDetailBean!.IsMyCollect!; + imageUrl = artDetailBean!.TaskResult!; + isShare = artDetailBean!.IsUserDrawGallery!; + drawState = artDetailBean!.DrawState!; + + if (NetworkConfig.userId == artDetailBean!.UserId.toString()) { + widget.isMyWork = true; + } else { + widget.isMyWork = false; + } + + NetworkConfig.prompt = artDetailBean!.Prompt!; + NetworkConfig.templateId = artDetailBean!.TemplateId!; + NetworkConfig.sizeTemplateId = artDetailBean!.SizeTemplateId!; + NetworkConfig.followId = artDetailBean!.Id!; + + switch (artDetailBean!.SizeTemplateId) { + case 0: + resolutionRatio = "512*512"; + break; + case 1: + resolutionRatio = "512*704"; + break; + case 2: + resolutionRatio = "704*512"; + break; + case 3: + resolutionRatio = "512*910"; + break; + case 4: + resolutionRatio = "910*512"; + break; + } + break; + case "delMyDrawCollect": //删除 + String message = newData['data']; + EasyLoading.showToast(message); + Navigator.pop(context); + break; + case "userDrawGallery": //上传画廊 + String message = newData['data']; + EasyLoading.showToast(message); + break; + default: + String message = newData['data']; + EasyLoading.showToast(message); + break; + } + } + setState(() {}); + }); + + if (widget.isCreate) { + getProgress(); + } else { + if (widget.status != 3) { + getProgress(); + } else { + getArtDetail(); + } + } + } + + //加载进度 + Future getProgress() async { + EasyLoading.show(status: 'loading...'); + NetworkConfig.prompt = widget.describeText!; + timer = Timer.periodic(const Duration(seconds: 2), (timer) { + _viewModel.getProgress(widget.taskId!); + }); + } + + //获取图片详情 + Future getArtDetail() async { + EasyLoading.show(status: 'loading...'); + _viewModel.getArtDetail(widget.drawId!); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + timer?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final h332 = size.width / 1.0843373493975; //332 + final t110 = size.width / 3.2727272727272; + final w23 = size.width / 15.652173913043; + final w200 = size.width / 1.8; + final w50 = size.width / 7.2; + final w66 = size.width / 5.45454545454; + final h32 = size.width / 11.25; + final w107 = size.width / 3.3644859813084; + final h70 = size.width / 5.1428571428571; + final t25 = size.width / 14.4; + final w39 = size.width / 9.2307692307692; + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 1, + title: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: EdgeInsets.only(right: 10), + child: Image( + width: w23, + height: w23, + image: AssetImage('assets/images/ic_title.png'), + ), + ), + Text( + S.of(context).details, + style: TextStyle(color: Colors.black, fontSize: 20), + ), + ], + ), + leading: IconButton( + icon: ImageIcon(AssetImage('assets/images/ic_return.png')), + color: Colors.black, + onPressed: () { + Navigator.pop(context); + }), + centerTitle: true, + ), + body: Stack( + children: [ + SingleChildScrollView( + child: Column( + children: [ + Container( + height: h332, + child: Stack( + alignment: Alignment.center, + children: [ + const Image(fit: BoxFit.fill, image: AssetImage('assets/images/ic_bg.png')), + //进度条 + widget.status != 3 + ? textToImageBean != null && textToImageBean!.TaskPercent != null && textToImageBean!.TaskPercent != 0 + ? SizedBox( + width: w200, + height: w200, + child: imageUrl == "" + ? CircularProgressIndicator( + value: pace ?? 0.0, + backgroundColor: Colors.grey, + valueColor: AlwaysStoppedAnimation(Colors.white), + ) + : Container(), + ) + : Container() + : Container(), + widget.status != 3 + ? textToImageBean != null && textToImageBean!.TaskPercent != null && textToImageBean!.TaskPercent != 0 + ? Text( + "${S.of(context).Current_progress}:${(pace * 100).toInt()}%", + style: TextStyle(color: Colors.white), + ) + : Container() + : Container(), + + ///加载动画 + Positioned( + top: t110, + child: Image( + width: w50, + height: w50, + image: AssetImage('assets/images/ic_loading.webp'), + ), + ), + + ///排队中 + textToImageBean != null && textToImageBean!.TaskPercent != null && textToImageBean!.TaskPercent == 0 + ? Positioned( + child: Text( + S.of(context).Waiting_in, + style: const TextStyle(color: Colors.white), + )) + : Container(), + + ///生成完成展示的图片 + imageUrl != "" + ? GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PictureDetailsPage(imageUrl), + )); + }, + child: CachedNetworkImage(imageUrl: imageUrl), + ) + : Container() + ], + ), + ), + + ///图片描述 + GestureDetector( + onTap: () { + EasyLoading.showToast(S.of(context).Already_copied); + Clipboard.setData(ClipboardData(text: widget.describeText)); + }, + child: widget.describeText != null + ? Container( + margin: EdgeInsets.only(top: 14, left: 15, right: 15), + alignment: Alignment.center, + child: ExpandableText( + widget.describeText!, + expandText: S.of(context).Expand, + collapseText: S.of(context).Close, + maxLines: 3, + linkColor: Colors.blue, + ), + ) + : Container(), + ), + Container( + margin: EdgeInsets.only(top: w23, left: 15, right: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ///删除-收藏 + GestureDetector( + onTap: () { + if (widget.isMyWork) { + FunctionUtil.popDialog(context, DeleteImg( + onTap: (index) { + switch (index) { + case 1: + List list = [widget.drawId!]; + String drawList = json.encode(list); + _viewModel.delMyDrawCollect(drawList); + break; + } + }, + )); + } else { + widget.isCollect = !widget.isCollect; + setState(() {}); + _viewModel.userDrawCollect(widget.isCollect, widget.drawId!); + } + }, + child: !widget.isMyWork + ? widget.isCreate + ? Container( + width: w66, + height: h32, + alignment: Alignment.center, + decoration: BoxDecoration(color: Color(0xFFEAEAEA), borderRadius: BorderRadius.all(Radius.circular(5))), + child: Text( + S.of(context).Delete, + style: TextStyle(color: Color(0xFF666666), fontSize: 13), + ), + ) + : Container( + width: w66, + height: h32, + alignment: Alignment.center, + decoration: BoxDecoration( + color: widget.isCollect ? Color(0xFFBA71E0) : Color(0xFFEAEAEA), + borderRadius: BorderRadius.all(Radius.circular(5))), + child: Text( + widget.isCollect ? S.of(context).Favorite : S.of(context).collect, + style: TextStyle(color: widget.isCollect ? Colors.white : Color(0xFF666666), fontSize: 13), + ), + ) + : Container( + width: w66, + height: h32, + alignment: Alignment.center, + decoration: BoxDecoration(color: Color(0xFFEAEAEA), borderRadius: BorderRadius.all(Radius.circular(5))), + child: Text( + S.of(context).Delete, + style: TextStyle(color: Color(0xFF666666), fontSize: 13), + ), + ), + ), + + ///下载 + GestureDetector( + onTap: () { + if (imageUrl != "") { + AppUtil.saveImage(imageUrl); + if (artDetailBean != null) { + SensorsAnalyticsFlutterPlugin.track( + 'PaintingDownload', {'AuthorUserID': artDetailBean!.UserId!, 'PaintID': artDetailBean!.Id.toString()}); + } + } + }, + child: Container( + width: w66, + height: h32, + alignment: Alignment.center, + decoration: BoxDecoration(color: Color(0xFFEAEAEA), borderRadius: BorderRadius.all(Radius.circular(5))), + child: Text( + S.of(context).Download, + style: TextStyle(color: Color(0xFF666666), fontSize: 13), + ), + ), + ), + + ///分享 + GestureDetector( + onTap: () { + if (imageUrl != "") { + if (artDetailBean != null && artDetailBean!.UserNickName != null) { + FunctionUtil.popDialog(context, ShareDialog(imageUrl, artDetailBean!.UserNickName!)); + } else { + FunctionUtil.popDialog(context, ShareDialog(imageUrl, NetworkConfig.userData!.NickName!)); + } + } else { + Fluttertoast.showToast( + msg: S.of(context).Please_wait, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 1, + backgroundColor: const Color(0x8B000000), + textColor: Colors.white, + fontSize: 16.0); + } + }, + child: Container( + width: w66, + height: h32, + alignment: Alignment.center, + decoration: BoxDecoration(color: Color(0xFFEAEAEA), borderRadius: BorderRadius.all(Radius.circular(5))), + child: Text( + S.of(context).Share, + style: TextStyle(color: Color(0xFF666666), fontSize: 13), + ), + ), + ), + + ///重新生成 再画一张 + GestureDetector( + onTap: () { + if (widget.isCreate) { + Navigator.pop(context); + } else { + NetworkConfig.isImitate = true; + EventBusUtil.fire(TabBarJumpEvent(1)); + EventBusUtil.fire(CopyDrawingEvent()); + Navigator.pop(context); + } + }, + child: Container( + width: w107, + height: h32, + alignment: Alignment.center, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(5)), + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), + ), + child: Text( + widget.isCreate || widget.isMyWork ? S.of(context).Draw_another_picture : S.of(context).Draw_the_same, + style: TextStyle(color: Colors.white, fontSize: NetworkConfig.Language != "zh" ? 14 : 12), + ), + ), + ), + ], + ), + ), + Container( + height: 1, + margin: EdgeInsets.only(top: 22), + color: Color(0xFFEAEAEA), + ), + + ///上传画廊 + widget.isMyWork || widget.isCreate + ? SizedBox( + height: h70, + width: size.width, + child: Stack( + children: [ + Positioned( + top: 14, + left: 15, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + S.of(context).share_to_gallery, + style: const TextStyle(color: Colors.black, fontSize: 16), + ), + drawState == 1 + ? Container( + padding: const EdgeInsets.only(left: 3, right: 3), + margin: const EdgeInsets.only(left: 7), + decoration: const BoxDecoration( + color: Color(0xFFF2F2F2), + borderRadius: BorderRadius.all(Radius.circular(2)), + ), + child: Text( + S.of(context).In_review, + style: const TextStyle(color: Color(0xFF999999), fontSize: 10), + ), + ) + : drawState == 2 + ? Container( + padding: const EdgeInsets.only(left: 3, right: 3), + margin: const EdgeInsets.only(left: 7), + decoration: const BoxDecoration( + color: Color(0xFFF2F2F2), + borderRadius: BorderRadius.all(Radius.circular(2)), + ), + child: Text( + S.of(context).uploaded, + style: const TextStyle(color: Color(0xFF999999), fontSize: 10), + ), + ) + : Container(), + ], + ), + ), + Positioned( + right: 15, + top: t25, + child: GestureDetector( + onTap: () { + isShare = !isShare; + if (isShare) { + drawState = 1; + } else { + drawState = 0; + } + setState(() {}); + _viewModel.userDrawGallery(isShare, widget.drawId!); + }, + child: Image( + width: w39, + height: 18, + image: isShare ? const AssetImage('assets/images/ic_open.png') : const AssetImage('assets/images/ic_close.png'), + ), + ), + ), + Positioned( + top: w39, + left: 15, + child: Text( + "${S.of(context).Obtained_after_review} ${NetworkConfig.appConfigBean!.SharingRewards!} ${S.of(context).Painting_points}", + style: const TextStyle(color: Color(0xFF8741FF), fontSize: 13), + ), + ), + Positioned( + bottom: 0, + child: Container( + height: 1, + width: size.width, + color: const Color(0xFFEAEAEA), + ), + ) + ], + ), + ) + : Container(), + widget.isCreate + ? Container( + alignment: Alignment.centerLeft, + margin: const EdgeInsets.all(15), + child: Text( + S.of(context).Check_in, + style: const TextStyle(color: Color(0xFF999999)), + ), + ) + : Container(), + + ///生成时间 + !widget.isCreate + ? Container( + margin: const EdgeInsets.only(left: 15, right: 15, top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + S.of(context).Generate_time, + style: const TextStyle( + color: Color(0xFF999999), + ), + ), + Text( + artDetailBean != null && artDetailBean!.CreateTime != null && artDetailBean!.CreateTime != "" + ? artDetailBean!.CreateTime!.toString() + : "", + style: const TextStyle(color: Color(0xFF999999)), + ), + ], + ), + ) + : Container(), + + ///分辨率 + !widget.isCreate + ? Container( + margin: const EdgeInsets.only(left: 15, right: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + S.of(context).Resolution, + style: const TextStyle( + color: Color(0xFF999999), + ), + ), + Text( + resolutionRatio, + style: const TextStyle(color: Color(0xFF999999)), + ), + ], + ), + ) + : Container(), + Container( + height: 1, + margin: const EdgeInsets.only(top: 22), + color: const Color(0xFFEAEAEA), + ), + + !widget.isMyWork + ? Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 16), + child: Text( + S.of(context).Author, + style: TextStyle(fontSize: 16), + ), + ) + : Container(), + + !widget.isMyWork + ? Container( + margin: EdgeInsets.only(left: 16, top: 7), + child: Row( + children: [ + artDetailBean != null && artDetailBean!.UserIocn != null + ? CachedNetworkImage( + fit: BoxFit.fitHeight, + width: 28, + height: 28, + imageUrl: artDetailBean!.UserIocn!, + errorWidget: (context, url, error) => const Image( + fit: BoxFit.fitWidth, + width: 28, + height: 28, + image: AssetImage('assets/images/head.png'), + ), + ) + : Container(), + artDetailBean != null && artDetailBean!.UserNickName != null + ? Container( + margin: const EdgeInsets.only(left: 11), + child: Text( + artDetailBean!.UserNickName!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Colors.black, fontSize: 13), + ), + ) + : Container(), + ], + ), + ) + : Container(), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/tools/drawdetails/expert_user_details_page.dart b/lib/tools/drawdetails/expert_user_details_page.dart new file mode 100644 index 0000000..5e82d63 --- /dev/null +++ b/lib/tools/drawdetails/expert_user_details_page.dart @@ -0,0 +1,461 @@ +import 'dart:async'; + +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; + +import '../../bean/user_center_bean.dart'; +import '../../bean/works_info_bean.dart'; +import '../../bean/works_list_bean.dart'; +import '../../generated/l10n.dart'; +import 'draw_details_model.dart'; +import 'influential_details_page2.dart'; + +///达人用户详情 +class ExpertUserDetailsPage extends StatefulWidget { + String workUserId; + String worksID; + + ExpertUserDetailsPage({super.key, required this.workUserId, required this.worksID}); + + @override + State createState() => _ExpertUserDetailsPageState(); +} + +class _ExpertUserDetailsPageState extends State { + StreamSubscription? subscription; + final DrawDetailsModel _viewModel = DrawDetailsModel(); + + UserCenterBean? userCenterBean; + List workList = []; + int sortType = 0; + int worksIndex = 0; + int workId = 0; + + Future getWorksInfo() async { + EasyLoading.show(status: 'loading...'); + _viewModel.getWorksInfo(widget.workUserId, "$workId", "$sortType"); + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + switch (code) { + case "getUserPersonalCenter": + userCenterBean = newData['data']; + workId = userCenterBean!.WorksList![0].WorkId!; + break; + case "getWorksInfo": + workList = newData['data']; + NetworkConfig.workList = workList; + break; + case "userFollow": + userCenterBean?.IsFollow = newData['data']; + EasyLoading.showToast(newData['message']); + break; + default: + // EasyLoading.showToast(newData['data']); + break; + } + setState(() {}); + } + }); + EasyLoading.show(status: 'loading...'); + _viewModel.getUserPersonalCenter(widget.workUserId, widget.worksID); + getWorksInfo(); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + title: Text( + S.of(context).User_details, + style: const TextStyle(color: Colors.black), + ), + centerTitle: true, + iconTheme: const IconThemeData(color: Colors.black), + elevation: 0, + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios_new), + onPressed: () { + Navigator.pop(context); + }, + ), + ), + body: SingleChildScrollView( + child: userCenterBean != null + ? Stack( + children: [ + Column( + children: [ + SizedBox( + width: size.width, + height: 70, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned( + left: 16, + child: ClipOval( + child: CachedNetworkImage( + width: 60, + height: 60, + imageUrl: userCenterBean!.UserIconUrl!, + errorWidget: (context, url, error) => const Icon(Icons.error), + ), + ), + ), + Positioned( + top: 10, + left: 84, + child: SizedBox( + width: 180, + child: Text( + "${userCenterBean!.NickName}", + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 18), + ), + ), + ), + Positioned( + bottom: 10, + left: 84, + child: Row( + children: [ + RichText( + text: TextSpan(children: [ + TextSpan( + text: S.of(context).Liked, + style: const TextStyle(color: Color(0xFF999999), fontSize: 13), + ), + TextSpan( + text: " ${userCenterBean!.LikeNum}", + style: const TextStyle(color: Colors.black, fontSize: 14), + ), + ]), + ), + Container( + margin: const EdgeInsets.only(left: 20), + child: RichText( + text: TextSpan(children: [ + TextSpan( + text: S.of(context).Fans, + style: const TextStyle(color: Color(0xFF999999), fontSize: 13), + ), + TextSpan( + text: " ${userCenterBean!.FansNum}", + style: const TextStyle(color: Colors.black, fontSize: 14), + ), + ]), + ), + ), + ], + )), + + ///关注 + NetworkConfig.userId != "${userCenterBean!.UserId}" + ? Positioned( + right: 20, + child: GestureDetector( + onTap: () { + _viewModel.userFollow("${userCenterBean!.UserId}"); + }, + child: !userCenterBean!.IsFollow! + ? Container( + width: 65, + height: 24, + alignment: Alignment.center, + decoration: + const BoxDecoration(color: Color(0xFF8841FF), borderRadius: BorderRadius.all(Radius.circular(12))), + child: Text( + "+${S.of(context).follow}", + style: const TextStyle(color: Colors.white, fontSize: 12), + ), + ) + : Container( + width: 62, + height: 24, + alignment: Alignment.center, + decoration: + const BoxDecoration(color: Color(0xFFC3C3C3), borderRadius: BorderRadius.all(Radius.circular(12))), + child: Text( + S.of(context).Followed, + style: const TextStyle(color: Colors.white, fontSize: 12), + ), + ), + )) + : Container(), + ], + ), + ), + + ///日期排序 //获赞排序 + Container( + margin: EdgeInsets.only(left: 16, top: 20), + child: Row( + children: [ + GestureDetector( + onTap: () { + sortType = 0; + getWorksInfo(); + setState(() {}); + }, + child: Column( + children: [ + Text( + S.of(context).Date_sort, + style: TextStyle(color: Color(sortType == 0 ? 0xFF8841FF : 0xFFA3A3A3)), + ), + sortType == 0 + ? Container( + width: 59, + height: 2, + color: const Color(0xFF8841FF), + ) + : Container( + height: 2, + ), + ], + ), + ), + GestureDetector( + onTap: () { + sortType = 1; + getWorksInfo(); + setState(() {}); + }, + child: Container( + margin: const EdgeInsets.only(left: 18), + child: Column( + children: [ + Text( + S.of(context).Like_sorting, + style: TextStyle(color: Color(sortType == 1 ? 0xFF8841FF : 0xFFA3A3A3)), + ), + sortType == 1 + ? Container( + width: 59, + height: 2, + color: const Color(0xFF8841FF), + ) + : Container( + height: 2, + ), + ], + ), + ), + ), + ], + ), + ), + + ///标签列表 + userCenterBean!.WorksList != null && userCenterBean!.WorksList!.isNotEmpty + ? Container( + width: size.width, + height: 24, + margin: const EdgeInsets.only(left: 16, top: 21), + child: ListView.builder( + itemCount: userCenterBean!.WorksList?.length, + itemBuilder: (context, index) { + return _worksItem(userCenterBean!.WorksList![index], index); + }, + scrollDirection: Axis.horizontal), + ) + : Container(), + + ///列表 + Container( + margin: const EdgeInsets.only(top: 16, right: 16, left: 16), + child: MasonryGridView.count( + crossAxisCount: 2, + itemCount: workList.length, + itemBuilder: (BuildContext context, int index) { + return _galleryItem(workList[index], index); + }, + shrinkWrap: true, + // 纵向元素间距 + mainAxisSpacing: 0, + // 横向元素间距 + crossAxisSpacing: 10, + physics: const NeverScrollableScrollPhysics(), + ), + ), + ], + ), + ], + ) + : Container(), + ), + ); + } + + _worksItem(WorksListBean data, index) { + return GestureDetector( + onTap: () { + worksIndex = index; + workId = data.WorkId!; + getWorksInfo(); + setState(() {}); + }, + child: Container( + height: 24, + margin: const EdgeInsets.only(right: 5), + padding: const EdgeInsets.only(left: 7, right: 7), + decoration: BoxDecoration( + border: Border.all(color: worksIndex == index ? Colors.black : const Color(0xFFC4C4C4), width: 1), + borderRadius: const BorderRadius.all(Radius.circular(3))), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image( + width: 13, + height: 9, + image: AssetImage(worksIndex == index ? 'assets/images/ic_works.png' : 'assets/images/ic_works_f.png'), + ), + Container( + margin: const EdgeInsets.only(left: 5), + child: Text( + '${data.WorkName}', + style: TextStyle(fontSize: 12, color: Color(worksIndex == index ? 0xFF000000 : 0xFFC4C4C4)), + ), + ), + ], + ), + ), + ); + } + + //画列表 + _galleryItem(WorksInfoBean bean, int index) { + return GestureDetector( + onTap: () {}, + child: Column( + children: [ + ///Ai图 + ClipRRect( + borderRadius: BorderRadius.circular(7), + child: GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => InfluentialDetailsPage2(bean.DrawId.toString()), + )); + }, + child: Stack( + children: [ + CachedNetworkImage( + imageUrl: bean.TaskResult, + errorWidget: (context, url, error) => const Icon(Icons.error), + ), + ], + ), + ), + ), + + Container( + height: 25, + margin: const EdgeInsets.only(bottom: 10), + child: Stack( + alignment: Alignment.center, + children: [ + ///头像 + Positioned( + left: 0, + child: ClipOval( + child: CachedNetworkImage( + fit: BoxFit.fitHeight, + width: 18, + height: 18, + imageUrl: bean.UserIocn, + errorWidget: (context, url, error) => const Image( + fit: BoxFit.fitWidth, + width: 18, + height: 18, + image: AssetImage('assets/images/head.png'), + ), + ), + ), + ), + Positioned( + left: 23, + child: Container( + width: 80, + child: Text( + bean.UserNickName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Colors.black, fontSize: 12), + ), + ), + ), + + ///点赞收藏 + Positioned( + right: 0, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + if (NetworkConfig.userId == "${bean.UserId}") { + return; + } + + bean.IsMyLike = !bean.IsMyLike; + if (bean.IsMyLike) { + bean.LikeNum = (bean.LikeNum + 1); + } else { + if (bean.LikeNum > 0) { + bean.LikeNum = (bean.LikeNum - 1); + } + } + setState(() {}); + _viewModel.userDrawCollect(bean.IsMyLike, bean.DrawId.toString()); + }, + child: Container( + padding: EdgeInsets.all(15), + child: Row( + children: [ + Image( + width: 13, + height: 12, + image: bean.IsMyLike + ? const AssetImage('assets/images/ic_collect_s.png') + : const AssetImage('assets/images/ic_collect.png'), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text( + bean.LikeNum.toString(), + style: TextStyle(color: bean.IsMyLike ? Color(0xFFBB72E0) : Colors.black, fontSize: 12), + ), + ) + ], + ), + )), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/tools/drawdetails/influential_details_page.dart b/lib/tools/drawdetails/influential_details_page.dart new file mode 100644 index 0000000..cfb3fca --- /dev/null +++ b/lib/tools/drawdetails/influential_details_page.dart @@ -0,0 +1,411 @@ +import 'dart:async'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +import '../../bean/works_detail_bean.dart'; +import '../../common/EventBusUtil.dart'; +import '../../common/app_util.dart'; +import '../../common/func.dart'; +import '../../dialog/influential_prompt_dialog.dart'; +import '../../dialog/share_dialog.dart'; +import '../../generated/l10n.dart'; +import '../../network/NetworkConfig.dart'; +import 'draw_details_model.dart'; +import 'expert_user_details_page.dart'; + +///达人详情 +class InfluentialDetailsPage extends StatefulWidget { + String drawId; + + InfluentialDetailsPage(this.drawId, {super.key}); + + @override + State createState() => _InfluentialDetailsPageState(); +} + +class _InfluentialDetailsPageState extends State { + StreamSubscription? subscription; + final DrawDetailsModel _viewModel = DrawDetailsModel(); + + /// 初始化控制器 + late PageController pageController; + + List DetailList = []; + int currentPage = 0; + + @override + void initState() { + // TODO: implement initState + super.initState(); + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + switch (code) { + case "getWorksDetailList": + DetailList.addAll(newData['data']); + break; + case "userFollow": + EasyLoading.showToast(newData['message']); + break; + case "userDrawCollect": + EasyLoading.showToast(newData['data']); + break; + default: + // EasyLoading.showToast(newData['data']); + break; + } + setState(() {}); + } + }); + + //创建控制器的实例 + pageController = PageController( + //用来配置PageView中默认显示的页面 从0开始 + initialPage: 0, + //为true是保持加载的每个页面的状态 + keepPage: true, + ); + + ///PageView设置滑动监听 + pageController.addListener(() { + //PageView滑动的距离 + double offset = pageController.offset; + //当前显示的页面的索引 + double? page = pageController.page; + print("pageView 滑动的距离 $offset 索引 $page"); + + if (pageController.position.pixels >= pageController.position.maxScrollExtent - 100) { + // 滑动到底部 + // 执行相应的操作 + EasyLoading.show(status: 'loading...'); + _viewModel.getWorksDetailList("0"); + } + }); + + _viewModel.getWorksDetailList(widget.drawId); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + pageController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.black, + title: Text(S.of(context).details), + leading: IconButton( + icon: Icon(Icons.arrow_back_ios_new), + onPressed: () { + Navigator.pop(context); + }, + ), + centerTitle: true, + ), + body: Stack( + alignment: Alignment.center, + children: [ + Container( + color: Colors.black, + width: size.width, + height: size.height, + child: PageView.builder( + onPageChanged: (int index) { + currentPage = index; + }, + itemCount: DetailList.length, + itemBuilder: (BuildContext context, int index) { + return _pageViewItem(context, DetailList[index]); + }, + //页面控制器 + controller: pageController, + scrollDirection: Axis.vertical, + ), + ), + ], + ), + ); + } + + _pageViewItem(BuildContext context, WorksDetailBean data) { + final size = MediaQuery.of(context).size; + return Container( + child: Stack( + children: [ + CachedNetworkImage( + width: size.width, + height: size.height, + imageUrl: data.TaskResult!, + errorWidget: (context, url, error) => Icon(Icons.error), + ), + Positioned( + right: 10, + bottom: 31, + child: Container( + width: 60, + child: Column( + children: [ + Stack( + alignment: Alignment.center, + children: [ + ///头像 + GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ExpertUserDetailsPage( + workUserId: "${data.UserId}", + worksID: '${data.Id}', + ), + )); + }, + child: Container( + height: 55, + alignment: Alignment.topCenter, + child: ClipOval( + child: CachedNetworkImage( + width: 43, + height: 43, + imageUrl: data.UserIocn!, + errorWidget: (context, url, error) => Icon(Icons.error), + ), + ), + ), + ), + + ///关注 + Positioned( + bottom: 2, + child: GestureDetector( + onTap: () { + if (!data.IsFollow!) { + data.IsFollow = true; + _viewModel.userFollow("${data.UserId}"); + } + }, + child: NetworkConfig.userId != "${data.UserId}" + ? !data.IsFollow! + ? const Image( + width: 20, + height: 20, + image: AssetImage('assets/images/ic_follow.png'), + ) + : Container() + : Container(), + ), + ) + ], + ), + + ///点赞收藏 + GestureDetector( + onTap: () { + if (NetworkConfig.userId != "${data.UserId}") { + data.IsMyLike = !data.IsMyLike!; + + if (data.IsMyLike!) { + data.LikeNum = data.LikeNum! + 1; + } else { + data.LikeNum = data.LikeNum! - 1; + if (data.LikeNum! < 0) { + data.LikeNum = data.LikeNum = 0; + } + } + setState(() {}); + } + _viewModel.userDrawCollect(data.IsMyLike!, "${data.Id}"); + }, + child: Container( + margin: const EdgeInsets.only(top: 17), + child: Column( + children: [ + Image( + width: 32, + height: 30, + image: data.IsMyLike! ? const AssetImage('assets/images/ic_like_in.png') : const AssetImage('assets/images/ic_like.png'), + ), + Text( + "${data.LikeNum}", + style: const TextStyle(color: Colors.white, fontSize: 12), + ), + ], + ), + ), + ), + + ///下载 + GestureDetector( + onTap: () { + if (data.TaskResult != "") { + AppUtil.saveImage(data.TaskResult!); + // if (artDetailBean != null) { + // SensorsAnalyticsFlutterPlugin.track( + // 'PaintingDownload', {'AuthorUserID': artDetailBean!.UserId!, 'PaintID': artDetailBean!.Id.toString()}); + // } + } + }, + child: Container( + margin: const EdgeInsets.only(top: 17), + child: Column( + children: [ + const Image( + width: 32, + height: 30, + image: AssetImage('assets/images/ic_download.png'), + ), + Text( + S.of(context).Download, + style: const TextStyle(color: Colors.white, fontSize: 10), + ), + ], + ), + ), + ), + + ///画同款 + GestureDetector( + onTap: () { + NetworkConfig.prompt = data.Prompt!; + NetworkConfig.templateId = data.TemplateId!; + NetworkConfig.sizeTemplateId = data.SizeTemplateId!; + NetworkConfig.followId = data.Id!; + NetworkConfig.followUrl = data.TaskResult!; + + NetworkConfig.isImitate = true; + EventBusUtil.fire(TabBarJumpEvent(1)); + EventBusUtil.fire(CopyDrawingEvent()); + + Navigator.of(context).popUntil(ModalRoute.withName('/HomePage')); + }, + child: Container( + margin: const EdgeInsets.only(top: 17), + child: Column( + children: [ + const Image( + width: 32, + height: 30, + image: AssetImage('assets/images/ic_same_style.png'), + ), + Text( + S.of(context).copy_it, + style: const TextStyle(color: Colors.white, fontSize: 10), + ), + ], + ), + ), + ), + + ///分享 + GestureDetector( + onTap: () { + if (data.TaskResult! != "") { + // if (artDetailBean != null && artDetailBean!.UserNickName != null) { + FunctionUtil.popDialog(context, ShareDialog(data.TaskResult!, data.UserNickName!)); + // } else { + // FunctionUtil.popDialog(context, ShareDialog(data.TaskResult!, NetworkConfig.userData!.NickName!)); + // } + } else { + Fluttertoast.showToast( + msg: S.of(context).Please_wait, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 1, + backgroundColor: const Color(0x8B000000), + textColor: Colors.white, + fontSize: 16.0); + } + }, + child: Container( + margin: const EdgeInsets.only(top: 17), + child: Column( + children: [ + const Image( + width: 32, + height: 30, + image: AssetImage('assets/images/ic_share.png'), + ), + Text( + S.of(context).Share, + style: const TextStyle(color: Colors.white, fontSize: 10), + ), + ], + ), + ), + ), + ], + ), + ), + ), + + ///展开 + Positioned( + left: 15, + bottom: 31, + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${data.UserNickName}", + style: TextStyle(color: Colors.white), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + margin: EdgeInsets.only(top: 12), + width: 230, + child: Text( + "${data.Prompt}", + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Colors.white, fontSize: 13), + ), + ), + GestureDetector( + onTap: () { + FunctionUtil.bottomSheetDialog( + context, + InfluentialPromptDialog( + prompt: "${data.Prompt}", + onTap: () { + NetworkConfig.prompt = data.Prompt!; + NetworkConfig.templateId = data.TemplateId!; + NetworkConfig.sizeTemplateId = data.SizeTemplateId!; + NetworkConfig.followId = data.Id!; + NetworkConfig.followUrl = ""; + + NetworkConfig.isImitate = true; + EventBusUtil.fire(TabBarJumpEvent(1)); + EventBusUtil.fire(CopyDrawingEvent()); + + Navigator.of(context).popUntil(ModalRoute.withName('/HomePage')); + }, + )); + }, + child: Text( + S.of(context).Expand, + style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500), + ), + ) + ], + ), + ], + ), + )), + ], + ), + ); + } +} diff --git a/lib/tools/drawdetails/influential_details_page2.dart b/lib/tools/drawdetails/influential_details_page2.dart new file mode 100644 index 0000000..16cfbed --- /dev/null +++ b/lib/tools/drawdetails/influential_details_page2.dart @@ -0,0 +1,408 @@ +import 'dart:async'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +import '../../bean/works_info_bean.dart'; +import '../../common/EventBusUtil.dart'; +import '../../common/app_util.dart'; +import '../../common/func.dart'; +import '../../dialog/influential_prompt_dialog.dart'; +import '../../dialog/share_dialog.dart'; +import '../../generated/l10n.dart'; +import '../../network/NetworkConfig.dart'; +import 'draw_details_model.dart'; +import 'expert_user_details_page.dart'; + +///达人详情 +class InfluentialDetailsPage2 extends StatefulWidget { + String drawId; + + InfluentialDetailsPage2(this.drawId, {super.key}); + + @override + State createState() => _InfluentialDetailsPage2State(); +} + +class _InfluentialDetailsPage2State extends State { + StreamSubscription? subscription; + final DrawDetailsModel _viewModel = DrawDetailsModel(); + + /// 初始化控制器 + late PageController pageController; + + // List DetailList = []; + int currentPage = 0; + int initialPage = 0; + + @override + void initState() { + // TODO: implement initState + super.initState(); + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + switch (code) { + case "getWorksDetailList": + // DetailList = newData['data']; + break; + case "userFollow": + EasyLoading.showToast(newData['message']); + break; + default: + // EasyLoading.showToast(newData['data']); + break; + } + setState(() {}); + } + }); + + for (int i = 0; i < NetworkConfig.workList.length; i++) { + if ("${NetworkConfig.workList[i].Id}" == widget.drawId) { + initialPage = i; + } + } + + //创建控制器的实例 + pageController = PageController( + //用来配置PageView中默认显示的页面 从0开始 + initialPage: initialPage, + //为true是保持加载的每个页面的状态 + keepPage: true, + ); + + ///PageView设置滑动监听 + pageController.addListener(() { + //PageView滑动的距离 + double offset = pageController.offset; + //当前显示的页面的索引 + double? page = pageController.page; + print("pageView 滑动的距离 $offset 索引 $page"); + + if (pageController.position.pixels >= pageController.position.maxScrollExtent - 100) { + // 滑动到底部 + // 执行相应的操作 + + } + }); + + // _viewModel.getWorksDetailList(widget.drawId); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + pageController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.black, + title: Text(S.of(context).details), + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios_new), + onPressed: () { + Navigator.pop(context); + }, + ), + centerTitle: true, + ), + body: Stack( + alignment: Alignment.center, + children: [ + Container( + color: Colors.black, + width: size.width, + height: size.height, + child: PageView.builder( + onPageChanged: (int index) { + currentPage = index; + }, + itemCount: NetworkConfig.workList.length, + itemBuilder: (BuildContext context, int index) { + return _pageViewItem(context, NetworkConfig.workList[index]); + }, + //页面控制器 + controller: pageController, + scrollDirection: Axis.vertical, + ), + ), + ], + ), + ); + } + + _pageViewItem(BuildContext context, WorksInfoBean data) { + final size = MediaQuery.of(context).size; + return Stack( + children: [ + CachedNetworkImage( + width: size.width, + height: size.height, + imageUrl: data.TaskResult, + errorWidget: (context, url, error) => const Icon(Icons.error), + ), + Positioned( + right: 10, + bottom: 31, + child: SizedBox( + width: 50, + child: Column( + children: [ + Stack( + alignment: Alignment.center, + children: [ + ///头像 + GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ExpertUserDetailsPage( + workUserId: "${data.UserId}", + worksID: '${data.Id}', + ), + )); + }, + child: Container( + height: 55, + alignment: Alignment.topCenter, + child: ClipOval( + child: CachedNetworkImage( + width: 43, + height: 43, + imageUrl: data.UserIocn, + errorWidget: (context, url, error) => const Icon(Icons.error), + ), + ), + ), + ), + + ///关注 + Positioned( + bottom: 2, + child: GestureDetector( + onTap: () { + if (!data.IsFollow) { + data.IsFollow = true; + _viewModel.userFollow("${data.UserId}"); + } + }, + child: !data.IsFollow + ? const Image( + width: 20, + height: 20, + image: AssetImage('assets/images/ic_follow.png'), + ) + : Container(), + ), + ) + ], + ), + + ///点赞收藏 + GestureDetector( + onTap: () { + if (NetworkConfig.userId == "${data.UserId}") { + return; + } + data.IsMyLike = !data.IsMyLike; + + if (data.IsMyLike) { + data.LikeNum = data.LikeNum + 1; + } else { + data.LikeNum = data.LikeNum - 1; + if (data.LikeNum < 0) { + data.LikeNum = data.LikeNum = 0; + } + } + _viewModel.userDrawCollect(data.IsMyLike, "${data.Id}"); + setState(() {}); + }, + child: Container( + margin: const EdgeInsets.only(top: 17), + child: Column( + children: [ + Image( + width: 32, + height: 30, + image: data.IsMyLike ? const AssetImage('assets/images/ic_like_in.png') : const AssetImage('assets/images/ic_like.png'), + ), + Text( + "${data.LikeNum}", + style: const TextStyle(color: Colors.white, fontSize: 12), + ), + ], + ), + ), + ), + + ///下载 + GestureDetector( + onTap: () { + if (data.TaskResult != "") { + AppUtil.saveImage(data.TaskResult); + // if (artDetailBean != null) { + // SensorsAnalyticsFlutterPlugin.track( + // 'PaintingDownload', {'AuthorUserID': artDetailBean!.UserId!, 'PaintID': artDetailBean!.Id.toString()}); + // } + } + }, + child: Container( + margin: const EdgeInsets.only(top: 17), + child: Column( + children: [ + const Image( + width: 32, + height: 30, + image: AssetImage('assets/images/ic_download.png'), + ), + Text( + S.of(context).Download, + style: const TextStyle(color: Colors.white, fontSize: 10), + ), + ], + ), + ), + ), + + ///画同款 + GestureDetector( + onTap: () { + NetworkConfig.prompt = data.Prompt; + NetworkConfig.templateId = data.TemplateId; + NetworkConfig.sizeTemplateId = data.SizeTemplateId; + NetworkConfig.followId = data.Id; + NetworkConfig.followUrl = data.TaskResult; + + NetworkConfig.isImitate = true; + EventBusUtil.fire(TabBarJumpEvent(1)); + EventBusUtil.fire(CopyDrawingEvent()); + + Navigator.of(context).popUntil(ModalRoute.withName('/HomePage')); + }, + child: Container( + margin: const EdgeInsets.only(top: 17), + child: Column( + children: [ + const Image( + width: 32, + height: 30, + image: AssetImage('assets/images/ic_same_style.png'), + ), + Text( + S.of(context).copy_it, + style: const TextStyle(color: Colors.white, fontSize: 10), + ), + ], + ), + ), + ), + + ///分享 + GestureDetector( + onTap: () { + if (data.TaskResult != "") { + // if (artDetailBean != null && artDetailBean!.UserNickName != null) { + FunctionUtil.popDialog(context, ShareDialog(data.TaskResult, data.UserNickName)); + // } else { + // FunctionUtil.popDialog(context, ShareDialog(data.TaskResult!, NetworkConfig.userData!.NickName!)); + // } + } else { + Fluttertoast.showToast( + msg: S.of(context).Please_wait, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 1, + backgroundColor: const Color(0x8B000000), + textColor: Colors.white, + fontSize: 16.0); + } + }, + child: Container( + margin: const EdgeInsets.only(top: 17), + child: Column( + children: [ + const Image( + width: 32, + height: 30, + image: AssetImage('assets/images/ic_share.png'), + ), + Text( + S.of(context).Share, + style: TextStyle(color: Colors.white, fontSize: 10), + ), + ], + ), + ), + ), + ], + ), + ), + ), + + ///展开 + Positioned( + left: 15, + bottom: 31, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + data.UserNickName, + style: const TextStyle(color: Colors.white), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + margin: const EdgeInsets.only(top: 12), + width: 230, + child: Text( + data.Prompt, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Colors.white, fontSize: 13), + ), + ), + GestureDetector( + onTap: () { + FunctionUtil.bottomSheetDialog( + context, + InfluentialPromptDialog( + prompt: data.Prompt, + onTap: () { + NetworkConfig.prompt = data.Prompt; + NetworkConfig.templateId = data.TemplateId; + NetworkConfig.sizeTemplateId = data.SizeTemplateId; + NetworkConfig.followId = data.Id; + NetworkConfig.followUrl = ""; + + NetworkConfig.isImitate = true; + EventBusUtil.fire(TabBarJumpEvent(1)); + EventBusUtil.fire(CopyDrawingEvent()); + + Navigator.of(context).popUntil(ModalRoute.withName('/HomePage')); + }, + )); + }, + child: Text( + S.of(context).Expand, + style: const TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500), + ), + ) + ], + ), + ], + )), + ], + ); + } +} diff --git a/lib/tools/drawdetails/picture_details_page.dart b/lib/tools/drawdetails/picture_details_page.dart new file mode 100644 index 0000000..a3bae1f --- /dev/null +++ b/lib/tools/drawdetails/picture_details_page.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:photo_view/photo_view.dart'; + +class PictureDetailsPage extends StatefulWidget { + String imageUrl; + + PictureDetailsPage(this.imageUrl, {super.key}); + + @override + State createState() => _PictureDetailsPageState(); +} + +class _PictureDetailsPageState extends State { + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Container( + width: size.width, + height: size.height, + color: Colors.black, + child: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: PhotoView( + imageProvider: NetworkImage(widget.imageUrl), + minScale: 0.5, + enableRotation: false, + loadingBuilder: (context, event) => Center( + child: Container( + width: 50, + height: 50, + alignment: Alignment.center, + child: const CircularProgressIndicator( + strokeWidth: 3, + valueColor: AlwaysStoppedAnimation(Color(0xFFBA71E0)), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/tools/gallery/gallery_content_model.dart b/lib/tools/gallery/gallery_content_model.dart new file mode 100644 index 0000000..ad4c523 --- /dev/null +++ b/lib/tools/gallery/gallery_content_model.dart @@ -0,0 +1,225 @@ +import 'dart:async'; + +import 'package:aiplot/bean/gallery_label_bean.dart'; +import 'package:aiplot/bean/levitating_ball_bean.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/network/RequestCenter.dart'; + +import '../../bean/gallery_work_label_bean.dart'; +import '../../bean/gallery_work_list_bean.dart'; +import '../../bean/recommender_bean.dart'; +import '../../network/BaseEntity.dart'; + +class GalleryContentModel { + StreamController streamController = StreamController.broadcast(); + + GalleryContentModel() { + setup(); + } + + void setup() { + //初始化 + } + + //获取画廊 + Future getGalleryLableList() async { + RequestCenter.instance.requestPlay(NetworkConfig.getGalleryLableList, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => GalleryLabelBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "getGalleryLableList", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //悬浮球 + Future getLevitatingBall() async { + RequestCenter.instance.requestPlay(NetworkConfig.getLevitatingBall, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + LevitatingBallBean data = LevitatingBallBean.fromJson(json); + streamController.sink.add({ + 'code': "getLevitatingBall", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } + + //领取悬浮球 + Future receiveAwardNewUserPackage() async { + RequestCenter.instance.requestPlay(NetworkConfig.receiveAwardNewUserPackage, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "receiveAwardNewUserPackage", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } + + //画廊推荐达人 + Future getRecommenderList() async { + RequestCenter.instance.requestPlay(NetworkConfig.getRecommenderList, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => RecommenderBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "getRecommenderList", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } + + //画廊标签列表 + Future getGalleryWorkLabel() async { + RequestCenter.instance.requestPlay(NetworkConfig.getGalleryWorkLabel, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = + (dataEntity.data as List).map((e) => GalleryWorkLabelBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "getGalleryWorkLabel", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } + + //根据标签获取画廊作品 + Future getWorksListByLabel(labelId, int childId, int index, bool isLoad) async { + RequestCenter.instance.requestPlay(NetworkConfig.getWorksListByLabel, { + "labelId": labelId, + "childId": childId, + "index": index, + "size": 20, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = + (dataEntity.data as List).map((e) => GalleryWorkListBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "getWorksListByLabel", //有数据 + 'data': data, + 'isLoad': isLoad, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } + + //收藏 + Future userDrawCollect(bool isCollect, String drawId) async { + RequestCenter.instance.requestPlay(NetworkConfig.userDrawCollect, { + "IsCollect": isCollect, + "DrawId": drawId, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + // List data = (dataEntity.data as List).map((e) => UserDrawBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "userDrawCollect", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //收藏 + Future getUserHomePageByPw(String invitationCode) async { + RequestCenter.instance.requestPlay(NetworkConfig.getUserHomePageByPw, { + "invitationCode": invitationCode, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + // List data = (dataEntity.data as List).map((e) => UserDrawBean.fromJson(e as Map)).toList(); + streamController.sink.add({ + 'code': "getUserHomePageByPw", //有数据 + 'data': dataEntity.data['UserId'], + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } +} diff --git a/lib/tools/gallery/gallery_content_page.dart b/lib/tools/gallery/gallery_content_page.dart new file mode 100644 index 0000000..ec9258b --- /dev/null +++ b/lib/tools/gallery/gallery_content_page.dart @@ -0,0 +1,697 @@ +import 'dart:async'; + +import 'package:aiplot/tools/gallery/gallery_content_model.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; + +import '../../bean/gallery_label_bean.dart'; +import '../../bean/gallery_work_label_bean.dart'; +import '../../bean/gallery_work_list_bean.dart'; +import '../../bean/recommender_bean.dart'; +import '../../common/Global.dart'; +import '../../common/dialog_bean.dart'; +import '../../common/dialog_manager.dart'; +import '../../common/dialog_util.dart'; +import '../../common/func.dart'; +import '../../dialog/login_dialog.dart'; +import '../../dialog/phone_login_dialog.dart'; +import '../../generated/l10n.dart'; +import '../../network/NetworkConfig.dart'; +import '../drawdetails/expert_user_details_page.dart'; +import '../drawdetails/influential_details_page.dart'; + +class GalleryContentPage extends StatefulWidget { + GalleryContentPage({Key? key}) : super(key: key); + + @override + State createState() => _GalleryContentPageState(); +} + +class _GalleryContentPageState extends State with SingleTickerProviderStateMixin { + StreamSubscription? subscription; + final GalleryContentModel _viewModel = GalleryContentModel(); + GlobalKey loginDialogKey = GlobalKey(); //登录弹框key + final ScrollController _scrollController = ScrollController(); + TabController? tabController; + List labelList = []; + List myTabs = []; + String influentialCode = ""; + List recommenderList = []; + List workLabelList = []; + int currentLabelIndex = 0; //当前选中标签 + int currentChild = 1; //当前选中的子标签 + List galleryList = []; + int index = 1; //当前页数 + FocusNode focusNode = FocusNode(); + + //创建StreamController + StreamController? streamController; + + // 获取StreamSink用于发射事件 + StreamSink? get streamSink => streamController?.sink; + + // 获取Stream用于监听 + Stream? get streamData => streamController?.stream; + + void influentialChange(String str) { + influentialCode = str.toUpperCase(); + } + + void getWorksListByLabel(bool isLoad) { + EasyLoading.show(status: 'loading...'); + _viewModel.getWorksListByLabel(workLabelList[currentLabelIndex].LabelId, currentChild, index, isLoad); + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + + streamController = StreamController(); + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + + switch (code) { + case "getRecommenderList": + recommenderList = newData['data']; + break; + + case "getGalleryWorkLabel": + workLabelList = newData['data']; + + getWorksListByLabel(false); + + break; + case "getWorksListByLabel": + if (newData['isLoad']) { + galleryList.addAll(newData['data']); + } else { + galleryList = newData['data']; + } + + break; + case "getUserHomePageByPw": //搜索达人 + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ExpertUserDetailsPage( + workUserId: "${newData['data']}", + worksID: '0', + ), + )); + break; + default: + String message = newData['data']; + EasyLoading.showToast(message); + break; + } + setState(() {}); + } + }); + + //上拉加载 + _scrollController.addListener(() { + //判断是否滑动到了页面的最底部 + if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { + //如果不是最后一页数据,则生成新的数据添加到list里面 + index++; + getWorksListByLabel(true); + } + + ///置顶按钮 + if (_scrollController.position.pixels > 600) { + streamSink?.add(true); + } else { + streamSink?.add(false); + } + }); + + _viewModel.getRecommenderList(); + _viewModel.getGalleryWorkLabel(); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + streamController?.close(); + tabController?.dispose(); + focusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.only(right: 10), + child: const Image( + width: 23, + height: 23, + image: AssetImage('assets/images/ic_title.png'), + ), + ), + Text( + "AI${S.of(context).Gallery}", + style: const TextStyle(color: Colors.black, fontSize: 20), + ), + ], + ), + centerTitle: true, + ), + body: RefreshIndicator( + onRefresh: _onRefresh, + child: Stack( + children: [ + SingleChildScrollView( + controller: _scrollController, + child: Container( + margin: const EdgeInsets.only(left: 15), + child: Column( + children: [ + ///搜索达人 + Container( + margin: const EdgeInsets.only(right: 15), + child: Container( + width: double.infinity, + height: 40, + decoration: BoxDecoration( + border: Border.all(width: 1, color: const Color(0xFF8841FF)), + borderRadius: const BorderRadius.all(Radius.circular(20)), + ), + child: Stack( + alignment: Alignment.center, + children: [ + const Positioned( + left: 17, + child: Image( + image: AssetImage('assets/images/ic_search.png'), + width: 19, + height: 19, + )), + Positioned( + left: 47, + right: 70, + child: Container( + height: 30, + width: double.infinity, + alignment: Alignment.centerLeft, + child: TextField( + keyboardType: TextInputType.text, + focusNode: focusNode, + decoration: InputDecoration( + hintText: S.of(context).Search_influential, + hintStyle: const TextStyle(fontSize: 14, color: Color(0xFF999999)), + border: InputBorder.none, + isCollapsed: true, + ), + onChanged: influentialChange, + ), + ), + ), + Positioned( + right: 7, + child: GestureDetector( + onTap: () { + if (NetworkConfig.userId == "") { + showLoginDialog(); + } else { + if (influentialCode != "") { + focusNode.unfocus(); + _viewModel.getUserHomePageByPw(influentialCode); + } + } + }, + child: Container( + width: 60, + height: 28, + alignment: Alignment.center, + decoration: BoxDecoration(color: const Color(0xFF8841FF), borderRadius: BorderRadius.circular(14)), + child: Text( + S.of(context).search, + style: const TextStyle(color: Colors.white, fontSize: 14), + ), + ), + )), + ], + ), + ), + ), + + ///推荐达人 + recommenderList.isNotEmpty + ? Container( + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(top: 20), + child: Text( + S.of(context).Recommended_influencers, + style: const TextStyle(fontSize: 16, color: Colors.black, fontWeight: FontWeight.w600), + ), + ) + : Container(), + recommenderList.isNotEmpty + ? Container( + height: 70, + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(top: 20, right: 15), + child: ListView.builder( + shrinkWrap: true, + itemCount: recommenderList.length, + itemBuilder: (context, index) { + return influential(recommenderList[index]); + }, + scrollDirection: Axis.horizontal), + ) + : Container(), + + ///作品展示 + Container( + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(top: 20), + child: Text( + S.of(context).Exhibition_works, + style: const TextStyle(fontSize: 16, color: Colors.black, fontWeight: FontWeight.w600), + ), + ), + + ///标签 + Container( + height: 25, + alignment: Alignment.center, + margin: const EdgeInsets.only(top: 12), + child: ListView.builder( + itemCount: workLabelList.length, + itemBuilder: (context, index) { + return _labelItem(workLabelList[index], index); + }, + scrollDirection: Axis.horizontal, + ), + ), + + ///子标签 + Container( + margin: const EdgeInsets.only(top: 11), + child: Row( + children: [ + GestureDetector( + onTap: () { + currentChild = 1; + getWorksListByLabel(false); + }, + child: Container( + margin: const EdgeInsets.only(right: 10), + child: Text( + S.of(context).Newest, + style: TextStyle(color: currentChild == 1 ? Colors.black : Color(0xFF999999)), + ), + ), + ), + GestureDetector( + onTap: () { + currentChild = 2; + getWorksListByLabel(false); + }, + child: Container( + margin: EdgeInsets.only(right: 10), + child: Text( + S.of(context).Popular, + style: TextStyle(color: currentChild == 2 ? Colors.black : Color(0xFF999999)), + ), + ), + ), + GestureDetector( + onTap: () { + currentChild = 3; + getWorksListByLabel(false); + }, + child: Container( + margin: EdgeInsets.only(right: 10), + child: Text( + S.of(context).all, + style: TextStyle(color: currentChild == 3 ? Colors.black : Color(0xFF999999)), + ), + ), + ), + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 16, right: 15), + child: MasonryGridView.count( + crossAxisCount: 2, + itemCount: galleryList.length, + itemBuilder: (BuildContext context, int index) { + return _galleryItem(galleryList[index], index); + }, + shrinkWrap: true, + // 纵向元素间距 + mainAxisSpacing: 0, + // 横向元素间距 + crossAxisSpacing: 10, + physics: const NeverScrollableScrollPhysics(), + ), + ), + ], + ), + ), + ), + + ///置顶 + StreamBuilder( + stream: streamData, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.data != null && snapshot.data) { + return Positioned( + right: 10, + bottom: 50, + child: GestureDetector( + onTap: () { + _scrollController.animateTo(0, duration: Duration(milliseconds: 500), curve: Curves.decelerate); + }, + child: const Image( + width: 60, + image: AssetImage('assets/images/ic_topping.png'), + ), + ), + ); + } else { + return Container(); + } + }), + ], + ), + ), + ); + } + + // 下拉刷新 + Future _onRefresh() async { + // 持续两秒 + await Future.delayed(const Duration(milliseconds: 1500), () { + currentLabelIndex = 0; + currentChild = 1; + index = 1; + galleryList = []; + _viewModel.getRecommenderList(); + _viewModel.getGalleryWorkLabel(); + }); + } + + //达人条目 + influential(RecommenderBean data) { + return GestureDetector( + onTap: () { + if (NetworkConfig.userId == "") { + showLoginDialog(); + } else { + focusNode.unfocus(); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ExpertUserDetailsPage( + workUserId: "${data.UserId}", + worksID: '${data.UserFollow}', + ), + )); + } + }, + child: Container( + width: 50, + margin: EdgeInsets.only(right: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ClipOval( + child: CachedNetworkImage( + width: 50, + height: 50, + imageUrl: data.UserIconUrl!, + errorWidget: (context, url, error) => Icon(Icons.error), + ), + ), + SizedBox( + width: 50, + child: Text( + "${data.NickName}", + style: TextStyle(fontSize: 12, color: Color(0xFF999999)), + overflow: TextOverflow.ellipsis, + ), + ) + ], + ), + )); + } + + //作品标签 + _labelItem(GalleryWorkLabelBean data, index) { + return GestureDetector( + onTap: () { + if (NetworkConfig.userId == "") { + showLoginDialog(); + } else { + focusNode.unfocus(); + currentLabelIndex = index; + currentChild = 1; + getWorksListByLabel(false); + setState(() {}); + } + }, + child: Container( + padding: const EdgeInsets.only(left: 10, right: 10), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(currentLabelIndex == index ? 0xFF8841FF : 0xFFF6F7FF), + borderRadius: const BorderRadius.all(Radius.circular(20)), + ), + margin: const EdgeInsets.only(right: 12), + child: Text( + "${data.LabelName}", + style: TextStyle(color: currentLabelIndex == index ? Colors.white : Color(0xFF999999), fontSize: 13), + ), + ), + ); + } + + //画廊 + _galleryItem(GalleryWorkListBean bean, int index) { + return Column( + children: [ + ///Ai图 + ClipRRect( + borderRadius: BorderRadius.circular(7), + child: GestureDetector( + onTap: () { + focusNode.unfocus(); + if (NetworkConfig.userId == "") { + showLoginDialog(); + } else { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => DrawDetailsPage( + // false, + // drawId: bean.DrawId.toString(), + // isMyWork: false, + // status: 3, + // ), + // )); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => InfluentialDetailsPage(bean.DrawId.toString()), + )); + } + }, + child: Stack( + children: [ + CachedNetworkImage( + imageUrl: bean.ImageUrl!, + errorWidget: (context, url, error) => Icon(Icons.error), + ), + bean.IsTalent == 1 + ? const Positioned( + left: 6, + top: 6, + child: Image( + width: 42, + image: AssetImage('assets/images/ic_portfolio.webp'), + )) + : Container(), + ], + ), + ), + ), + Row( + children: [ + bean.IsTalent == 1 + ? Container( + width: 48, + height: 15, + alignment: Alignment.center, + margin: EdgeInsets.only(top: 2), + decoration: BoxDecoration( + border: Border.all(color: Color(0xFFFF6316), width: 1), + borderRadius: BorderRadius.all(Radius.circular(3)), + ), + child: Text( + S.of(context).Expert_selection, + style: TextStyle(fontSize: 10, color: Color(0xFFFF661B)), + ), + ) + : Container(), + Container( + width: bean.IsTalent == 1 ? 100 : 140, + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(left: 5), + child: Text( + "${bean.Title}", + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Colors.black), + ), + ), + ], + ), + + Container( + height: 25, + margin: EdgeInsets.only(bottom: 10), + child: Stack( + alignment: Alignment.center, + children: [ + ///头像 + Positioned( + left: 0, + child: ClipOval( + child: CachedNetworkImage( + fit: BoxFit.fitHeight, + width: 18, + height: 18, + imageUrl: bean.UserIocn!, + errorWidget: (context, url, error) => Image( + fit: BoxFit.fitWidth, + width: 18, + height: 18, + image: AssetImage('assets/images/head.png'), + ), + ), + ), + ), + Positioned( + left: 23, + child: Container( + width: 80, + child: Text( + bean.UserNickName!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Colors.black, fontSize: 12), + ), + ), + ), + + ///点赞收藏 + Positioned( + right: 0, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + focusNode.unfocus(); + if (NetworkConfig.userId == "") { + showLoginDialog(); + } else { + if (NetworkConfig.userId != "${bean.UserId}") { + bean.IsCollect = !bean.IsCollect!; + if (bean.IsCollect!) { + bean.LikeNum = (bean.LikeNum! + 1); + } else { + if (bean.LikeNum! > 0) { + bean.LikeNum = (bean.LikeNum! - 1); + } + } + setState(() {}); + } + _viewModel.userDrawCollect(bean.IsCollect!, bean.DrawId.toString()); + } + }, + child: Container( + padding: EdgeInsets.all(15), + child: Row( + children: [ + Image( + width: 13, + height: 12, + image: bean.IsCollect! + ? const AssetImage('assets/images/ic_collect_s.png') + : const AssetImage('assets/images/ic_collect.png'), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text( + bean.LikeNum.toString(), + style: TextStyle(color: bean.IsCollect! ? Color(0xFFBB72E0) : Colors.black, fontSize: 12), + ), + ) + ], + ), + )), + ), + ], + ), + ), + ], + ); + } + + //弹出登录 + showLoginDialog() { + DialogManager() + ..add(DialogBean( + dialogPriority: DialogPriority.highClear, + createDialogWidget: () => DialogUtil.createTipWidget( + context, + LoginDialog( + loginDialogKey, + onTap: (index) { + switch (index) { + case 0: + if (loginDialogKey.currentState != null) { + loginDialogKey.currentState!.Pop(); + } + FunctionUtil.bottomSheetDialog(context, PhoneLoginDialog()); + break; + case 1: //谷歌登录 + Map map = {"googleLogin": "googleLogin"}; + invokeNativeMethod("googleLogin", map); + break; + } + }, + ), + "LoginDialog", + canceled: true))) + ..show(context); + } + + // 获取原生的值 + invokeNativeMethod(String method, Map map) async { + dynamic args; + try { + args = await Global.method.invokeMethod(method, map); + } on PlatformException catch (e) {} + } +} diff --git a/lib/tools/gallery/gallery_model.dart b/lib/tools/gallery/gallery_model.dart new file mode 100644 index 0000000..c5f6cc0 --- /dev/null +++ b/lib/tools/gallery/gallery_model.dart @@ -0,0 +1,119 @@ +import 'dart:async'; + +import 'package:aiplot/bean/levitating_ball_bean.dart'; +import 'package:aiplot/bean/popout_bean.dart'; +import 'package:aiplot/bean/user_draw_bean.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/network/RequestCenter.dart'; + +import '../../network/BaseEntity.dart'; + +class GalleryModel { + StreamController streamController = StreamController.broadcast(); + + GalleryModel() { + setup(); + } + + void setup() { + //初始化 + } + + //获取画廊 + Future getGalleryList(int index, int size, int DrawLabele) async { + RequestCenter.instance.requestPlay(NetworkConfig.getGalleryList, {"index": index, "size": size, "DrawLabele": DrawLabele}, + (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => UserDrawBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "getGalleryList", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //收藏 + Future userDrawCollect(bool isCollect, String drawId) async { + RequestCenter.instance.requestPlay(NetworkConfig.userDrawCollect, { + "IsCollect": isCollect, + "DrawId": drawId, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + // List data = (dataEntity.data as List).map((e) => UserDrawBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "userDrawCollect", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //悬浮球 + Future getLevitatingBall() async { + RequestCenter.instance.requestPlay(NetworkConfig.getLevitatingBall, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + LevitatingBallBean data = LevitatingBallBean.fromJson(json); + streamController.sink.add({ + 'code': "getLevitatingBall", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } + + //领取悬浮球 + Future receiveAwardNewUserPackage() async { + RequestCenter.instance.requestPlay(NetworkConfig.receiveAwardNewUserPackage, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "receiveAwardNewUserPackage", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } +} diff --git a/lib/tools/gallery/gallery_page.dart b/lib/tools/gallery/gallery_page.dart new file mode 100644 index 0000000..500cb50 --- /dev/null +++ b/lib/tools/gallery/gallery_page.dart @@ -0,0 +1,418 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:aiplot/tools/gallery/gallery_model.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; + +import '../../bean/levitating_ball_bean.dart'; +import '../../bean/popout_bean.dart'; +import '../../bean/user_draw_bean.dart'; +import '../../common/Global.dart'; +import '../../common/dialog_bean.dart'; +import '../../common/dialog_manager.dart'; +import '../../common/dialog_util.dart'; +import '../../common/func.dart'; +import '../../dialog/login_dialog.dart'; +import '../../dialog/newDialog.dart'; +import '../../dialog/new_ball_dialog.dart'; +import '../../dialog/phone_login_dialog.dart'; +import '../../network/NetworkConfig.dart'; +import '../drawdetails/draw_details_page.dart'; + +///画廊 +class GalleryPage extends StatefulWidget { + int labelId; + + GalleryPage(this.labelId, {Key? key}) : super(key: key); + + @override + State createState() => _GalleryPageState(); +} + +class _GalleryPageState extends State with AutomaticKeepAliveClientMixin, SingleTickerProviderStateMixin { + @override + bool get wantKeepAlive => true; + + StreamSubscription? subscription; + final GalleryModel _viewModel = GalleryModel(); + + final ScrollController _scrollController = ScrollController(); + GlobalKey loginDialogKey = GlobalKey(); //登录弹框key + List galleryList = []; + int pageIndex = 1; + int pageSize = 30; + List popList = []; + LevitatingBallBean? levitatingBallBean; + + //动画 + AnimationController? _controller; + Animation? _animation; + + @override + void initState() { + // TODO: implement initState + super.initState(); + + if (Platform.isIOS) { + subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { + // Got a new connectivity status! + if (result == ConnectivityResult.mobile || result == ConnectivityResult.wifi) { + setState(() { + getData(); + }); + } + }); + } + + //缩放动画 + _controller = AnimationController(duration: const Duration(milliseconds: 800), vsync: this); + _animation = Tween(begin: 1.0, end: 1.2).animate(CurvedAnimation(parent: _controller!, curve: Curves.linear)) + ..addStatusListener((status) { + if (status == AnimationStatus.completed) { + _controller!.reverse(); + } else if (status == AnimationStatus.dismissed) { + _controller!.forward(); + } + }); + _controller!.forward(); + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + switch (code) { + case "getGalleryList": + galleryList.addAll(newData['data']); + break; + + case "getPopoutList": + popList = newData['data']; + if (popList.length > 0) { + for (int i = 0; i < popList.length; i++) { + DialogManager() + ..add(DialogBean( + createDialogWidget: () => DialogUtil.createTipWidget( + context, + newDialog( + onTap: (PopoutId, PopoutType, text) { + // ObtainPopoutAwards(PopoutId, PopoutType, text); + }, + popoutBean: popList[i], + ), + "Popout" + i.toString(), + canceled: false))) + ..show(context); + } + } + break; + case "getLevitatingBall": //悬浮球 + levitatingBallBean = newData['data']; + if (levitatingBallBean != null) { + setState(() {}); + } + break; + + case "receiveAwardNewUserPackage": //领取悬浮球 + levitatingBallBean = null; + String message = newData['data']; + EasyLoading.showToast(message); + setState(() {}); + break; + + default: + String message = newData['data']; + EasyLoading.showToast(message); + break; + } + } + setState(() {}); + }); + + //上拉加载 + _scrollController.addListener(() { + //判断是否滑动到了页面的最底部 + if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { + //如果不是最后一页数据,则生成新的数据添加到list里面 + pageIndex++; + _viewModel.getGalleryList(pageIndex, pageSize, widget.labelId); + } + }); + getData(); + } + + Future getData() async { + EasyLoading.show(status: 'loading...'); + _viewModel.getGalleryList(pageIndex, pageSize, widget.labelId); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Scaffold( + backgroundColor: Colors.white, + body: Stack( + children: [ + galleryList.isNotEmpty + ? Container( + margin: EdgeInsets.only(top: 5), + child: SingleChildScrollView( + controller: _scrollController, + child: Container( + padding: EdgeInsets.only(bottom: 20, left: 15, right: 15), + height: galleryList.length <= 4 ? size.height : null, + child: MasonryGridView.count( + crossAxisCount: 2, + itemCount: galleryList.length, + itemBuilder: (BuildContext context, int index) { + return _item(galleryList[index], index); + }, + // 纵向元素间距 + mainAxisSpacing: 0, + // 横向元素间距 + crossAxisSpacing: 10, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + ), + ), + ), + ) + : SingleChildScrollView( + controller: _scrollController, + child: Container( + width: size.width, + height: size.height, + ), + ), + levitatingBallBean != null && levitatingBallBean!.Popup != null + ? Positioned( + right: 5, + bottom: 100, + child: GestureDetector( + onTap: () { + DialogManager() + ..add(DialogBean( + createDialogWidget: () => DialogUtil.createTipWidget( + context, + NewBallDialog( + onTap: (PopoutType, text) { + _viewModel.receiveAwardNewUserPackage(); + }, + popoutBean: levitatingBallBean!.Popup!, + ), + "NewBallDialog", + canceled: false))) + ..show(context); + }, + child: ScaleTransition( + scale: _animation!, + child: CachedNetworkImage( + fit: BoxFit.fitWidth, + width: 60, + height: 65, + imageUrl: levitatingBallBean!.ImageUrl!, + errorWidget: (context, url, error) => const Image( + fit: BoxFit.fitWidth, + width: 60, + height: 65, + image: AssetImage('assets/images/btn_cirilibao.webp'), + ), + ), + ), + ), + ) + : Container(), + ], + ), + ); + } + + // 下拉刷新 + Future _onRefresh() async { + // 持续两秒 + await Future.delayed(const Duration(milliseconds: 1500), () { + pageIndex = 1; + pageSize = 40; + galleryList = []; + _viewModel.getGalleryList(pageIndex, pageSize, widget.labelId); + // setState(() {}); + }); + } + + _item(UserDrawBean bean, int index) { + return GestureDetector( + onTap: () {}, + child: Column( + children: [ + ///Ai图 + ClipRRect( + borderRadius: BorderRadius.circular(7), + child: GestureDetector( + onTap: () { + if (NetworkConfig.userId == "") { + showLoginDialog(); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DrawDetailsPage( + false, + drawId: bean.DrawId.toString(), + isMyWork: false, + status: 3, + ), + )); + } + }, + child: CachedNetworkImage( + imageUrl: bean.ImageUrl!, + errorWidget: (context, url, error) => Icon(Icons.error), + ), + ), + ), + + // Container( + // alignment: Alignment.centerLeft, + // margin: EdgeInsets.only(top: 11), + // child: Text( + // bean.Title, + // maxLines: 1, + // overflow: TextOverflow.ellipsis, + // style: TextStyle(color: Colors.black), + // ), + // ), + Container( + height: 40, + child: Stack( + alignment: Alignment.center, + children: [ + ///头像 + Positioned( + left: 0, + child: CachedNetworkImage( + fit: BoxFit.fitHeight, + width: 18, + height: 18, + imageUrl: bean.UserIocn!, + errorWidget: (context, url, error) => Image( + fit: BoxFit.fitWidth, + width: 18, + height: 18, + image: AssetImage('assets/images/head.png'), + ), + ), + ), + Positioned( + left: 23, + child: Container( + width: 80, + child: Text( + bean.UserNickName!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Colors.black, fontSize: 12), + ), + ), + ), + + ///收藏 + Positioned( + right: 0, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + if (NetworkConfig.userId == "") { + showLoginDialog(); + } else { + bean.IsCollect = !bean.IsCollect!; + if (bean.IsCollect!) { + bean.CollectNumber = (bean.CollectNumber! + 1); + } else { + if (bean.CollectNumber! > 0) { + bean.CollectNumber = (bean.CollectNumber! - 1); + } + } + setState(() {}); + _viewModel.userDrawCollect(bean.IsCollect!, bean.DrawId.toString()); + } + }, + child: Container( + padding: EdgeInsets.all(15), + child: Row( + children: [ + Image( + width: 13, + height: 12, + image: bean.IsCollect! + ? const AssetImage('assets/images/ic_collect_s.png') + : const AssetImage('assets/images/ic_collect.png'), + ), + Container( + margin: EdgeInsets.only(left: 5), + child: Text( + bean.CollectNumber.toString(), + style: TextStyle(color: bean.IsCollect! ? Color(0xFFBB72E0) : Colors.black, fontSize: 12), + ), + ) + ], + ), + )), + ), + ], + ), + ), + ], + ), + ); + } + + //弹出登录 + showLoginDialog() { + DialogManager() + ..add(DialogBean( + dialogPriority: DialogPriority.highClear, + createDialogWidget: () => DialogUtil.createTipWidget( + context, + LoginDialog( + loginDialogKey, + onTap: (index) { + switch (index) { + case 0: + if (loginDialogKey.currentState != null) { + loginDialogKey.currentState!.Pop(); + } + FunctionUtil.bottomSheetDialog(context, PhoneLoginDialog()); + break; + case 1: //谷歌登录 + Map map = {"googleLogin": "googleLogin"}; + invokeNativeMethod("googleLogin", map); + break; + } + }, + ), + "LoginDialog", + canceled: true))) + ..show(context); + } + + // 获取原生的值 + invokeNativeMethod(String method, Map map) async { + dynamic args; + try { + args = await Global.method.invokeMethod(method, map); + } on PlatformException catch (e) {} + } +} diff --git a/lib/tools/home/home_model.dart b/lib/tools/home/home_model.dart new file mode 100644 index 0000000..02d919a --- /dev/null +++ b/lib/tools/home/home_model.dart @@ -0,0 +1,147 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:aiplot/bean/login_bean.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/network/RequestCenter.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../bean/levitating_ball_pop_bean.dart'; +import '../../bean/popout_bean.dart'; +import '../../bean/user_bean.dart'; +import '../../network/BaseEntity.dart'; + +class HomeModel { + StreamController streamController = StreamController.broadcast(); + + HomeModel() { + setup(); + } + + void setup() { + //初始化 + } + + //登录 + /// loginType 0 普通用户名密码登录 1 手机 2 邮箱 3 微信 4 QQ 5 钉钉 6 谷歌 7 苹果 100 游客 + /// phoneNum 手机号 | userName + /// password 密码(没有传"") + /// VerificationCode 验证码(verCode) + /// LoginInfos 第三方登录(token) + /// + Future userLogin(int loginType, String phoneNum, String password, String verCode, String token) async { + RequestCenter.instance.requestPlay(NetworkConfig.userLogin, { + "LoginType": loginType, + "UserName": phoneNum, + "Password": password, + "VerificationCode": verCode, + "LoginInfos": token, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + LoginBean data = LoginBean.fromJson(json); + + NetworkConfig.userId = data.UserId.toString(); + NetworkConfig.userName = data.UserName.toString(); + if (data.Token != null && data.Token != "") { + NetworkConfig.token = data.Token.toString(); + NetworkConfig.userToken = data.Token?.split('.')[2] as String; + } + + UserBean userBean = UserBean(NetworkConfig.userId, NetworkConfig.token, NetworkConfig.userToken); + setUser(userBean); + + streamController.sink.add({ + 'code': "login", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //新用户弹框 + Future getNewUserPackage() async { + RequestCenter.instance.requestPlay(NetworkConfig.getNewUserPackage, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + LevitatingBallPopBean data = LevitatingBallPopBean.fromJson(json); + streamController.sink.add({ + 'code': "getNewUserPackage", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } + + //观看广告 + Future lookAdReward() async { + RequestCenter.instance.requestPlay(NetworkConfig.lookAdReward, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "lookAdReward", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } + + //弹框 + Future getPopoutList() async { + RequestCenter.instance.requestPlay(NetworkConfig.getPopoutList, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => PopoutBean.fromJson(e as Map)).toList(); + streamController.sink.add({ + 'code': "getPopoutList", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } + + + //保存用户登录验签 + setUser(UserBean bean) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setString("UserBean", jsonEncode(bean.toJson())); + } +} diff --git a/lib/tools/home/home_page.dart b/lib/tools/home/home_page.dart new file mode 100644 index 0000000..707f257 --- /dev/null +++ b/lib/tools/home/home_page.dart @@ -0,0 +1,420 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:aiplot/common/func.dart'; +import 'package:aiplot/dialog/login_dialog.dart'; +import 'package:aiplot/dialog/phone_login_dialog.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/tools/me/me_page.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:ironsource_mediation/ironsource_mediation.dart'; +import 'package:sensors_analytics_flutter_plugin/sensors_analytics_flutter_plugin.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../../bean/levitating_ball_pop_bean.dart'; +import '../../bean/popout_bean.dart'; +import '../../common/EventBusUtil.dart'; +import '../../common/Global.dart'; +import '../../common/dialog_bean.dart'; +import '../../common/dialog_manager.dart'; +import '../../common/dialog_util.dart'; +import '../../dialog/newDialog.dart'; +import '../../dialog/new_ball_dialog.dart'; +import '../../generated/l10n.dart'; +import '../create/create_page.dart'; +import '../gallery/gallery_content_page.dart'; +import '../upload/upload_page.dart'; +import 'home_model.dart'; + +class HomePage extends StatefulWidget { + const HomePage({Key? key}) : super(key: key); + + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State with IronSourceRewardedVideoListener { + StreamSubscription? subscription; + final HomeModel _viewModel = HomeModel(); + + //创建StreamController + StreamController? streamController; + + // 获取StreamSink用于发射事件 + StreamSink? get streamSink => streamController?.sink; + + // 获取Stream用于监听 + Stream? get streamData => streamController?.stream; + + int currentIndex = 0; + late List items; + late List bodyList; + late PageController pageController; // + + GlobalKey loginDialogKey = GlobalKey(); //登录弹框key + + AssetImage galleryImg = const AssetImage('assets/images/gallery.png'); + AssetImage galleryImgS = const AssetImage('assets/images/gallery_r.png'); + AssetImage createImg = const AssetImage('assets/images/create.png'); + AssetImage createImgS = const AssetImage('assets/images/create_r.png'); + AssetImage meImg = const AssetImage('assets/images/me.png'); + AssetImage meImgS = const AssetImage('assets/images/me_r.png'); + + AssetImage createImg1 = const AssetImage('assets/images/jia.png'); + AssetImage createImgS1 = const AssetImage('assets/images/jia_w.png'); + + late StreamSubscription _phoneLoginBackEvent; + late StreamSubscription _tabBarJumpEvent; + late StreamSubscription _loginSuccess; + + late LevitatingBallPopBean levitatingBallPopBean; + List popList = []; + + @override + void initState() { + // TODO: implement initState + super.initState(); + IronSource.setRVListener(this); + streamController = StreamController(); + pageController = PageController(initialPage: NetworkConfig.appConfigBean != null && !NetworkConfig.appConfigBean!.IsCheckRemark! ? 1 : 0); + NetworkConfig.appConfigBean != null && !NetworkConfig.appConfigBean!.IsCheckRemark! ? streamSink!.add(1) : streamSink!.add(0); + + ///eventBus + //手机登录返回 + _phoneLoginBackEvent = EventBusUtil.listen((event) { + showLoginDialog(); + }); + + //导航跳转 + _tabBarJumpEvent = EventBusUtil.listen((event) { + if (currentIndex != event.index) { + pageController.animateToPage( + event.index, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + }); + + //登录完成 + _loginSuccess = EventBusUtil.listen((event) { + //新用户弹框 + _viewModel.getNewUserPackage(); + }); + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + switch (code) { + case "getNewUserPackage": //新用户弹框 + levitatingBallPopBean = newData['data']; + if (levitatingBallPopBean.BgPicInfo != null) { + DialogManager() + ..add(DialogBean( + createDialogWidget: () => DialogUtil.createTipWidget( + context, + NewBallDialog( + onTap: () { + EventBusUtil.fire(RefreshUserdata()); + }, + popoutBean: levitatingBallPopBean, + ), + "NewBallDialog", + canceled: false))) + ..show(context); + } + break; + case "lookAdReward": //看完广告 + Fluttertoast.showToast( + msg: newData['data'], + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.CENTER, + timeInSecForIosWeb: 1, + backgroundColor: Colors.black, + textColor: Colors.white, + fontSize: 16.0); + EventBusUtil.fire(RefreshUserdata()); + break; + case "getPopoutList": + popList = newData['data']; + if (popList.length > 0) { + for (int i = 0; i < popList.length; i++) { + DialogManager() + ..add(DialogBean( + createDialogWidget: () => DialogUtil.createTipWidget( + context, + newDialog( + onTap: (PopoutId, PopoutType, text) { + // ObtainPopoutAwards(PopoutId, PopoutType, text); + _xy(text); + }, + popoutBean: popList[i], + ), + "Popout" + i.toString(), + canceled: false))) + ..show(context); + } + } + break; + } + } + setState(() {}); + }); + _viewModel.getNewUserPackage(); + _viewModel.getPopoutList(); + _firstFiring(); + } + + //判断首次启动 + _firstFiring() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + bool boolValue = prefs.getBool('firstFiring') ?? false; + if (!boolValue) { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setBool('firstFiring', true); + SensorsAnalyticsFlutterPlugin.track('Device_activation', {'IsDefaultTourist': 0, 'WUID': NetworkConfig.deviceID}); + } + } + + @override + Widget build(BuildContext context) { + bottomItem(); + return WillPopScope( + onWillPop: doubleClickBack, + child: Scaffold( + backgroundColor: Colors.white, + bottomNavigationBar: StreamBuilder( + stream: streamData, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.data != null) { + currentIndex = snapshot.data; + return BottomNavigationBar( + items: items, + elevation: 0, + backgroundColor: Colors.white, + currentIndex: snapshot.data, + onTap: onTap, + selectedItemColor: Color(0xFFAF78E3), + unselectedItemColor: Color(0xFF818181), + selectedFontSize: 12, + unselectedFontSize: 12, + type: BottomNavigationBarType.fixed, + ); + } else { + return Container(); + } + }, + ), + body: Stack( + children: [ + PageView( + controller: pageController, + onPageChanged: onPageChanged, + children: bodyList, + physics: NeverScrollableScrollPhysics(), + ) + ], + ), + ), + ); + } + + ///底部导航 + bottomItem() { + items = [ + BottomNavigationBarItem( + icon: Image( + width: 34, + height: 34, + image: galleryImg, + ), + activeIcon: Image( + width: 34, + height: 34, + image: galleryImgS, + ), + label: S.of(context).Gallery), + BottomNavigationBarItem( + icon: Image( + width: 34, + height: 34, + image: !NetworkConfig.appConfigBean!.IsCheckRemark! ? createImg : createImg1, + ), + activeIcon: Image( + width: 34, + height: 34, + image: !NetworkConfig.appConfigBean!.IsCheckRemark! ? createImgS : createImgS1, + ), + label: !NetworkConfig.appConfigBean!.IsCheckRemark! ? S.of(context).Creation : S.of(context).Upload), + BottomNavigationBarItem( + icon: Image( + width: 34, + height: 34, + image: meImg, + ), + activeIcon: Image( + width: 34, + height: 34, + image: meImgS, + ), + label: S.of(context).Me), + ]; + bodyList = [ + GalleryContentPage(), + !NetworkConfig.appConfigBean!.IsCheckRemark! ? const CreatePage() : const UploadPage(), + const MePage(), + ]; + } + + void onTap(int index) { + if (index > 1 && NetworkConfig.userId == "") { + showLoginDialog(); + } else { + EventBusUtil.fire(TabBarEvent(index)); + pageController.animateToPage( + index, + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + } + + void onPageChanged(int index) { + streamSink!.add(index); + } + + //弹出登录 + showLoginDialog() { + DialogManager() + ..add(DialogBean( + dialogPriority: DialogPriority.highClear, + createDialogWidget: () => DialogUtil.createTipWidget( + context, + LoginDialog( + loginDialogKey, + onTap: (index) { + switch (index) { + case 0: + if (loginDialogKey.currentState != null) { + loginDialogKey.currentState!.Pop(); + } + FunctionUtil.bottomSheetDialog(context, PhoneLoginDialog()); + break; + case 1: //谷歌登录 + Map map = {"googleLogin": "googleLogin"}; + invokeNativeMethod("googleLogin", map); + break; + } + }, + ), + "LoginDialog", + canceled: true))) + ..show(context); + } + + // 获取原生的值 + invokeNativeMethod(String method, Map map) async { + dynamic args; + try { + args = await Global.method.invokeMethod(method, map); + } on PlatformException catch (e) {} + } + + int last = 0; + + //双击退出 + Future doubleClickBack() async { + int now = DateTime.now().millisecondsSinceEpoch; + // if (currentIndex != 0) { + // EventBusUtil.fire(TabBarEvent(0)); + // } else { + if (now - last > 2500) { + last = DateTime.now().millisecondsSinceEpoch; + EasyLoading.showToast("${S.of(context).Press_again}HissAi"); + return Future.value(false); + } else { + exit(0); + } + // } + } + + Future _xy(String AppUrl) async { + String url = AppUrl; + if (await canLaunch(url)) { + await launch(url); + } else { + throw 'Could not launch $url'; + } + } + + @override + void dispose() { + // TODO: implement dispose + streamController?.close(); + subscription?.cancel(); + _phoneLoginBackEvent?.cancel(); + _tabBarJumpEvent?.cancel(); + _loginSuccess?.cancel(); + pageController.dispose(); + super.dispose(); + } + + ///单击视频广告时调用。 + ///-点击广告的奖励数据作为【放置】进行传递。 + @override + void onRewardedVideoAdClicked(IronSourceRVPlacement placement) { + // TODO: implement onRewardedVideoAdClicked + } + + ///当RewardedVideo广告视图即将关闭时调用。 + @override + void onRewardedVideoAdClosed() { + // TODO: implement onRewardedVideoAdClosed + _viewModel.lookAdReward(); + } + + ///当视频广告播放完毕时调用。 + @override + void onRewardedVideoAdEnded() { + // TODO: implement onRewardedVideoAdEnded + } + + ///打开 + @override + void onRewardedVideoAdOpened() {} + + ///当用户完成视频并应获得奖励时调用。 + ///-【放置】包含奖励数据。 + ///-如果您正在使用服务器对服务器的奖励回调, + ///您可以忽略此事件并等待ironSource服务器的回调。 + @override + void onRewardedVideoAdRewarded(IronSourceRVPlacement placement) { + debugPrint("完成"); + } + + ///当“奖励视频”无法显示时调用。 + ///-您可以通过检查[error]来了解原因 + @override + void onRewardedVideoAdShowFailed(IronSourceError error) { + // TODO: implement onRewardedVideoAdShowFailed + debugPrint("$error"); + } + + ///当视频广告开始播放时调用。 + @override + void onRewardedVideoAdStarted() { + // TODO: implement onRewardedVideoAdStarted + } + + @override + void onRewardedVideoAvailabilityChanged(bool isAvailable) { + ///广告是否可用 + NetworkConfig.isAdAvailable = isAvailable; + } +} diff --git a/lib/tools/me/about_page.dart b/lib/tools/me/about_page.dart new file mode 100644 index 0000000..6dfaad1 --- /dev/null +++ b/lib/tools/me/about_page.dart @@ -0,0 +1,68 @@ + +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:flutter/material.dart'; + +import '../../generated/l10n.dart'; + +class AboutPage extends StatefulWidget { + const AboutPage({Key? key}) : super(key: key); + + @override + State createState() => _AboutPageState(); +} + +class _AboutPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + title: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only(right: 10), + child: Image( + width: 23, + height: 23, + image: AssetImage('assets/images/ic_title.png'), + ), + ), + Text( + S.of(context).About, + style: TextStyle(color: Colors.black, fontSize: 20), + ), + ], + ), + centerTitle: true, + leading: IconButton( + icon: ImageIcon(AssetImage('assets/images/ic_return.png')), + color: Colors.black, + onPressed: () { + Navigator.pop(context); + }), + ), + body: Stack( + alignment: Alignment.center, + children: [ + Positioned( + top: 20, + child: Container( + child: Image( + width: 60, + image: AssetImage('assets/images/ic_title.png'), + ), + ), + ), + Positioned( + top: 120, + child: Container( + child: Text("Version${NetworkConfig.Version}"), + ), + ), + ], + ), + ); + } +} diff --git a/lib/tools/me/feedback_model.dart b/lib/tools/me/feedback_model.dart new file mode 100644 index 0000000..510f610 --- /dev/null +++ b/lib/tools/me/feedback_model.dart @@ -0,0 +1,43 @@ +import 'dart:async'; + +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/network/RequestCenter.dart'; + +import '../../network/BaseEntity.dart'; + +class BeedbackModel { + StreamController streamController = StreamController.broadcast(); + + BeedbackModel() { + setup(); + } + + void setup() { + //初始化 + } + + //反馈 + Future submitUserFeedback(String description, String contactInfo) async { + RequestCenter.instance.requestPlay(NetworkConfig.submitUserFeedback, { + "description": description, + "contactInfo": contactInfo, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "submitUserFeedback", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.message, + }); + }); + } +} diff --git a/lib/tools/me/feedback_page.dart b/lib/tools/me/feedback_page.dart new file mode 100644 index 0000000..70785bf --- /dev/null +++ b/lib/tools/me/feedback_page.dart @@ -0,0 +1,215 @@ + +import 'dart:async'; + +import 'package:aiplot/tools/me/feedback_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +import '../../generated/l10n.dart'; + +class FeedbackPage extends StatefulWidget { + const FeedbackPage({Key? key}) : super(key: key); + + @override + State createState() => _FeedbackPageState(); +} + +class _FeedbackPageState extends State { + StreamSubscription? subscription; + final BeedbackModel _viewModel = BeedbackModel(); + + //反馈内容 + String feedbackText = ""; + + void _textFieldChanged(String str) { + feedbackText = str; + setState(() {}); + } + + //联系内容 + String contactText = ""; + + void _textContactChanged(String str) { + contactText = str; + setState(() {}); + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + if (code == "submitUserFeedback") { + EasyLoading.showToast(newData['data']); + Navigator.pop(context); + } + } + setState(() {}); + }); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final w301 = size.width / 1.1960132890365; + final h45 = size.width / 8; + final t188 = size.width / 1.9148936170212; + + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 1, + title: Container( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only(right: 10), + child: const Image( + width: 23, + height: 23, + image: AssetImage('assets/images/ic_title.png'), + ), + ), + Text( + S.of(context).Feedback, + style: const TextStyle(color: Colors.black, fontSize: 20), + ), + ], + ), + ), + leading: IconButton( + icon: const ImageIcon(AssetImage('assets/images/ic_return.png')), + color: Colors.black, + onPressed: () { + Navigator.pop(context); + }), + centerTitle: true, + ), + body: SingleChildScrollView( + child: Stack( + children: [ + Column( + children: [ + Container( + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(left: 15, top: 17), + child: Text( + S.of(context).problems_encountered, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + ), + + ///反馈内容 + Container( + alignment: Alignment.center, + margin: const EdgeInsets.only(top: 13, left: 15, right: 15), + padding: const EdgeInsets.only(left: 9, top: 13, right: 9), + decoration: const BoxDecoration( + //背景 + color: Color(0xFFF3F3FB), + //设置四周圆角 角度 + borderRadius: BorderRadius.all(Radius.circular(6.6)), + //设置四周边框 + ), + child: TextField( + keyboardType: TextInputType.name, + decoration: InputDecoration.collapsed( + hintText: S.of(context).Please_describe, hintStyle: const TextStyle(fontSize: 16.0, color: Color(0xFFB5B5B5))), + textAlign: TextAlign.left, + //文本对齐方式 + //最大长度,设置此项会让TextField右下角有一个输入数量的统计字符串 + maxLines: 7, + //最大行数 + style: const TextStyle(fontSize: 16.0, color: Colors.black), + //输入文本的样式 + onChanged: _textFieldChanged, + autofocus: false, + maxLength: 500, + ), + ), + Container( + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(left: 15, top: 17), + child: Text( + S.of(context).Contact_information, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + ), + + ///联系方式 + Container( + alignment: Alignment.center, + margin: const EdgeInsets.only(top: 13, left: 15, right: 15), + padding: const EdgeInsets.only(left: 9, top: 13, right: 9, bottom: 9), + decoration: const BoxDecoration( + //背景 + color: Color(0xFFF3F3FB), + //设置四周圆角 角度 + borderRadius: BorderRadius.all(Radius.circular(6.6)), + //设置四周边框 + ), + child: TextField( + keyboardType: TextInputType.name, + decoration: InputDecoration.collapsed( + hintText: S.of(context).Please_enter, hintStyle: const TextStyle(fontSize: 16.0, color: Color(0xFFB5B5B5))), + textAlign: TextAlign.left, + //文本对齐方式 + //最大长度,设置此项会让TextField右下角有一个输入数量的统计字符串 + maxLines: 1, + //最大行数 + style: const TextStyle(fontSize: 16.0, color: Colors.black), + //输入文本的样式 + onChanged: _textContactChanged, + autofocus: false, + ), + ), + + ///提交 + GestureDetector( + onTap: () { + if (feedbackText != "" && contactText != "") { + _viewModel.submitUserFeedback(feedbackText, contactText); + } + }, + child: Container( + width: w301, + height: h45, + alignment: Alignment.center, + margin: EdgeInsets.only(top: t188), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [ + feedbackText != "" && contactText != "" ? Color(0xFF843FFF) : Color(0xFFB4B4B4), + feedbackText != "" && contactText != "" ? Color(0xFFF87DFF) : Color(0xFFB4B4B4) + ]), + borderRadius: BorderRadius.all(Radius.circular(25))), + child: Text( + S.of(context).Submit, + style: const TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ) + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/tools/me/me_info_model.dart b/lib/tools/me/me_info_model.dart new file mode 100644 index 0000000..01f13d5 --- /dev/null +++ b/lib/tools/me/me_info_model.dart @@ -0,0 +1,100 @@ +import 'dart:async'; + +import 'package:aiplot/bean/user_info_bean.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/network/RequestCenter.dart'; + +import '../../bean/equity_bean.dart'; +import '../../network/BaseEntity.dart'; + +class MeInfoModel { + StreamController streamController = StreamController.broadcast(); + + MeInfoModel() { + setup(); + } + + void setup() { + //初始化 + } + + //获取用户信息 + Future getUserData() async { + RequestCenter.instance.requestPlay(NetworkConfig.getUserData, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + UserInfoBean data = UserInfoBean.fromJson(json); + NetworkConfig.userData = data; + double num = data.AllCurrency!; + NetworkConfig.allCurrency = num.truncate().toString(); + NetworkConfig.currency = num; + NetworkConfig.saveImageNumber = data.SaveImageNumber.toString(); + NetworkConfig.usedRewardCount = data.UserAdLog!.UsedRewardCount; + NetworkConfig.totalRewardCount = data.UserAdLog!.TotalRewardCount; + NetworkConfig.invitationCode = data.InvitationCode; + + streamController.sink.add({ + 'code': "getUserData", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //填写邀请码 + Future fillInInvitationCode(String invitationCode) async { + RequestCenter.instance.requestPlay(NetworkConfig.fillInInvitationCode, {"invitationCode": invitationCode}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "fillInInvitationCode", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "invitationCodeError", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //审核下获取权益 + Future getQuanYi() async { + RequestCenter.instance.requestPlay(NetworkConfig.getQuanYi, {}, (BaseEntity dataEntity) { + Map json = dataEntity.data; + EquityBean data = EquityBean.fromJson(json); + + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "getQuanYi", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "invitationCodeError", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } +} diff --git a/lib/tools/me/me_model.dart b/lib/tools/me/me_model.dart new file mode 100644 index 0000000..a5c5c7d --- /dev/null +++ b/lib/tools/me/me_model.dart @@ -0,0 +1,89 @@ +import 'dart:async'; + +import 'package:aiplot/bean/user_draw_bean.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/network/RequestCenter.dart'; + +import '../../network/BaseEntity.dart'; + +class MeModel { + StreamController streamController = StreamController.broadcast(); + + MeModel() { + setup(); + } + + void setup() { + //初始化 + } + + //我的作品 + Future getUserDrawList() async { + RequestCenter.instance.requestPlay(NetworkConfig.getUserDrawList, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => UserDrawBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "getUserDrawList", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //我的收藏 + Future getMyFavoriteList() async { + RequestCenter.instance.requestPlay(NetworkConfig.getMyFavoriteList, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => UserDrawBean.fromJson(e as Map)).toList(); + + streamController.sink.add({ + 'code': "getMyFavoriteList", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //删除 + Future delMyDrawCollect(String drawId) async { + RequestCenter.instance.requestPlay(NetworkConfig.delMyDrawCollect, {"DrawIds": drawId}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "delMyDrawCollect", //有数据 + 'data': dataEntity.message, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.message, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } +} diff --git a/lib/tools/me/me_page.dart b/lib/tools/me/me_page.dart new file mode 100644 index 0000000..55c0d62 --- /dev/null +++ b/lib/tools/me/me_page.dart @@ -0,0 +1,483 @@ +import 'dart:async'; + +import 'package:aiplot/bean/user_info_bean.dart'; +import 'package:aiplot/tools/me/my_collect_page.dart'; +import 'package:aiplot/tools/me/my_works_page.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:ironsource_mediation/ironsource_mediation.dart'; + +import '../../bean/equity_bean.dart'; +import '../../common/EventBusUtil.dart'; +import '../../common/TabUnderLine.dart'; +import '../../common/func.dart'; +import '../../dialog/invitation_code_dialog.dart'; +import '../../dialog/obtaining_benefits_dialog.dart'; +import '../../generated/l10n.dart'; +import '../../network/NetworkConfig.dart'; +import 'me_info_model.dart'; + +///我的 +class MePage extends StatefulWidget { + const MePage({Key? key}) : super(key: key); + + @override + State createState() => _MePageState(); +} + +class _MePageState extends State with SingleTickerProviderStateMixin { + StreamSubscription? subscription; + final MeInfoModel _viewModel = MeInfoModel(); + + TabController? _tabController; + PageController? _pageController; + List? tabView; //包含内容必须和tab对应 + final ScrollController _scrollController = ScrollController(); + StreamSubscription? _refreshUserdata; + + UserInfoBean? userInfoBean; + EquityBean? equityBean; + + @override + void initState() { + // TODO: implement initState + super.initState(); + + //我的作品 收藏 + tabView = [const MyWorksPage(), const MyCollectPage()]; + _tabController = TabController(initialIndex: 0, length: 2, vsync: this); + _pageController = PageController(); + + ///eventbus + _refreshUserdata = EventBusUtil.listen((event) { + getUserInfo(); + }); + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + switch (code) { + case "getUserData": + userInfoBean = newData['data']; + break; + case "getQuanYi": + equityBean = newData['data']; + break; + } + } + setState(() {}); + }); + getUserInfo(); + } + + //用户信息 + getUserInfo() { + EasyLoading.show(status: 'loading...', maskType: EasyLoadingMaskType.black); + _viewModel.getUserData(); + _viewModel.getQuanYi(); + } + + @override + void dispose() { + // TODO: implement dispose + _tabController?.dispose(); + _pageController?.dispose(); + _refreshUserdata?.cancel(); + subscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final h270 = size.width / 1.333333333; + final t70 = size.width / 5.1428571428571; + final w60 = size.width / 6; + final l85 = size.width / 4.235294117647; + final t35 = size.width / 10.285714285714; + final h340 = size.width / 1.0588235294117; + final t40 = size.width / 9; + final w90 = size.width / 4; + final h45 = size.width / 8; + final w150 = size.width / 2.4; + final h140 = size.width / 2.5714285714285; + final h60 = size.width / 6; + final h80 = size.width / 4.5; + + return Scaffold( + backgroundColor: Colors.white, + body: NestedScrollView( + controller: _scrollController, + headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar( + backgroundColor: Colors.white, + elevation: 0, + centerTitle: true, + actions: [ + ///邀请码 + Container( + alignment: Alignment.center, + child: GestureDetector( + onTap: () { + FunctionUtil.popDialog(context, InvitationCodeDialog()); + }, + child: Container( + padding: const EdgeInsets.all(6), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), + borderRadius: BorderRadius.all(Radius.circular(20))), + child: Text( + S.of(context).Invitation_code, + style: TextStyle(color: Colors.white, fontSize: 10), + )), + ), + ), + + ///设置 + Container( + padding: EdgeInsets.zero, + child: IconButton( + icon: const Image( + width: 20, + height: 20, + image: AssetImage('assets/images/ic_setting.png'), + ), + onPressed: () { + Navigator.pushNamed(context, "/SettingPage"); + }), + ), + ], + expandedHeight: NetworkConfig.appConfigBean != null && !NetworkConfig.appConfigBean!.IsCheckRemark! ? h340 : h140, + flexibleSpace: FlexibleSpaceBar( + background: Column( + children: [ + ///用户信息 + Container( + margin: EdgeInsets.only(top: w60), + width: double.infinity, + height: t70, + child: Stack( + children: [ + //头像 + Positioned( + left: 15, + child: userInfoBean != null && userInfoBean!.UserIconUrl != null + ? CachedNetworkImage( + fit: BoxFit.fitHeight, + width: w60, + height: w60, + imageUrl: userInfoBean!.UserIconUrl!, + errorWidget: (context, url, error) => Image( + fit: BoxFit.fitWidth, + width: w60, + height: w60, + image: const AssetImage('assets/images/head.png'), + ), + ) + : Container(), + ), + //昵称 + userInfoBean != null + ? Positioned( + left: l85, + top: 5, + child: SizedBox( + width: w150, + child: Text( + userInfoBean!.NickName!, + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500), + ), + ), + ) + : Container(height: 1), + + ///点数 + Positioned( + left: l85, + top: t35, + child: Row( + children: [ + Text( + S.of(context).Painting_point, + style: const TextStyle(color: Color(0xFF999999), fontSize: 12), + ), + Container( + margin: const EdgeInsets.only(left: 5), + child: const Image( + width: 16, + height: 16, + image: AssetImage('assets/images/ic_count.png'), + ), + ), + Container( + margin: const EdgeInsets.only(left: 5), + child: Text( + NetworkConfig.allCurrency, + style: const TextStyle(color: Color(0xFF8841FF)), + ), + ), + Container( + margin: const EdgeInsets.only(left: 17), + child: Text( + S.of(context).Collected, + style: const TextStyle(color: Color(0xFF999999), fontSize: 12), + ), + ), + userInfoBean != null && userInfoBean!.CollectNumber != null + ? Container( + margin: const EdgeInsets.only(left: 10), + child: Text( + userInfoBean!.CollectNumber.toString(), + style: const TextStyle(color: Color(0xFF999999), fontSize: 12), + ), + ) + : Container(), + ], + ), + ), + + ///审核 获取权益 + NetworkConfig.appConfigBean?.IsShowUserPageEquityBtn != null && NetworkConfig.appConfigBean!.IsShowUserPageEquityBtn! + ? Positioned( + top: 10, + right: 16, + child: GestureDetector( + onTap: () { + FunctionUtil.popDialog( + context, + ObtainingBenefitsDialog( + onTap: (index) { + switch (index) { + case 0: //看广告 + if (NetworkConfig.isAdAvailable) { + IronSource.showRewardedVideo(); + } else { + EasyLoading.showToast(S.of(context).no_advertisements); + } + break; + + case 1: //购买 + break; + } + }, + equityBean: equityBean, + )); + }, + child: Container( + width: w90, + height: t40, + alignment: Alignment.center, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF843FFF), Color(0xFFEB76FF)])), + child: Text( + S.of(context).obtaining_benefits, + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ), + )) + : Container() + ], + ), + ), + + ///商城 + NetworkConfig.appConfigBean != null && + !NetworkConfig.appConfigBean!.IsCheckRemark! && + NetworkConfig.appConfigBean?.MallInletImage != null + ? Align( + child: GestureDetector( + onTap: () { + Navigator.pushNamed(context, "/ShopPage"); + }, + child: Container( + margin: const EdgeInsets.only(left: 15, right: 15), + child: CachedNetworkImage(height: h80, imageUrl: NetworkConfig.appConfigBean!.MallInletImage!), + ), + ), + ) + : Container(), + + NetworkConfig.appConfigBean != null && + !NetworkConfig.appConfigBean!.IsCheckRemark! && + userInfoBean != null && + userInfoBean!.UserAdLog != null && + userInfoBean!.UserAdLog!.UsedRewardCount != null && + userInfoBean!.UserAdLog!.TotalRewardCount != null + ? Container( + height: h140, + decoration: const BoxDecoration( + color: Color(0xFFF8F8FF), + borderRadius: BorderRadius.all(Radius.circular(7)), + ), + margin: const EdgeInsets.only(left: 15, right: 15, top: 5), + child: Column( + children: [ + ///看广告 + GestureDetector( + onTap: () { + if (userInfoBean!.UserAdLog!.UsedRewardCount != userInfoBean!.UserAdLog!.TotalRewardCount) { + if (NetworkConfig.isAdAvailable) { + IronSource.showRewardedVideo(); + } else { + EasyLoading.showToast(S.of(context).no_advertisements); + } + } else { + EasyLoading.showToast(S.of(context).received_all); + } + }, + child: Container( + height: h60, + child: Stack( + children: [ + Positioned( + top: 20, + left: 10, + child: Text( + "${S.of(context).Watch_the} (${userInfoBean!.UserAdLog!.UsedRewardCount}/${userInfoBean!.UserAdLog!.TotalRewardCount})", + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + ), + ), + Positioned( + top: t40, + left: 10, + child: Text( + S.of(context).Earn_paint, + style: TextStyle(fontSize: 12, color: Color(0xFF999999)), + ), + ), + Positioned( + right: 7, + top: 18, + child: Stack( + alignment: Alignment.center, + children: [ + Image(width: w90, height: h45, image: AssetImage('assets/images/view_ad.png')), + Positioned( + top: 10, + child: Text( + S.of(context).Watch, + style: TextStyle(fontSize: 14, color: Colors.white), + )) + ], + )) + ], + ), + ), + ), + + Container( + height: 1, + width: size.width, + color: Color(0xFFEAEAEA), + margin: EdgeInsets.only(top: 10, left: 15, right: 15), + ), + + ///去创作 + GestureDetector( + onTap: () { + EventBusUtil.fire(TabBarJumpEvent(1)); + }, + child: SizedBox( + height: h60, + child: Stack( + children: [ + Positioned( + top: 20, + left: 10, + child: Text( + S.of(context).Upload_artwork_gallery, + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + ), + ), + Positioned( + top: t40, + left: 10, + child: Text( + "${S.of(context).Obtained_after_review} ${NetworkConfig.appConfigBean!.SharingRewards} ${S.of(context).Painting_points}", + style: const TextStyle(fontSize: 12, color: Color(0xFF999999)), + ), + ), + Positioned( + right: 7, + top: 18, + child: Stack( + alignment: Alignment.center, + children: [ + Image(width: w90, height: h45, image: const AssetImage('assets/images/view_ad.png')), + Positioned( + top: 10, + child: Text( + S.of(context).To_create, + style: const TextStyle(fontSize: 14, color: Colors.white), + )) + ], + )) + ], + ), + ), + ) + ], + ), + ) + : Container(), + ], + ), + ), + ), + ) + ]; + }, + body: Column( + children: [ + ///作品/收藏 + Container( + height: 30, + width: size.width, + margin: EdgeInsets.only(top: NetworkConfig.statusHeight + 0.1), + child: TabBar( + tabs: [ + Text(S.of(context).My_Works), + Text(S.of(context).Collection), + ], + controller: _tabController, + indicator: const RoundUnderlineTabIndicator(borderSide: BorderSide(width: 2, color: Color(0xFF8841FF))), + labelColor: const Color(0xFF8841FF), + //设置选中时的字体颜色,tabs里面的字体样式优先级最高 + labelStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w700), + unselectedLabelColor: const Color(0xFF666666), + //设置未选中时的字体颜色,tabs里面的字体样式优先级最高 + unselectedLabelStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w700), + onTap: (int index) { + _pageController!.jumpToPage(index); + }, + ), + ), + Expanded( + child: PageView( + controller: _pageController, + children: tabView!, + onPageChanged: (index) { + _tabController!.animateTo(index); + }, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/tools/me/my_collect_page.dart b/lib/tools/me/my_collect_page.dart new file mode 100644 index 0000000..c664a0b --- /dev/null +++ b/lib/tools/me/my_collect_page.dart @@ -0,0 +1,233 @@ + +import 'dart:async'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; + +import '../../bean/user_draw_bean.dart'; +import '../../generated/l10n.dart'; +import '../drawdetails/draw_details_page.dart'; +import 'me_model.dart'; +import 'screen_tips.dart'; + +///收藏 +class MyCollectPage extends StatefulWidget { + const MyCollectPage({Key? key}) : super(key: key); + + @override + State createState() => _MyCollectPageState(); +} + +class _MyCollectPageState extends State { + StreamSubscription? subscription; + final MeModel _viewModel = MeModel(); + List list = []; + int sortType = 0; //排序类型 + + @override + void initState() { + // TODO: implement initState + super.initState(); + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + if (code == "getMyFavoriteList") { + list = newData['data']; + for (var value in list) { + value.IsCheck = false; + } + list.sort((a, b) => b.FavoriteDateTime!.compareTo(a.FavoriteDateTime!)); + } + } + setState(() {}); + }); + EasyLoading.show(status: 'loading...'); + _viewModel.getMyFavoriteList(); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + subscription?.cancel(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Scaffold( + backgroundColor: Colors.white, + body: Stack( + children: [ + Column( + children: [ + list.isNotEmpty + ? Container( + height: 20, + alignment: Alignment.centerLeft, + margin: const EdgeInsets.only(top: 30), + child: Stack( + children: [ + ///收藏数量 + Positioned( + left: 15, + child: Text( + '${S.of(context).Number_collections}:${list.length}', + style: const TextStyle(color: Colors.black, fontSize: 12), + ), + ), + + ///排序 + Positioned( + right: 15, + child: GestureDetector( + onTapDown: (details) { + ///排序弹框 + showDialog( + context: context, + builder: (BuildContext ctx) => ScreenTips( + index: sortType, + dx: details.globalPosition.dx, + dy: details.globalPosition.dy, + type: 1, + onTap: (index) { + sortType = index; + if (sortType == 0) { + list.sort((a, b) => b.FavoriteDateTime!.compareTo(a.FavoriteDateTime!)); + } else if (sortType == 1) { + list.sort((a, b) => a.FavoriteDateTime!.compareTo(b.FavoriteDateTime!)); + } + setState(() {}); + }, + )); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Image(width: 13, height: 13, image: AssetImage('assets/images/ic_sort.png')), + Container( + margin: const EdgeInsets.only(left: 4), + child: Text( + S.of(context).Sort_by, + style: const TextStyle(color: Color(0xFF666666), fontSize: 12), + ), + ), + ], + ), + ), + ), + ], + ), + ) + : Container(), + + ///收藏列表 + list != null && list.isNotEmpty + ? Expanded( + child: Container( + margin: const EdgeInsets.only(left: 15, right: 15), + child: SingleChildScrollView( + child: MasonryGridView.count( + padding: const EdgeInsets.only(left: 0, right: 0, top: 10), + crossAxisCount: 2, + itemCount: list.length, + itemBuilder: (BuildContext context, int index) { + return _item(list[index], index); + }, + // 纵向元素间距 + mainAxisSpacing: 10, + // 横向元素间距 + crossAxisSpacing: 10, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + ), + ), + ), + ) + : Expanded( + child: Container( + alignment: Alignment.center, + child: const Image( + width: 150, + image: AssetImage('assets/images/ic_no_collect.png'), + ), + ), + ), + ], + ), + ], + )); + } + + _item(UserDrawBean bean, int index) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DrawDetailsPage( + false, + drawId: bean.DrawId.toString(), + isMyWork: false, + status: 3, + ))); + }, + child: Stack( + children: [ + Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(7), + child: CachedNetworkImage(imageUrl: bean.ImageUrl!, errorWidget: (context, url, error) => Icon(Icons.error)), + ), + SizedBox( + height: 40, + width: double.infinity, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned( + left: 0, + child: SizedBox( + width: 100, + child: Text( + bean.Title!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Colors.black), + ), + ), + ), + Positioned( + right: 10, + child: Row( + children: [ + const Image( + width: 13, + height: 12, + image: AssetImage('assets/images/ic_collect_s.png'), + ), + Container( + margin: const EdgeInsets.only(left: 5), + child: Text( + bean.CollectNumber.toString(), + style: const TextStyle(color: Color(0xFFBB72E0), fontSize: 12), + ), + ) + ], + ), + ), + ], + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/tools/me/my_works_page.dart b/lib/tools/me/my_works_page.dart new file mode 100644 index 0000000..10d0ba2 --- /dev/null +++ b/lib/tools/me/my_works_page.dart @@ -0,0 +1,420 @@ + +import 'dart:async'; +import 'dart:convert'; + +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; + +import '../../bean/user_draw_bean.dart'; +import '../../generated/l10n.dart'; +import '../drawdetails/draw_details_page.dart'; +import 'me_model.dart'; +import 'screen_tips.dart'; + +///我的作品 +class MyWorksPage extends StatefulWidget { + const MyWorksPage({Key? key}) : super(key: key); + + @override + State createState() => _MyWorksPageState(); +} + +class _MyWorksPageState extends State { + StreamSubscription? subscription; + final MeModel _viewModel = MeModel(); + List? list; + bool isChecks = false; //是否多选状态 + int isCheckNum = 0; //选中数量 + int sortType = 0; //排序类型 + List drawIdList = []; //多选删除集合 + + @override + void initState() { + // TODO: implement initState + super.initState(); + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + switch (code) { + case "getUserDrawList": + list = newData['data']; + for (var value in list!) { + value.IsCheck = false; + } + list!.sort((a, b) => b.FavoriteDateTime!.compareTo(a.FavoriteDateTime!)); + break; + case "delMyDrawCollect": //删除 + String message = newData['data']; + EasyLoading.showToast(message); + drawIdList = []; + sortType = 0; + isChecks = false; + _viewModel.getUserDrawList(); + break; + } + } + setState(() {}); + }); + EasyLoading.show(status: 'loading...'); + _viewModel.getUserDrawList(); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + subscription?.cancel(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Scaffold( + backgroundColor: Colors.white, + body: Stack( + alignment: Alignment.center, + children: [ + Column( + children: [ + list != null && list!.isNotEmpty + ? Container( + height: 20, + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(top: 30), + child: Stack( + children: [ + ///作品数量 + Positioned( + left: 15, + child: Text( + '${S.of(context).Number_works}:${list!.length}/${NetworkConfig.saveImageNumber}', + style: TextStyle(color: Colors.black, fontSize: 12), + ), + ), + + ///排序 + !isChecks + ? Positioned( + right: 15, + child: GestureDetector( + onTapDown: (details) { + //排序弹框 + showDialog( + context: context, + builder: (BuildContext ctx) => ScreenTips( + index: sortType, + dx: details.globalPosition.dx, + dy: details.globalPosition.dy, + type: 0, + onTap: (index) { + sortType = index; + if (sortType == 0) { + list!.sort((a, b) => b.FavoriteDateTime!.compareTo(a.FavoriteDateTime!)); + } else if (sortType == 1) { + list!.sort((a, b) => a.FavoriteDateTime!.compareTo(b.FavoriteDateTime!)); + } else if (sortType == 2) { + list!.sort((a, b) => b.FavoriteDateTime!.compareTo(a.FavoriteDateTime!)); + //根据优先级进行排序:降序 + list!.sort((a, b) => b.CollectNumber!.compareTo(a.CollectNumber!)); + } else if (sortType == 3) { + list!.sort((a, b) => b.FavoriteDateTime!.compareTo(a.FavoriteDateTime!)); + //根据优先级进行排序:降序 + list!.sort((a, b) => a.CollectNumber!.compareTo(b.CollectNumber!)); + } + setState(() {}); + }, + )); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Image(width: 13, height: 13, image: AssetImage('assets/images/ic_sort.png')), + Container( + margin: const EdgeInsets.only(left: 4), + child: Text( + S.of(context).Sort_by, + style: const TextStyle(color: Color(0xFF666666), fontSize: 12), + ), + ), + ], + ), + ), + ) + : Container(), + + ///多选 + !isChecks + ? Positioned( + right: NetworkConfig.Language != "zh" ? 90 : 70, + child: GestureDetector( + onTap: () { + isChecks = true; + setState(() {}); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Image(width: 13, height: 13, image: AssetImage('assets/images/ic_check.png')), + Container( + margin: const EdgeInsets.only(left: 4), + child: Text( + S.of(context).Selects, + style: const TextStyle(color: Color(0xFF666666), fontSize: 12), + ), + ), + ], + ), + ), + ) + : Container(), + + ///取消 + isChecks + ? Positioned( + right: 15, + child: GestureDetector( + onTap: () { + isChecks = false; + for (var value in list!) { + value.IsCheck = false; + } + setState(() {}); + }, + child: Text( + S.of(context).Cancel, + style: const TextStyle(color: Color(0xFF666666), fontSize: 12), + ), + )) + : Container(), + ], + ), + ) + : Container(), + + ///作品列表 + list != null && list!.isNotEmpty + ? Expanded( + child: Container( + margin: const EdgeInsets.only(left: 15, right: 15), + child: SingleChildScrollView( + child: MasonryGridView.count( + crossAxisCount: 2, + padding: const EdgeInsets.only(left: 0, right: 0, top: 10), + itemCount: list!.length, + itemBuilder: (BuildContext context, int index) { + return _item(list![index], index); + }, + // 纵向元素间距 + mainAxisSpacing: 10, + // 横向元素间距 + crossAxisSpacing: 10, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + ), + ), + ), + ) + : Expanded( + child: Container( + alignment: Alignment.center, + child: const Image( + width: 150, + image: AssetImage('assets/images/ic_no_content.png'), + ), + ), + ), + ], + ), + + ///批量删除 + isChecks + ? Positioned( + bottom: 0, + child: Container( + color: const Color(0x99000000), + width: size.width, + height: 50, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned( + left: 15, + child: GestureDetector( + onTap: () { + isChecks = false; + for (var value in list!) { + value.IsCheck = false; + isCheckNum = 0; + } + setState(() {}); + }, + child: Text( + S.of(context).Cancel, + style: const TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ), + + ///已选中 + GestureDetector( + child: Text( + "${S.of(context).Selected} $isCheckNum/${list!.length}", + style: const TextStyle(color: Colors.white, fontSize: 16), + ), + ), + Positioned( + right: 15, + child: GestureDetector( + onTap: () { + if (drawIdList.isNotEmpty) { + EasyLoading.show(status: 'loading...'); + + String drawList = json.encode(drawIdList); + _viewModel.delMyDrawCollect(drawList); + } else { + EasyLoading.showToast(S.of(context).Please_select); + } + }, + child: Text( + S.of(context).Delete, + style: const TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ), + ], + ), + )) + : Container(), + ], + )); + } + + _item(UserDrawBean bean, int index) { + return GestureDetector( + onTap: () { + //选中判断 + if (!isChecks) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DrawDetailsPage( + false, + taskId: bean.TaskId, + describeText: bean.Title, + drawId: bean.DrawId.toString(), + isMyWork: true, + status: bean.Status!, + ))).then((value) => {_viewModel.getUserDrawList()}); + } else { + setState(() { + _deleteList(bean.DrawId.toString()); + bean.IsCheck = !bean.IsCheck!; + if (bean.IsCheck!) { + isCheckNum++; + } else { + isCheckNum--; + } + }); + } + }, + child: Stack( + children: [ + Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(7), + child: CachedNetworkImage( + imageUrl: bean.ImageUrl!, + errorWidget: (context, url, error) => Icon(Icons.error), + ), + ), + SizedBox( + height: 40, + width: double.infinity, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned( + left: 0, + child: SizedBox( + width: 100, + child: Text( + bean.Title!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Colors.black), + ), + ), + ), + Positioned( + right: 10, + child: Row( + children: [ + const Image( + width: 13, + height: 12, + image: AssetImage('assets/images/ic_collect.png'), + ), + Container( + margin: const EdgeInsets.only(left: 5), + child: Text( + bean.CollectNumber.toString(), + style: const TextStyle(color: Colors.black, fontSize: 12), + ), + ) + ], + ), + ), + ], + ), + ), + ], + ), + + ///复选框 + isChecks + ? Positioned( + right: 5, + top: 5, + child: Container( + width: 20, + height: 20, + decoration: BoxDecoration(color: Colors.white, border: Border.all(color: const Color(0xFFBB72E0))), + child: Checkbox( + value: bean.IsCheck, + checkColor: const Color(0xFF8841FF), + fillColor: MaterialStateProperty.resolveWith((Set states) { + return Colors.white; + }), + onChanged: (value) { + setState(() { + _deleteList(bean.DrawId.toString()); + if (value!) { + isCheckNum++; + } else { + isCheckNum--; + } + bean.IsCheck = value; + }); + }, + ), + )) + : Container() + ], + ), + ); + } + + _deleteList(String drawId) { + if (drawIdList.contains(drawId)) { + drawIdList.remove(drawId); + } else { + drawIdList.add(drawId); + } + } +} diff --git a/lib/tools/me/screen_tips.dart b/lib/tools/me/screen_tips.dart new file mode 100644 index 0000000..5522131 --- /dev/null +++ b/lib/tools/me/screen_tips.dart @@ -0,0 +1,116 @@ + +import 'package:flutter/material.dart'; + +import '../../generated/l10n.dart'; + +///排序弹框 +class ScreenTips extends StatefulWidget { + // 点击返回index 0 1 + final double dx; + final double dy; + final int index; + final int type; //0 我的作品 1 收藏 + Function onTap; + + ScreenTips({required this.dx, required this.dy, required this.index, required this.type, required this.onTap}); + + @override + _ScreenTipsState createState() => _ScreenTipsState(); +} + +class _ScreenTipsState extends State { + List items = []; + + @override + void initState() { + // TODO: implement initState + super.initState(); + Future.delayed(const Duration(seconds: 0), () { + if (widget.type == 0) { + items = [S.of(context).Newest, S.of(context).Oldest, S.of(context).Most_favorite, S.of(context).Least_Favorite]; + } else { + items = [S.of(context).Newest, S.of(context).Oldest]; + } + + setState(() {}); + }); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + double h = items.length * 30 + 0.33; + return Material( + type: MaterialType.transparency, //透明类型 + color: const Color(0x00000000), + child: SizedBox( + width: double.infinity, + height: double.infinity, + child: Stack( + children: [ + Positioned( + top: widget.dy - 5, + right: 5, + child: SizedBox( + width: 90, + height: h, + child: Card( + clipBehavior: Clip.antiAlias, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(4.0)), + ), + margin: const EdgeInsets.all(0), // + child: ListView.builder( + shrinkWrap: true, + itemCount: items.length, + itemExtent: 30, + padding: const EdgeInsets.only(left: 0, right: 0), + //数据的数量 + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + Navigator.pop(context); + if (widget.onTap != null) { + widget.onTap(index); + } + }, + child: Container( + color: Color(widget.index == index ? 0xFFE0E0E0 : 0xFFFFFFFF), + child: Stack( + children: [ + index == 0 + ? Container() + : Container( + height: 1, + width: double.infinity, + color: const Color(0xFFE0E0E0), + ), + Container( + alignment: Alignment.center, + margin: const EdgeInsets.only(left: 0, top: 0), + width: double.infinity, + child: Text( + items[index], + style: TextStyle( + color: widget.index == index ? const Color(0xFF8841FF) : const Color(0xFF666666), + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + )); + }, + physics: const BouncingScrollPhysics(), + //类似 cellForRow 函数 + scrollDirection: Axis.vertical), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/tools/me/setting_page.dart b/lib/tools/me/setting_page.dart new file mode 100644 index 0000000..d1748b1 --- /dev/null +++ b/lib/tools/me/setting_page.dart @@ -0,0 +1,369 @@ + +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../common/Global.dart'; +import '../../common/func.dart'; +import '../../generated/l10n.dart'; +import '../../network/NetworkConfig.dart'; +import '../start_model.dart'; +import '../web/CommonlyWebPage.dart'; + +///设置 +class SettingPage extends StatefulWidget { + const SettingPage({Key? key}) : super(key: key); + + @override + State createState() => _SettingPageState(); +} + +class _SettingPageState extends State { + final StartModel _viewModel = StartModel(); + StreamSubscription? subscription; + + @override + void initState() { + // TODO: implement initState + super.initState(); + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + if (code == "getAppConfig") { + Navigator.of(context).pushNamedAndRemoveUntil('/HomePage', ModalRoute.withName('/')); + } else if (code == "-1") { + Navigator.of(context).pushNamedAndRemoveUntil('/HomePage', ModalRoute.withName('/')); + } + } + }); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + subscription?.cancel(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 1, + title: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only(right: 10), + child: const Image( + width: 23, + height: 23, + image: AssetImage('assets/images/ic_title.png'), + ), + ), + Text( + S.of(context).Settings, + style: const TextStyle(color: Colors.black, fontSize: 20), + ), + ], + ), + leading: IconButton( + icon: const ImageIcon(AssetImage('assets/images/ic_return.png')), + color: Colors.black, + onPressed: () { + Navigator.pop(context); + }), + centerTitle: true, + ), + body: Column( + children: [ + ///语言切换 + _ButtonSw(), + + ///反馈 + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.pushNamed(context, "/FeedbackPage"); + }, + child: SizedBox( + height: 50, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned(left: 15, child: Text(S.of(context).Feedback)), + const Positioned( + right: 15, + child: Image( + width: 7, + height: 12, + image: AssetImage('assets/images/ic_jump.png'), + )) + ], + ), + ), + ), + + ///隐私协议 + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + //导航打开新视图 + builder: (context) => CommonlyWebPage( + url: NetworkConfig.Language == "zh" + ? "https://appfiles.hissai.com/hissai/PrivacyPolicy.html" + : "https://appfiles.hissai.com/hissai/PrivacyPolicy_EN.html", + title: S.of(context).Privacy_Policy, + ) //打开第二个页面,并传值,传递值的名称是model + )); + }, + child: SizedBox( + height: 50, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned(left: 15, child: Text(S.of(context).Privacy_Policy)), + const Positioned( + right: 15, + child: Image( + width: 7, + height: 12, + image: AssetImage('assets/images/ic_jump.png'), + )) + ], + ), + ), + ), + + ///用户协议 + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + //导航打开新视图 + builder: (context) => CommonlyWebPage( + url: NetworkConfig.Language == "zh" + ? "https://appfiles.hissai.com/hissai/UserAgreement.html" + : "https://appfiles.hissai.com/hissai/UserAgreement_EN.html", + title: S.of(context).User_Agreement, + ) //打开第二个页面,并传值,传递值的名称是model + )); + }, + child: SizedBox( + height: 50, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned(left: 15, child: Text(S.of(context).User_Agreement)), + const Positioned( + right: 15, + child: Image( + width: 7, + height: 12, + image: AssetImage('assets/images/ic_jump.png'), + )) + ], + ), + ), + ), + + ///退出登录 + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + cleanUser(); + }, + child: SizedBox( + height: 50, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned(left: 15, child: Text(S.of(context).Exit_login)), + const Positioned( + right: 15, + child: Image( + width: 7, + height: 12, + image: AssetImage('assets/images/ic_jump.png'), + )) + ], + ), + ), + ), + + ///关于 + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.pushNamed(context, "/AboutPage"); + }, + child: SizedBox( + height: 50, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned(left: 15, child: Text(S.of(context).About)), + const Positioned( + right: 15, + child: Image( + width: 7, + height: 12, + image: AssetImage('assets/images/ic_jump.png'), + )) + ], + ), + ), + ), + ], + ), + ); + } + + ///语言切换 + _ButtonSw() { + return GestureDetector( + onTap: () { + FunctionUtil.bottomSheetDialog( + context, + Container( + decoration: const BoxDecoration( + color: Colors.white, borderRadius: BorderRadius.only(topLeft: Radius.circular(10.0), topRight: Radius.circular(10.0))), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () { + setLanguageSw(1); + }, + child: Container( + alignment: Alignment.center, + height: 50, + width: double.infinity, + color: Colors.white, + child: Text( + "English(United States)", + style: TextStyle(color: NetworkConfig.Language == '' || NetworkConfig.Language == 'en' ? Colors.red : Colors.black), + ), + ), + ), + _Line(), + GestureDetector( + onTap: () { + //Navigator.pop(context); + setLanguageSw(2); + }, + child: Container( + alignment: Alignment.center, + height: 50, + width: double.infinity, + color: Colors.white, + child: Text( + "中文简体(中国)", + style: TextStyle(color: NetworkConfig.Language == 'zh' ? Colors.red : Colors.black), + ), + ), + ), + ], + ), + )); + }, + child: Container( + margin: const EdgeInsets.only(top: 0, left: 0, right: 0), + color: Colors.white, + height: 50, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only(top: 0, left: 15, bottom: 0, right: 15), + child: Text( + S.of(context).Language_switching, + style: const TextStyle( + color: Colors.black, + ), + )), + Container( + alignment: Alignment.centerRight, + margin: const EdgeInsets.only(right: 10, left: 10), + child: Text( + NetworkConfig.Language == 'zh' ? "中文简体" : "English", + overflow: TextOverflow.ellipsis, + style: const TextStyle( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + )); + } + + setLanguageSw(index) async { + var lc; + if (index == 1) { + lc = "en"; + } else if (index == 2) { + lc = "zh"; + } else if (index == 3) { + lc = "ja"; + } + S.load(Locale.fromSubtags(languageCode: lc)); + NetworkConfig.Language = lc; + Map map = {"languageCode": NetworkConfig.Language}; + invokeNativeMethod("LanguageSw", map); + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setString("LanguageSw", NetworkConfig.Language); + + EasyLoading.show(status: 'loading...', maskType: EasyLoadingMaskType.black); + + _viewModel.getAppConfig(); + } + + _Line() { + return DecoratedBox( + //线 + decoration: BoxDecoration(border: Border.all(color: const Color(0x4cCFCFCF), width: 1.0)), + child: const SizedBox( + height: 1, + width: double.infinity, + ), + ); + } + + //清除用户数据 退出登录 + cleanUser() async { + NetworkConfig.userId = ""; + NetworkConfig.token = ""; + NetworkConfig.userToken = ""; + NetworkConfig.allCurrency = "0"; + Navigator.of(context).pushNamedAndRemoveUntil('/HomePage', ModalRoute.withName('/')); + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setString("UserBean", ""); + + Map map = {"exitLogin": "exitLogin"}; + invokeNativeMethod("exitLogin", map); + } + + // 获取原生的值 + invokeNativeMethod(String method, Map map) async { + dynamic args; + try { + args = await Global.method.invokeMethod(method, map); + } on PlatformException catch (e) {} + } +} diff --git a/lib/tools/message/message_model.dart b/lib/tools/message/message_model.dart new file mode 100644 index 0000000..c4b4dc0 --- /dev/null +++ b/lib/tools/message/message_model.dart @@ -0,0 +1,42 @@ +import 'dart:async'; + +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/network/RequestCenter.dart'; + +import '../../network/BaseEntity.dart'; + +class MessageModel { + StreamController streamController = StreamController.broadcast(); + + MessageModel() { + setup(); + } + + void setup() { + //初始化 + } + + //我的作品 + Future getUserMessage() async { + RequestCenter.instance.requestPlay(NetworkConfig.getUserMessage, { + "MessageType": 2, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "getUserMessage", //有数据 + 'data': "data", + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } +} diff --git a/lib/tools/message/message_page.dart b/lib/tools/message/message_page.dart new file mode 100644 index 0000000..21d44f6 --- /dev/null +++ b/lib/tools/message/message_page.dart @@ -0,0 +1,132 @@ + +import 'dart:async'; + +import 'package:aiplot/tools/message/message_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +import '../../generated/l10n.dart'; + +class MessagePage extends StatefulWidget { + const MessagePage({Key? key}) : super(key: key); + + @override + State createState() => _MessagePageState(); +} + +class _MessagePageState extends State { + StreamSubscription? subscription; + final MessageModel _viewModel = MessageModel(); + + + + @override + void initState() { + // TODO: implement initState + super.initState(); + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + + } + setState(() {}); + }); + getData(); + } + getData() async { + _viewModel.getUserMessage(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + title: Container( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: EdgeInsets.only(right: 10), + child: Image( + width: 23, + height: 23, + image: AssetImage('assets/images/ic_title.png'), + ), + ), + Text( + S.of(context).message, + style: TextStyle(color: Colors.black, fontSize: 20), + ), + ], + ), + ), + leading: IconButton( + icon: ImageIcon(AssetImage('assets/images/ic_return.png')), + color: Colors.black, + onPressed: () { + Navigator.pop(context); + }), + centerTitle: true, + ), + body: Stack( + children: [ + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + flex: 1, + child: GestureDetector( + child: Container( + height: 105, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned( + top: 10, + child: Image(width: 40, image: AssetImage('assets/images/ic_message_notice.png')), + ), + Positioned(bottom: 30, child: Text("公告")), + ], + ), + ), + )), + Expanded( + flex: 1, + child: GestureDetector( + child: Container( + height: 105, + child: Stack( + alignment: Alignment.center, + children: [ + Positioned( + top: 10, + child: Image(width: 40, image: AssetImage('assets/images/ic_message_collect.png')), + ), + Positioned(bottom: 30, child: Text("收藏")), + ], + ), + ), + )), + ], + ), + Expanded(child: ListView.builder( + itemBuilder: (BuildContext context, int index) { + return _item(); + }, + )) + ], + ), + ], + ), + ); + } + + _item() {} +} diff --git a/lib/tools/shop/shop_model.dart b/lib/tools/shop/shop_model.dart new file mode 100644 index 0000000..e0dc40d --- /dev/null +++ b/lib/tools/shop/shop_model.dart @@ -0,0 +1,97 @@ +import 'dart:async'; + +import 'package:aiplot/bean/create_order_bean.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/network/RequestCenter.dart'; + +import '../../bean/product_bean.dart'; +import '../../network/BaseEntity.dart'; + +class ShopModel { + StreamController streamController = StreamController.broadcast(); + + ShopModel() { + setup(); + } + + void setup() { + //初始化 + } + + //获取商品列表 + Future getProductList() async { + RequestCenter.instance.requestPlay(NetworkConfig.getProductList, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + List data = (dataEntity.data as List).map((e) => ProductBean.fromJson(e as Map)).toList(); + streamController.sink.add({ + 'code': "getProductList", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //生成订单 + Future createOrder(String productId) async { + RequestCenter.instance.requestPlay(NetworkConfig.createOrder, { + "ProductId": productId, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + CreateOrderBean data = CreateOrderBean.fromJson(json); + streamController.sink.add({ + 'code': "createOrder", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //完成订单 + Future completeOrder(String orderCode, String productId, String token) async { + RequestCenter.instance.requestPlay(NetworkConfig.completeOrder, { + "OrderCode": orderCode, + "ProductId": productId, + "Token": token, + }, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + CreateOrderBean data = CreateOrderBean.fromJson(json); + streamController.sink.add({ + 'code': "completeOrder", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } +} diff --git a/lib/tools/shop/shop_page.dart b/lib/tools/shop/shop_page.dart new file mode 100644 index 0000000..5a68383 --- /dev/null +++ b/lib/tools/shop/shop_page.dart @@ -0,0 +1,155 @@ + +import 'dart:async'; + +import 'package:aiplot/tools/shop/shop_model.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +import '../../bean/create_order_bean.dart'; +import '../../bean/product_bean.dart'; +import '../../generated/l10n.dart'; + +class ShopPage extends StatefulWidget { + const ShopPage({Key? key}) : super(key: key); + + @override + State createState() => _ShopPageState(); +} + +class _ShopPageState extends State { + StreamSubscription? subscription; + final ShopModel _viewModel = ShopModel(); + List productList = []; + CreateOrderBean? createOrderBean; + int currentIndex = 0; + + @override + void initState() { + // TODO: implement initState + super.initState(); + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + EasyLoading.dismiss(); + switch (code) { + case "getProductList": + productList = newData['data']; + break; + case "createOrder": + createOrderBean = newData['data']; + completeOrder(createOrderBean!.OrderCode!, productList[currentIndex].ProductId!, "a"); + break; + } + } + setState(() {}); + }); + getProductList(); + } + + //获取商品列表 + getProductList() { + EasyLoading.show(status: 'loading...'); + _viewModel.getProductList(); + } + + //生成订单 + createOrder(String productId) { + EasyLoading.show(status: 'loading...', maskType: EasyLoadingMaskType.black); + _viewModel.createOrder(productId); + } + + //完成订单 + completeOrder(String orderCode, String productId, String token) { + EasyLoading.show(status: 'loading...'); + _viewModel.completeOrder(orderCode, productId, token); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + title: Text( + S.of(context).Mall, + style: const TextStyle(fontSize: 20, color: Colors.black), + ), + centerTitle: true, + leading: IconButton( + icon: const ImageIcon(AssetImage('assets/images/ic_return.png')), + color: Colors.black, + onPressed: () { + Navigator.pop(context); + }), + ), + body: Stack( + alignment: Alignment.center, + children: [ + Column( + children: [ + Image(width: size.width, fit: BoxFit.fitWidth, image: const AssetImage('assets/images/shop_bg.png')), + Container( + margin: const EdgeInsets.only(top: 28, left: 15), + child: Row( + children: [ + const Image(width: 14, height: 14, image: AssetImage('assets/images/shop_star.png')), + Container( + margin: const EdgeInsets.only(left: 9), + child: Text(S.of(context).Paint_points), + ) + ], + )), + Container( + margin: const EdgeInsets.only(top: 10, left: 15), + child: Row( + children: [ + const Image(width: 14, height: 14, image: AssetImage('assets/images/shop_star.png')), + Container( + margin: const EdgeInsets.only(left: 9), + child: Text(S.of(context).Painting_points_never), + ) + ], + )), + //商品列表 + Expanded( + child: SizedBox( + width: size.width, + child: ListView.builder( + itemCount: productList.length, + itemBuilder: (BuildContext context, int index) { + return _item(productList[index], index); + }, + scrollDirection: Axis.vertical), + )) + ], + ), + ], + ), + ); + } + + _item(ProductBean bean, int index) { + return GestureDetector( + onTap: () { + currentIndex = index; + createOrder(bean.ProductId!); + }, + child: Container( + margin: const EdgeInsets.only(left: 10, top: 10, right: 10), + child: CachedNetworkImage(imageUrl: bean.ImageUrl!), + ), + ); + } +} diff --git a/lib/tools/start_model.dart b/lib/tools/start_model.dart new file mode 100644 index 0000000..f1eb74b --- /dev/null +++ b/lib/tools/start_model.dart @@ -0,0 +1,140 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:aiplot/bean/app_config_bean.dart'; +import 'package:aiplot/bean/server_bean.dart'; +import 'package:aiplot/network/NetworkConfig.dart'; +import 'package:aiplot/network/RequestCenter.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../bean/login_bean.dart'; +import '../bean/user_bean.dart'; +import '../network/BaseEntity.dart'; + +class StartModel { + StreamController streamController = StreamController.broadcast(); + + StartModel() { + setup(); + } + + void setup() { + //初始化 + } + + //获取服务地址 + Future getServerList() async { + RequestCenter.instance.requestPlay(NetworkConfig.getServerList, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + ServerBean data = ServerBean.fromJson(json); + + NetworkConfig.ServerDomain_Online = data.HissAiApiUrl!; + NetworkConfig.payCenter = data.HissAiPayUrl!; + + streamController.sink.add({ + 'code': "getServerList", //有数据 + 'data': "", + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //获取配置信息 + Future getAppConfig() async { + RequestCenter.instance.requestPlay(NetworkConfig.getAppConfig, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + AppConfigBean data = AppConfigBean.fromJson(json); + NetworkConfig.appConfigBean = data; + streamController.sink.add({ + 'code': "getAppConfig", //有数据 + 'data': "", + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //获取用户信息(验证用户token是否有效) + Future getUserData() async { + RequestCenter.instance.requestPlay(NetworkConfig.getUserData, {}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + streamController.sink.add({ + 'code': "getUserData", //验签有效 + 'data': "", + }); + } else { + streamController.sink.add({ + 'code': "userTokenExpire", //验签失败 + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //登录 (游客) + Future userLogin() async { + RequestCenter.instance.requestPlay(NetworkConfig.userLogin, {"LoginType": 101, "UserName": NetworkConfig.deviceID}, (BaseEntity dataEntity) { + if (dataEntity.code == 0) { + Map json = dataEntity.data; + LoginBean data = LoginBean.fromJson(json); + + NetworkConfig.userId = data.UserId.toString(); + NetworkConfig.userName = data.UserName.toString(); + if (data.Token != null && data.Token != "") { + NetworkConfig.token = data.Token.toString(); + NetworkConfig.userToken = data.Token?.split('.')[2] as String; + } + + UserBean userBean = UserBean(NetworkConfig.userId, NetworkConfig.token, NetworkConfig.userToken); + setUser(userBean); + + streamController.sink.add({ + 'code': "visitorLogin", //有数据 + 'data': data, + }); + } else { + streamController.sink.add({ + 'code': "-1", // + 'data': dataEntity.code, + }); + } + }, (ErrorEntity errorEntity) { + streamController.sink.add({ + 'code': "0", //无数据 + 'data': errorEntity.code, + }); + }); + } + + //保存用户登录验签 + setUser(UserBean bean) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setString("UserBean", jsonEncode(bean.toJson())); + } +} diff --git a/lib/tools/start_page.dart b/lib/tools/start_page.dart new file mode 100644 index 0000000..16a1c8c --- /dev/null +++ b/lib/tools/start_page.dart @@ -0,0 +1,250 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:aiplot/tools/start_model.dart'; +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:device_info/device_info.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../bean/user_bean.dart'; +import '../common/Global.dart'; +import '../generated/l10n.dart'; +import '../network/NetworkConfig.dart'; + +class StartPage extends StatefulWidget { + StartPage({Key? key, this.thisParams}) : super(key: key); + final Map? thisParams; + + @override + _StartPageState createState() => _StartPageState(); +} + +class _StartPageState extends State { + static final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); + StreamSubscription? subscription; + final StartModel _viewModel = StartModel(); + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + } + + // 获取原生的值 + invokeNativeMethod(String method, Map map) async { + dynamic args; + try { + args = await Global.method.invokeMethod(method, map); + } on PlatformException catch (e) {} + } + + //获取用户验签 + getUser() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String userName = prefs.getString("UserBean")!; + if (userName != null && userName.isNotEmpty) { + Map responseData = jsonDecode(userName); + UserBean bean = UserBean.fromJson(responseData); + NetworkConfig.userId = bean.userId!; + NetworkConfig.token = bean.token!; + NetworkConfig.userToken = bean.userToken!; + Map map = { + "userId": NetworkConfig.userId, + "token": NetworkConfig.token, + "userToken": NetworkConfig.userToken, + }; + invokeNativeMethod("userData", map); + } else { + NetworkConfig.userId = ""; + NetworkConfig.token = ""; + NetworkConfig.userToken = ""; + } + } + + geLanguageSw() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? NetworkSet = prefs.getString("LanguageSw"); + return NetworkSet; + } + + getIsFirst() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? IsFirst = prefs.getString("IsFirst"); + return IsFirst; + } + + setIsFirst() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setString("IsFirst", "1"); + } + + cleanUser() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setString("UserBean", ""); + } + + var nTime; + + @override + void initState() { + // TODO: implement initState + super.initState(); + var nowTime = DateTime.now(); //获取当前时间 + nTime = nowTime.millisecondsSinceEpoch; //单位是毫秒(千分之一秒),13位时间戳 + + if (Platform.isIOS) { + subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { + // Got a new connectivity status! + if (result == ConnectivityResult.mobile || result == ConnectivityResult.wifi) { + setState(() { + getServerInfo(); + }); + } + }); + } + + //网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + if (code.isNotEmpty) { + switch (code) { + case "getServerList": + //获取配置 + _viewModel.getAppConfig(); + break; + case "getAppConfig": + if (!NetworkConfig.isTest) { + if (NetworkConfig.userId == "") { + //进入首页 + Navigator.of(context).pushReplacementNamed('/HomePage'); + } else { + //请求用户信息接口,判断用户验签是否过期 + _viewModel.getUserData(); + } + } else { + _viewModel.userLogin(); + } + break; + case "visitorLogin": //游客登录 + Navigator.of(context).pushReplacementNamed('/HomePage'); + break; + case "getUserData": //验签成功 + //进入首页 + Navigator.of(context).pushReplacementNamed('/HomePage'); + break; + case "userTokenExpire": //用户token过期,重置信息 + cleanUser(); + NetworkConfig.userId = ""; + NetworkConfig.token = ""; + NetworkConfig.userToken = ""; + Navigator.of(context).pushReplacementNamed('/HomePage'); + break; + default: + Navigator.of(context).pushReplacementNamed('/HomePage'); + break; + } + } + setState(() {}); + }); + + //初始化信息 + initData(); + } + + // 获取原生的值 + Future initData() async { + try { + Future IsFirst = getIsFirst(); //是否首次打开 + IsFirst.then((dynamic bean) { + initApi(); + }); + } on PlatformException catch (e) {} + } + + //初始化信息 + initApi() async { + initPlatformState(); + getUser(); + //原生回调参数 + dynamic headers = await Global.method.invokeMethod("getRequestHeaders"); + Map headersMap = Map.from(headers); + NetworkConfig.AppId = headersMap["AppId"]; + NetworkConfig.BossId = headersMap["BossId"]; + NetworkConfig.Version = headersMap["Version"]; + NetworkConfig.CPU = headersMap["CPU"]; + NetworkConfig.imsi = headersMap["imsi"]; + NetworkConfig.ip = headersMap["ip"]; + NetworkConfig.timeZone = headersMap["timeZone"]; + NetworkConfig.statusHeight = headersMap["statusHeight"]; + + Future isLanguageSw = geLanguageSw(); + isLanguageSw.then((dynamic bean) { + if (bean != null && bean != "") { + NetworkConfig.Language = bean; + } else { + String lc = Localizations.localeOf(context).languageCode; + if (lc != "zh") { + if (lc != "ja") { + NetworkConfig.Language = "en"; + } else { + NetworkConfig.Language = Localizations.localeOf(context).languageCode; + } + } else { + NetworkConfig.Language = Localizations.localeOf(context).languageCode; + } + } + S.load(Locale.fromSubtags(languageCode: NetworkConfig.Language)); + }); + getServerInfo(); + } + + //获取设备信息 + Future initPlatformState() async { + try { + if (Platform.isAndroid) { + var build = await deviceInfoPlugin.androidInfo; + NetworkConfig.deviceID = build.androidId; + NetworkConfig.systemVersion = build.version.release; + } else if (Platform.isIOS) { + var build = await deviceInfoPlugin.iosInfo; + NetworkConfig.deviceID = build.identifierForVendor; + } + } on PlatformException {} + Map map = {"SensorsAnaly": "0"}; + invokeNativeMethod("initAPI", map); + } + + //获取服务信息 + getServerInfo() { + _viewModel.getServerList(); + } + + @override + void dispose() { + subscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Scaffold( + backgroundColor: Colors.white, + body: Stack( + children: [ + Container( + width: double.infinity, + height: double.infinity, + child: const Image( + fit: BoxFit.fitHeight, + height: double.infinity, + image: AssetImage('assets/images/kpy.png'), + )), + ], + )); + } +} diff --git a/lib/tools/upload/upload_page.dart b/lib/tools/upload/upload_page.dart new file mode 100644 index 0000000..00155f6 --- /dev/null +++ b/lib/tools/upload/upload_page.dart @@ -0,0 +1,396 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_native_image/flutter_native_image.dart'; +import 'package:image_cropper/image_cropper.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:ironsource_mediation/ironsource_mediation.dart'; + +import '../../common/EventBusUtil.dart'; +import '../../common/Global.dart'; +import '../../common/TabUnderLine.dart'; +import '../../common/app_util.dart'; +import '../../common/dialog_bean.dart'; +import '../../common/dialog_manager.dart'; +import '../../common/dialog_util.dart'; +import '../../common/func.dart'; +import '../../dialog/invitation_code_dialog.dart'; +import '../../dialog/login_dialog.dart'; +import '../../dialog/phone_login_dialog.dart'; +import '../../generated/l10n.dart'; +import '../../network/NetworkConfig.dart'; +import '../create/create_model.dart'; + +///上传 +class UploadPage extends StatefulWidget { + const UploadPage({Key? key}) : super(key: key); + + @override + State createState() => _MePageState(); +} + +class _MePageState extends State with SingleTickerProviderStateMixin { + StreamSubscription? subscription; + final CreateModel _viewModel = CreateModel(); + GlobalKey loginDialogKey = GlobalKey(); //登录弹框key + CroppedFile? selectImage; //选择的相册图 + int currentSizeIndex = 0; //当前尺寸下标 + String initImg = ""; //参考图 + var imageValue = false; + + Future _createPic() async { + EasyLoading.show(status: 'loading...'); + _viewModel.uploadImg(initImg); + _viewModel.getUserData(); + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + + ///网络请求回调 + subscription = _viewModel.streamController.stream.listen((newData) { + String code = newData['code']; + EasyLoading.dismiss(); + if (code.isNotEmpty) { + switch (code) { + case "uploadOk": //上传成功 + EasyLoading.showToast(S().Upload_successful); + selectImage = null; + break; + + case "uploadNo": //上传失败 + String message = newData['data']; + EasyLoading.showToast(message); + selectImage = null; + break; + default: + String message = newData['data']; + EasyLoading.showToast(message); + break; + } + } + setState(() {}); + }); + } + + @override + void dispose() { + // TODO: implement dispose + subscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final h270 = size.width / 1.333333333; + final t70 = size.width / 5.1428571428571; + final w60 = size.width / 6; + final l85 = size.width / 4.235294117647; + final t35 = size.width / 10.285714285714; + final h340 = size.width / 1.0588235294117; + final t40 = size.width / 9; + final w90 = size.width / 4; + final h45 = size.width / 8; + final w150 = size.width / 2.4; + final h140 = size.width / 2.5714285714285; + final h60 = size.width / 6; + final h80 = size.width / 4.5; + + return Scaffold( + backgroundColor: Colors.white, + body: Stack( + children: [ + const Image( + width: double.infinity, + fit: BoxFit.fitWidth, + image: AssetImage('assets/images/upbg.webp'), + ), + Column( + children: [ + GestureDetector( + onTap: () async { + XFile img = await AppUtil.getImages(); + selectImage = await AppUtil.cropImage(img.path, currentSizeIndex); + + setState(() {}); + }, + child: Container( + margin: const EdgeInsets.only(top: 100, left: 60, right: 60), + child: selectImage != null + ? Image.file( + File(selectImage!.path), + fit: BoxFit.cover, + ) + : const Image( + width: double.infinity, + fit: BoxFit.fitWidth, + image: AssetImage('assets/images/kuang.png'), + ), + )), + Container( + margin: const EdgeInsets.only(top: 20, left: 20, right: 20), + child: Text( + S.of(context).Upload_gallery, + style: const TextStyle(color: Color(0xFF000000), fontSize: 14), + ), + ), + GestureDetector( + onTap: () async { + _generateImages(); + }, + child: Container( + height: 50, + margin: const EdgeInsets.only(top: 20, left: 50, right: 50), + width: double.infinity, + alignment: Alignment.center, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, //渐变开始于上面的中间开始 + end: Alignment.centerRight, //渐变结束于下面的中间 + colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), + borderRadius: BorderRadius.all(Radius.circular(25))), + child: Text( + S.of(context).Confirm_submission, + style: const TextStyle(color: Color(0xFFFFFFFF), fontSize: 18), + ), + )) + ], + ), + ], + ), + ); + } + + ///生成图片 + _generateImages() async { + if (NetworkConfig.userId != "") { + if (selectImage != null) { + //处理图片 + initImg = await _compressPictures(); + + ///图生图 + _createPic(); + } + } else { + showLoginDialog(); + } + } + + //处理图片 + _compressPictures() async { + String img = ""; + //1,取方向,判断原图方向横竖 + // 2,同方向取宽高中最大值,匹配已选择的画面比例宽高值。反方向小值 + + //1:1 512*512 3:4 512*704 4:3 704*512 9:16 512*910 16:9 910*512 + File file = File(selectImage!.path); + File? compressedFile; + ImageProperties properties = await FlutterNativeImage.getImageProperties(file.path); + //判断当前方向 + int isDirection = 0; //0 正方形 1 横向长方形 2 纵向长方形 + if (properties.width == properties.height) { + isDirection = 0; + } else if (properties.width! > properties.height!) { + isDirection = 1; + } else if (properties.width! < properties.height!) { + isDirection = 2; + } + //下标选择方向 + if (currentSizeIndex == 0) { + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 512, targetHeight: (properties.height! * 512 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 512 / properties.height!).round(), targetHeight: 512); + } else { + compressedFile = file; + } + } + } else if (currentSizeIndex == 1) { + //下标方向为纵向 + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + //横向 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 512, targetHeight: (properties.height! * 512 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + //纵向 + if (properties.height! > 704) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 704 / properties.height!).round(), targetHeight: 704); + } else { + compressedFile = file; + } + } + } else if (currentSizeIndex == 2) { + //下标方向为横向 + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + //横向 + if (properties.width! > 704) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 704, targetHeight: (properties.height! * 704 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + //纵向 + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 512 / properties.height!).round(), targetHeight: 512); + } else { + compressedFile = file; + } + } + } else if (currentSizeIndex == 3) { + //下标方向为纵向 + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + //横向 + if (properties.width! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 512, targetHeight: (properties.height! * 512 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + //纵向 + if (properties.height! > 910) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 910 / properties.height!).round(), targetHeight: 910); + } else { + compressedFile = file; + } + } + } else if (currentSizeIndex == 4) { + //下标方向为横向 + if (isDirection == 0) { + //如果大于512的正方形直接换比例成512,否则使用原图 + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); + } else { + compressedFile = file; + } + } else if (isDirection == 1) { + //横向 + if (properties.width! > 910) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: 910, targetHeight: (properties.height! * 910 / properties.width!).round()); + } else { + compressedFile = file; + } + } else if (isDirection == 2) { + //纵向 + if (properties.height! > 512) { + compressedFile = await FlutterNativeImage.compressImage(file.path, + quality: 100, targetWidth: (properties.width! * 512 / properties.height!).round(), targetHeight: 512); + } else { + compressedFile = file; + } + } + } + + ImageProperties properties2 = await FlutterNativeImage.getImageProperties(compressedFile!.path); + print("ImageProperties===" + properties2.width.toString() + "*" + properties2.height.toString()); + + ///判断图片大小 + double size = AppUtil.getFileSizeDouble(bytes: compressedFile.lengthSync()); + //取整 大于10m直接抛弃 + var s = size.ceil(); + if (s > 10) { + EasyLoading.showToast(S.of(context).Image_too_large); + } else { + //取整 大于1m直接压缩,小于1m使用原图 + if (s > 1) { + //图片压缩,压缩算法为 (10-s)*10,m越大调整后百分比越小 + int percentage = (10 - s) * 10; + File compressedFile2 = await FlutterNativeImage.compressImage(compressedFile.path, quality: 80, percentage: percentage); + //AppUtil.getFileSizeDouble(bytes: compressedFile2.lengthSync()); + img = await AppUtil.uploadImage2(compressedFile2); + } else { + //不压 + img = await AppUtil.uploadImage2(compressedFile); + } + } + return img; + } + + //弹出登录 + showLoginDialog() { + DialogManager() + ..add(DialogBean( + dialogPriority: DialogPriority.highClear, + createDialogWidget: () => DialogUtil.createTipWidget( + context, + LoginDialog( + loginDialogKey, + onTap: (index) { + switch (index) { + case 0: + if (loginDialogKey.currentState != null) { + loginDialogKey.currentState!.Pop(); + } + FunctionUtil.bottomSheetDialog(context, const PhoneLoginDialog()); + break; + case 1: //谷歌登录 + Map map = {"googleLogin": "googleLogin"}; + invokeNativeMethod("googleLogin", map); + break; + } + }, + ), + "LoginDialog", + canceled: true))) + ..show(context); + } + + // 获取原生的值 + invokeNativeMethod(String method, Map map) async { + dynamic args; + try { + args = await Global.method.invokeMethod(method, map); + } on PlatformException catch (e) {} + } +} diff --git a/lib/tools/web/CommonlyWebPage.dart b/lib/tools/web/CommonlyWebPage.dart new file mode 100644 index 0000000..301e773 --- /dev/null +++ b/lib/tools/web/CommonlyWebPage.dart @@ -0,0 +1,148 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +import '../../common/Global.dart'; +import '../../network/RequestCenter.dart'; + +class CommonlyWebPage extends StatefulWidget { + String? url; + final String? title; + final bool isLocalUrl; + + + CommonlyWebPage({super.key,this.url, this.isLocalUrl = false, this.title}); + + @override + State createState() => CommonlyWebPageState(); +} + +class CommonlyWebPageState extends State { + StreamSubscription? subscription; + String Token = ""; + WebViewController? _webViewController; + + @override + void initState() { + // TODO: implement initState + super.initState(); + } + + @override + void dispose() { + //subscription?.cancel(); + // TODO: implement dispose + super.dispose(); + } + + // 获取原生的值 + invokeNativeMethod(String method, Map map) async { + dynamic args; + try { + args = await Global.method.invokeMethod(method, map); + } on PlatformException catch (e) {} + } + + @override + Widget build(BuildContext context) { + return Scaffold(appBar: _buildAppbar(), body: _buildBody()); + } + + _buildAppbar() { + return AppBar( + brightness: Brightness.light, + iconTheme: IconThemeData(color: Colors.black), + flexibleSpace: Container( + decoration: BoxDecoration( + color: Color(0xFFBB72E0), + // gradient: LinearGradient(colors: [ + // Color(0xFF52B5FF), + // Color(0xFF8869F2), + // ], begin: Alignment.centerLeft, end: Alignment.centerRight), + ), + ), + centerTitle: true, + elevation: 0, + leading: IconButton( + color: Colors.white, + icon: ImageIcon(AssetImage('assets/images/ic_return.png')), + onPressed: () { + Navigator.pop(context); + }), + title: Text( + widget.title!, + style: TextStyle( + color: Colors.white, + fontSize: 17, + fontWeight: FontWeight.w600, + ), + ), + actions: []); + } + + _buildBody() { + return Column( + children: [ + SizedBox( + height: 1, + width: double.infinity, + child: const DecoratedBox(decoration: BoxDecoration(color: Color(0xFFEEEEEE))), + ), + Expanded( + flex: 1, + child: WebView( + initialUrl: widget.isLocalUrl + ? Uri.dataFromString(widget.url!, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString() + : widget.url, + javascriptMode: JavascriptMode.unrestricted, + javascriptChannels: [ + JavascriptChannel( + name: 'close', //handleName + onMessageReceived: (JavascriptMessage message) { + Navigator.pop(context); + }), + + JavascriptChannel( + name: 'getUserInfos', //handleName + onMessageReceived: (JavascriptMessage message) {}), + JavascriptChannel( + name: 'Toast', //handleName + onMessageReceived: (JavascriptMessage message) { + print(message.message); + //接收到js返回的数据 + //收到js返回并作出应答 + String callbackname = message.message; + String data = "收到消息调用了"; + String script = "$callbackname($data)"; + }), + ].toSet(), + onWebViewCreated: (WebViewController controller) { + _webViewController = controller; + if (widget.isLocalUrl) { + _loadHtmlAssets(controller); + } else { + controller.loadUrl(widget.url!); + } + controller.canGoBack().then((value) => debugPrint(value.toString())); + controller.canGoForward().then((value) => debugPrint(value.toString())); + controller.currentUrl().then((value) => debugPrint(value)); + }, + onPageFinished: (String value) { + _webViewController!.evaluateJavascript('document.title').then((title) => debugPrint(title)); + }, + ), + ) + ], + ); + } + +//加载本地文件 + _loadHtmlAssets(WebViewController controller) async { + String htmlPath = await rootBundle.loadString(widget.url! + "?" + Token); + controller.loadUrl(Uri.dataFromString(htmlPath, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString()); + } +} diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..e759cda --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,78 @@ +name: aiplot +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.1.0+1 + +environment: + sdk: '>=2.18.0 <3.0.0' + +dependencies: + flutter: + sdk: flutter + flutter_localizations: + sdk: flutter + + dio: ^5.1.1 #网络请求 + cupertino_icons: ^1.0.2 + flutter_easyloading: ^3.0.3 #简单的加载loading + event_bus: ^2.0.0 + common_utils: ^2.1.0 + shared_preferences: ^2.0.15 + device_info: ^2.0.3 + url_launcher: ^6.1.5 + flutter_staggered_grid_view: ^0.6.2 + image_gallery_saver: ^2.0.3 + cached_network_image: ^3.2.3 + permission_handler: ^10.4.5 + json_annotation: ^4.1.0 + image_picker: ^0.8.4 + mime: ^1.0.4 + flutter_native_image: ^0.0.6 + webview_flutter: ^2.8.0 + image_cropper: ^3.0.2 + expandable_text: ^2.3.0 + fluttertoast: ^8.2.1 + sensors_analytics_flutter_plugin: ^2.3.0 + ironsource_mediation: ^1.2.0 + share_plus: ^7.0.1 + path_provider: ^2.0.15 + connectivity_plus: ^3.0.0 + photo_view: ^0.14.0 + + +dev_dependencies: + build_runner: ^2.1.11 + flutter_test: + sdk: flutter + json_serializable: ^4.1.4 + + flutter_lints: ^2.0.0 + sa_aspectd_impl: + git: + url: https://github.com/sensorsdata/sa_aspectd_impl.git # 模块 github 地址 + ref: v2.2.1 # 对应版本 tag,建议使用最新版本 + +flutter: + + uses-material-design: true + assets: + - assets/ + - assets/images/ +flutter_intl: + enabled: true