admin
2022-03-31 36754ba47da7a3277d5be183a523c912a1dc4cef
service服务bug修复
5 文件已重命名
50个文件已修改
12个文件已添加
2535 ■■■■ 已修改文件
src/main/java/com/ks/codegenerator/controller/GeneratorController.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ks/codegenerator/utils/ServiceBuilder.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ks/codegenerator/vo/ServiceVO.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/app/build.gradle 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/app/src/main/AndroidManifest.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/app/src/main/java/com/demo/app/MyApplication.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/app/src/main/java/com/demo/app/ui/MainActivity.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/app/src/main/java/com/demo/app/ui/SplashActivity.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/app/src/main/res/layout/fragment_mine.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-ad/build.gradle 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-ad/src/main/AndroidManifest.xml 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-common/build/intermediates/compile_library_classes_jar/debug/classes.jar 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-common/build/intermediates/runtime_library_classes_jar/debug/classes.jar 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-common/build/tmp/compileDebugJavaWithJavac/source-classes-mapping.txt 116 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-dp/build.gradle 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-ec/build.gradle 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-flutter/build.gradle 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-flutter/src/main/AndroidManifest.xml 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-flutter/src/main/java/com/demo/library_flutter/FlutterCommonActivity.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-flutter/src/main/java/com/demo/library_flutter/message/AdMethodChannel.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-flutter/src/main/java/com/demo/library_flutter/message/DataMethodChannel.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-flutter/src/main/java/com/demo/library_flutter/message/UIMethodChannel.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/android/library-login/build.gradle 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/lib/api/http.dart 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/lib/utils/des/crypto_util.dart 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/lib/utils/des/des.dart 415 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/lib/utils/des/number_utils.dart 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/lib/utils/des/padding.dart 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/lib/utils/image_util.dart 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/lib/utils/sqlite_utils.dart 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/lib/utils/string_util.dart 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/pubspec.lock 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter/pubspec.yaml 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/main.dart 449 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/pubspec.lock 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/pubspec.yaml 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/test/widget_test.dart 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/UserLoginValid.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/UserController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/admin/AdminUserDao.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/feedback/AdviceDao.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/feedback/PrivacyComplainDao.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/QQUserInfoMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/UserInfoMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/WXUserInfoMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/OrderRecordMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/UserVIPInfoMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/feedback/AdviceServiceImpl.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/feedback/PrivacyComplainServiceImpl.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/QQUserInfoServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserInfoServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/WXUserInfoServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/OrderServiceImpl.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/VIPServiceImpl.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserInfoService.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/SystemInfoUtil.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/application-dev.yml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/application-pro.yml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/OrderRecordMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/QQUserInfoMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/UserInfoMapper.xml 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/UserVIPInfoMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/WXUserInfoMapper.xml 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mysql.sql 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/index.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/pom.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/service.html 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ks/codegenerator/controller/GeneratorController.java
@@ -2,6 +2,7 @@
import com.ks.codegenerator.utils.AndroidBuilder;
import com.ks.codegenerator.utils.ServiceBuilder;
import com.ks.codegenerator.vo.ServiceVO;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.yeshi.utils.JsonUtil;
@@ -23,14 +24,21 @@
    //生成service
    @RequestMapping("createService")
    public void service(String name, String pks, String subpks, PrintWriter out, HttpServletRequest request) {
        if (StringUtil.isNullOrEmpty(name) || StringUtil.isNullOrEmpty(pks) || StringUtil.isNullOrEmpty(subpks)) {
            out.print(JsonUtil.loadFalseResult("项目名称,项目包名,应用包名不能为空"));
    public void service(ServiceVO vo, PrintWriter out, HttpServletRequest request) {
        if (StringUtil.isNullOrEmpty(vo.getName()) || StringUtil.isNullOrEmpty(vo.getPks()) || StringUtil.isNullOrEmpty(vo.getSubpks()) || StringUtil.isNullOrEmpty(vo.getChineseName())) {
            out.print(JsonUtil.loadFalseResult("参数不完整"));
            return;
        }
        if (StringUtil.isNullOrEmpty(vo.getSqlDataBaseName()) || StringUtil.isNullOrEmpty(vo.getSqlTablePrefix()) || StringUtil.isNullOrEmpty(vo.getMongoDataBaseName())) {
            out.print(JsonUtil.loadFalseResult("参数不完整"));
            return;
        }
        String rootPath = request.getServletContext().getRealPath("cache");
        try {
            String path = new ServiceBuilder().setCacheDir(rootPath).setName(name).setPks(pks).setSubpks(subpks).build();
            String path = new ServiceBuilder().setCacheDir(rootPath).setName(vo.getName()).setPks(vo.getPks()).setSubpks(vo.getSubpks()).setProjectChineseName(vo.getChineseName()).setMongoDatabaseName(vo.getMongoDataBaseName()).setSqlDatabaseName(vo.getSqlDataBaseName()).setSqlTablePrefix(vo.getSqlTablePrefix()).build();
            out.print(JsonUtil.loadTrueResult(path));
        } catch (Exception e) {
            e.printStackTrace();
src/main/java/com/ks/codegenerator/utils/ServiceBuilder.java
@@ -30,6 +30,11 @@
    private String subpks;
    private String cacheDir;
    private String projectChineseName;
    private String sqlTablePrefix;
    private String sqlDatabaseName;
    private String mongoDatabaseName;
    public ServiceBuilder setName(String name) {
        this.name = name;
@@ -48,6 +53,26 @@
    public ServiceBuilder setCacheDir(String cacheDir) {
        this.cacheDir = cacheDir;
        return this;
    }
    public ServiceBuilder setProjectChineseName(String projectChineseName) {
        this.projectChineseName = projectChineseName;
        return this;
    }
    public ServiceBuilder setSqlTablePrefix(String sqlTablePrefix) {
        this.sqlTablePrefix = sqlTablePrefix;
        return this;
    }
    public ServiceBuilder setSqlDatabaseName(String sqlDatabaseName) {
        this.sqlDatabaseName = sqlDatabaseName;
        return this;
    }
    public ServiceBuilder setMongoDatabaseName(String mongoDatabaseName) {
        this.mongoDatabaseName = mongoDatabaseName;
        return this;
    }
@@ -119,7 +144,31 @@
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-dev.yml", "com.ks.app", subpks);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-dev.yml", "${mongoDataBaseName}", mongoDatabaseName);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-dev.yml", "${sqlDataBaseName}", sqlDatabaseName);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-dev.yml", "${projectName}", name);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-pro.yml", "com.ks.app", subpks);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-pro.yml", "${mongoDataBaseName}", mongoDatabaseName);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-pro.yml", "${sqlDataBaseName}", sqlDatabaseName);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/application-pro.yml", "${projectName}", name);
        //替换Mapper下的表前缀
        String mapperDir = path + "/app/src/main/resources/mapper";
        File mapperFiles = new File(mapperDir);
        for (File f : mapperFiles.listFiles()) {
            FileUtils.replaceFileContent(f.getAbsolutePath(), "com.ks.app", subpks);
            FileUtils.replaceFileContent(f.getAbsolutePath(), "lt_", sqlTablePrefix);
        }
        FileUtils.replaceFileContent(path + "/app/src/main/resources/mysql.sql", "${sqlDataBaseName}", sqlDatabaseName);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/mysql.sql", "${sqlTablePrefix}", sqlTablePrefix);
        FileUtils.replaceFileContent(path + "/app/src/main/resources/static/index.html", "${projectChineseName}", projectChineseName);
        FileUtils.replaceFileContent(path + "/app/src/main/java/"+subpks.replace(".","/")+"/aop/AdminApiFilter.java", "com.ks.app", subpks);
        FileUtils.replaceFileContent(path + "/app/src/main/java/"+subpks.replace(".","/")+"/aop/SignValidate.java", "com.ks.app", subpks);
        FileUtils.replaceFileContent(path + "/app/src/main/java/"+subpks.replace(".","/")+"/aop/UserLoginValid.java", "com.ks.app", subpks);
        FileUtils.replaceFileContent(path + "/app/src/main/java/"+subpks.replace(".","/")+"/Application.java", "com.ks.app", subpks);
    }
    //重新命名文件夹与文件
src/main/java/com/ks/codegenerator/vo/ServiceVO.java
New file
@@ -0,0 +1,75 @@
package com.ks.codegenerator.vo;
/**
 * @author hxh
 * @title: ServiceVO
 * @description: TODO
 * @date 2022/3/31 14:17
 */
public class ServiceVO {
    private String chineseName;
    private String name;
    private String pks;
    private String subpks;
    private String sqlDataBaseName;
    private String sqlTablePrefix;
    private String mongoDataBaseName;
    public String getChineseName() {
        return chineseName;
    }
    public void setChineseName(String chineseName) {
        this.chineseName = chineseName;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPks() {
        return pks;
    }
    public void setPks(String pks) {
        this.pks = pks;
    }
    public String getSubpks() {
        return subpks;
    }
    public void setSubpks(String subpks) {
        this.subpks = subpks;
    }
    public String getSqlDataBaseName() {
        return sqlDataBaseName;
    }
    public void setSqlDataBaseName(String sqlDataBaseName) {
        this.sqlDataBaseName = sqlDataBaseName;
    }
    public String getSqlTablePrefix() {
        return sqlTablePrefix;
    }
    public void setSqlTablePrefix(String sqlTablePrefix) {
        this.sqlTablePrefix = sqlTablePrefix;
    }
    public String getMongoDataBaseName() {
        return mongoDataBaseName;
    }
    public void setMongoDataBaseName(String mongoDataBaseName) {
        this.mongoDataBaseName = mongoDataBaseName;
    }
}
src/main/resources/code/android/app/build.gradle
@@ -6,7 +6,7 @@
    useLibrary 'org.apache.http.legacy'
    compileSdk 29
    compileSdk 31
    defaultConfig {
        applicationId "com.demo.android"
@@ -42,7 +42,6 @@
    implementation project(path: ':library-ec')
    implementation project(path: ':library-login')
    implementation project(path: ':library-flutter')
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation 'androidx.cardview:cardview:1.0.0'
src/main/resources/code/android/app/src/main/AndroidManifest.xml
@@ -3,6 +3,8 @@
    xmlns:tools="http://schemas.android.com/tools"
    package="com.demo.app">
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
    <application
        android:name="com.demo.app.MyApplication"
        android:allowBackup="true"
src/main/resources/code/android/app/src/main/java/com/demo/app/MyApplication.java
@@ -25,10 +25,12 @@
import com.idlefish.flutterboost.FlutterBoost;
import com.idlefish.flutterboost.FlutterBoostDelegate;
import com.idlefish.flutterboost.FlutterBoostRouteOptions;
import com.idlefish.flutterboost.FlutterBoostSetupOptions;
import com.idlefish.flutterboost.containers.FlutterBoostActivity;
import com.umeng.analytics.MobclickAgent;
import com.umeng.commonsdk.UMConfigure;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -36,6 +38,8 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.multidex.MultiDex;
import io.flutter.Log;
import io.flutter.app.FlutterApplication;
import io.flutter.embedding.android.FlutterActivityLaunchConfigs;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodCall;
@@ -82,9 +86,9 @@
        initAd(application, initListener);
        //小说
        initNovel(application);
//        initNovel(application);
        //穿山甲小视频
        initDPSDK(application);
//        initDPSDK(application);
        initFlutter(application);
    }
@@ -139,16 +143,30 @@
    public static void initFlutter(Application application) {
        FlutterBoostSetupOptions options = new FlutterBoostSetupOptions.Builder().build();
        FlutterBoost.instance().setup(application, new FlutterBoostDelegate() {
            @Override
            public void pushNativeRoute(FlutterBoostRouteOptions options) {
                Log.i(TAG, "pushNativeRoute");
//                options.arguments()
                //这里根据options.pageName来判断你想跳转哪个页面,这里简单给一个
                Intent intent = new Intent(FlutterBoost.instance().currentActivity(), FlutterCommonActivity.class);
                FlutterBoost.instance().currentActivity().startActivityForResult(intent, options.requestCode());
//                Intent intent = new Intent(FlutterBoost.instance().currentActivity(), FlutterCommonActivity.class);
//                intent.putExtra("pageRoute", options.pageName());
//                FlutterBoost.instance().currentActivity().startActivityForResult(intent, options.requestCode());
                Intent intent = new FlutterBoostActivity.CachedEngineIntentBuilder(FlutterCommonActivity.class)
                        .backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
                        .destroyEngineWithActivity(false)
                        .uniqueId(options.uniqueId())
                        .url(options.pageName())
                        .urlParams(options.arguments())
                        .build(FlutterBoost.instance().currentActivity());
                FlutterBoost.instance().currentActivity().startActivity(intent);
            }
            @Override
            public void pushFlutterRoute(FlutterBoostRouteOptions options) {
                Log.i(TAG, "pushFlutterRoute");
                Intent intent = new FlutterBoostActivity.CachedEngineIntentBuilder(FlutterBoostActivity.class)
                        .backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
                        .destroyEngineWithActivity(false)
@@ -157,6 +175,12 @@
                        .urlParams(options.arguments())
                        .build(FlutterBoost.instance().currentActivity());
                FlutterBoost.instance().currentActivity().startActivity(intent);
            }
            @Override
            public boolean popRoute(FlutterBoostRouteOptions options) {
                Log.i(TAG, "popRoute");
                return false;
            }
        }, engine -> {
            PlatformViewRegistry registry = engine.getPlatformViewsController().getRegistry();
@@ -186,13 +210,13 @@
                    return true;
                }
            });
            //广告接口
//            //广告接口
            new AdMethodChannel(engine.getDartExecutor().getBinaryMessenger(), application.getApplicationContext(), new AdMethodChannel.DataListener() {
            });
        });
        }, options);
    }
src/main/resources/code/android/app/src/main/java/com/demo/app/ui/MainActivity.java
@@ -3,7 +3,6 @@
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.RadioButton;
import android.widget.RadioGroup;
@@ -15,11 +14,16 @@
import com.demo.lib.common.activity.BaseActivity;
import com.demo.lib.common.dialog.DialogUtil;
import com.demo.lib.common.util.FragmentSwitchHelperV2;
import com.demo.library_flutter.FlutterRecommendFragment;
import com.idlefish.flutterboost.containers.FlutterBoostFragment;
import com.jaeger.library.StatusBarUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import androidx.fragment.app.Fragment;
import io.flutter.embedding.android.FlutterFragment;
public class MainActivity extends BaseActivity {
@@ -30,8 +34,21 @@
    private void initFragment() {
        List<Fragment> list = new ArrayList<>();
        FlutterRecommendFragment flutterRecommendFragment = new FlutterBoostFragment.CachedEngineFragmentBuilder(FlutterRecommendFragment.class)
                .url("/")
                .urlParams(new HashMap<>())
                .build();
        list.add(flutterRecommendFragment);
        MineFragment mineFragment = new MineFragment();
        list.add(mineFragment);
        Fragment[] fs = new Fragment[list.size()];
        list.toArray(fs);
        mFragmentSwitchHelper = FragmentSwitchHelperV2.create(R.id.fl_container, getSupportFragmentManager(), fs);
    }
@@ -50,7 +67,7 @@
                switch (checkedId) {
                    case R.id.rb_nav_recommend: {
                        mFragmentSwitchHelper
                                .changeFragment(HomeFragment.class);
                                .changeFragment(FlutterRecommendFragment.class);
                    }
                    break;
@@ -85,6 +102,7 @@
    }
    ExitDialog exitDialog = null;
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
src/main/resources/code/android/app/src/main/java/com/demo/app/ui/SplashActivity.java
@@ -25,10 +25,12 @@
import org.apache.http.Header;
import org.json.JSONObject;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
public class SplashActivity extends AppCompatActivity {
@@ -123,64 +125,86 @@
        SharedPreferences sharedPreferences = getSharedPreferences("permission", Context.MODE_PRIVATE);
        boolean showPermission = sharedPreferences.getBoolean("show", true);
//        if (1 > 0) {
//            toMainActivity();
//            return;
//        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PERMISSION_GRANTED && showPermission) {
            ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_CODE);
        } else {
            MyApplication.init(MyApplication.application, new MyApplication.InitListener() {
                @Override
                public void onFinish() {
            next();
        }
    }
                }
            });
            int delayMs = 1;
    void next() {
        MyApplication.init(MyApplication.application, new MyApplication.InitListener() {
            @Override
            public void onFinish() {
            }
        });
        if (1 > 0) {
            vg_ad.postDelayed(new Runnable() {
                @Override
                public void run() {
                    HttpApiUtil.getConfig(getApplicationContext(), new BasicTextHttpResponseHandler() {
                        @Override
                        public void onSuccessPerfect(int statusCode, Header[] headers, JSONObject jsonObject) throws Exception {
                            if (jsonObject != null) {
                                if (jsonObject.getBoolean("IsPost")) {
                                    JSONObject data = jsonObject.getJSONObject("Data");
                                    JSONObject ad = data.optJSONObject("adNew");
                                    //浏览器外跳协议
                                    AppConfigUtil.saveBrowserJumpOutProtocolPrefix(getApplicationContext(), data.optString("jumpAppProtocolPrefix"));
                                    //保存联系客服,注销链接
                                    AppConfigUtil.saveConcatUsLink(getApplicationContext(), data.optString("contactUsLink"));
                                    AppConfigUtil.saveUnRegisterLink(getApplicationContext(), data.optString("unRegisterLink"));
                                    AdUtil.saveAdConfig(getApplicationContext(), ad);
                                    MyApplication.initAd(MyApplication.application, new MyApplication.InitListener() {
                                        @Override
                                        public void onFinish() {
                                            runOnUiThread(new Runnable() {
                                                @Override
                                                public void run() {
                                                    loadSplashAd();
                                                }
                                            });
                                        }
                                    });
                                    return;
                                }
                            }
                            loadSplashAd();
                        }
                        @Override
                        public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                            super.onFailure(statusCode, headers, responseString, throwable);
                            loadSplashAd();
                        }
                    });
                    toMainActivity();
                }
            }, delayMs);
            },3000);
            return;
        }
        int delayMs = 1;
        vg_ad.postDelayed(new Runnable() {
            @Override
            public void run() {
                HttpApiUtil.getConfig(getApplicationContext(), new BasicTextHttpResponseHandler() {
                    @Override
                    public void onSuccessPerfect(int statusCode, Header[] headers, JSONObject jsonObject) throws Exception {
                        if (jsonObject != null) {
                            if (jsonObject.getBoolean("IsPost")) {
                                JSONObject data = jsonObject.getJSONObject("Data");
                                JSONObject ad = data.optJSONObject("adNew");
                                //浏览器外跳协议
                                AppConfigUtil.saveBrowserJumpOutProtocolPrefix(getApplicationContext(), data.optString("jumpAppProtocolPrefix"));
                                //保存联系客服,注销链接
                                AppConfigUtil.saveConcatUsLink(getApplicationContext(), data.optString("contactUsLink"));
                                AppConfigUtil.saveUnRegisterLink(getApplicationContext(), data.optString("unRegisterLink"));
                                AdUtil.saveAdConfig(getApplicationContext(), ad);
                                MyApplication.initAd(MyApplication.application, new MyApplication.InitListener() {
                                    @Override
                                    public void onFinish() {
                                        runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                loadSplashAd();
                                            }
                                        });
                                    }
                                });
                                return;
                            }
                        }
                        loadSplashAd();
                    }
                    @Override
                    public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                        super.onFailure(statusCode, headers, responseString, throwable);
                        loadSplashAd();
                    }
                });
            }
        }, delayMs);
    }
@@ -188,6 +212,7 @@
     * 加载开屏广告
     */
    private void loadSplashAd() {
        AdUtil.AD_TYPE splashType = AdUtil.getAdType(getApplicationContext(), "");
        if (splashType == null) {
            vg_ad.postDelayed(new Runnable() {
@@ -286,4 +311,26 @@
            finish();
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE) {
            for (int i = 0; i < permissions.length; i++) {
                if (grantResults[i] == PERMISSION_GRANTED) {//选择了“始终允许”
                    requetPermission();
                } else {
                    //拒绝了授权
                    if (grantResults[i] == PERMISSION_DENIED) {
                        SharedPreferences sharedPreferences = getSharedPreferences("permission", Context.MODE_PRIVATE);
                        SharedPreferences.Editor editor = sharedPreferences.edit();
                        editor.putBoolean("show", false);
                        editor.commit();
                    }
                    next();
                }
            }
        }
    }
}
src/main/resources/code/android/app/src/main/res/layout/fragment_mine.xml
@@ -5,6 +5,12 @@
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="我的"></TextView>
    <LinearLayout
        android:id="@+id/ll_user_info"
src/main/resources/code/android/library-ad/build.gradle
@@ -30,7 +30,6 @@
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation project(path: ':library-common')
src/main/resources/code/android/library-ad/src/main/AndroidManifest.xml
@@ -12,7 +12,52 @@
        android:allowBackup="true"
        android:label="@string/app_name"
        android:supportsRtl="true"
        tools:replace="android:allowBackup,android:theme"
        android:theme="@style/Theme.Android" />
        android:theme="@style/Theme.Android"
        tools:replace="android:allowBackup,android:theme">
        <!--广点通广告-->
        <!-- targetSDKVersion >= 24时才需要添加这个provider。provider的authorities属性的值为${applicationId}.fileprovider,请开发者根据自己的${applicationId}来设置这个值,例如本例中applicationId为"com.qq.e.union.demo"。 -->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/gdt_file_path"
                tools:replace="android:resource" />
        </provider>
        <provider
            android:name="com.qq.e.comm.GDTFileProvider"
            android:authorities="${applicationId}.gdt.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/gdt_file_path" />
        </provider>
        <service
            android:name="com.qq.e.comm.DownloadService"
            android:exported="false" />
        <!-- 网盟广告 -->
        <provider
            android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
            android:authorities="${applicationId}.TTFileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
        <!-- 网盟广告 -->
        <provider
            android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider"
            android:authorities="${applicationId}.TTMultiProvider" />
    </application>
</manifest>
src/main/resources/code/android/library-common/build/intermediates/compile_library_classes_jar/debug/classes.jar
Binary files differ
src/main/resources/code/android/library-common/build/intermediates/runtime_library_classes_jar/debug/classes.jar
Binary files differ
src/main/resources/code/android/library-common/build/tmp/compileDebugJavaWithJavac/source-classes-mapping.txt
@@ -4,6 +4,8 @@
 com.demo.lib.common.okhttp.request.CountingRequestBody$Listener
com/demo/lib/common/okhttp/cookie/store/SerializableHttpCookie.java
 com.demo.lib.common.okhttp.cookie.store.SerializableHttpCookie
com/demo/lib/common/widget/FlowLayout.java
 com.demo.lib.common.widget.FlowLayout
com/demo/lib/common/activity/BaseActivity.java
 com.demo.lib.common.activity.BaseActivity
com/demo/lib/common/upgrade/UpdateService.java
@@ -28,10 +30,8 @@
 com.demo.lib.common.util.common.ConnectionUtils$3
com/demo/lib/common/DatabaseContext.java
 com.demo.lib.common.DatabaseContext
com/demo/lib/common/okhttp/request/PostFormRequest.java
 com.demo.lib.common.okhttp.request.PostFormRequest
 com.demo.lib.common.okhttp.request.PostFormRequest$1
 com.demo.lib.common.okhttp.request.PostFormRequest$1$1
com/demo/lib/common/util/ui/LoadingDialogUtil.java
 com.demo.lib.common.util.ui.LoadingDialogUtil
com/demo/lib/common/util/FragmentSwitchHelper.java
 com.demo.lib.common.util.FragmentSwitchHelper
com/demo/lib/common/util/device/MobileUtil.java
@@ -46,34 +46,31 @@
 com.demo.lib.common.widget.SystemBarTintManager
 com.demo.lib.common.widget.SystemBarTintManager$1
 com.demo.lib.common.widget.SystemBarTintManager$SystemBarConfig
com/demo/lib/common/util/ui/MyActivityManager.java
 com.demo.lib.common.util.ui.MyActivityManager
com/demo/lib/common/okhttp/builder/HeadBuilder.java
 com.demo.lib.common.okhttp.builder.HeadBuilder
com/demo/lib/common/util/common/DimenUtils.java
 com.demo.lib.common.util.common.DimenUtils
com/demo/lib/common/okhttp/utils/L.java
 com.demo.lib.common.okhttp.utils.L
com/demo/lib/common/dialog/BottomDialog.java
 com.demo.lib.common.dialog.BottomDialog
com/demo/lib/common/okhttp/builder/OtherRequestBuilder.java
 com.demo.lib.common.okhttp.builder.OtherRequestBuilder
com/demo/lib/common/widget/TagCloudLayout.java
 com.demo.lib.common.widget.TagCloudLayout
 com.demo.lib.common.widget.TagCloudLayout$FlingRunnable
 com.demo.lib.common.widget.TagCloudLayout$OnScrollListener
 com.demo.lib.common.widget.TagCloudLayout$TagView
com/demo/lib/common/widget/ShelfView.java
 com.demo.lib.common.widget.ShelfView
com/demo/lib/common/util/ManifestDataUtil.java
 com.demo.lib.common.util.ManifestDataUtil
com/demo/lib/common/util/SingleToast.java
 com.demo.lib.common.util.SingleToast
 com.demo.lib.common.util.SingleToast$1
com/demo/lib/common/okhttp/utils/Platform.java
 com.demo.lib.common.okhttp.utils.Platform
 com.demo.lib.common.okhttp.utils.Platform$Android
 com.demo.lib.common.okhttp.utils.Platform$Android$MainThreadExecutor
com/demo/lib/common/dialog/SlidingDialog.java
 com.demo.lib.common.dialog.SlidingDialog
com/demo/lib/common/okhttp/log/LoggerInterceptor.java
 com.demo.lib.common.okhttp.log.LoggerInterceptor
com/demo/lib/common/util/common/SoftKeyboardUtils.java
 com.demo.lib.common.util.common.SoftKeyboardUtils
com/demo/lib/common/widget/verticalviewpager/ExtendedWebView.java
 com.demo.lib.common.widget.verticalviewpager.ExtendedWebView
com/demo/lib/common/emotion/EmotionEditText.java
 com.demo.lib.common.emotion.EmotionEditText
com/demo/lib/common/util/MarketUtils.java
 com.demo.lib.common.util.MarketUtils
com/demo/lib/common/upgrade/Version.java
@@ -82,8 +79,8 @@
 com.demo.lib.common.okhttp.builder.PostStringBuilder
com/demo/lib/common/okhttp/request/RequestCall.java
 com.demo.lib.common.okhttp.request.RequestCall
com/demo/lib/common/util/common/StringUtils.java
 com.demo.lib.common.util.common.StringUtils
com/demo/lib/common/drawable/SpotlightDrawable.java
 com.demo.lib.common.drawable.SpotlightDrawable
com/lcjian/lcjianlibrary/BuildConfig.java
 com.lcjian.lcjianlibrary.BuildConfig
com/demo/lib/common/okhttp/request/PostFileRequest.java
@@ -114,8 +111,8 @@
com/demo/lib/common/util/cache/StrictLineReader.java
 com.demo.lib.common.util.cache.StrictLineReader
 com.demo.lib.common.util.cache.StrictLineReader$1
com/demo/lib/common/widget/MyGridView.java
 com.demo.lib.common.widget.MyGridView
com/demo/lib/common/emotion/EmotionTextView.java
 com.demo.lib.common.emotion.EmotionTextView
com/demo/lib/common/entity/IsSeeking.java
 com.demo.lib.common.entity.IsSeeking
com/demo/lib/common/util/security/MD5Utils.java
@@ -148,14 +145,17 @@
 com.demo.lib.common.okhttp.cookie.store.PersistentCookieStore
com/demo/lib/common/okhttp/builder/PostFileBuilder.java
 com.demo.lib.common.okhttp.builder.PostFileBuilder
com/demo/lib/common/entity/ClipCopyContent.java
 com.demo.lib.common.entity.ClipCopyContent
com/demo/lib/common/widget/RatioLayout.java
 com.demo.lib.common.widget.RatioLayout
com/demo/lib/common/upgrade/UpdateActivity.java
 com.demo.lib.common.upgrade.UpdateActivity
 com.demo.lib.common.upgrade.UpdateActivity$1
 com.demo.lib.common.upgrade.UpdateActivity$2
com/demo/lib/common/util/PermissionsChecker.java
 com.demo.lib.common.util.PermissionsChecker
com/demo/lib/common/emotion/EmotionGridFragment.java
 com.demo.lib.common.emotion.EmotionGridFragment
 com.demo.lib.common.emotion.EmotionGridFragment$1
 com.demo.lib.common.emotion.EmotionGridFragment$EmotionAdapter
 com.demo.lib.common.emotion.EmotionGridFragment$OnEditListener
com/demo/lib/common/DeviceUuidFactory.java
 com.demo.lib.common.DeviceUuidFactory
com/demo/lib/common/widget/myswiperefreshlayout/MySwipeRefreshLayout.java
@@ -192,8 +192,9 @@
com/demo/lib/common/drawable/CrossFadeDrawable.java
 com.demo.lib.common.drawable.CrossFadeDrawable
 com.demo.lib.common.drawable.CrossFadeDrawable$1
com/demo/lib/common/widget/MyViewPager.java
 com.demo.lib.common.widget.MyViewPager
com/demo/lib/common/util/RefreshLayout.java
 com.demo.lib.common.util.RefreshLayout
 com.demo.lib.common.util.RefreshLayout$OnLoadListener
com/demo/lib/common/util/common/SerializeUtils.java
 com.demo.lib.common.util.common.SerializeUtils
com/demo/lib/common/okhttp/callback/StringCallback.java
@@ -306,35 +307,36 @@
 com.demo.lib.common.util.common.IClipboardContentListener
com/demo/lib/common/drawable/FastBitmapDrawable.java
 com.demo.lib.common.drawable.FastBitmapDrawable
com/demo/lib/common/okhttp/request/PostStringRequest.java
 com.demo.lib.common.okhttp.request.PostStringRequest
com/demo/lib/common/content/CursorLoader.java
 com.demo.lib.common.content.CursorLoader
com/demo/lib/common/dialog/BottomDialog.java
 com.demo.lib.common.dialog.BottomDialog
com/demo/lib/common/emotion/EmotionEditText.java
 com.demo.lib.common.emotion.EmotionEditText
com/demo/lib/common/widget/FlowLayout.java
 com.demo.lib.common.widget.FlowLayout
com/demo/lib/common/widget/ShelfView.java
 com.demo.lib.common.widget.ShelfView
com/demo/lib/common/util/ui/LoadingDialogUtil.java
 com.demo.lib.common.util.ui.LoadingDialogUtil
com/demo/lib/common/widget/AdaptiveListView.java
 com.demo.lib.common.widget.AdaptiveListView
com/demo/lib/common/emotion/EmotionTextView.java
 com.demo.lib.common.emotion.EmotionTextView
com/demo/lib/common/widget/RatioLayout.java
 com.demo.lib.common.widget.RatioLayout
com/demo/lib/common/emotion/EmotionGridFragment.java
 com.demo.lib.common.emotion.EmotionGridFragment
 com.demo.lib.common.emotion.EmotionGridFragment$1
 com.demo.lib.common.emotion.EmotionGridFragment$EmotionAdapter
 com.demo.lib.common.emotion.EmotionGridFragment$OnEditListener
com/demo/lib/common/drawable/SpotlightDrawable.java
 com.demo.lib.common.drawable.SpotlightDrawable
com/demo/lib/common/util/RefreshLayout.java
 com.demo.lib.common.util.RefreshLayout
 com.demo.lib.common.util.RefreshLayout$OnLoadListener
com/demo/lib/common/dialog/SlidingDialog.java
 com.demo.lib.common.dialog.SlidingDialog
com/demo/lib/common/content/CursorLoader.java
 com.demo.lib.common.content.CursorLoader
com/demo/lib/common/okhttp/utils/Platform.java
 com.demo.lib.common.okhttp.utils.Platform
 com.demo.lib.common.okhttp.utils.Platform$Android
 com.demo.lib.common.okhttp.utils.Platform$Android$MainThreadExecutor
com/demo/lib/common/widget/MyViewPager.java
 com.demo.lib.common.widget.MyViewPager
com/demo/lib/common/util/common/StringUtils.java
 com.demo.lib.common.util.common.StringUtils
com/demo/lib/common/util/PermissionsChecker.java
 com.demo.lib.common.util.PermissionsChecker
com/demo/lib/common/entity/ClipCopyContent.java
 com.demo.lib.common.entity.ClipCopyContent
com/demo/lib/common/widget/MyGridView.java
 com.demo.lib.common.widget.MyGridView
com/demo/lib/common/okhttp/request/PostStringRequest.java
 com.demo.lib.common.okhttp.request.PostStringRequest
com/demo/lib/common/okhttp/request/PostFormRequest.java
 com.demo.lib.common.okhttp.request.PostFormRequest
 com.demo.lib.common.okhttp.request.PostFormRequest$1
 com.demo.lib.common.okhttp.request.PostFormRequest$1$1
com/demo/lib/common/widget/TagCloudLayout.java
 com.demo.lib.common.widget.TagCloudLayout
 com.demo.lib.common.widget.TagCloudLayout$FlingRunnable
 com.demo.lib.common.widget.TagCloudLayout$OnScrollListener
 com.demo.lib.common.widget.TagCloudLayout$TagView
com/demo/lib/common/widget/verticalviewpager/ExtendedWebView.java
 com.demo.lib.common.widget.verticalviewpager.ExtendedWebView
com/demo/lib/common/okhttp/utils/L.java
 com.demo.lib.common.okhttp.utils.L
src/main/resources/code/android/library-dp/build.gradle
@@ -31,7 +31,6 @@
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation project(path: ':library-common')
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    api project(path: ':library-ad')
src/main/resources/code/android/library-ec/build.gradle
@@ -32,7 +32,7 @@
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    testImplementation 'junit:junit:4.+'
    implementation project(path: ':fluwx_no_pay')
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
@@ -71,5 +71,5 @@
    implementation files('libs/JDSDK_h.jar')
    api 'com.umeng.umsdk:share-wx:7.1.6' //微信完整版
    api 'com.tencent.mm.opensdk:wechat-sdk-android:6.8.0'//微信官方依赖库,必选
//    api 'com.tencent.mm.opensdk:wechat-sdk-android:6.8.0'//微信官方依赖库,必选
}
src/main/resources/code/android/library-flutter/build.gradle
@@ -6,7 +6,6 @@
    compileSdkVersion 31
    defaultConfig {
        applicationId "com.demo.library_flutter"
        minSdkVersion 19
        targetSdkVersion 31
        versionCode 1
@@ -20,9 +19,9 @@
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        profile {
            initWith debug
        }
//        profile {
//            initWith release
//        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
@@ -37,10 +36,10 @@
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation project(path: ':library-ad')
    implementation project(path: ':library-common')
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    api project(':flutter')
    api project(':flutter_boost')
    api project(path: ':flutter')
    api project(path: ':flutter_boost')
}
src/main/resources/code/android/library-flutter/src/main/AndroidManifest.xml
@@ -2,6 +2,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.demo.library_flutter">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
@@ -11,20 +19,24 @@
        android:theme="@style/Theme.Android">
        <activity
            android:name=".FlutterCommonActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
            android:exported="true"></activity>
        <activity
            android:name="io.flutter.embedding.android.FlutterActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize"
            />
            android:windowSoftInputMode="adjustResize" />
        <activity
            android:name="com.idlefish.flutterboost.containers.FlutterBoostActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize" />
        <meta-data
            android:name="flutterEmbedding"
            android:value="2"></meta-data>
    </application>
src/main/resources/code/android/library-flutter/src/main/java/com/demo/library_flutter/FlutterCommonActivity.java
@@ -1,14 +1,13 @@
package com.demo.library_flutter;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class FlutterCommonActivity extends AppCompatActivity {
import com.idlefish.flutterboost.containers.FlutterBoostActivity;
public class FlutterCommonActivity extends FlutterBoostActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
src/main/resources/code/android/library-flutter/src/main/java/com/demo/library_flutter/message/AdMethodChannel.java
@@ -17,10 +17,11 @@
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodCodec;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.common.StandardMethodCodec;
public class AdMethodChannel extends MethodChannel {
    public AdMethodChannel(BinaryMessenger messenger, Context context, DataListener dataListener) {
        super(messenger, "com.yeshi.video/ad", (MethodCodec) StandardMessageCodec.INSTANCE);
        super(messenger, "com.yeshi.video/ad", StandardMethodCodec.INSTANCE);
        setMethodCallHandler(new MethodCallHandler() {
            @Override
            public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
src/main/resources/code/android/library-flutter/src/main/java/com/demo/library_flutter/message/DataMethodChannel.java
@@ -14,10 +14,11 @@
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodCodec;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.common.StandardMethodCodec;
public class DataMethodChannel extends MethodChannel {
    public DataMethodChannel(BinaryMessenger messenger, Context context, DataListener dataListener) {
        super(messenger, "com.yeshi.video/data", (MethodCodec) StandardMessageCodec.INSTANCE);
        super(messenger, "com.yeshi.video/data", StandardMethodCodec.INSTANCE);
        setMethodCallHandler(new MethodCallHandler() {
            @Override
            public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
src/main/resources/code/android/library-flutter/src/main/java/com/demo/library_flutter/message/UIMethodChannel.java
@@ -16,10 +16,11 @@
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodCodec;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.common.StandardMethodCodec;
public class UIMethodChannel extends MethodChannel {
    public UIMethodChannel(BinaryMessenger messenger, Context context, DataListener dataListener) {
        super(messenger, "com.yeshi.video/ui", (MethodCodec) StandardMessageCodec.INSTANCE);
        super(messenger, "com.yeshi.video/ui", StandardMethodCodec.INSTANCE);
        setMethodCallHandler(new MethodCallHandler() {
            @Override
            public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
src/main/resources/code/android/library-login/build.gradle
@@ -30,7 +30,6 @@
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation project(path: ':library-common')
src/main/resources/code/flutter/lib/api/http.dart
@@ -14,6 +14,8 @@
import '../ui/widget/dialog.dart';
import '../utils/ui_utils.dart';
import '../model/common/http_model.dart';
import 'package:dio/dio.dart';
import 'package:dio/adapter.dart';
typedef OnHttpRequestFinish = void Function(HttpRequestResult result);
@@ -100,42 +102,52 @@
    // params ??= {};
    params = await getBaseParams(params);
    var httpClient = HttpClient();
    httpClient.connectionTimeout = const Duration(seconds: 20);
    var uri = Uri(
        scheme: "http",
        host: "api.location.izzql.com",
        path: api,
        port: 8090,
        queryParameters: params);
    // var uri = Uri(
    //     scheme: "http",
    //     host: "192.168.3.122",
    //     path: api,
    //     port: 8082,
    //     queryParameters: params);
    print("uri:$uri");
    if (onStart != null) {
      onStart();
    }
    HttpRequestResult requestResult;
    try {
      HttpClientRequest request = await httpClient.postUrl(uri);
      var response = await request.close();
      var dio = Dio()
        ..options = BaseOptions(
            baseUrl: "http://api.hanju.goxcw.com:8089/BuWan",
            connectTimeout: 20000,
            receiveTimeout: 1000 * 60,
            contentType: "application/x-www-form-urlencoded");
      //设置代理
      (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
          (HttpClient client) {
        client.findProxy = (uri) {
          return 'PROXY 192.168.3.122:8888';
        };
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) => true;
      };
      // FormData formData = FormData.fromMap(params);
      var response = await dio.post(
        api,
        data: params,
        onSendProgress: (int sent, int total) {
          print('$sent $total');
        },
      );
      if (response.statusCode == HttpStatus.ok) {
        String result = await response.transform(const Utf8Decoder()).join();
        String result = response.data.toString();
        print("网络请求结果:$result");
        requestResult = HttpRequestResult(true, jsonDecode(result));
      } else {
        requestResult = HttpRequestResult(false, null, msg: "网络请求失败");
      }
    } on TimeoutException catch (_) {
      requestResult = HttpRequestResult(false, null, msg: "网络请求超时");
    } on SocketException catch (_) {
      Fluttertoast.showToast(msg: "网络请求出错");
    } on DioError catch (_) {
      if (_.type == DioErrorType.connectTimeout ||
          _.type == DioErrorType.receiveTimeout ||
          _.type == DioErrorType.sendTimeout) {
        requestResult = HttpRequestResult(false, null, msg: "网络请求超时");
      } else {
        requestResult = HttpRequestResult(false, null, msg: "网络请求出错");
      }
    } catch (e) {
      requestResult = HttpRequestResult(false, null, msg: "网络请求出错");
    }
    if (notifyError && !requestResult.success) {
src/main/resources/code/flutter/lib/utils/des/crypto_util.dart
New file
@@ -0,0 +1,34 @@
import 'dart:typed_data';
class CryptoUtil {
  static List<int>? hex2List(String hexStr) {
    if (hexStr == null || hexStr.length % 2 != 0) {
      //十六进制字符串错误
      return null;
    }
    if (hexStr.startsWith('0x')) {
      hexStr = hexStr.substring(2);
    }
    List<int> result = List.filled(hexStr.length ~/ 2,0);
    String temp = '0123456789ABCDEF';
    for (int i = 0; i < hexStr.length; i += 2) {
      int h = temp.indexOf(hexStr.substring(i, i + 1));
      int l = temp.indexOf(hexStr.substring(i + 1, i + 2));
      result[i ~/ 2] = (h * 16 + l);
    }
    return result;
  }
  static String list2Hex(List<int> list) {
    List<String> results =  List.filled(list.length * 2,"");
    String temp = '0123456789ABCDEF';
    for (int i = 0; i < list.length; i++) {
      int h = list[i] ~/ 16;
      int l = list[i] % 16;
      results[i * 2] = temp.substring(h, h + 1);
      results[i * 2 + 1] = temp.substring(l, l + 1);
    }
    return results.join();
  }
}
src/main/resources/code/flutter/lib/utils/des/des.dart
New file
@@ -0,0 +1,415 @@
import 'dart:convert';
import 'dart:typed_data';
import 'crypto_util.dart';
import 'number_utils.dart';
import 'padding.dart';
/// author: karedem
/// 参考至: https://blog.csdn.net/yxtxiaotian/article/details/52025653
/// 以及 https://www.cnblogs.com/songwenlong/p/5944139.html
///
class DES {
  static const String _iv = '01234567';
  static const BLOCK_SIZE = 8;
  List<List<int>>? dispareKeys;
  static const E_box = [
    //E
    32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
    8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
    16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
    24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1
  ];
  static const IP = [
    //IP
    58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
    62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
    57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
    61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
  ];
  static const IP_1 = [
    //IP_R
    40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
    38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
    36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
    34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
  ];
  static const PC_1 = [
    //PC_1
    57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
    10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
    63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
    14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
  ];
  static const PC_2 = [
    //PC_2
    14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
    23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
    41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
    44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
  ];
  static const S_Box = [
    [
      // S1
      14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
      0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
      4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
      15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
    ],
    [
      //S2
      15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
      3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
      0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
      13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
    ],
    [
      //S3
      10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
      13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
      13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
      1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
    ],
    [
      //S4
      7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
      13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
      10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
      3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
    ],
    [
      //S5
      2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
      14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
      4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
      11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
    ],
    [
      //S6
      12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
      10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
      9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
      4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
    ],
    [
      //S7
      4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
      13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
      1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
      6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
    ],
    [
      //S8
      13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
      1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
      7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
      2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
    ]
  ];
  static const P_Box = [
    //P_box
    16, 7, 20, 21,
    29, 12, 28, 17,
    1, 15, 23, 26,
    5, 18, 31, 10,
    2, 8, 24, 14,
    32, 27, 3, 9,
    19, 13, 30, 6,
    22, 11, 4, 25
  ];
  static const shift_digit = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
  ///将64字节的密钥压缩成56字节  字节数组转为二进制数组
  List<int> _compressKeyTo56(List<int> key) {
    List<int> bitKey = List.filled(56,0);
    for (int i = 0; i < 56; i++) {
      int realIndex = PC_1[i] - 1;
      bitKey[i] = (key[realIndex >> 3] >> (7 - realIndex & 7)) & 1;
    }
    return bitKey;
  }
  ///离散得到16个子密钥
  List<List<int>> dispareKey(List<int> compressKey) {
    List<List<int>> dispareKeys = List.filled(16,[]);
    List<int> c0 = compressKey.sublist(0, 28);
    List<int> d0 = compressKey.sublist(28);
    List<int> tempc = c0;
    List<int> tempd = d0;
    for (int i = 0; i < 16; i++) {
      tempc = left_shift(i, tempc);
      tempd = left_shift(i, tempd);
      List<int> tempAll = [];
      tempAll.addAll(tempc);
      tempAll.addAll(tempd);
      List<int> dispareKey = compressDispareKey(tempAll);
      dispareKeys[i] = dispareKey;
    }
    return dispareKeys;
  }
  ///左移函数  需要根据次数 左移
  static List<int> left_shift(int times, List<int> key) {
    ///需移动的位数
    int shift_length = shift_digit[times];
    List<int> newList = key.sublist(shift_length);
    newList.addAll(key.sublist(0, shift_length));
    return newList;
  }
  ///将56位的密钥压缩为48位 二进制数组 处理
  List<int> compressDispareKey(List<int> dispareKey) {
    List<int> bitKey = List.filled(48,0);
    for (int i = 0; i < 48; i++) {
      int realIndex = PC_2[i] - 1;
      bitKey[i] = dispareKey[realIndex];
    }
    return bitKey;
  }
  //01001  9  1111 1111 >> 6
  ///明文转换  字节数组转二进制数组
  List<int> compressPlain(List<int> plain) {
    List<int> bitKey = List.filled(64,0);
    for (int i = 0; i < 64; i++) {
      int realIndex = IP[i] - 1;
      bitKey[i] = (plain[realIndex >> 3] >> (7 - realIndex & 7)) & 1;
    }
    return bitKey;
  }
  ///E盒扩展
  List<int> E_transform(List<int> list) {
    ///左半部分为 L0  右半部分为R0
    //print("before E transform : " + list.toString());
    List<int> result = List.filled(48,0);
    for (int i = 0; i < 48; i++) {
      result[i] = list[E_box[i] - 1];
    }
    //print("after E transform : " + result.toString());
    return result;
  }
  ///P盒置换
  List<int> P_transform(List<int> list) {
    List<int> bitKey = List.filled(32,0);
    for (int i = 0; i < 32; i++) {
      int realIndex = P_Box[i] - 1;
      bitKey[i] = list[realIndex];
    }
    return bitKey;
  }
  ///S盒变换 二进制结果
  List<int> _S_Box_transform(List<int> list) {
    ///check list length 48
    List<int> result = List.filled(32,0);
    for (int i = 0; i < list.length; i += 6) {
      int x = (list[i + 1] << 3 |
          list[i + 2] << 2 |
          list[i + 3] << 1 |
          list[i + 4]);
      int y = (list[i] << 1 | list[i + 5]);
      int i_n = S_Box[i ~/ 6][(y << 4) + x];
      result[(i << 1) ~/ 3] = (i_n >> 3) & 1;
      result[(i << 1) ~/ 3 + 1] = (i_n >> 2) & 1;
      result[(i << 1) ~/ 3 + 2] = (i_n >> 1) & 1;
      result[(i << 1) ~/ 3 + 3] = i_n & 1;
    }
    //print('before S box : ${list.toString()}');
    //print('after S box : ${result.toString()}');
    return result;
  }
  ///异或
  List<int> _XOR_with_Left(List<int> left, List<int> presult) {
    List<int> result = List.filled(left.length,0);
    for (int i = 0; i < left.length; i++) {
      result[i] = left[i] ^ presult[i];
    }
    return result;
  }
  ///IP_1置换
  List<int> _IP_1_transform(List<int> list) {
    ///check list length 48
    List<int> bitKey = List.filled(64,0);
    for (int i = 0; i < 64; i++) {
      int realIndex = IP_1[i] - 1;
      bitKey[i] = list[realIndex];
    }
    return bitKey;
  }
  void initKey(List<int> key) {
    if (dispareKeys != null) {
      return;
    }
    List<int> pc1_key = _compressKeyTo56(key);
    dispareKeys = dispareKey(pc1_key);
  }
  /// ECB加密 加密结果为十六进制 默认为PKCS7填充
  /// plain : 待加密数据 (utf-8)
  /// hexKey : 十六进制密钥
  String encryptToHexWithECB(String plain, String hexKey) {
    return CryptoUtil.list2Hex(encrypWithEcb(
        Utf8Encoder().convert(plain).toList(), CryptoUtil.hex2List(hexKey)!));
  }
  /// CBC加密 加密结果为十六进制 默认为PKCS7填充
  /// plain : 待加密数据 (utf-8)
  /// hexKey : 十六进制密钥
  /// iv : 向量 (utf-8 默认值为_iv)
  String encryptToHexWithCBC(String plain, String hexKey, {String iv = _iv}) {
    return CryptoUtil.list2Hex(encryptWithCBC(
        Utf8Encoder().convert(plain).toList(), CryptoUtil.hex2List(hexKey)!,
        iv: iv));
  }
  /// CBC解密
  /// cipher : 待解密数据 (十六进制)
  /// hexKey : 十六进制密钥
  /// iv : 向量 (utf-8 默认值为_iv)
  String decryptFromHexWithCBC(String cipher, String hexKey,
      {String iv = _iv}) {
    return Utf8Decoder().convert(decryptWithCBC(
        CryptoUtil.hex2List(cipher)!, CryptoUtil.hex2List(hexKey)!,
        iv: iv));
  }
  /// ECB解密
  /// cipher : 待解密数据 (十六进制)
  /// hexKey : 十六进制密钥
  String decryptFromHexWithECB(String cipher, String hexKey,
      {String iv = _iv}) {
    return Utf8Decoder().convert(decryptWithEcb(
        CryptoUtil.hex2List(cipher)!, CryptoUtil.hex2List(hexKey)!));
  }
  ///加密   明文字节数组  密钥字节数组
  List<int> _encryptBlock(List<int> block) {
    ///dispareKey right!
    //print("block " + block.toString());
    var plainCompressed = compressPlain(block);
    //print("plainCompressed " + plainCompressed.toString());
    List<int> L0 = plainCompressed.sublist(0, 32);
    List<int> R0 = plainCompressed.sublist(32);
    List<int> L0Z = L0;
    List<int> R0Z = R0;
    for (int i = 0; i < 16; i++) {
      var ln = R0Z;
      var pResult = P_transform(
          _S_Box_transform(_XOR_with_Left(dispareKeys![i], E_transform(R0Z))));
      ///P盒置换的结果盒L0做异或
      var rn = _XOR_with_Left(pResult, L0Z);
      L0Z = ln;
      R0Z = rn;
    }
    List<int> result = [];
    result.addAll(R0Z);
    result.addAll(L0Z);
    result = _IP_1_transform(result);
    return NumberUtils.intListFromBits(result);
  }
  List<int> encryptWithCBC(List<int> plain, List<int> key, {String iv = _iv}) {
    int allLen = plain.length;
    int blockCount = allLen >> 3;
    List<int> padPlain = plain.sublist(0, blockCount << 3);
    padPlain.addAll(Padding.pkcs7Padding(plain.sublist(blockCount << 3)));
    //List<int> blockCipher = List(padPlain.length);
    List<int> blockCipher = [];
    List<int> tempIv = iv.codeUnits;
    initKey(key);
    for (int i = 0; i < padPlain.length; i += BLOCK_SIZE) {
      List<int> xorPlain =
          _XOR_with_Left(padPlain.sublist(i, i + BLOCK_SIZE), tempIv);
      tempIv = _encryptBlock(xorPlain);
      blockCipher.addAll(tempIv);
    }
    return blockCipher;
  }
  List<int> decryptWithCBC(List<int> cipher, List<int> key, {String iv = _iv}) {
    List<int> plain = [];
    List<int> tempIv = iv.codeUnits;
    initKey(key);
    for (int i = 0; i < cipher.length; i += BLOCK_SIZE) {
      if (i == cipher.length - BLOCK_SIZE) {
        List<int> plainXor = decryptBlock(cipher.sublist(i, i + BLOCK_SIZE));
        List<int> plainBlock =
            Padding.pkcs7UnPadding(_XOR_with_Left(plainXor, tempIv));
        tempIv = cipher.sublist(i, i + BLOCK_SIZE);
        plain.addAll(plainBlock);
      } else {
        List<int> plainXor = decryptBlock(cipher.sublist(i, i + BLOCK_SIZE));
        List<int> plainBlock = _XOR_with_Left(plainXor, tempIv);
        tempIv = cipher.sublist(i, i + BLOCK_SIZE);
        plain.addAll(plainBlock);
      }
    }
    return plain;
  }
  ///加密   明文字节数组  密钥字节数组
  List<int> encrypWithEcb(List<int> plain, List<int> key) {
    List<int> blockCipher = [];
    int allLen = plain.length;
    int blockCount = allLen >> 3;
    List<int> padPlain = plain.sublist(0, blockCount << 3).toList();
    padPlain.addAll(Padding.pkcs7Padding(plain.sublist(blockCount << 3)));
    initKey(key);
    for (int i = 0; i < padPlain.length; i += BLOCK_SIZE) {
      blockCipher.addAll(_encryptBlock(padPlain.sublist(i, i + BLOCK_SIZE)));
    }
    return blockCipher;
  }
  List<int> decryptBlock(List<int> cipher) {
    var plainCompressed = compressPlain(cipher);
    List<int> L0 = plainCompressed.sublist(0, plainCompressed.length >> 1);
    List<int> R0 = plainCompressed.sublist(plainCompressed.length >> 1);
    List<int> L0Z = L0;
    List<int> R0Z = R0;
    for (int i = 0; i < 16; i++) {
      var ln = R0Z;
      var pResult = P_transform(_S_Box_transform(
          _XOR_with_Left(dispareKeys![15 - i], E_transform(R0Z))));
      var rn = _XOR_with_Left(pResult, L0Z);
      L0Z = ln;
      R0Z = rn;
    }
    List<int> result = [];
    result.addAll(R0Z);
    result.addAll(L0Z);
    result = _IP_1_transform(result);
    return NumberUtils.intListFromBits(result);
  }
  ///支持长数据解密
  List<int> decryptWithEcb(List<int> cipher, List<int> key) {
    List<int> plain = [];
    initKey(key);
    for (int i = 0; i < cipher.length; i += BLOCK_SIZE) {
      if (i == cipher.length - BLOCK_SIZE) {
        plain.addAll(Padding.pkcs7UnPadding(
            decryptBlock(cipher.sublist(i, i + BLOCK_SIZE))));
      } else {
        plain.addAll(decryptBlock(cipher.sublist(i, i + BLOCK_SIZE)));
      }
    }
    return plain;
  }
}
src/main/resources/code/flutter/lib/utils/des/number_utils.dart
New file
@@ -0,0 +1,95 @@
import 'dart:math';
class NumberUtils {
  ///二进制数组转字节数组
  static List<int> intListFromBits(List<int> bits) {
    //print("${bits.toString()} ${bits.length ~/ 8}");
    List<int> result = List.generate(bits.length >> 3, (index) => 0);
    for (int i = 0; i < bits.length; i++) {
      result[i >> 3] |= (bits[i] << (7 - i & 7));
    }
    return result;
  }
  ///字节数组转二进制数组
  static List<int> bitsFromIntList(List<int> ints) {
    List<int> result = List.filled(ints.length << 3,0);
    for (int i = 0; i < (ints.length << 3); ++i) {
      result[i] = (ints[i >> 3] >> (7 - i & 7)) & 1;
    }
    return result;
//    List<int> result = [];
//    ints.forEach((i) {
//      result.addAll(to8Bit(i));
//    });
//    return result;
  }
  ///二进制字符串转数字
  static int intFromBits(List<int> bits) {
    //return int.parse(bits.join(), radix: 2);
    int result = 0;
    for (int i = 0; i < bits.length; i++) {
      result |= (bits[i] << (7 - i & 7));
    }
    return result;
  }
  ///to8Bit  01100100
  static List<int> t8Bit(List<int> bytes) {
    List<int> result = List.filled(8 * bytes.length,0);
    for (int i = 0; i < 8 * bytes.length; ++i) {
      result[i] = (bytes[i >> 3] >> (7 - i & 7)) & 1;
    }
    return result;
  }
  /// 4 -> 00000100
  static List<int> to8Bit(int num) {
    List<int> result = List.filled(8,0);
    for (int i = 0; i < 8; i++) {
      result[i] = (num >> (7 - i & 7)) & 1;
    }
    return result;
    String temp = num.toRadixString(2);
    int zeroLen = 8 - temp.length;
    for (int i = 0; i < 8; i++) {
      if (i < zeroLen) {
        result[i] = 0;
      } else {
        result[i] = (temp.codeUnitAt(i - zeroLen) - 48);
      }
    }
    return result;
  }
  /// 4 -> 0100
  static List<int> to4Bit(int num) {
    List<int> result = List.filled(4,0);
    for (int i = 0; i < 4; i++) {
      result[i] = (num >> (3 - i & 3)) & 1;
    }
    return result;
    String temp = num.toRadixString(2);
    temp.codeUnits.forEach((code) {
      result.add(code - 48);
    });
    int len = result.length;
    if (len < 4) {
      result.insertAll(0, List.generate(4, (index) => 0).sublist(len));
    }
    return result;
  }
  static String formatSeeds(int seeds) {
    if (seeds > 9999) {
      return '${(seeds / 10000.0).toStringAsFixed(1)}w';
    } else if (seeds > 999) {
      return '${(seeds / 1000.0).toStringAsFixed(1)}k';
    } else {
      return '$seeds';
    }
  }
}
src/main/resources/code/flutter/lib/utils/des/padding.dart
New file
@@ -0,0 +1,19 @@
class Padding {
  static List<int> pkcs7Padding(List<int> data) {
    int fillLen = 8 - data.length % 8;
    List<int> padDate = data.toList();
    for (int i = 0; i < fillLen; i++) {
      padDate.add(fillLen);
    }
    return padDate;
  }
  static List<int> pkcs7UnPadding(List<int> padData) {
    int fillLen = padData.last;
    if (fillLen < 0 || fillLen > 8) {
      return padData;
    }
    List<int> data = padData.sublist(0, padData.length - fillLen);
    return data;
  }
}
src/main/resources/code/flutter/lib/utils/image_util.dart
New file
@@ -0,0 +1,36 @@
//图片工具
import 'package:flutter/material.dart';
import 'package:hanju/utils/ui_constant.dart';
import 'package:image_cropper/image_cropper.dart';
import 'dart:io';
import 'package:image_picker/image_picker.dart';
class ImageUtil{
  //选择并裁剪图片
  static Future<File?> selectAndCropImage() async{
    final ImagePicker _picker = ImagePicker();
    final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
    ImageCropper cropper=ImageCropper();
    File? croppedFile = await cropper.cropImage(
        cropStyle:CropStyle.circle,
        sourcePath: image!.path,
        aspectRatioPresets: [
          CropAspectRatioPreset.square
        ],
        androidUiSettings: const AndroidUiSettings(
            toolbarTitle: 'Cropper',
            toolbarColor: ColorConstant.theme,
            toolbarWidgetColor: Colors.white,
            initAspectRatio: CropAspectRatioPreset.square,
            lockAspectRatio: true),
        iosUiSettings: const IOSUiSettings(
          minimumAspectRatio: 1.0,
        )
    );
    return croppedFile;
  }
}
src/main/resources/code/flutter/lib/utils/sqlite_utils.dart
New file
@@ -0,0 +1,68 @@
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
class SQLiteUtil {
  static const String DB_NAME = "hanju.db";
  static Future<Database> _getDB() async {
    var path = await getDatabasesPath() + "/$DB_NAME";
    print("databasepath:$path");
    Database database = await openDatabase(path, version: 1,
        onCreate: (Database db, int version) async {
      // TODO
      List<String> tables =[];
      for (var i = 0; i < tables.length; i++) {
        await db.execute(tables[i]);
      }
    });
    return database;
  }
  static Future executeSQL(String sql) async {
    var db = await openDatabase("");
    await db.execute(sql);
    await db.close();
  }
  static Future executeSQLWithParams(String sql, List params) async {
    var db = await _getDB();
    await db.execute(sql, params);
    await db.close();
  }
  static Future executeSQLs(List<String> sqls) async {
    var db = await _getDB();
    for (var i = 0; i < sqls.length; i++) {
      await db.execute(sqls[i]);
    }
    await db.close();
  }
  ///批量插入
  ///sql示例:INSERT INTO artists (name) VALUES (?)
  static Future insert(String sql, List<List> list) async {
    var db = await _getDB();
    await db.transaction((txn) async {
      for (var i = 0; i < list.length; i++) {
        await txn.rawInsert(sql, list[i]);
      }
    });
    await db.close();
  }
  ///查询
  static Future<List<Map>> select(String sql, List params) async {
    var db = await _getDB();
    List<Map> list = await db.rawQuery(sql, params);
    await db.close();
    return list;
  }
  static Future<int> count(String sql, List params) async {
    var db = await _getDB();
    int? count = Sqflite.firstIntValue(await db.rawQuery(sql, params));
    await db.close();
    return count!;
  }
}
src/main/resources/code/flutter/lib/utils/string_util.dart
@@ -6,6 +6,12 @@
        .hasMatch(str);
  }
  static bool isEmail(String str) {
    return RegExp(
        '^(\\w)+(\\.\\w+)*@(\\w)+((\\.\\w+)+)\$')
        .hasMatch(str);
  }
  static bool isNullOrEmpty(String? str) {
    return str==null|| str.isEmpty || str.trim().isEmpty;
  }
src/main/resources/code/flutter/pubspec.lock
@@ -15,6 +15,27 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.1.0"
  cached_network_image:
    dependency: "direct dev"
    description:
      name: cached_network_image
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "3.2.0"
  cached_network_image_platform_interface:
    dependency: transitive
    description:
      name: cached_network_image_platform_interface
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.0.0"
  cached_network_image_web:
    dependency: transitive
    description:
      name: cached_network_image_web
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.0.1"
  characters:
    dependency: transitive
    description:
@@ -43,6 +64,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.15.0"
  cross_file:
    dependency: transitive
    description:
      name: cross_file
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.3.2"
  crypto:
    dependency: "direct dev"
    description:
@@ -125,6 +153,20 @@
    description: flutter
    source: sdk
    version: "0.0.0"
  flutter_blurhash:
    dependency: transitive
    description:
      name: flutter_blurhash
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.6.4"
  flutter_cache_manager:
    dependency: transitive
    description:
      name: flutter_cache_manager
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "3.3.0"
  flutter_datetime_picker:
    dependency: "direct dev"
    description:
@@ -146,6 +188,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.0.3"
  flutter_plugin_android_lifecycle:
    dependency: transitive
    description:
      name: flutter_plugin_android_lifecycle
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.5"
  flutter_spinkit:
    dependency: "direct dev"
    description:
@@ -160,6 +209,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.1.6"
  flutter_swiper_null_safety:
    dependency: "direct dev"
    description:
      name: flutter_swiper_null_safety
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.0.2"
  flutter_tencentad:
    dependency: "direct dev"
    description:
@@ -219,6 +275,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.15.0"
  http:
    dependency: transitive
    description:
      name: http
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.13.4"
  http_parser:
    dependency: transitive
    description:
@@ -226,6 +289,41 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "4.0.0"
  image_cropper:
    dependency: "direct dev"
    description:
      name: image_cropper
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.5.0"
  image_gallery_saver:
    dependency: "direct dev"
    description:
      name: image_gallery_saver
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.7.1"
  image_picker:
    dependency: "direct dev"
    description:
      name: image_picker
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.8.4+11"
  image_picker_for_web:
    dependency: transitive
    description:
      name: image_picker_for_web
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.1.6"
  image_picker_platform_interface:
    dependency: transitive
    description:
      name: image_picker_platform_interface
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.4.4"
  jpush_flutter:
    dependency: "direct dev"
    description:
@@ -272,6 +370,13 @@
    dependency: transitive
    description:
      name: mime
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.0.1"
  octo_image:
    dependency: transitive
    description:
      name: octo_image
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.0.1"
@@ -338,6 +443,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.5"
  pedantic:
    dependency: transitive
    description:
      name: pedantic
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.11.1"
  permission_handler:
    dependency: "direct dev"
    description:
@@ -394,6 +506,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "4.0.0"
  rxdart:
    dependency: transitive
    description:
      name: rxdart
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.27.3"
  screenshot:
    dependency: "direct dev"
    description:
@@ -637,6 +756,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.2"
  uuid:
    dependency: transitive
    description:
      name: uuid
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "3.0.6"
  vector_math:
    dependency: transitive
    description:
src/main/resources/code/flutter/pubspec.yaml
@@ -51,12 +51,13 @@
  shared_preferences: ^2.0.8
  sqflite: ^2.0.0+3
  dio: ^4.0.0
  #轮播图插件
  flutter_swiper: ^1.1.6
  #轮播图插件
  flutter_swiper_null_safety: ^1.0.2
  fluttertoast: ^8.0.8
@@ -107,6 +108,19 @@
  #截图插件
  screenshot: ^1.2.3
  #网络图片加载框架
  cached_network_image: ^3.2.0
  #图片选择
  image_picker: ^0.8.4+9
  #图片裁剪
  image_cropper: ^1.5.0
  sqflite: ^2.0.2
  #保存图片到相册
  image_gallery_saver: ^1.7.1
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
src/main/resources/code/flutter_module/lib/main.dart
@@ -1,112 +1,371 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_boost/flutter_boost.dart';
void main() => runApp(const MyApp());
import '../../home.dart';
import '../../model/video/video_model.dart';
import '../../ui/common/browser.dart';
import '../../ui/demo_page.dart';
import '../../ui/mine/email_login.dart';
import '../../ui/mine/login.dart';
import '../../ui/mine/person_info.dart';
import '../../ui/mine/settings.dart';
import '../../ui/video/video_collected_list.dart';
import '../../ui/video/video_detail.dart';
import '../../ui/video/video_list.dart';
import '../../ui/video/video_scan_record_list.dart';
import 'mine.dart';
import 'ui/mine/about_us.dart';
import 'ui/mine/advice.dart';
import 'ui/search/search.dart';
import 'ui/video/video_attention_list.dart';
import 'ui/video/video_download_list.dart';
import 'ui/video/video_player_browser.dart';
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
// void main() {
//   runApp(getBasePage(
//     AboutUsPage(title: ""),
//   ));
// }
  // This widget is the root of your application.
void main() {
  ///添加全局生命周期监听类
  PageVisibilityBinding.instance.addGlobalObserver(AppLifecycleObserver());
  CustomFlutterBinding();
  //window.defaultRouteName
  runApp(MyApp());
}
class CustomFlutterBinding extends WidgetsFlutterBinding
    with BoostFlutterBinding {}
class MyApp extends StatefulWidget {
  @override
  Widget build(BuildContext context) {
  _MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
  /// 由于很多同学说没有跳转动画,这里是因为之前exmaple里面用的是 [PageRouteBuilder],
  /// 其实这里是可以自定义的,和Boost没太多关系,比如我想用类似iOS平台的动画,
  /// 那么只需要像下面这样写成 [CupertinoPageRoute] 即可
  /// (这里全写成[MaterialPageRoute]也行,这里只不过用[CupertinoPageRoute]举例子)
  ///
  /// 注意,如果需要push的时候,两个页面都需要动的话,
  /// (就是像iOS native那样,在push的时候,前面一个页面也会向左推一段距离)
  /// 那么前后两个页面都必须是遵循CupertinoRouteTransitionMixin的路由
  /// 简单来说,就两个页面都是CupertinoPageRoute就好
  /// 如果用MaterialPageRoute的话同理
  static Route<dynamic>? _getSimpleRoute(
      RouteSettings settings, String? uniqueId, Widget page) {
    return CupertinoPageRoute(
        settings: settings,
        builder: (_) {
          return page;
        });
  }
  Map<String, FlutterBoostRouteFactory> routerMap = {
    '/': (RouteSettings settings, String? uniqueId) {
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            // Map<String, Object> map = settings.arguments as Map<String, Object> ;
            // String data = map['data'] as String;
            return HomePage(
              title: "",
            );
          });
    },
    'home': (RouteSettings settings, String? uniqueId) {
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            // Map<String, Object> map = settings.arguments as Map<String, Object> ;
            // String data = map['data'] as String;
            return HomePage(
              title: "",
            );
          });
    },
    'mine': (RouteSettings settings, String? uniqueId) {
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            return MinePage(
              title: "",
            );
          });
    },
    'VideoDetailPage': (RouteSettings settings, String? uniqueId) {
      if (settings.arguments == null) {
        return null;
      }
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            Map<String, dynamic> params =
                settings.arguments as Map<String, dynamic>;
            int position = params["position"] ?? 0;
            return VideoDetailPage(
              videoInfo: VideoInfoModel.fromJson(params["video"]),
              position: position,
            );
          });
    },
    'VideoCollectedPage': (RouteSettings settings, String? uniqueId) {
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            return VideoCollectedPage(
              title: "",
            );
          });
    },
    'VideoAttentionPage': (RouteSettings settings, String? uniqueId) {
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            return VideoAttentionPage(
              title: "",
            );
          });
    },
    'VideoScanRecordPage': (RouteSettings settings, String? uniqueId) {
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            return VideoScanRecordPage(
              title: "",
            );
          });
    },
    'VideoDownloadPage': (RouteSettings settings, String? uniqueId) {
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            return VideoDownloadPage(
              title: "",
            );
          });
    },
    "PersonInfoPage": (RouteSettings settings, String? uniqueId) {
      return _getSimpleRoute(settings, uniqueId, PersonInfoPage(title: ""));
    },
    "SettingPage": (RouteSettings settings, String? uniqueId) {
      return _getSimpleRoute(settings, uniqueId, SettingPage(title: ""));
    },
    "EmailLoginPage": (RouteSettings settings, String? uniqueId) {
      return _getSimpleRoute(settings, uniqueId, EmailLoginPage(title: ""));
    },
    "LoginPage": (RouteSettings settings, String? uniqueId) {
      return _getSimpleRoute(settings, uniqueId, LoginPage(title: ""));
    },
    "AdvicePage": (RouteSettings settings, String? uniqueId) {
      return _getSimpleRoute(settings, uniqueId, AdvicePage(title: ""));
    },
    "AboutUsPage": (RouteSettings settings, String? uniqueId) {
      return _getSimpleRoute(settings, uniqueId, AboutUsPage(title: ""));
    },
    'SearchPage': (RouteSettings settings, String? uniqueId) {
      if (settings.arguments == null) {
        return null;
      }
      Map<String, dynamic> params = settings.arguments as Map<String, dynamic>;
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            return SearchPage(
              title: params["title"] ?? "",
            );
          });
    },
    'VideoListPage': (RouteSettings settings, String? uniqueId) {
      if (settings.arguments == null) {
        return null;
      }
      Map<String, dynamic> params = settings.arguments as Map<String, dynamic>;
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            String kw = params["kw"]!;
            String title = params["title"] ?? "";
            return VideoListPage(
              title: title,
              kw: kw,
            );
          });
    },
    'BrowserPage': (RouteSettings settings, String? uniqueId) {
      if (settings.arguments == null) {
        return null;
      }
      Map<String, dynamic> params = settings.arguments as Map<String, dynamic>;
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            String title = params["title"] ?? "";
            return BrowserPage(title: title, url: params["url"]);
          });
    },
    'VideoPlayerWebPage': (RouteSettings settings, String? uniqueId) {
      if (settings.arguments == null) {
        return null;
      }
      Map<String, dynamic> params = settings.arguments as Map<String, dynamic>;
      return CupertinoPageRoute(
          settings: settings,
          builder: (_) {
            String title = params["title"] ?? "";
            return VideoPlayerWebPage(title: title, url: params["url"]);
          });
    },
  };
  Route<dynamic>? routeFactory(RouteSettings settings, String? uniqueId) {
    print("路由构造:${settings}");
    FlutterBoostRouteFactory? func = routerMap[settings.name!];
    if (func == null) {
      return null;
    }
    return func(settings, uniqueId);
  }
  Widget appBuilder(Widget home) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the
        // counter didn't reset back to zero; the application is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
      home: home,
      debugShowCheckedModeBanner: true,
      ///必须加上builder参数,否则showDialog等会出问题
      builder: (_, __) {
        return home;
      },
    );
  }
}
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.
  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".
  final String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  void initState() {
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    return FlutterBoostApp(
      routeFactory,
      appBuilder: appBuilder,
    );
  }
}
Widget widgetForRoute(String route) {
  print("flutter page: $route");
  Map<String, dynamic> json = jsonDecode(route);
  String page = json["page"];
  dynamic params = json["params"];
  switch (page) {
    case "DemoPage":
      return DemoPage(
        title: '',
      );
    case "home":
      return HomePage(
        title: '',
      );
    case "mine":
      return MinePage(title: "");
    case "VideoCollectedPage":
      return VideoCollectedPage(title: "");
    case "VideoAttentionPage":
      return VideoAttentionPage(title: "");
    case "VideoScanRecordPage":
      return VideoScanRecordPage(title: "");
    case "VideoDownloadPage":
      return VideoDownloadPage(title: "");
    case "PersonInfoPage":
      return PersonInfoPage(title: "");
    case "SettingPage":
      return SettingPage(title: "");
    case "EmailLoginPage":
      return EmailLoginPage(title: "");
    case "LoginPage":
      return LoginPage(title: "");
    case "AdvicePage":
      return AdvicePage(title: "");
    case "SearchPage":
      return SearchPage(title: params!["title"]);
    case "AboutUsPage":
      return AboutUsPage(title: "");
    case "VideoDetailPage":
      {
        int position = params!["position"] ?? 0;
        return VideoDetailPage(
          videoInfo: VideoInfoModel.fromJson(params!["video"]),
          position: position,
        );
      }
    case "VideoListPage":
      {
        String kw = params!["kw"]!;
        String title = params!["title"] ?? "";
        return VideoListPage(
          title: title,
          kw: kw,
        );
      }
    case "BrowserPage":
      {
        String title = params!["title"] ?? "";
        return BrowserPage(title: title, url: params!["url"]);
      }
    case "VideoPlayerWebPage":
      {
        String title = params!["title"] ?? "";
        return VideoPlayerWebPage(title: title, url: params!["url"]);
      }
  }
  return Container();
}
///全局生命周期监听示例
class AppLifecycleObserver with GlobalPageVisibilityObserver {
  @override
  void onBackground(Route route) {
    super.onBackground(route);
    print("AppLifecycleObserver - ${route.settings.name} - onBackground");
  }
  @override
  void onForeground(Route route) {
    super.onForeground(route);
    print("AppLifecycleObserver ${route.settings.name} - onForground");
  }
  @override
  void onPagePush(Route route) {
    super.onPagePush(route);
    print("AppLifecycleObserver - ${route.settings.name}- onPagePush");
  }
  @override
  void onPagePop(Route route) {
    super.onPagePop(route);
    print("AppLifecycleObserver - ${route.settings.name}- onPagePop");
  }
  @override
  void onPageHide(Route route) {
    super.onPageHide(route);
    print("AppLifecycleObserver - ${route.settings.name}- onPageHide");
  }
  @override
  void onPageShow(Route route) {
    super.onPageShow(route);
    print("AppLifecycleObserver - ${route.settings.name}- onPageShow");
  }
}
src/main/resources/code/flutter_module/pubspec.lock
@@ -164,8 +164,8 @@
    dependency: "direct dev"
    description:
      path: "."
      ref: "v3.0-null-safety-preview.18"
      resolved-ref: c4e5ed7c0471fe11b202b5df70b6ee6fe28369ed
      ref: "v3.0-null-safety-release.1"
      resolved-ref: "3684506c38d2f52a62d6d92bce6ffe1e54395216"
      url: "https://github.com/alibaba/flutter_boost.git"
    source: git
    version: "3.0.0"
@@ -430,7 +430,7 @@
      name: permission_handler
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "8.3.0"
    version: "9.0.2"
  permission_handler_platform_interface:
    dependency: transitive
    description:
src/main/resources/code/flutter_module/pubspec.yaml
@@ -1,6 +1,8 @@
name: flutter_module
description: A new Flutter module.
publish_to: 'none'
# 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 +.
@@ -33,7 +35,7 @@
    sdk: flutter
  flutter_lints: ^1.0.0
  cupertino_icons: ^1.0.3
  permission_handler: ^8.2.6
  permission_handler: ^9.0.2
  shared_preferences: ^2.0.8
@@ -61,7 +63,7 @@
  path_provider: ^2.0.6
  #微信登录
  fluwx_no_pay: ^3.6.1+5
  fluwx_no_pay: ^3.8.1
  event_bus: ^2.0.0
@@ -106,7 +108,7 @@
  flutter_boost:
    git:
      url: 'https://github.com/alibaba/flutter_boost.git'
      ref: 'v3.0-null-safety-preview.18'
      ref: 'v3.0-null-safety-release.1'
# For information on the generic Dart part of this file, see the
@@ -118,6 +120,14 @@
  # the material Icons class.
  uses-material-design: true
  assets:
    - assets/imgs/
    - assets/imgs/advice/
    - assets/imgs/common/
    - assets/imgs/login/
    - assets/imgs/video/
    - assets/imgs/home/
  # To add Flutter specific assets to your application, add an assets section,
  # like this:
  # assets:
src/main/resources/code/flutter_module/test/widget_test.dart
@@ -13,7 +13,7 @@
void main() {
  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
    // Build our app and trigger a frame.
    await tester.pumpWidget(const MyApp());
    await tester.pumpWidget(MyApp());
    // Verify that our counter starts at 0.
    expect(find.text('0'), findsOneWidget);
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/UserLoginValid.java
@@ -21,7 +21,7 @@
@Component
public class UserLoginValid {
    public static final String EDP = "execution(* com.yeshi.location.app.controller.client..*.*(..))";
    public static final String EDP = "execution(* com.ks.app.controller.client..*.*(..))";
    @Resource
    private SystemConfigService systemConfigService;
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/UserController.java
@@ -50,7 +50,7 @@
    @Resource
    private VerifyCodeManager verifyCodeManager;
    @Reference(version = "1.0", check = false)
    //@Reference(version = "1.0", check = false)
    private BDeviceTokenService bDeviceTokenService;
    @ResponseBody
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/admin/AdminUserDao.java
@@ -16,7 +16,7 @@
public class AdminUserDao extends MongodbBaseDao<AdminUser> {
    /**
     * @return com.ks.app.entity.AdminUser
     * @return AdminUser
     * @author hxh
     * @description 根据账号查询
     * @date 13:10 2021/11/13
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/feedback/AdviceDao.java
New file
@@ -0,0 +1,94 @@
package com.ks.app.dao.feedback;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.feedback.Advice;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import org.yeshi.utils.mongo.MongodbBaseDao;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Repository
public class AdviceDao extends MongodbBaseDao<Advice> {
    public void updateSelective(Advice bean) {
        Query query = new Query();
        Update update = new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if (bean.getSystem() != null) {
            update.set("system", bean.getSystem());
        }
        if (bean.getUid() != null) {
            update.set("uid", bean.getUid());
        }
        if (bean.getDevice() != null) {
            update.set("device", bean.getDevice());
        }
        if (bean.getType() != null) {
            update.set("type", bean.getType());
        }
        if (bean.getContent() != null) {
            update.set("content", bean.getContent());
        }
        if (bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
    }
    public List<Advice> list(DaoQuery daoQuery) {
        Query query = getQuery(daoQuery);
        if (daoQuery.sortList != null && daoQuery.sortList.size() > 0) {
            query.with(Sort.by(daoQuery.sortList));
        }
        query.skip(daoQuery.start);
        query.limit(daoQuery.count);
        return findList(query);
    }
    public long count(DaoQuery daoQuery) {
        Query query = getQuery(daoQuery);
        return count(query);
    }
    private Query getQuery(DaoQuery daoQuery) {
        List<Criteria> andList = new ArrayList<>();
        if (daoQuery.system != null) {
            andList.add(Criteria.where("system").is(daoQuery.system));
        }
        if (daoQuery.uid != null) {
            andList.add(Criteria.where("uid").is(daoQuery.uid));
        }
        if (daoQuery.maxCreateTime != null) {
            andList.add(Criteria.where("createTime").lt(daoQuery.maxCreateTime));
        }
        if (daoQuery.minCreateTime != null) {
            andList.add(Criteria.where("createTime").gte(daoQuery.minCreateTime));
        }
        Query query = new Query();
        Criteria[] ands = new Criteria[andList.size()];
        andList.toArray(ands);
        if (ands.length > 0) {
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
    }
    public static class DaoQuery {
        public SystemEnum system;
        public Long uid;
        public Date maxCreateTime;
        public Date minCreateTime;
        public int start;
        public int count;
        public List<Sort.Order> sortList;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/feedback/PrivacyComplainDao.java
New file
@@ -0,0 +1,94 @@
package com.ks.app.dao.feedback;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.feedback.PrivacyComplain;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import org.yeshi.utils.mongo.MongodbBaseDao;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Repository
public class PrivacyComplainDao extends MongodbBaseDao<PrivacyComplain> {
    public void updateSelective(PrivacyComplain bean) {
        Query query = new Query();
        Update update = new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if (bean.getSystem() != null) {
            update.set("system", bean.getSystem());
        }
        if (bean.getUid() != null) {
            update.set("uid", bean.getUid());
        }
        if (bean.getDevice() != null) {
            update.set("device", bean.getDevice());
        }
        if (bean.getContent() != null) {
            update.set("content", bean.getContent());
        }
        if (bean.getImgList() != null) {
            update.set("imgList", bean.getImgList());
        }
        if (bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
    }
    public List<PrivacyComplain> list(DaoQuery daoQuery) {
        Query query = getQuery(daoQuery);
        if (daoQuery.sortList != null && daoQuery.sortList.size() > 0) {
            query.with(Sort.by(daoQuery.sortList));
        }
        query.skip(daoQuery.start);
        query.limit(daoQuery.count);
        return findList(query);
    }
    public long count(DaoQuery daoQuery) {
        Query query = getQuery(daoQuery);
        return count(query);
    }
    private Query getQuery(DaoQuery daoQuery) {
        List<Criteria> andList = new ArrayList<>();
        if (daoQuery.system != null) {
            andList.add(Criteria.where("system").is(daoQuery.system));
        }
        if (daoQuery.uid != null) {
            andList.add(Criteria.where("uid").is(daoQuery.uid));
        }
        if (daoQuery.maxCreateTime != null) {
            andList.add(Criteria.where("createTime").lt(daoQuery.maxCreateTime));
        }
        if (daoQuery.minCreateTime != null) {
            andList.add(Criteria.where("createTime").gte(daoQuery.minCreateTime));
        }
        Query query = new Query();
        Criteria[] ands = new Criteria[andList.size()];
        andList.toArray(ands);
        if (ands.length > 0) {
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
    }
    public static class DaoQuery {
        public SystemEnum system;
        public Long uid;
        public Date maxCreateTime;
        public Date minCreateTime;
        public int start;
        public int count;
        public List<Sort.Order> sortList;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/QQUserInfoMapper.java
File was renamed from src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/QQUserInfoDao.java
@@ -12,7 +12,7 @@
import com.ks.app.entity.user.QQUserInfo;
@Repository
public interface QQUserInfoDao extends BaseMapper<QQUserInfo> {
public interface QQUserInfoMapper extends BaseMapper<QQUserInfo> {
    QQUserInfo selectByPrimaryKeyForUpdate(@Param("id") Long id);
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/UserInfoMapper.java
File was renamed from src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/UserInfoDao.java
@@ -12,7 +12,7 @@
import java.util.List;
@Repository
public interface UserInfoDao extends BaseMapper<UserInfo> {
public interface UserInfoMapper extends BaseMapper<UserInfo> {
    UserInfo selectByPrimaryKeyForUpdate(@Param("id") java.lang.Long id);
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/WXUserInfoMapper.java
File was renamed from src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/WXUserInfoDao.java
@@ -12,7 +12,7 @@
import com.ks.app.entity.user.WXUserInfo;
@Repository
public interface WXUserInfoDao extends BaseMapper<WXUserInfo> {
public interface WXUserInfoMapper extends BaseMapper<WXUserInfo> {
    WXUserInfo selectByPrimaryKeyForUpdate(@Param("id") java.lang.Long id);
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/OrderRecordMapper.java
File was renamed from src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/OrderRecordDao.java
@@ -10,7 +10,7 @@
import com.ks.app.entity.vip.OrderRecord;
@Repository
public interface OrderRecordDao extends BaseMapper<OrderRecord> {
public interface OrderRecordMapper extends BaseMapper<OrderRecord> {
  OrderRecord selectByPrimaryKeyForUpdate(@Param("id") java.lang.Long id);
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/UserVIPInfoMapper.java
File was renamed from src/main/resources/code/service/app/src/main/java/com/ks/app/dao/vip/UserVIPInfoDao.java
@@ -11,7 +11,7 @@
import com.ks.app.entity.vip.UserVIPInfo;
@Repository
public interface UserVIPInfoDao extends BaseMapper<UserVIPInfo> {
public interface UserVIPInfoMapper extends BaseMapper<UserVIPInfo> {
    UserVIPInfo selectByPrimaryKeyForUpdate(@Param("id") java.lang.Long id);
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/feedback/AdviceServiceImpl.java
New file
@@ -0,0 +1,90 @@
package com.ks.app.service.impl.feedback;
import com.yeshi.makemoney.app.dao.feedback.AdviceDao;
import com.yeshi.makemoney.app.entity.feedback.Advice;
import com.yeshi.makemoney.app.service.inter.feedback.AdviceService;
import com.yeshi.makemoney.app.service.query.feedback.AdviceQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.yeshi.utils.bean.BeanUtil;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@Service
public class AdviceServiceImpl implements AdviceService {
    @Resource
    private AdviceDao adviceDao;
    @Override
    public List<Advice> list(AdviceQuery adviceQuery, int page, int pageSize) {
        AdviceDao.DaoQuery daoQuery = new AdviceDao.DaoQuery();
        try {
            BeanUtil.copyProperties(adviceQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        daoQuery.start = (page - 1) * pageSize;
        daoQuery.count = pageSize;
        return adviceDao.list(daoQuery);
    }
    @Override
    public long count(AdviceQuery adviceQuery) {
        AdviceDao.DaoQuery daoQuery = new AdviceDao.DaoQuery();
        try {
            BeanUtil.copyProperties(adviceQuery, daoQuery);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return adviceDao.count(daoQuery);
    }
    @Override
    public Advice get(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
        return adviceDao.findOne(query);
    }
    @Override
    public void add(Advice advice) throws Exception {
        if (advice.getId() == null) {
            advice.setId(UUID.randomUUID().toString());
        }
        //查询主键ID是否存在
        if (adviceDao.get(advice.getId()) != null) {
            throw new Exception("已存在");
        }
        if (advice.getCreateTime() == null) {
            advice.setCreateTime(new Date());
        }
        //保存
        adviceDao.save(advice);
    }
    @Override
    public void update(Advice advice) {
        if (advice.getUpdateTime() == null) {
            advice.setUpdateTime(new Date());
        }
        //更新
        adviceDao.updateSelective(advice);
    }
    @Override
    public void delete(List<String> idList) {
        for (String id : idList) {
            adviceDao.delete(id);
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/feedback/PrivacyComplainServiceImpl.java
New file
@@ -0,0 +1,89 @@
package com.ks.app.service.impl.feedback;
import com.ks.app.dao.feedback.PrivacyComplainDao;
import com.ks.app.entity.feedback.PrivacyComplain;
import com.ks.app.service.inter.feedback.PrivacyComplainService;
import com.ks.app.service.query.feedback.PrivacyComplainQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.yeshi.utils.bean.BeanUtil;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@Service
public class PrivacyComplainServiceImpl implements PrivacyComplainService {
  @Resource
  private PrivacyComplainDao privacyComplainDao;
  @Override
  public List<PrivacyComplain> list(PrivacyComplainQuery privacyComplainQuery, int page, int pageSize)  {
    PrivacyComplainDao.DaoQuery daoQuery = new PrivacyComplainDao.DaoQuery();
    try {
        BeanUtil.copyProperties(privacyComplainQuery, daoQuery);
    } catch (IllegalAccessException e) {
          e.printStackTrace();
    }
    daoQuery.start=(page-1)*pageSize;
    daoQuery.count=pageSize;
    return privacyComplainDao.list(daoQuery);
  }
  @Override
  public long count(PrivacyComplainQuery privacyComplainQuery)  {
    PrivacyComplainDao.DaoQuery daoQuery = new PrivacyComplainDao.DaoQuery();
    try {
        BeanUtil.copyProperties(privacyComplainQuery, daoQuery);
    } catch (IllegalAccessException e) {
          e.printStackTrace();
    }
    return privacyComplainDao.count(daoQuery);
  }
  @Override
  public PrivacyComplain get(String id)  {
    Query query=new Query();
    query.addCriteria(Criteria.where("_id").is(id));
    return privacyComplainDao.findOne(query);
  }
  @Override
  public void add(PrivacyComplain privacyComplain)  throws Exception {
      if (privacyComplain.getId() == null) {
          privacyComplain.setId(UUID.randomUUID().toString());
      }
     //查询主键ID是否存在
     if(privacyComplainDao.get(privacyComplain.getId())!=null){
        throw new Exception("已存在");
     }
     if(privacyComplain.getCreateTime()==null){
        privacyComplain.setCreateTime(new Date());
     }
     //保存
     privacyComplainDao.save(privacyComplain);
  }
  @Override
  public void update(PrivacyComplain privacyComplain)  {
     if(privacyComplain.getUpdateTime()==null){
        privacyComplain.setUpdateTime(new Date());
     }
     //更新
     privacyComplainDao.updateSelective(privacyComplain);
  }
  @Override
  public void delete(List<String> idList)  {
     for (String id : idList){
        privacyComplainDao.delete(id);
     }
  }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/QQUserInfoServiceImpl.java
@@ -13,17 +13,17 @@
import java.util.List;
import com.ks.app.dao.user.QQUserInfoDao;
import com.ks.app.dao.user.QQUserInfoMapper;
import com.ks.app.entity.user.QQUserInfo;
import com.ks.app.service.inter.user.QQUserInfoService;
import com.ks.app.service.query.user.QQUserInfoQuery;
import com.ks.app.dao.user.QQUserInfoDao.DaoQuery;
import com.ks.app.dao.user.QQUserInfoMapper.DaoQuery;
@Service
public class QQUserInfoServiceImpl implements QQUserInfoService {
    @Resource
    private QQUserInfoDao qQUserInfoMapper;
    private QQUserInfoMapper qQUserInfoMapper;
    @Override
    public List<QQUserInfo> list(QQUserInfoQuery qQUserInfoQuery, int page, int pageSize) {
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserInfoServiceImpl.java
@@ -15,11 +15,11 @@
import java.util.List;
import com.ks.app.dao.user.UserInfoDao;
import com.ks.app.dao.user.UserInfoMapper;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.service.inter.user.UserInfoService;
import com.ks.app.service.query.user.UserInfoQuery;
import com.ks.app.dao.user.UserInfoDao.DaoQuery;
import com.ks.app.dao.user.UserInfoMapper.DaoQuery;
import org.yeshi.utils.statistic.BaseStatisticMySQLTimeQuery;
import org.yeshi.utils.statistic.BaseStatisticTimeQuery;
import org.yeshi.utils.statistic.StatisticNumberResult;
@@ -28,7 +28,7 @@
public class UserInfoServiceImpl implements UserInfoService {
    @Resource
    private UserInfoDao userInfoMapper;
    private UserInfoMapper userInfoMapper;
    @Resource
    private WXUserInfoService wxUserInfoService;
    @Resource
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/WXUserInfoServiceImpl.java
@@ -14,17 +14,17 @@
import java.util.List;
import com.ks.app.dao.user.WXUserInfoDao;
import com.ks.app.dao.user.WXUserInfoMapper;
import com.ks.app.entity.user.WXUserInfo;
import com.ks.app.service.inter.user.WXUserInfoService;
import com.ks.app.service.query.user.WXUserInfoQuery;
import com.ks.app.dao.user.WXUserInfoDao.DaoQuery;
import com.ks.app.dao.user.WXUserInfoMapper.DaoQuery;
@Service
public class WXUserInfoServiceImpl implements WXUserInfoService {
    @Resource
    private WXUserInfoDao wXUserInfoMapper;
    private WXUserInfoMapper wXUserInfoMapper;
    @Override
    public List<WXUserInfo> list(WXUserInfoQuery wXUserInfoQuery, int page, int pageSize) {
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/OrderServiceImpl.java
@@ -2,8 +2,8 @@
import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.ks.app.dao.vip.OrderRecordDao;
import com.ks.app.dao.vip.UserVIPInfoDao;
import com.ks.app.dao.vip.OrderRecordMapper;
import com.ks.app.dao.vip.UserVIPInfoMapper;
import com.ks.app.dto.vip.OrderPaySuccessForm;
import com.ks.app.dto.vip.PayWayInfoDTO;
import com.ks.app.entity.SystemEnum;
@@ -56,7 +56,7 @@
    private static Logger orderLogger = LoggerFactory.getLogger("order");
    @Resource
    private OrderRecordDao OrderRecordDao;
    private OrderRecordMapper OrderRecordDao;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
@@ -71,7 +71,7 @@
    private UserInfoService userInfoService;
    @Resource
    private UserVIPInfoDao userVIPInfoDao;
    private UserVIPInfoMapper userVIPInfoDao;
    @Transactional(rollbackFor = Exception.class)
    @Override
@@ -334,7 +334,7 @@
    @Override
    public List<OrderRecord> getCanCancelOrderList(int page, int pageSize) {
        OrderRecordDao.DaoQuery daoQuery = new OrderRecordDao.DaoQuery();
        OrderRecordMapper.DaoQuery daoQuery = new OrderRecordMapper.DaoQuery();
        daoQuery.state = OrderRecord.STATE_NOT_PAY;
        //30分钟未支付取消订单
        daoQuery.maxCreateTime = new Date(System.currentTimeMillis() - 1000 * 60 * 30);
@@ -427,7 +427,7 @@
    @Override
    public List<OrderRecord> listOrderRecord(Long uid, OrderType orderType, Integer state, int page, int pageSize) {
        OrderRecordDao.DaoQuery query = new OrderRecordDao.DaoQuery();
        OrderRecordMapper.DaoQuery query = new OrderRecordMapper.DaoQuery();
        query.start = (page - 1) * pageSize;
        query.count = pageSize;
        query.uid = uid;
@@ -438,7 +438,7 @@
    @Override
    public long countOrderRecord(Long uid, OrderType orderType, Integer state) {
        OrderRecordDao.DaoQuery query = new OrderRecordDao.DaoQuery();
        OrderRecordMapper.DaoQuery query = new OrderRecordMapper.DaoQuery();
        query.uid = uid;
        query.state = state;
        query.orderType = orderType;
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/vip/VIPServiceImpl.java
@@ -1,6 +1,6 @@
package com.ks.app.service.impl.vip;
import com.ks.app.dao.vip.UserVIPInfoDao;
import com.ks.app.dao.vip.UserVIPInfoMapper;
import com.ks.app.entity.vip.UserVIPInfo;
import com.ks.app.service.inter.vip.VIPService;
import org.slf4j.Logger;
@@ -25,7 +25,7 @@
    Logger logger = LoggerFactory.getLogger(VIPServiceImpl.class);
    @Resource
    private UserVIPInfoDao userVIPInfoDao;
    private UserVIPInfoMapper userVIPInfoDao;
    @Override
    public UserVIPInfo getVIPInfo(Long uid) {
@@ -76,7 +76,7 @@
    @Override
    public List<UserVIPInfo> listVIPUser(Date minVIPExpireDate, Date maxVIPExpireDate, int page, int pageSize) {
        UserVIPInfoDao.DaoQuery daoQuery = new UserVIPInfoDao.DaoQuery();
        UserVIPInfoMapper.DaoQuery daoQuery = new UserVIPInfoMapper.DaoQuery();
        daoQuery.maxExpireDate = maxVIPExpireDate;
        daoQuery.minExpireDate = minVIPExpireDate;
        daoQuery.start = (page - 1) * pageSize;
@@ -87,7 +87,7 @@
    @Override
    public long countVIPUser(Date minVIPExpireDate, Date maxVIPExpireDate) {
        UserVIPInfoDao.DaoQuery daoQuery = new UserVIPInfoDao.DaoQuery();
        UserVIPInfoMapper.DaoQuery daoQuery = new UserVIPInfoMapper.DaoQuery();
        daoQuery.maxExpireDate = maxVIPExpireDate;
        daoQuery.minExpireDate = minVIPExpireDate;
        return userVIPInfoDao.count(daoQuery);
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserInfoService.java
@@ -57,7 +57,7 @@
    /**
     * @return com.yeshi.location.app.entity.user.UserInfo
     * @return UserInfo
     * @author hxh
     * @description 获取用户信息详情
     * @date 17:15 2021/11/15
@@ -67,7 +67,7 @@
    /**
     * @return java.util.List<com.yeshi.location.app.entity.user.UserInfo>
     * @return java.util.List<UserInfo>
     * @author hxh
     * @description 批量获取用户信息详情
     * @date 17:39 2021/11/15
@@ -77,7 +77,7 @@
    /**
     * @return com.yeshi.location.app.entity.user.UserInfo
     * @return UserInfo
     * @author hxh
     * @description 根据电话和系统查询
     * @date 10:26 2021/11/16
@@ -96,7 +96,7 @@
    /**
     * @return com.yeshi.location.app.entity.SystemEnum
     * @return SystemEnum
     * @author hxh
     * @description //获取用户系统
     * @date 15:06 2021/11/17
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/SystemInfoUtil.java
@@ -14,7 +14,7 @@
public class SystemInfoUtil {
    /**
     * @return com.ks.app.entity.SystemEnum
     * @return SystemEnum
     * @author hxh
     * @description 获取系统
     * @date 18:02 2021/11/16
src/main/resources/code/service/app/src/main/resources/application-dev.yml
@@ -17,7 +17,7 @@
      password: 'Yeshi2016@'
      host: 193.112.35.168
      port: 27016
      database: location
      database: ${mongoDataBaseName}
      authentication-database: admin
  redis:
    host: 193.112.35.168 #193.112.34.40
@@ -44,7 +44,7 @@
  datasource:
    url: jdbc:mysql://gz-cdb-r13d0yi9.sql.tencentcdb.com:62929/location?serverTimezone=GMT%2B8
    url: jdbc:mysql://gz-cdb-r13d0yi9.sql.tencentcdb.com:62929/${sqlDataBaseName}?serverTimezone=GMT%2B8
    username: root
    password: Yeshi2016@
    driver-class-name: com.mysql.jdbc.Driver
@@ -76,7 +76,7 @@
  job:
    accessToken:
    executor:
      appname: service-push
      appname: service-${projectName}
      ip:
      logpath: /data/applogs/xxl-job/jobhandler
      logretentiondays: -1
src/main/resources/code/service/app/src/main/resources/application-pro.yml
@@ -17,7 +17,7 @@
      password: 'Yeshi2016@'
      host: 172.16.16.44
      port: 27017
      database: push
      database: ${mongoDataBaseName}
      authentication-database: admin
  redis:
    host: 172.16.16.15 #193.112.34.40
@@ -45,7 +45,7 @@
  datasource:
    #jdbc:mysql://gz-cdb-r13d0yi9.sql.tencentcdb.com:62929/ks_goldcorn?serverTimezone=GMT%2B8
    url: jdbc:mysql://172.16.16.17:3306/bpush?serverTimezone=GMT%2B8
    url: jdbc:mysql://172.16.16.17:3306/${sqlDataBaseName}?serverTimezone=GMT%2B8
    username: root
    password: Yeshi2016@
    driver-class-name: com.mysql.jdbc.Driver
@@ -76,7 +76,7 @@
  job:
    accessToken:
    executor:
      appname: service-push
      appname: service-${projectName}
      ip:
      logpath: /data/applogs/xxl-job/jobhandler
      logretentiondays: -1
src/main/resources/code/service/app/src/main/resources/mapper/OrderRecordMapper.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ks.app.dao.vip.OrderRecordDao">
<mapper namespace="com.ks.app.dao.vip.OrderRecordMapper">
    <resultMap id="BaseResultMap"
               type="com.ks.app.entity.vip.OrderRecord">
        <id column="id" property="id" jdbcType="BIGINT"/>
src/main/resources/code/service/app/src/main/resources/mapper/QQUserInfoMapper.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ks.app.dao.user.QQUserInfoDao">
<mapper namespace="com.ks.app.dao.user.QQUserInfoMapper">
    <resultMap id="BaseResultMap"
               type="com.ks.app.entity.user.QQUserInfo">
        <id column="id" property="id" jdbcType="BIGINT"/>
src/main/resources/code/service/app/src/main/resources/mapper/UserInfoMapper.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ks.app.dao.user.UserInfoDao">
<mapper namespace="com.ks.app.dao.user.UserInfoMapper">
    <resultMap id="BaseResultMap"
               type="com.ks.app.entity.user.UserInfo">
        <id column="id" property="id" jdbcType="BIGINT"/>
@@ -159,9 +159,6 @@
    <sql id="listWhere">
        public SystemEnum system;
        public Long wxId;
        public Long qqId;
        <if test="query.system!=null">
            and system = #{query.system}
        </if>
src/main/resources/code/service/app/src/main/resources/mapper/UserVIPInfoMapper.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ks.app.dao.vip.UserVIPInfoDao">
<mapper namespace="com.ks.app.dao.vip.UserVIPInfoMapper">
    <resultMap id="BaseResultMap"
               type="com.ks.app.entity.vip.UserVIPInfo">
        <id column="uid" property="uid" jdbcType="BIGINT"/>
src/main/resources/code/service/app/src/main/resources/mapper/WXUserInfoMapper.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yeshi.location.app.mapper.user.WXUserInfoMapper">
<mapper namespace="com.ks.app.mapper.user.WXUserInfoMapper">
    <resultMap id="BaseResultMap"
               type="com.yeshi.location.app.entity.user.WXUserInfo">
               type="com.ks.app.entity.user.WXUserInfo">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="system" property="system" jdbcType="VARCHAR"/>
        <result column="nick_name" property="nickName" jdbcType="VARCHAR"/>
@@ -44,7 +44,7 @@
        lt_user_wx where id = #{id,jdbcType=BIGINT}
    </delete>
    <insert id="insert"
            parameterType="com.yeshi.location.app.entity.user.WXUserInfo"
            parameterType="com.ks.app.entity.user.WXUserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into
        lt_user_wx
@@ -80,7 +80,7 @@
    </insert>
    <insert id="insertSelective"
            parameterType="com.yeshi.location.app.entity.user.WXUserInfo"
            parameterType="com.ks.app.entity.user.WXUserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into lt_user_wx
        <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -114,7 +114,7 @@
        </trim>
    </insert>
    <update id="updateByPrimaryKey"
            parameterType="com.yeshi.location.app.entity.user.WXUserInfo">
            parameterType="com.ks.app.entity.user.WXUserInfo">
        update lt_user_wx
        <set>
            <if test="id != null">id = #{id,jdbcType=BIGINT},</if>
@@ -133,7 +133,7 @@
        where id = #{id,jdbcType=BIGINT}
    </update>
    <update id="updateByPrimaryKeySelective"
            parameterType="com.yeshi.location.app.entity.user.WXUserInfo">
            parameterType="com.ks.app.entity.user.WXUserInfo">
        update lt_user_wx
        <set>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
src/main/resources/code/service/app/src/main/resources/mysql.sql
New file
@@ -0,0 +1,99 @@
CREATE DATABASE /*!32312 IF NOT EXISTS*/`${sqlDataBaseName}` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
USE `${sqlDataBaseName}`;
DROP TABLE IF EXISTS `${sqlTablePrefix}user`;
CREATE TABLE `${sqlTablePrefix}user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `system` varchar(32) DEFAULT NULL COMMENT '系统',
  `nick_name` varchar(128) DEFAULT NULL COMMENT '昵称',
  `portrait` varchar(512) DEFAULT NULL COMMENT '头像',
  `phone` varchar(64) DEFAULT NULL COMMENT '手机号',
  `email` varchar(64) DEFAULT NULL COMMENT '邮箱',
  `pwd` varchar(32) DEFAULT NULL COMMENT '密码',
  `wx_id` bigint(20) DEFAULT NULL COMMENT '微信索引',
  `qq_id` bigint(20) DEFAULT NULL COMMENT 'QQ索引',
  `status` int(11) DEFAULT '0' COMMENT '状态',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UX_SYSTEM_PHONE` (`system`,`phone`),
  UNIQUE KEY `UX_SYSTEM_EMAIL` (`system`,`email`),
  KEY `INX_EMAIL` (`email`),
  KEY `INX_PHONE` (`phone`)
) ENGINE=InnoDB AUTO_INCREMENT=22380 DEFAULT CHARSET=utf8mb4 COMMENT='用户信息';
DROP TABLE IF EXISTS `${sqlTablePrefix}user_qq`;
CREATE TABLE `${sqlTablePrefix}user_qq` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `system` varchar(32) DEFAULT NULL,
  `nick_name` varchar(64) DEFAULT NULL COMMENT '昵称',
  `portrait` varchar(512) DEFAULT NULL COMMENT '头像',
  `open_id` varchar(64) DEFAULT NULL COMMENT 'openid',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UX_SYSTEM_OPEN_ID` (`system`,`open_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='QQ授权信息';
DROP TABLE IF EXISTS `${sqlTablePrefix}user_vip_info`;
CREATE TABLE `${sqlTablePrefix}user_vip_info` (
  `uid` bigint(20) NOT NULL,
  `expire_date` datetime DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `${sqlTablePrefix}user_wx`;
CREATE TABLE `${sqlTablePrefix}user_wx` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `system` varchar(32) DEFAULT NULL,
  `nick_name` varchar(64) DEFAULT NULL COMMENT '昵称',
  `sex` int(11) DEFAULT NULL COMMENT '性别',
  `province` varchar(64) DEFAULT NULL COMMENT '省',
  `city` varchar(64) DEFAULT NULL COMMENT '市',
  `country` varchar(64) DEFAULT NULL COMMENT '国家',
  `head_img_url` varchar(512) DEFAULT NULL COMMENT '头像',
  `open_id` varchar(64) DEFAULT NULL COMMENT 'openid',
  `union_id` varchar(64) DEFAULT NULL COMMENT 'unionid',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UX_SYSTEM_UNION_ID` (`system`,`union_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微信授权信息';
DROP TABLE IF EXISTS `${sqlTablePrefix}vip_order_record`;
CREATE TABLE `${sqlTablePrefix}vip_order_record` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `order_type` varchar(64) DEFAULT NULL,
  `uid` bigint(20) DEFAULT NULL,
  `state` int(11) DEFAULT NULL,
  `money_pay` tinyint(4) DEFAULT NULL,
  `gold_corn_pay` tinyint(4) DEFAULT NULL,
  `gold_corn` int(11) DEFAULT NULL,
  `type` varchar(64) DEFAULT NULL,
  `money` decimal(8,2) DEFAULT NULL,
  `pay_way` int(11) DEFAULT NULL,
  `pay_money` decimal(8,2) DEFAULT NULL,
  `ip_info` varchar(64) DEFAULT NULL,
  `pay_time` datetime DEFAULT NULL,
  `vip_start_time` datetime DEFAULT NULL,
  `vip_end_time` datetime DEFAULT NULL,
  `remarks` varchar(256) DEFAULT NULL,
  `apple_transaction_id` varchar(64) DEFAULT NULL,
  `apple_original_transaction_id` varchar(64) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=200010 DEFAULT CHARSET=utf8mb4;
src/main/resources/code/service/app/src/main/resources/static/index.html
@@ -40,7 +40,7 @@
<!-- 顶部开始 -->
<div class="container">
    <div class="logo">
        <a href="index.html">定位追踪系统</a></div>
        <a href="index.html">${projectChineseName}系统</a></div>
    <div class="left_open">
        <a><i title="展开左侧栏" class="iconfont">&#xe699;</i></a>
    </div>
src/main/resources/code/service/pom.xml
@@ -160,7 +160,7 @@
        <dependency>
            <groupId>com.yeshi</groupId>
            <artifactId>utils</artifactId>
            <version>0.2.9</version>
            <version>0.3.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.data</groupId>
src/main/resources/static/service.html
@@ -60,9 +60,14 @@
<p>数据库框架:mybatis,mongodb,redis</p>
<p>RPC框架:dubbo</p>
<p>分布式任务框架:xxl-job</p>
<p>常用工具类:com.yeshi.utils_0.1.5</p>
<p>常用工具类:com.yeshi.utils_0.3.2</p>
<p>可采用自动工具类中的代码生成工具,根据entity以及entity上的配置,自动生成相关的功能逻辑代码,尽量做到新项目就可开箱即用</p>
<p style="color: red;">下载代码之前需填写如下信息:</p>
<p>
    <input type="text" class="layui-text" placeholder="请填写项目名称(中文名称)">
</p>
<p>
    <input type="text" class="layui-text" placeholder="请填写项目名称(英文名称)">
@@ -72,6 +77,18 @@
</p>
<p>
    <input type="text" class="layui-text" placeholder="请填写应用包名(如com.ks.push.app)">
</p>
<p>
    <input type="text" class="layui-text" placeholder="请填写MySQl数据库名称">
</p>
<p>
    <input type="text" class="layui-text" placeholder="请填写MySql表前缀">
</p>
<p>
    <input type="text" class="layui-text" placeholder="请填写Mongodb数据库名称">
</p>
@@ -89,9 +106,13 @@
    function startDownLoad() {
        ksapp.post("api/generator/createService", {
            name: $("input[type=text]").eq(0).val(),
            pks: $("input[type=text]").eq(1).val(),
            subpks: $("input[type=text]").eq(2).val()
            chineseName: $("input[type=text]").eq(0).val(),
            name: $("input[type=text]").eq(1).val(),
            pks: $("input[type=text]").eq(2).val(),
            subpks: $("input[type=text]").eq(3).val(),
            sqlDataBaseName: $("input[type=text]").eq(4).val(),
            sqlTablePrefix: $("input[type=text]").eq(5).val(),
            mongoDataBaseName: $("input[type=text]").eq(6).val(),
        }, function (res) {
            if (res.code == 0) {
                window.location.href = "api/generator/downloadZIP?name=" + encodeURIComponent(res.data)