admin
2022-05-12 fa705507ba574c857b1667553737d23b1b7ff495
后端模板代码优化
29个文件已添加
56个文件已修改
15个文件已删除
10542 ■■■■■ 已修改文件
src/main/resources/code/flutter_module/lib/api/http.dart 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/api/video_api.dart 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/home.dart 418 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/main.dart 193 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/mine.dart 798 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/splash.dart 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/common/browser.dart 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/mine/person_info.dart 567 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/mine/settings.dart 70 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/search/search.dart 369 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/search/search_result.dart 286 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/video/video_attention_list.dart 228 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/video/video_collected_list.dart 296 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/video/video_detail.dart 935 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/video/video_download_list.dart 302 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/video/video_list.dart 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/video/video_player_browser.dart 321 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/video/video_scan_record_list.dart 321 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/widget/dialog.dart 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/widget/images_widget.dart 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/widget/nav.dart 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/widget/refresh_listview.dart 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/widget/search_widget.dart 313 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/widget/sos_ui.dart 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/ui/widget/video_item.dart 755 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/ad_util.dart 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/config_util.dart 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/encrypt_util.dart 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/image_util.dart 110 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/jsinterface.dart 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/jump_page.dart 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/network_util.dart 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/setting_util.dart 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/share_utils.dart 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/ui_constant.dart 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/ui_utils.dart 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/utils/wx_util.dart 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/pubspec.lock 70 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/pubspec.yaml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/pom.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/Application.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/AdminApiFilter.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/SignValidate.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/config/RedisConfig.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/config/WebSecurityConfig.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/config/XXLJobConfig.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/FileController.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/config/SystemConfigAdminController.java 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/ConfigController.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/SMSController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/UserController.java 164 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/config/SystemConfigDao.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/user/UserExtraInfoDao.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/config/AdSourceConfig.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/config/AlipayConfig.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/config/WXTransferConfig.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/mq/TestMQMsg.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/AdminUser.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/AppJumpType.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/AppName.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfig.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfigKey.java 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfigType.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/UserExtraInfo.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/user/UserAccountException.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/user/UserExtraInfoException.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/user/UserInfoException.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/config/SystemConfigServiceImpl.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserAccountServiceImpl.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/config/SystemConfigService.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserAccountService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserExtraInfoService.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/manager/PushManager.java 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/manager/VerifyCodeManager.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/config/SystemConfigQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/Constant.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/ImageUtil.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/JedisUtil.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/ValidatorUtils.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/factory/AppJumpParamsFactory.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/mq/CMQManager.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/pay/AlipayUtil.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/user/InviteCodeUtil.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/user/UserVOUtil.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/AcceptAdminData.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/user/UserInfoVO.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/alipay.properties 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/application-dev.yml 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/application-pro.yml 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/cos.properties 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/UserInfoMapper.xml 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/mapper/WXUserInfoMapper.xml 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/config/system_config_add.html 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/config/system_config_list.html 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/config/system_config_update.html 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/index.html 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/static/welcome.html 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/wx/apiclient_cert.p12 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/app/src/main/resources/wx_transfer.properties 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/service/pom.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/code/flutter_module/lib/api/http.dart
@@ -2,14 +2,14 @@
import 'dart:convert';
import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:device_info/device_info.dart';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../utils/des/des.dart';
import '../../utils/share_preference.dart';
import '../../utils/share_preference.dart';
import '../model/common/http_model.dart';
import '../ui/widget/dialog.dart';
import '../utils/app_util.dart';
@@ -40,7 +40,11 @@
    List list = [];
    //签名
    params.forEach((key, value) {
      list.add("$key=$value");
      print(value.runtimeType);
      //文件不参与签名
      if(value.runtimeType.toString() != "_File"&&value.runtimeType.toString() != "MultipartFile") {
        list.add("$key=$value");
      }
    });
    //排序
    list.sort();
@@ -48,33 +52,43 @@
    list.forEach((element) {
      signStr += element + "&";
    });
    print("签名字符串:$signStr");
    if (signStr.endsWith("&")) {
      signStr = signStr.substring(0, signStr.length - 1);
    }
    signStr += "8888B&*@-uWan88/',@@^";
    signStr += "BuWan*@_%MakeMoney!!";
    return EncryptUtil.MD5(signStr);
  }
  static String _decode(String content) {
    String key = utf8.decode(base64Decode("VW1nT3R2WVk="));
    String iv = utf8.decode(base64Decode("WXlIeEhsY0o="));
  // static String _decode(String content) {
  //   String key = utf8.decode(base64Decode("VW1nT3R2WVk="));
  //   String iv = utf8.decode(base64Decode("WXlIeEhsY0o="));
  //
  //   List<int> result =
  //       DES().decryptWithCBC(base64Decode(content), key.codeUnits, iv: iv);
  //
  //   return utf8.decode(result);
  // }
    List<int> result =
        DES().decryptWithCBC(base64Decode(content), key.codeUnits, iv: iv);
    return utf8.decode(result);
  }
  static Future<Map<String, dynamic>> getBaseParams(
      Map<String, dynamic>? params) async {
  static Future<dynamic> getBaseParams(Map<String, dynamic>? params) async {
    params ??= {};
    //判断params中是否有文件类型
    List<String> fileKeys = [];
    params.forEach((key, value) async {
      print("$key: ${value.runtimeType}");
      if (value.runtimeType.toString() == "_File") {
        fileKeys.add(key);
      }
    });
    for (int i = 0; i < fileKeys.length; i++) {
      params[fileKeys[i]] =
      await MultipartFile.fromFile((params[fileKeys[i]] as File).path);
    }
    if (Platform.isIOS) {
      String finalParams =
          await dataMethodChannel.invokeMethod("getBaseRequestParams", params);
      await dataMethodChannel.invokeMethod("getBaseRequestParams", params);
      return jsonDecode(finalParams);
    }
    if (Platform.isAndroid) {
@@ -83,49 +97,46 @@
        _androidInfo = await deviceInfo.androidInfo;
      }
      print("androidInfo:${_androidInfo!.version}");
      params["Version"] = (await AppUtil.getVersionCode()).toString();
      params["version"] = (await AppUtil.getVersionCode()).toString();
    } else if (Platform.isIOS) {
      if (_iosInfo == null) {
        DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
        _iosInfo = await deviceInfo.iosInfo;
      }
      params["Version"] = "105";
      params["version"] = "105";
    }
    //添加附加参数
    params["Timestamp"] = DateTime.now().millisecondsSinceEpoch.toString();
    params["Platform"] = "Android"; // Platform.isAndroid ? "Android" : "IOS";
    params["Package"] = "com.hanju.video";
    params["System"] = "1";
    params["timestamp"] = DateTime.now().millisecondsSinceEpoch.toString();
    params["platform"] = "android"; // Platform.isAndroid ? "Android" : "IOS";
    params["packages"] = "com.yeshi.makemoney.video";
    Global.utdId = "testtest";
    Global.channel = "QQ";
    if (Platform.isAndroid) {
      if (Global.utdId != null) {
        params["UtdId"] = Global.utdId;
        params["Device"] = Global.utdId;
        params["utdId"] = Global.utdId;
      }
      params["osVersion"] = _androidInfo!.version.release;
    } else if (Platform.isIOS) {
      params["Device"] = "test123123"; //_iosInfo!.identifierForVendor;
      params["device"] = "test123123"; //_iosInfo!.identifierForVendor;
    }
    if (Global.channel != null) {
      params["Channel"] = Global.channel;
      params["channel"] = Global.channel;
    }
    //青少年模式
    params["YouthMode"] = false;
    params["sign"] = _getSign(params);
    params["Sign"] = _getSign(params);
    return params;
    return fileKeys.isNotEmpty ? FormData.fromMap(params) : params;
  }
  static var cookieJar = CookieJar();
  static Future<HttpRequestResult> baseRequest(BuildContext context, String api,
      Map<String, dynamic> params, OnHttpRequestStart? onStart,
      {bool notifyError = false}) async {
    // params ??= {};
    params = await getBaseParams(params);
    dynamic paramsNew = await getBaseParams(params);
    if (onStart != null) {
      onStart();
@@ -135,31 +146,31 @@
    try {
      var dio = Dio()
        ..options = BaseOptions(
            baseUrl: "http://api.hanju.goxcw.com:8089/BuWan",
            baseUrl: "http://api.dsp.yeshitv.com",
            connectTimeout: 20000,
            receiveTimeout: 1000 * 60,
            contentType: "application/x-www-form-urlencoded");
      dio.interceptors.add(CookieManager(cookieJar));
      //设置代理
      (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;
      };
      // (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,
        data: paramsNew,
        onSendProgress: (int sent, int total) {
          print('$sent $total');
        },
      );
      if (response.statusCode == HttpStatus.ok) {
        String result = response.data.toString();
        result = _decode(result);
        // result = _decode(result);
        print("网络请求结果:$result");
        requestResult = HttpRequestResult(true, jsonDecode(result));
      } else {
src/main/resources/code/flutter_module/lib/api/video_api.dart
File was deleted
src/main/resources/code/flutter_module/lib/home.dart
File was deleted
src/main/resources/code/flutter_module/lib/main.dart
@@ -2,41 +2,47 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_boost/flutter_boost.dart';
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';
import 'utils/ui_constant.dart';
import 'utils/ui_utils.dart';
// void main() {
//   runApp(getBasePage(
//     AboutUsPage(title: ""),
//     MinePage(title: ""),
//   ));
// }
void main() {
void _runNative() {
  ///添加全局生命周期监听类
  PageVisibilityBinding.instance.addGlobalObserver(AppLifecycleObserver());
  CustomFlutterBinding();
  //window.defaultRouteName
  runApp(MyApp());
}
void _runLocal() {
  runApp(getBasePage(
    MinePage(
      title: "",
    ),
  ));
}
void main() {
  if (Constant.NATIVE) {
    _runNative();
  } else {
    _runLocal();
  }
}
class CustomFlutterBinding extends WidgetsFlutterBinding
@@ -68,85 +74,11 @@
  }
  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: "",
            );
          });
@@ -169,35 +101,6 @@
    "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;
@@ -209,19 +112,7 @@
            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) {
@@ -237,6 +128,7 @@
    return MaterialApp(
      home: home,
      debugShowCheckedModeBanner: true,
      theme: ThemeData(primaryColor: ColorConstant.theme),
      ///必须加上builder参数,否则showDialog等会出问题
      builder: (_, __) {
@@ -266,24 +158,8 @@
  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":
@@ -294,37 +170,12 @@
      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"]);
      }
  }
src/main/resources/code/flutter_module/lib/mine.dart
@@ -1,22 +1,16 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_boost/flutter_boost.dart';
import '../../api/video_api.dart';
import '../../ui/widget/button.dart';
import '../../ui/widget/video_item.dart';
import '../../utils/db_manager.dart';
import '../../utils/jump_page.dart';
import '../../utils/string_util.dart';
import '../../utils/ui_constant.dart';
import '../../utils/user_util.dart';
import 'model/user/user_info.dart';
import 'model/video/watch_record_model.dart';
import 'utils/share_preference.dart';
import 'package:share_plus/share_plus.dart';
import 'ui/widget/ad_express.dart';
import 'ui/widget/images_widget.dart';
import 'utils/config_util.dart';
class MinePage extends StatefulWidget {
  MinePage({Key? key, required this.title}) : super(key: key);
@@ -29,32 +23,30 @@
class _MinePageState extends State<MinePage>
    with SingleTickerProviderStateMixin, PageVisibilityObserver {
  static const Color COLOR_CONTENT = Color(0xFF999999);
  static const Color COLOR_TITLE = Color(0xFF000000);
  static const Color COLOR_PORTRAIT_BG = Color(0xFFDBDBDB);
  static const Color COLOR_HIGHLIGHT = ColorConstant.theme;
  int index = 1;
  UserInfo? _user;
  List<WatchRecordModel> recordList = [];
  int collectedVideoCount = 0;
  int favoriteVideoCount = 0;
  String applink = "";
  int goldCorn = 0;
  String balance = "0.00";
  int firstTeamCount = 0;
  int secondTeamCount = 0;
  int msgCount = 0;
  @override
  void initState() {
    super.initState();
    if (Platform.isIOS) {
      MySharedPreferences.getInstance().getString("appLink").then((value) {
        setState(() {
          applink = value!;
        });
      });
    }
    _refreshData();
  }
  void _refreshData() {
    updateUserInfo();
    loadWatchRecord();
    loadUserVideoCount();
  }
  void updateUserInfo() async {
@@ -65,6 +57,8 @@
      return;
    }
    _user = await UserUtil.getUserInfo();
    UserUtil.updateUserInfo(context).then((value) {
      print("user:$value");
      setState(() {
@@ -73,33 +67,15 @@
    });
  }
  void loadWatchRecord() async {
    List<WatchRecordModel> temp = await DBManager.listWatchRecord(1, 20);
    setState(() {
      recordList = temp;
    });
  }
  void loadUserVideoCount() async {
    if (!await UserUtil.isLogin()) {
  void jumpPage(String name,
      {Map<String, dynamic>? params, bool needLogin = true}) async {
    bool login = await UserUtil.isLogin();
    if (!login && needLogin) {
      jumpPage("LoginPage", needLogin: false);
      return;
    }
    Map<String, dynamic>? result =
        await VideoApiUtil.getUserVideoCount(context);
    if (result == null) {
      return;
    }
    if (result["IsPost"] == "true") {
      setState(() {
        collectedVideoCount = result["Data"]["collectionCount"];
        favoriteVideoCount = result["Data"]["attentionCount"];
      });
    }
  }
  void jumpPage(String name, {Map<String, dynamic>? params}) {
    JumpPageUtil.jumpPage(name, context, native: Platform.isIOS,params: params,
        callback: (data) {
    JumpPageUtil.jumpPage(name, context,
        native: Constant.NATIVE, params: params, callback: (data) {
      _refreshData();
    });
  }
@@ -148,452 +124,316 @@
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.white,
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Container(
              alignment: Alignment.center,
              padding: EdgeInsets.only(
                  top: 15 + MediaQuery.of(context).viewPadding.top, bottom: 15),
              color: ColorConstant.theme,
              child: const Text("我的",
                  style: TextStyle(fontSize: 20, color: Colors.white)),
        body: Column(children: [
          Expanded(
              child: Stack(children: [
            AspectRatio(
              aspectRatio: 1.344,
              child: Image.asset("assets/imgs/mine/ic_top_bg.png"),
            ),
            Expanded(
                child: Container(
              height: 20,
              color: Colors.white,
              child: SingleChildScrollView(
                  child: Column(
                children: [
                  Container(
                    height: 51,
                  ),
                  //个人信息
                  InkWell(
                    child: Row(
                      children: [
                        Container(
                          width: 18,
                        ),
                        portraitWidget(),
                        Container(
                          width: 10,
                        ),
                        _user != null
                            ? personInfoWidget()
                            :
                            //登录框
                            loginBtnWidget(),
                        Container(
                          width: 18,
                        ),
                      ],
                    ),
                    onTap: () {
                      UserUtil.isLogin().then((value) {
                        if (value) {
                          jumpPage("PersonInfoPage");
                        }
                      });
                    },
                  ),
                  Container(
                    height: 8,
                  ),
                  //签名
                  signWidget(),
                  Container(
                    height: 23,
                  ),
                  //收藏,追剧,缓存
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: [
                      InkWell(
                          onTap: () {
                            UserUtil.isLogin().then((value) {
                              if (!value) {
                                jumpPage("EmailLoginPage");
                                return;
                              }
                              jumpPage("VideoCollectedPage");
                            });
                          },
                          child: Column(
                            children: [
                              const Text(
                                "收藏",
                                style: TextStyle(
                                    fontSize: 18, color: Color(0xFF888888)),
                              ),
                              Text(
                                "$collectedVideoCount",
                                style: const TextStyle(
                                    fontSize: 12, color: Color(0xFF888888)),
                              ),
                            ],
                          )),
                      InkWell(
                        onTap: () {
                          UserUtil.isLogin().then((value) {
                            if (!value) {
                              jumpPage("EmailLoginPage");
                              return;
                            }
                            jumpPage("VideoAttentionPage");
                          });
                        },
                        child: Column(
                          children: [
                            const Text(
                              "追剧",
                              style: TextStyle(
                                  fontSize: 18, color: Color(0xFF888888)),
                            ),
                            Text(
                              "$favoriteVideoCount",
                              style: const TextStyle(
                                  fontSize: 12, color: Color(0xFF888888)),
                            ),
                          ],
                        ),
                      ),
                      InkWell(
                          onTap: () {
                            jumpPage("VideoDownloadPage");
                          },
                          child: Column(
                            children: const [
                              Text(
                                "缓存",
                                style: TextStyle(
                                    fontSize: 18, color: Color(0xFF888888)),
                              ),
                              Text(
                                "0",
                                style: TextStyle(
                                    fontSize: 12, color: Color(0xFF888888)),
                              ),
                            ],
                          )),
                    ],
                  ),
                  //历史记录
                  Container(
                    height: 20,
                  ),
                  recordList.isNotEmpty
                      ? Column(
                          children: [
                            //title
                            InkWell(
                                onTap: () {
                                  jumpPage("VideoScanRecordPage");
                                },
                                child: Row(
                                  children: [
                                    Container(
                                      width: 16,
                                    ),
                                    const Text(
                                      "历史记录",
                                      style: TextStyle(
                                          color: Color(0xFFAAAAAA),
                                          fontSize: 15),
                                    ),
                                    Expanded(child: Container()),
                                    const Text(
                                      "全部",
                                      style: TextStyle(
                                          color: Color(0xFFAAAAAA),
                                          fontSize: 15),
                                    ),
                                    Container(
                                      width: 6,
                                    ),
                                    Image.asset(
                                      "assets/imgs/icon_mine_fun_input.png",
                                      width: 6.5,
                                    ),
                                    Container(
                                      width: 16,
                                    ),
                                  ],
                                )),
                            //内容
                            Container(
                              margin: const EdgeInsets.only(top: 15),
                              height: 270,
                              child: SingleChildScrollView(
                                  scrollDirection: Axis.horizontal,
                                  child: Container(
                                      constraints: BoxConstraints(
                                          minWidth: MediaQuery.of(context)
                                              .size
                                              .width),
                                      alignment: Alignment.centerLeft,
                                      child: Wrap(
                                          direction: Axis.vertical,
                                          alignment: WrapAlignment.start,
                                          spacing: 10,
                                          runSpacing: 10,
                                          children: getRecordListWidget()))),
                            )
                          ],
                        )
                      : Container(),
                  //功能
                  Container(
                    margin: const EdgeInsets.fromLTRB(16, 23, 16, 16),
                    padding: const EdgeInsets.fromLTRB(24, 10, 24, 10),
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(12.5),
                        border: Border.all(
                            color: const Color(0xFFDDDDDD), width: 1)),
                    child: Column(
                      children: [
                        functionWidget(
                            "assets/imgs/icon_mine_fun_share.png", "分享APP", 16,
                            () {
                          Share.share("海量韩剧,尽在应用:$applink");
                        }),
                        functionWidget("assets/imgs/icon_mine_fun_privacy.png",
                            "隐私政策", 13.5, () {
                              jumpPage("BrowserPage", params: {"url": Constant.PRIVACY_URL,"title":"隐私政策"});
                            }),
                        functionWidget("assets/imgs/icon_mine_fun_feedback.png",
                            "反馈吐槽", 13.5, () {
                          jumpPage("AdvicePage");
                        }),
                        functionWidget("assets/imgs/icon_mine_fun_about_us.png",
                            "关于我们", 17, () {
                          MySharedPreferences.getInstance()
                              .getString("aboutUsLink")
                              .then((value) {
                            if (!StringUtil.isNullOrEmpty(value)) {
                              jumpPage("AboutUsPage");
                            }
                          });
                        }),
                        functionWidget("assets/imgs/icon_mine_fun_settings.png",
                            "设置", 17.5, () {
                          jumpPage("SettingPage");
                        }),
                      ],
                    ),
                  )
                ],
              )),
            ))
          ],
        ));
  }
  List<Widget> getRecordListWidget() {
    List<Widget> list = recordList.map((e) {
      //是否为主分类
      List<int> mainTypes = [150, 151, 152, 153];
      if (mainTypes.contains(e.video!.videoType!.id!)) {
        return InkWell(
          child: getBigRecordItem(e),
          onTap: () {
            jumpVideoDetail(context, e.video, Platform.isIOS,
                position: e.position!);
          },
        );
      } else {
        return InkWell(
          child: getSmallRecordItem(e),
          onTap: () {
            jumpVideoDetail(context, e.video, Platform.isIOS,
                position: e.position!);
          },
        );
      }
    }).toList();
    list.insert(
        0,
        InkWell(
            child: Container(
          width: 5,
          height: 270,
        )));
    list.add(InkWell(
        child: Container(
      width: 5,
      height: 270,
    )));
    return list;
  }
  Widget getSmallRecordItem(WatchRecordModel record) {
    return Container(
        height: 130,
        child: Stack(
          children: [
            Container(
              margin: const EdgeInsets.only(top: 20),
              height: 110,
              width: 120 * 1.4,
              decoration: BoxDecoration(
                  color: Colors.black38,
                  borderRadius: BorderRadius.circular(10)),
            ),
            Container(
                alignment: Alignment.center,
                width: 120 * 1.4,
                padding: const EdgeInsets.only(left: 10, right: 10),
            SingleChildScrollView(
                child: Column(
                  children: [
                    ClipRRect(
                      borderRadius: BorderRadius.circular(10),
                      child: SizedBox(
                        height: 100,
                        width: 120 * 1.4 - 20,
                        child: VideoImage(record.video!.picture),
                      ),
                    ),
                    Container(
                      height: 5,
                    ),
                    Text(
                      record.video!.name!,
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                      style: const TextStyle(color: Colors.white),
                    )
                  ],
                ))
          ],
        ));
  }
  Widget getBigRecordItem(WatchRecordModel record) {
    return Stack(
      children: [
        Container(
          margin: const EdgeInsets.only(top: 20),
          height: 250,
          width: 150,
          decoration: BoxDecoration(
              color: Colors.black38, borderRadius: BorderRadius.circular(10)),
        ),
        Container(
            alignment: Alignment.center,
            width: 150,
            padding: EdgeInsets.only(left: 10, right: 10),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                ClipRRect(
                  borderRadius: BorderRadius.circular(10),
                  child: Container(
                    height: 200,
                    child: VideoImage(
                        record.video!.vpicture ?? record.video!.picture),
                  ),
                Container(
                  height: 100,
                ),
                Container(
                  height: 5,
                ),
                Text(
                  record.video!.name!,
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                  style: const TextStyle(color: Colors.white),
                )
                    child: Stack(
                  children: [
                    Container(
                        alignment: Alignment.bottomRight,
                        color: Colors.white,
                        padding: EdgeInsets.only(bottom: 10),
                        margin: EdgeInsets.only(top: 28),
                        child: Column(
                          children: [
                            const SizedBox(
                              height: 15,
                            ),
                            Container(
                              alignment: Alignment.topCenter,
                              color: Colors.white,
                              height: 100,
                              padding:
                                  const EdgeInsets.fromLTRB(20, 25, 20, 20),
                              child: _user != null
                                  ? personInfoWidget()
                                  :
                                  //登录框
                                  loginBtnWidget(),
                            ),
                            Container(
                              color: Colors.white,
                              padding:
                                  const EdgeInsets.only(left: 12, right: 12),
                              child: Row(
                                mainAxisSize: MainAxisSize.min,
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceAround,
                                children: [
                                  Expanded(
                                      child: InkWell(
                                          onTap: () {
                                            jumpPage("GoldCornPage");
                                          },
                                          child: Container(
                                            alignment: Alignment.centerLeft,
                                            child: AspectRatio(
                                              aspectRatio: 2.048,
                                              child: Stack(
                                                alignment: Alignment.centerLeft,
                                                children: [
                                                  ClipRRect(
                                                      borderRadius:
                                                          BorderRadius.circular(
                                                              12),
                                                      child: Image.asset(
                                                          "assets/imgs/mine/ic_goldcorn_bg.png")),
                                                  Wrap(children: [
                                                    const SizedBox(
                                                      width: 14,
                                                    ),
                                                    Text.rich(TextSpan(
                                                        text: "$goldCorn",
                                                        style: const TextStyle(
                                                            color: Colors.white,
                                                            fontSize: 30),
                                                        children: const [
                                                          TextSpan(
                                                              text: "个",
                                                              style: TextStyle(
                                                                  fontSize: 15))
                                                        ]))
                                                  ])
                                                ],
                                              ),
                                            ),
                                          ))),
                                  const SizedBox(
                                    width: 13.5,
                                  ),
                                  Expanded(
                                      child: InkWell(
                                          onTap: () {
                                            jumpPage("BalancePage");
                                          },
                                          child: Container(
                                            alignment: Alignment.centerLeft,
                                            child: AspectRatio(
                                              aspectRatio: 2.048,
                                              child: Stack(
                                                alignment: Alignment.centerLeft,
                                                children: [
                                                  ClipRRect(
                                                      borderRadius:
                                                          BorderRadius.circular(
                                                              12),
                                                      child: Image.asset(
                                                          "assets/imgs/mine/ic_money_bg.png")),
                                                  Wrap(
                                                    children: [
                                                      SizedBox(
                                                        width: 14,
                                                      ),
                                                      Text.rich(TextSpan(
                                                          text: balance,
                                                          style: TextStyle(
                                                              color:
                                                                  Colors.white,
                                                              fontSize: 30),
                                                          children: [
                                                            TextSpan(
                                                                text: "元",
                                                                style: TextStyle(
                                                                    fontSize:
                                                                        15))
                                                          ]))
                                                    ],
                                                  )
                                                ],
                                              ),
                                            ),
                                          ))),
                                ],
                              ),
                            ),
                            //功能
                            Container(
                              height: 200,
                              margin: const EdgeInsets.fromLTRB(10, 20, 13, 16),
                              padding:
                                  const EdgeInsets.fromLTRB(10, 10, 10, 10),
                              decoration: BoxDecoration(
                                  color: Color(0xFFFAFAFA),
                                  borderRadius: BorderRadius.circular(13)),
                              child: GridView(
                                padding: EdgeInsets.zero,
                                gridDelegate:
                                    const SliverGridDelegateWithFixedCrossAxisCount(
                                        crossAxisCount: 4, mainAxisSpacing: 10),
                                physics: const NeverScrollableScrollPhysics(),
                                children: [
                                  functionWidget(
                                      "assets/imgs/mine/ic_fun_invite.png",
                                      "邀请好友",
                                      28.5, () {
                                    jumpPage("InviteFriendsPage");
                                  }),
                                  functionWidget(
                                      "assets/imgs/mine/ic_fun_help.png",
                                      "帮助中心",
                                      27, () {
                                    ConfigUtil.getConfig(context, "helpLink")
                                        .then((value) {
                                      jumpPage("BrowserPage",
                                          params: {
                                            "url": value,
                                            "title": "帮助中心"
                                          },
                                          needLogin: false);
                                    });
                                  }),
                                  functionWidget(
                                      "assets/imgs/mine/ic_fun_kefu.png",
                                      "在线客服",
                                      28.5, () {
                                    ConfigUtil.getConfig(context, "kefu")
                                        .then((value) {
                                      jumpPage("BrowserPage",
                                          params: {"url": value, "title": "客服"},
                                          needLogin: false);
                                    });
                                  }),
                                  functionWidget(
                                      "assets/imgs/mine/ic_fun_about_us.png",
                                      "关于我们",
                                      25, () {
                                    // MySharedPreferences.getInstance()
                                    //     .getString("aboutUsLink")
                                    //     .then((value) {
                                    //   if (!StringUtil.isNullOrEmpty(value)) {
                                    jumpPage("AboutUsPage", needLogin: false);
                                    //   }
                                    // });
                                  }),
                                  functionWidget(
                                      "assets/imgs/mine/ic_fun_settings.png",
                                      "设置",
                                      24.5, () {
                                    jumpPage("SettingPage", needLogin: false);
                                  }),
                                ],
                              ),
                            ),
                            Container(
                              margin:
                                  const EdgeInsets.only(left: 12, right: 12),
                              width: MediaQuery.of(context).size.width - 12 * 2,
                              height:
                                  (MediaQuery.of(context).size.width - 12 * 2) *
                                      0.6,
                              alignment: Alignment.center,
                              child: CSJEXpressAd(
                                  "948486374",
                                  MediaQuery.of(context).size.width - 12 * 2,
                                  (MediaQuery.of(context).size.width - 12 * 2) *
                                      0.6),
                            )
                          ],
                        )),
                    Container(
                      margin: EdgeInsets.only(left: 25),
                      child: portraitWidget(),
                    )
                  ],
                )),
              ],
            ))
      ],
    );
            )),
          ]))
        ]));
  }
  Widget portraitWidget() {
    return Container(
        width: 80,
        height: 80,
        padding: const EdgeInsets.all(2),
        alignment: Alignment.center,
        decoration: BoxDecoration(
            color: const Color(0xFFAAAAAA),
            borderRadius: BorderRadius.circular(40)),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(40),
          child: CommonImage(
              _user == null
                  ? "assets/imgs/ic_portrait_default.png"
                  : _user!.portrait!,
              defaultWidget:
                  Image.asset("assets/imgs/ic_portrait_default.png")),
        ));
    return InkWell(
        onTap: () {
          if (_user != null) {
            jumpPage("PersonInfoPage");
          }
        },
        child: Container(
            width: 81,
            height: 81,
            padding: const EdgeInsets.all(4),
            alignment: Alignment.center,
            decoration: BoxDecoration(
                color: Colors.white, borderRadius: BorderRadius.circular(40)),
            child: ClipRRect(
              borderRadius: BorderRadius.circular(40),
              child: _user == null
                  ? Container(
                      color: COLOR_PORTRAIT_BG,
                      alignment: Alignment.center,
                      child: Image.asset(
                        "assets/imgs/mine/icon_no_login_portrait.png",
                        height: 39,
                      ),
                    )
                  : CommonImage(
                      (_user == null || _user!.portrait == null)
                          ? "assets/imgs/ic_portrait_default.png"
                          : _user!.portrait!,
                      defaultWidget:
                          Image.asset("assets/imgs/ic_portrait_default.png")),
            )));
  }
  Widget loginBtnWidget() {
    return MyFillButton(
      "立即登录",
      12.5,
      width: 138,
      fontSize: 14,
      onClick: () {
        jumpPage("EmailLoginPage");
      },
    );
    return MyFillButton("登录", 13, width: 230, fontSize: 15, height: 41,
        onClick: () {
      jumpPage("LoginPage", needLogin: false);
    }, color: COLOR_HIGHLIGHT);
  }
  Widget personInfoWidget() {
    print("用户信息:${_user!.toJson()}");
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(_user!.nickname!,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
            style: const TextStyle(
              fontSize: 18,
              color: ColorConstant.theme,
              fontSize: 21,
              color: COLOR_TITLE,
            )),
        Container(
          height: 6,
        ),
        Text("ID:${_user!.id!}",
            style: const TextStyle(
              fontSize: 15,
              color: Color(0xFFA9A9A9),
            )),
      ],
    );
  }
  Widget signWidget() {
    return Container(
      padding: const EdgeInsets.only(top: 21.5, left: 12.5, right: 12.5),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topCenter,
          end: Alignment.bottomCenter,
          colors: [
            ColorConstant.theme.withAlpha(0),
            ColorConstant.theme.withAlpha(108),
  Widget userContent(int number, String content, VoidCallback click,
      {color: COLOR_CONTENT}) {
    return InkWell(
        onTap: () {
          click();
        },
        child: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Text(
              "$number",
              style: TextStyle(color: color, fontSize: 18),
            ),
            Text(
              content,
              style: TextStyle(color: color, fontSize: 10),
            )
          ],
        ),
      ),
      child: Container(
        height: 64,
        padding: const EdgeInsets.only(left: 23, right: 23),
        alignment: Alignment.centerLeft,
        decoration: const BoxDecoration(
            color: ColorConstant.theme,
            borderRadius: BorderRadius.only(
                topLeft: Radius.circular(15), topRight: Radius.circular(15))),
        child: Text(
          "个性签名:${(_user == null || _user!.sign == null || _user!.sign!.isEmpty) ? "这个人非常有趣,但是什么也没写~" : _user!.sign}",
          maxLines: 3,
          overflow: TextOverflow.ellipsis,
          style: const TextStyle(fontSize: 12, color: Colors.white),
        ),
      ),
    );
        ));
  }
  Widget functionWidget(
@@ -603,28 +443,22 @@
        click();
      },
      child: Container(
          padding: const EdgeInsets.only(top: 15, bottom: 15),
          child: Row(
          padding: const EdgeInsets.only(top: 15, bottom: 14),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Image.asset(
                icon,
                width: width,
              ),
              Container(
                  width: 20,
                  alignment: Alignment.center,
                  child: Image.asset(
                    icon,
                    width: width,
                  )),
              Container(
                width: 10,
                height: 10,
              ),
              Text(
                text,
                style: const TextStyle(color: Color(0xFFAAAAAA), fontSize: 15),
              ),
              Expanded(child: Container()),
              Image.asset(
                "assets/imgs/icon_mine_fun_input.png",
                width: 6.5,
              ),
                style: const TextStyle(color: COLOR_CONTENT, fontSize: 12),
              )
            ],
          )),
    );
src/main/resources/code/flutter_module/lib/splash.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/common/browser.dart
@@ -31,7 +31,7 @@
  void initState() {
    super.initState();
    if (Platform.isAndroid) {
      WebView.platform = SurfaceAndroidWebView();
      WebView.platform = AndroidWebView();
    }
  }
@@ -59,6 +59,7 @@
          return false;
        },
        child: Scaffold(
            resizeToAvoidBottomInset: true,
            backgroundColor: Colors.white,
            body: Flex(
              direction: Axis.vertical,
@@ -68,9 +69,21 @@
                  back: () {
                    _back();
                  },
                  rightIcon: const Icon(Icons.refresh,size: 30,),
                  rightClick: (){
                    if(_webViewController!=null){
                  leftWidget: const Padding(
                      padding: EdgeInsets.only(left: 5, right: 10),
                      child: Icon(
                        Icons.close_rounded,
                        size: 30,
                      )),
                  leftWidgetClick: () {
                    popPage(context);
                  },
                  rightIcon: const Icon(
                    Icons.refresh,
                    size: 30,
                  ),
                  rightClick: () {
                    if (_webViewController != null) {
                      _webViewController!.reload();
                    }
                  },
@@ -79,14 +92,16 @@
                  height: 1,
                  child: LinearProgressIndicator(
                    backgroundColor: Colors.white,
                    valueColor: const AlwaysStoppedAnimation(ColorConstant.theme),
                    valueColor:
                        const AlwaysStoppedAnimation(ColorConstant.theme),
                    value: progress,
                  ),
                ),
                Expanded(
                    child: WebView(
                  //http://192.168.3.122:8848/test/JsTest.html
                  initialUrl:url,
                  backgroundColor: Colors.white,
                  initialUrl: url,
                  onWebViewCreated: (WebViewController webViewController) {
                    _webViewController = webViewController;
                  },
src/main/resources/code/flutter_module/lib/ui/mine/person_info.dart
@@ -1,19 +1,24 @@
import 'dart:ui';
import 'dart:io';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_module/utils/wx_util.dart';
import 'package:image_picker/image_picker.dart';
import 'package:package_info/package_info.dart';
import '../../api/http.dart';
import '../../api/user_api.dart';
import '../../model/user/user_info.dart';
import '../../ui/widget/button.dart';
import '../../ui/widget/video_item.dart';
import '../../utils/image_util.dart';
import '../../api/http.dart';
import '../../ui/common/browser.dart';
import '../../ui/widget/button.dart';
import '../../ui/widget/dialog.dart';
import '../../ui/widget/nav.dart';
import '../../ui/widget/video_item.dart';
import '../../utils/cache_util.dart';
import '../../utils/config_util.dart';
import '../../utils/event_bus_util.dart';
import '../../utils/image_util.dart';
import '../../utils/pageutils.dart';
import '../../utils/push_util.dart';
import '../../utils/setting_util.dart';
@@ -21,8 +26,7 @@
import '../../utils/ui_constant.dart';
import '../../utils/ui_utils.dart';
import '../../utils/user_util.dart';
import 'package:package_info/package_info.dart';
import 'package:image_picker/image_picker.dart';
import 'login.dart';
void main() {
  runApp(MyApp());
@@ -64,17 +68,18 @@
  String? editPortrait;
  String? editNickName;
  int? editSex;
  DateTime? editBirthday;
  String? editSign;
  @override
  void initState() {
    super.initState();
    UserUtil.getUserInfo().then((value) {
      setState(() {
        _user = value;
      });
    getUserInfo();
  }
  void getUserInfo() async {
    await UserUtil.updateUserInfo(context);
    UserInfo? temp = await UserUtil.getUserInfo();
    setState(() {
      _user = temp;
    });
  }
@@ -92,124 +97,138 @@
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: const Color(0xFFDADADA),
        backgroundColor: const Color(0xFFF3F3F3),
        body: _user == null
            ? Container()
            : Column(
                children: [
                  TopNavBar(
                    title: "个人信息",
                    rightText: canSave() ? "保存" : null,
                    rightClick: canSave()
                        ? () {
                            //保存
                            UserApiUtil.updateUserInfo(context,
                                    nickName: editNickName,
                                    sex: editSex,
                                    birthDay: editBirthday == null
                                        ? null
                                        : "${editBirthday!.year}/${editBirthday!.month}/${editBirthday!.day}",
                                    sign: editSign,
                                    portraitPath: editPortrait)
                                .then((value) {
                              if (value == null) {
                                return;
                              }
          children: [
            TopNavBar(
              title: "个人信息",
              rightText: canSave() ? "保存" : null,
              rightClick: canSave()
                  ? () {
                //保存
                UserApiUtil.updateUserInfo(context,
                    nickName: editNickName,
                    portraitPath: editPortrait)
                    .then((value) {
                  if (value == null) {
                    return;
                  }
                              if (value["IsPost"] == "true") {
                                ToastUtil.toast("修改成功", context);
                                popPage(context);
                              } else {
                                ToastUtil.toast(value["Error"], context);
                              }
                            });
                          }
                        : null,
                  ),
                  Expanded(
                      child: SingleChildScrollView(
                          child: Column(children: [
                    Container(
                      height: 10,
                      color: const Color(0xFFDADADA),
                    ),
                    getPortraitItemView(onClick: () {
                      //选择头像
                      selectImg();
                    }),
                    getCommonItemView(
                        title: "昵称",
                        content: editNickName ?? _user!.nickname!,
                        onClick: () {
                          showEditNickName(editNickName ?? _user!.nickname!);
                        }),
                    getCommonItemView(
                        title: "性别",
                        content:
                            _getSexDesc((editSex ?? int.parse(_user!.sex!))),
                        onClick: () {
                          showEditSex(editSex ?? int.parse(_user!.sex!));
                        }),
                    getCommonItemView(
                        title: "生日",
                        content: _getBirthDay(),
                        onClick: () {
                          showEditBirthDay((editBirthday ??
                              ((_user!.birthday == null ||
                                      _user!.birthday!.isEmpty)
                                  ? null
                                  : parseDate(_user!.birthday!))));
                        }),
                    getCommonItemView(
                        title: "邮箱",
                        content: _user!.email!,
                        onClick: () {},
                        canIn: false),
                    getCommonItemView(
                        title: "ID",
                        content: _user!.id!,
                        onClick: () {},
                        canIn: false),
                    Container(
                      height: 10,
                      color: const Color(0xFFDADADA),
                    ),
                    getSignItemView(onClick: () {
                      showEditSign(editSign ?? _user!.sign);
                    }),
                  ]))),
                ],
              ));
                  if (value["code"] == 0) {
                    ToastUtil.toast("修改成功", context);
                    popPage(context);
                  } else {
                    ToastUtil.toast(value["msg"], context);
                  }
                });
              }
                  : null,
            ),
            Expanded(
                child: SingleChildScrollView(
                    child: Column(children: [
                      Container(
                        height: 10,
                      ),
                      Row(
                          mainAxisSize: MainAxisSize.min,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            Container(
                              width: 15,
                              height: 50 * 4 +
                                  (DimenUtil.getOnePixel(context)) * 3 * 2,
                              alignment: Alignment.center,
                              color: Colors.white,
                            ),
                            Expanded(
                                child: Column(
                                    mainAxisSize: MainAxisSize.min,
                                    children: [
                                      getPortraitItemView(onClick: () {
                                        //选择头像
                                        selectImg();
                                      }),
                                      getCommonItemView(
                                          title: "昵称",
                                          content: editNickName ?? _user!.nickname!,
                                          onClick: () {
                                            showEditNickName(
                                                editNickName ?? _user!.nickname!);
                                          }),
                                      getCommonItemView(
                                          title: "ID",
                                          content: _user!.id!,
                                          onClick: () {},
                                          canIn: false)
                                    ]))
                          ]),
                      Container(
                        height: 14,
                      ),
                      Row(
                          mainAxisSize: MainAxisSize.min,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            Container(
                              width: 15,
                              height: 50 * 2 +
                                  (DimenUtil.getOnePixel(context)) * 1 * 2,
                              alignment: Alignment.center,
                              color: Colors.white,
                            ),
                            Expanded(
                                child: Column(
                                    mainAxisSize: MainAxisSize.min,
                                    children: [
                                      getCommonItemView(
                                          title: "手机号",
                                          content:
                                          StringUtil.isNullOrEmpty(_user!.phone)
                                              ? "未添加"
                                              : _user!.phone!,
                                          onClick: () {
                                            if (StringUtil.isNullOrEmpty(
                                                _user!.phone)) {
                                              //手机号绑定
                                              NavigatorUtil.navigateToNextPage(
                                                  context,
                                                  LoginPage(
                                                    title: "",
                                                    bindPhone: true,
                                                  ), (data) {
                                                getUserInfo();
                                              });
                                            }
                                          },
                                          canIn:
                                          StringUtil.isNullOrEmpty(_user!.phone)),
                                      getCommonItemView(
                                          title: "微信授权",
                                          content: StringUtil.isNullOrEmpty(
                                              _user!.wxNickName)
                                              ? "去授权"
                                              : _user!.wxNickName!,
                                          onClick: () {
                                            if (!StringUtil.isNullOrEmpty(
                                                _user!.wxNickName)) {
                                              return;
                                            }
                                            WXAuthUtil.startAuth(context);
                                          },
                                          canIn: StringUtil.isNullOrEmpty(
                                              _user!.wxNickName))
                                    ]))
                          ]),
                    ]))),
          ],
        ));
  }
  bool canSave() {
    return editNickName != null ||
        editSex != null ||
        editBirthday != null ||
        editSign != null ||
        editPortrait != null;
  }
  String _getSexDesc(int? sex) {
    switch (sex) {
      case 1:
        return "男";
      case 2:
        return "女";
    }
    return "未知";
  }
  String _getBirthDay() {
    DateTime? date = (editBirthday ??
        ((_user!.birthday == null || _user!.birthday!.isEmpty)
            ? null
            : parseDate(_user!.birthday!)));
    if (date == null) {
      return "请选择出生日期";
    }
    return "${date.year}/${date.month}/${date.day}";
    return editNickName != null || editPortrait != null;
  }
  DateTime parseDate(String date) {
@@ -220,19 +239,22 @@
  Widget getCommonItemView(
      {required String title,
      String content = "",
      required GestureTapCallback onClick,
      bool canIn = true}) {
        String content = "",
        required GestureTapCallback onClick,
        bool canIn = true}) {
    return Container(
      height: 53,
      margin: const EdgeInsets.fromLTRB(0, 0, 0, 1),
      height: 50,
      margin: EdgeInsets.fromLTRB(0, 0, 0, DimenUtil.getOnePixel(context) * 2),
      color: Colors.white,
      child: InkWell(
        onTap: () {
          if (!canIn) {
            return;
          }
          onClick();
        },
        child: Container(
            padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
            padding: const EdgeInsets.fromLTRB(0, 0, 20, 0),
            child: Flex(
              crossAxisAlignment: CrossAxisAlignment.center,
              direction: Axis.horizontal,
@@ -240,27 +262,36 @@
                Text(
                  title,
                  style:
                      const TextStyle(fontSize: 16, color: Color(0xFF333333)),
                  const TextStyle(fontSize: 16, color: Color(0xFF333333)),
                ),
                Expanded(
                    child: Flex(
                  direction: Axis.horizontal,
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    Container(
                      child: Text(content,
                          style: const TextStyle(
                              fontSize: 14, color: Color(0xFF959595))),
                      margin: const EdgeInsets.fromLTRB(0, 0, 13.5, 0),
                    ),
                    canIn
                        ? Image.asset(
                            "assets/imgs/icon_person_info_input.png",
                            height: 13.5,
                          )
                        : Container()
                  ],
                ))
                    child: Wrap(
                      alignment: WrapAlignment.end,
                      crossAxisAlignment: WrapCrossAlignment.center,
                      children: [
                        Container(
                          child: Text(content,
                              style: const TextStyle(
                                  fontSize: 14, color: Color(0xFF888888))),
                          margin: const EdgeInsets.fromLTRB(0, 0, 0, 0),
                        ),
                        canIn
                            ? const SizedBox(
                          width: 10.5,
                        )
                            : const SizedBox(
                          width: 0,
                        ),
                        canIn
                            ? Image.asset(
                          "assets/imgs/icon_person_info_input.png",
                          height: 13.5,
                        )
                            : Container(
                          width: 0,
                        )
                      ],
                    ))
              ],
            )),
      ),
@@ -269,15 +300,15 @@
  Widget getPortraitItemView({required GestureTapCallback onClick}) {
    return Container(
      height: 75,
      margin: const EdgeInsets.fromLTRB(0, 0, 0, 1),
      height: 50,
      margin: EdgeInsets.fromLTRB(0, 0, 0, DimenUtil.getOnePixel(context) * 2),
      color: Colors.white,
      child: InkWell(
        onTap: () {
          onClick();
        },
        child: Container(
            padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
            padding: const EdgeInsets.fromLTRB(0, 0, 20, 0),
            child: Flex(
              crossAxisAlignment: CrossAxisAlignment.center,
              direction: Axis.horizontal,
@@ -288,93 +319,38 @@
                ),
                Expanded(
                    child: Flex(
                  direction: Axis.horizontal,
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    Container(
                      child: ClipRRect(
                          borderRadius: BorderRadius.circular(60),
                          child: editPortrait == null
                              ? CommonImage(
                                  _user!.portrait!,
                                  height: 57,
                                  width: 57,
                                )
                              : Image.file(
                                  File(editPortrait!),
                                  fit: BoxFit.cover,
                                  height: 57,
                                  width: 57,
                                )),
                      margin: const EdgeInsets.fromLTRB(0, 0, 13.5, 0),
                    ),
                    Image.asset(
                      "assets/imgs/icon_person_info_input.png",
                      height: 13.5,
                    )
                  ],
                ))
                      direction: Axis.horizontal,
                      mainAxisAlignment: MainAxisAlignment.end,
                      children: [
                        Container(
                          child: ClipRRect(
                              borderRadius: BorderRadius.circular(60),
                              child: editPortrait == null
                                  ? CommonImage(
                                _user!.portrait == null
                                    ? 'assets/imgs/ic_portrait_default.png'
                                    : _user!.portrait!,
                                height: 33,
                                width: 33,
                              )
                                  : Image.file(
                                File(editPortrait!),
                                fit: BoxFit.cover,
                                height: 33,
                                width: 33,
                              )),
                          margin: const EdgeInsets.fromLTRB(0, 0, 10.5, 0),
                        ),
                        Image.asset(
                          "assets/imgs/icon_person_info_input.png",
                          height: 13.5,
                        )
                      ],
                    ))
              ],
            )),
      ),
    );
  }
  Widget getSignItemView({required GestureTapCallback onClick}) {
    return Container(
        height: 200,
        margin: const EdgeInsets.fromLTRB(0, 0, 0, 1),
        color: Colors.white,
        child: InkWell(
          onTap: () {
            onClick();
          },
          child: Container(
            padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
            child:
                Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
              Container(
                height: 18,
              ),
              Flex(
                crossAxisAlignment: CrossAxisAlignment.center,
                direction: Axis.horizontal,
                children: [
                  const Text(
                    "个性签名",
                    style: TextStyle(fontSize: 16, color: Color(0xFF333333)),
                  ),
                  Expanded(
                      child: Flex(
                    direction: Axis.horizontal,
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      Image.asset(
                        "assets/imgs/icon_person_info_input.png",
                        height: 13.5,
                      )
                    ],
                  ))
                ],
              ),
              Container(
                height: 21,
              ),
              Text(
                _getSign(),
                textAlign: TextAlign.start,
                style: const TextStyle(color: Color(0xFFBEBEBE), fontSize: 15),
              )
            ]),
          ),
        ));
  }
  _getSign() {
    return editSign ??
        ((_user!.sign == null || _user!.sign!.isEmpty)
            ? "这个人很懒,什么也没有留下"
            : _user!.sign!);
  }
  showAlertDilaog(String title, Widget content, VoidCallback sure,
@@ -389,7 +365,7 @@
              TextButton(
                child: Text('取消'),
                onPressed: () {
                  Navigator.of(context).pop();
                  popPage(context);
                },
              ),
              TextButton(
@@ -414,123 +390,10 @@
      if (controller.text.isEmpty) {
        return;
      }
      Navigator.of(context).pop();
      popPage(context);
      setState(() {
        editNickName = controller.text;
      });
    });
  }
  void showEditSex(int sex) {
    int? tempSex;
    setState(() {
      tempSex = sex;
    });
    DialogUtil.showDialogBottom(
        context,
        Container(
            margin: const EdgeInsets.all(10),
            alignment: Alignment.bottomCenter,
            child: Stack(alignment: Alignment.bottomCenter, children: [
              Container(
                  margin: const EdgeInsets.only(bottom: 50),
                  decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(10)),
                  child: Container(
                      height: 100,
                      alignment: Alignment.center,
                      child: Column(
                        children: [
                          InkWell(
                              onTap: () {
                                setState(() {
                                  editSex = 1;
                                });
                                Navigator.of(context).pop();
                              },
                              child: Container(
                                  height: 50,
                                  alignment: Alignment.center,
                                  child: const Text(
                                    "男",
                                    style: TextStyle(
                                        fontSize: 18,
                                        color: ColorConstant.theme),
                                  ))),
                          InkWell(
                              onTap: () {
                                setState(() {
                                  editSex = 2;
                                });
                                Navigator.of(context).pop();
                              },
                              child: Container(
                                  height: 50,
                                  alignment: Alignment.center,
                                  child: const Text(
                                    "女",
                                    style: TextStyle(
                                        fontSize: 18,
                                        color: ColorConstant.theme),
                                  ))),
                        ],
                      ))),
              MyFillButton(
                "取消",
                20,
                height: 40,
                color: Colors.grey,
                fontSize: 14,
                onClick: () {
                  popPage(context);
                },
              )
            ])));
  }
  //编辑生日
  void showEditBirthDay(DateTime? dateTime) async {
    dateTime ??= DateTime.now();
    Locale myLocale = Localizations.localeOf(context);
    DateTime? date = await showDatePicker(
        context: context,
        initialDate: dateTime,
        firstDate: DateTime(1900),
        lastDate: DateTime(DateTime.now().year + 1),
        locale: myLocale);
    if (date != null) {
      setState(() {
        editBirthday = date;
      });
    }
  }
  void showEditSign(String? sign) {
    sign ??= "";
    TextEditingController controller = TextEditingController();
    controller.text = sign;
    showAlertDilaog(
        "编辑签名",
        TextField(
          controller: controller,
          maxLines: 5,
          maxLength: 200,
          decoration: const InputDecoration(
              focusedBorder: InputBorder.none,
              border: InputBorder.none,
              counterStyle: TextStyle(color: Color(0xFF666666)),
              hintText: "请输入签名内容",
              hintStyle: TextStyle(fontSize: 15, color: Color(0xFF999999))),
        ), () {
      if (controller.text.isEmpty) {
        return;
      }
      Navigator.of(context).pop();
      setState(() {
        editSign = controller.text;
      });
    });
  }
}
}
src/main/resources/code/flutter_module/lib/ui/mine/settings.dart
@@ -57,7 +57,8 @@
class _SettingPageState extends State<SettingPage>
    with SingleTickerProviderStateMixin {
  bool msg = false;
  bool ad = false;
  bool ad = true;
  bool content = true;
  bool login = false;
  String cacheSize = "0B";
@@ -77,12 +78,20 @@
    SettingUtil.isEnablePush().then((value) {
      setState(() {
        msg = value;
        msg = value!;
      });
    });
    SettingUtil.isEnableRecommendAd().then((value) {
      ad = value;
      setState(() {
        ad = value!;
      });
    });
    SettingUtil.isEnableRecommendContent().then((value) {
      setState(() {
        content = value!;
      });
    });
  }
@@ -125,7 +134,6 @@
        UserUtil.getUid();
        // popPage(context);
      });
    } else {
      ToastUtil.toast(map["msg"], context);
    }
@@ -141,7 +149,7 @@
            TopNavBar(title: "设置"),
            getBigItemView(
                title: "推送免打扰",
                content: "关闭后,21:00-09:00不接受任何推送",
                content: "开启后,21:00-9:00不接受任何推送",
                marginTop: 14,
                marginBottom: 1,
                checked: msg,
@@ -149,6 +157,19 @@
                  SettingUtil.setPush(value).then((value1) {
                    setState(() {
                      msg = value;
                    });
                  });
                }),
            getBigItemView(
                title: "个性化内容推荐",
                content: "关闭后,内容数量将不变,但内容相关度会降低",
                marginTop: 0,
                marginBottom: 1,
                checked: content,
                changed: (bool value) {
                  SettingUtil.setRecommendContent(value).then((value1) {
                    setState(() {
                      content = value;
                    });
                  });
                }),
@@ -166,36 +187,6 @@
                  });
                }),
            getCommonItemView(
                title: "清理缓存",
                content: cacheSize,
                onClick: () {
                  showCupertinoDialog(
                      context: context,
                      builder: (context) {
                        return AlertDialog(
                          title: const Text("是否清楚缓存"),
                          actions: <Widget>[
                            TextButton(
                              child: const Text('取消'),
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                            ),
                            TextButton(
                              child: const Text('确定'),
                              onPressed: () {
                                CacheUtil.clear().then((value) {
                                  ToastUtil.toast("缓存清除成功", context);
                                  _getCacheSize();
                                });
                                Navigator.of(context).pop();
                              },
                            ),
                          ],
                        );
                      });
                }),
            getCommonItemView(
                title: "检查更新",
                content: "版本号:$version",
                onClick: () {
@@ -205,8 +196,9 @@
                title: "账户注销",
                content: "",
                onClick: () {
    MySharedPreferences.getInstance().getString("unRegisterLink").then((value) {
                  MySharedPreferences.getInstance()
                      .getString("unRegisterLink")
                      .then((value) {
                    if (!StringUtil.isNullOrEmpty(value)) {
                      NavigatorUtil.navigateToNextPage(context,
                          BrowserPage(title: "账户注销", url: value!), (data) {});
@@ -217,7 +209,9 @@
                title: "隐私投诉",
                content: "",
                onClick: () {
    MySharedPreferences.getInstance().getString("feedBackLink").then((value) {
                  MySharedPreferences.getInstance()
                      .getString("feedBackLink")
                      .then((value) {
                    if (!StringUtil.isNullOrEmpty(value)) {
                      NavigatorUtil.navigateToNextPage(context,
                          BrowserPage(title: "隐私投诉", url: value!), (data) {});
src/main/resources/code/flutter_module/lib/ui/search/search.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/search/search_result.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/video/video_attention_list.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/video/video_collected_list.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/video/video_detail.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/video/video_download_list.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/video/video_list.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/video/video_player_browser.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/video/video_scan_record_list.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/widget/dialog.dart
@@ -2,12 +2,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import '../../ui/search/search.dart';
import 'package:html/dom.dart' as dom;
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import '../../ui/common/browser.dart';
import '../../utils/pageutils.dart';
import '../../utils/ui_constant.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import '../widget/nav.dart';
//通用弹框
src/main/resources/code/flutter_module/lib/ui/widget/images_widget.dart
New file
@@ -0,0 +1,39 @@
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import '../../model/video/home_type_model.dart';
import '../../model/video/video_model.dart';
import '../../utils/jump_page.dart';
import '../../utils/ui_constant.dart';
import '../../utils/ui_utils.dart';
import '../../utils/video/video_util.dart';
Widget CommonImage(String url,
    {fit = BoxFit.cover,
    double? width,
    double? height,
    Widget? defaultWidget}) {
  if (url.startsWith("http")) {
    return CachedNetworkImage(
      imageUrl: url,
      fit: fit,
      width: width,
      height: height,
      placeholder: (context, st) =>
          defaultWidget ??
          Container(
            color: const Color(0xFFFFE8F0),
          ),
      errorWidget: (context, url, error) =>
          defaultWidget ?? const Icon(Icons.error),
    );
  } else {
    return Image.asset(
      url,
      width: width,
      height: height,
      fit: fit,
    );
  }
}
src/main/resources/code/flutter_module/lib/ui/widget/nav.dart
@@ -18,9 +18,12 @@
class TopNavBar extends StatelessWidget {
  final String title;
  GestureTapCallback? back;
  GestureTapCallback? leftWidgetClick;
  String? rightText;
  String? leftText;
  Widget? leftWidget;
  Icon? rightIcon;
  Image? rightImage;
  GestureTapCallback? rightClick;
  final Color textColor;
  final Color backGround;
@@ -31,6 +34,9 @@
      this.back,
      this.rightText,
      this.rightIcon,
      this.leftWidget,
      this.leftWidgetClick,
      this.rightImage,
      this.leftText = "",
      this.rightClick,
      this.textColor = const Color(0xFF333333),
@@ -77,7 +83,9 @@
                        )
                      ],
                    ))),
            ((rightText != null && rightText!.isNotEmpty) || rightIcon != null)
            ((rightText != null && rightText!.isNotEmpty) ||
                    rightIcon != null ||
                    rightImage != null)
                ? Positioned(
                    right: 0,
                    top: 0,
@@ -90,11 +98,12 @@
                          alignment: Alignment.center,
                          padding: const EdgeInsets.only(right: 10),
                          child: rightIcon ??
                              Text(
                                rightText!,
                                style:
                                    TextStyle(fontSize: 15, color: textColor),
                              ),
                              (rightImage ??
                                  Text(
                                    rightText!,
                                    style: TextStyle(
                                        fontSize: 15, color: textColor),
                                  )),
                        )))
                : Container(),
            InkWell(
@@ -102,24 +111,38 @@
                  if (back != null) {
                    back!();
                  } else {
                   popPage(context);
                    popPage(context);
                  }
                },
                child: Container(
                  padding: const EdgeInsets.only(left: 10),
                  height: 48,
                  child: Row(mainAxisSize: MainAxisSize.min,crossAxisAlignment: CrossAxisAlignment.center, children: [
                    Icon(
                      Icons.arrow_back_ios,
                      color: textColor,
                    ),
                    leftText!.isNotEmpty
                        ? Text(
                            leftText!,
                            style: const TextStyle(fontSize: 16),
                          )
                        : Container()
                  ]),
                  child: Row(
                      mainAxisSize: MainAxisSize.min,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.arrow_back_ios,
                          color: textColor,
                        ),
                        leftText!.isNotEmpty
                            ? Text(
                                leftText!,
                                style: const TextStyle(fontSize: 16),
                              )
                            : Container(),
                        leftWidget == null
                            ? Container()
                            : InkWell(
                                onTap: () {
                                  if (leftWidgetClick == null) {
                                    return;
                                  }
                                  leftWidgetClick!();
                                },
                                child: leftWidget!,
                              )
                      ]),
                ))
          ],
        ),
src/main/resources/code/flutter_module/lib/ui/widget/refresh_listview.dart
@@ -1,17 +1,19 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../ui/widget/button.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
typedef OnRefresh = void Function();
typedef OnLoadMore = void Function();
typedef BoolCallback = void Function(bool b);
typedef StringCallback = void Function(String s);
typedef GetViewState = RefreshListViewState Function();
class MyRefreshController extends RefreshController {
  MyRefreshController({
    bool initialRefresh = true,
  }) : super(
            initialRefresh: initialRefresh, initialLoadStatus: LoadStatus.idle);
      initialRefresh: initialRefresh, initialLoadStatus: LoadStatus.idle);
  //api错误
  VoidCallback? apiError;
@@ -37,7 +39,7 @@
  void dispose() {
    apiError = null;
    dataEmpty = null;
    dataNormal=null;
    dataNormal = null;
    setPullDownEnable = null;
    setPullUpEnable = null;
    setEditMode = null;
@@ -47,19 +49,23 @@
class RefreshListView extends StatefulWidget {
  final MyRefreshController refreshController;
  final Widget content;
  final Widget? emptyView;
  final OnRefresh? refresh;
  final OnLoadMore? loadMore;
  final Color loadTextColor;
  bool? enablePullDown;
  bool? enablePullUp;
  RefreshListView(
      {required this.refreshController,
      required this.content,
      this.refresh,
      this.loadMore,
      this.enablePullDown = true,
      this.enablePullUp = true});
        required this.content,
        this.emptyView,
        this.refresh,
        this.loadTextColor = const Color(0xFFB8AFB5),
        this.loadMore,
        this.enablePullDown = true,
        this.enablePullUp = true});
  @override
  State<StatefulWidget> createState() => _RefreshListViewState();
@@ -77,7 +83,7 @@
  bindController() {
    widget.refreshController.apiError = _apiError;
    widget.refreshController.dataEmpty = _dataEmpty;
    widget.refreshController.dataNormal =_dataNormal;
    widget.refreshController.dataNormal = _dataNormal;
    widget.refreshController.setPullDownEnable = _pullDownEnable;
    widget.refreshController.setPullUpEnable = _pullUpEnable;
    widget.refreshController.viewState = () {
@@ -88,7 +94,6 @@
        editMode = enable;
      });
    };
  }
  //视图状态 0-正常  1-空视图  2-网络请求错误
@@ -151,85 +156,100 @@
    return editMode
        ? widget.content
        : SmartRefresher(
            enablePullDown: widget.enablePullDown!,
            enablePullUp: widget.enablePullUp!,
            header: const WaterDropHeader(
              complete: Text(
                "刷新完成",
                style: TextStyle(color: Color(0xFFB8AFB5)),
              ),
            ),
            footer: CustomFooter(
              builder: (BuildContext context, LoadStatus? mode) {
                Widget body;
                if (mode == LoadStatus.idle) {
                  body = const Text("",
                      style: TextStyle(color: Color(0xFFB8AFB5)));
                } else if (mode == LoadStatus.loading) {
                  body = const CupertinoActivityIndicator();
                } else if (mode == LoadStatus.failed) {
                  body = const Text("加载失败!点击重试!",
                      style: TextStyle(color: Color(0xFFB8AFB5)));
                } else if (mode == LoadStatus.canLoading) {
                  body = const Text("松手,加载更多!",
                      style: TextStyle(color: Color(0xFFB8AFB5)));
                } else {
                  body = const Text("没有更多数据了!",
                      style: TextStyle(color: Color(0xFFB8AFB5)));
                }
                return SizedBox(
                  height: 55.0,
                  child: Center(child: body),
                );
              },
            ),
            controller: widget.refreshController,
            onRefresh: _onRefresh,
            onLoading: _onLoading,
            child: widget.content,
          );
  }
      enablePullDown: widget.enablePullDown!,
      enablePullUp: widget.enablePullUp!,
      header:
      MaterialClassicHeader(),
  Widget emptyView() {
    return Container(
      width: MediaQuery.of(context).size.width * 2 / 3,
      alignment: Alignment.center,
      // color: Colors.yellow,
      child: Stack(
        alignment: Alignment.bottomCenter,
        children: [
          Image.asset(
            "assets/imgs/common/ic_empty.png",
          ),
          const Text(
            "暂无数据     ",
            style: TextStyle(color: Color(0xFFF698C9), fontSize: 18),
          )
        ],
      // const WaterDropHeader(
      //   complete: Text(
      //     "刷新完成",
      //     style: TextStyle(color: Color(0xFFB8AFB5)),
      //   ),
      // ),
      footer: CustomFooter(
        builder: (BuildContext context, LoadStatus? mode) {
          Widget body;
          if (mode == LoadStatus.idle) {
            body = const Text("",
                style: TextStyle(color: Color(0xFFB8AFB5)));
          } else if (mode == LoadStatus.loading) {
            body = const CupertinoActivityIndicator();
          } else if (mode == LoadStatus.failed) {
            body = const Text("加载失败!点击重试!",
                style: TextStyle(color: Color(0xFFB8AFB5)));
          } else if (mode == LoadStatus.canLoading) {
            body = const Text("松手,加载更多!",
                style: TextStyle(color: Color(0xFFB8AFB5)));
          } else {
            body = Text("~到底了~",
                style: TextStyle(color: widget.loadTextColor));
          }
          return SizedBox(
            height: 55.0,
            child: Center(child: body),
          );
        },
      ),
      controller: widget.refreshController,
      onRefresh: _onRefresh,
      onLoading: _onLoading,
      child: widget.content,
    );
  }
  Widget errorView() {
    return InkWell(
        onTap: () {
          _onRefresh();
        },
        child: Container(
  Widget emptyView() {
    return widget.emptyView ??
        Container(
          width: MediaQuery.of(context).size.width * 2 / 3,
          alignment: Alignment.center,
          // color: Colors.yellow,
          child: Stack(
            alignment: Alignment.bottomCenter,
            children: [
              Image.asset("assets/imgs/common/ic_network_error.png",
                  width: MediaQuery.of(context).size.width * 2 / 5),
              Image.asset(
                "assets/imgs/common/ic_empty.png",
              ),
              const Text(
                "网络异常,点击重新加载",
                style: TextStyle(color: Color(0xFFF698C9), fontSize: 18),
                "~空空如也~",
                style: TextStyle(color: Color(0xFF999999), fontSize: 18),
              )
            ],
          ),
        ));
        );
  }
  Widget errorView() {
    return Container(
      alignment: Alignment.center,
      // color: Colors.yellow,
      child: Stack(
        alignment: Alignment.bottomCenter,
        children: [
          Image.asset("assets/imgs/common/ic_network_error.png",
              width: MediaQuery.of(context).size.width * 3 / 5),
          const Positioned(
              bottom: 50,
              left: 0,
              right: 0,
              child: Text(
                "网络请求出错",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 15, color: Color(0xFF999999)),
              )),
          MyFillButton(
            "点击重新加载",
            18,
            width: 170,
            height: 36,
            fontSize: 15,
            onClick: () {
              _onRefresh();
            },
          )
        ],
      ),
    );
  }
  @override
src/main/resources/code/flutter_module/lib/ui/widget/search_widget.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/widget/sos_ui.dart
File was deleted
src/main/resources/code/flutter_module/lib/ui/widget/video_item.dart
File was deleted
src/main/resources/code/flutter_module/lib/utils/ad_util.dart
@@ -1,7 +1,7 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import '../../utils/share_preference.dart';
import '../../utils/string_util.dart';
src/main/resources/code/flutter_module/lib/utils/config_util.dart
@@ -5,31 +5,12 @@
import '../api/http.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ConfigUtil {
  ///保存配置信息
  static void saveConfig(Map<String, dynamic> map) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setString("config_value", jsonEncode(map));
  }
import 'share_preference.dart';
class ConfigUtil {
  static Future<String?> getConfig(BuildContext context, String key) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String? result = prefs.getString("config_value");
    if (result != null) {
      Map<String, dynamic> map = jsonDecode(result);
      return map[key];
    } else {
      //重新请求
      ConfigApiUtil.getConfig(context).then((value) {
        if (value == null) {
          return;
        }
        if (value["code"] == 0) {
          saveConfig(value["data"]);
        }
      });
    }
    return null;
    String? value = await dataMethodChannel.invokeMethod("getConfig", key);
    return value;
  }
}
@@ -53,4 +34,4 @@
  static const String sdkList = "sdkList";
}
enum SharePlatform { wx, wxcircle, qq, qqzone, sina }
enum SharePlatform { all, wx, wxcircle, qq, qqzone, sina }
src/main/resources/code/flutter_module/lib/utils/encrypt_util.dart
@@ -5,6 +5,8 @@
  static String MD5(String data) {
    return md5.convert(utf8.encode(data)).toString();
  }
  static String md5Bytes(List<int> bytes) {
    return md5.convert(bytes).toString();
  }
}
src/main/resources/code/flutter_module/lib/utils/image_util.dart
@@ -1,23 +1,31 @@
//图片工具
import 'package:flutter/material.dart';
import '../../utils/ui_constant.dart';
import 'package:image_cropper/image_cropper.dart';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
class ImageUtil{
import '../../utils/ui_constant.dart';
import 'config_util.dart';
import 'encrypt_util.dart';
import 'permission_util.dart';
import 'share_utils.dart';
import 'ui_utils.dart';
class ImageUtil {
  //选择并裁剪图片
  static Future<File?> selectAndCropImage() async{
  static Future<File?> selectAndCropImage() async {
    final ImagePicker _picker = ImagePicker();
    final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
    ImageCropper cropper=ImageCropper();
    ImageCropper cropper = ImageCropper();
    File? croppedFile = await cropper.cropImage(
        cropStyle:CropStyle.circle,
        cropStyle: CropStyle.circle,
        sourcePath: image!.path,
        aspectRatioPresets: [
          CropAspectRatioPreset.square
        ],
        aspectRatioPresets: [CropAspectRatioPreset.square],
        androidUiSettings: const AndroidUiSettings(
            toolbarTitle: 'Cropper',
            toolbarColor: ColorConstant.theme,
@@ -26,11 +34,87 @@
            lockAspectRatio: true),
        iosUiSettings: const IOSUiSettings(
          minimumAspectRatio: 1.0,
        )
    );
        ));
    return croppedFile;
  }
  //保存图片
  static saveImg(String url, BuildContext context) {
    Future<Directory?> dir;
    if (Platform.isAndroid) {
      dir = getExternalStorageDirectory();
    } else {
      dir = getApplicationDocumentsDirectory();
    }
    dir.then((value) {
      if (value == null) {
        ToastUtil.toast("获取缓存目录失败", context);
        return;
      }
      String doc = value.path;
      String path = doc + "/" + EncryptUtil.MD5(url) + ".png";
      _dowloadImg(url, path, context).then((value) {
        if (value) {
          ToastUtil.toast("保存成功", context);
        }
      });
    });
  }
}
  ///分享图片
  ///type: 1-微信  2-qq 3-新浪
  static shareImg(String url, int type, BuildContext context) {
    getTemporaryDirectory().then((value) {
      String path = value.path + "/" + EncryptUtil.MD5(url) + ".png";
      _dowloadImg(url, path, context).then((value) {
        if (value) {
          //开始分享
          switch (type) {
            case 0:
              ShareUtil.shareImg(context, File(path), SharePlatform.all);
              break;
            case 1:
              ShareUtil.shareImg(context, File(path), SharePlatform.wx);
              break;
            case 2:
              ShareUtil.shareImg(context, File(path), SharePlatform.qq);
              break;
            case 3:
              ShareUtil.shareImg(context, File(path), SharePlatform.sina);
              break;
          }
        }
      });
    });
  }
  static Future<bool> _dowloadImg(
      String url, String path, BuildContext context) async {
    PermissionStatus status =
        await PermissionUtil.openPermission(Permission.storage, force: true);
    if (status != PermissionStatus.granted) {
      return false;
    }
    //下载图片
    Dio dio = Dio();
    //设置连接超时时间
    dio.options.connectTimeout = 20000;
    //设置数据接收超时时间
    dio.options.receiveTimeout = 20000;
    Response response;
    try {
      response = await dio.download(url, path);
      if (response.statusCode == 200) {
        await ImageGallerySaver.saveFile(path);
        return true;
      } else {
        return false;
      }
    } catch (e) {
      ToastUtil.toast("网络连接失败", context);
      return false;
    }
  }
}
src/main/resources/code/flutter_module/lib/utils/jsinterface.dart
@@ -1,26 +1,16 @@
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import '../api/http.dart' as http;
import '../utils/encrypt_util.dart';
import '../utils/permission_util.dart';
import '../utils/share_utils.dart';
import '../utils/string_util.dart';
import '../utils/ui_constant.dart';
import '../utils/ui_utils.dart';
import '../utils/user_util.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:package_info/package_info.dart';
import 'package:webview_flutter/platform_interface.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:path_provider/path_provider.dart';
import '../ui/widget/nav.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'config_util.dart';
import 'package:package_info/package_info.dart';
import '../api/http.dart' as http;
import '../ui/widget/nav.dart';
import '../utils/ui_utils.dart';
import '../utils/user_util.dart';
import 'image_util.dart';
class JavascriptInterface {
  final BuildContext context;
@@ -69,12 +59,12 @@
              break;
            case "saveImg":
              String url = params["url"];
              saveImg(url);
              ImageUtil.saveImg(url,context);
              break;
            case "shareImg":
              String url = params["url"];
              String type = params["type"];
              shareImg(url, int.parse(type));
              ImageUtil.shareImg(url, int.parse(type),context);
              break;
          }
        }));
@@ -172,79 +162,4 @@
    popPage(context);
  }
  Future<bool> _dowloadImg(String url, String path) async {
    PermissionStatus status =
        await PermissionUtil.openPermission(Permission.storage, force: true);
    if (status != PermissionStatus.granted) {
      return false;
    }
    //下载图片
    Dio dio = Dio();
    //设置连接超时时间
    dio.options.connectTimeout = 20000;
    //设置数据接收超时时间
    dio.options.receiveTimeout = 20000;
    Response response;
    try {
      response = await dio.download(url, path);
      if (response.statusCode == 200) {
        await ImageGallerySaver.saveFile(path);
        return true;
      } else {
        return false;
      }
    } catch (e) {
      ToastUtil.toast("网络连接失败", context);
      return false;
    }
  }
  //保存图片
  saveImg(String url) {
    Future<Directory?> dir;
    if (Platform.isAndroid) {
      dir = getExternalStorageDirectory();
    } else {
      dir = getApplicationDocumentsDirectory();
    }
    dir.then((value) {
      if (value == null) {
        ToastUtil.toast("获取缓存目录失败", context);
        return;
      }
      String doc = value.path;
      String path = doc + "/" + EncryptUtil.MD5(url) + ".png";
      _dowloadImg(url, path).then((value) {
        if (value) {
          ToastUtil.toast("保存成功", context);
        }
      });
    });
  }
  ///分享图片
  ///type: 1-微信  2-qq 3-新浪
  shareImg(String url, int type) {
    getTemporaryDirectory().then((value) {
      String path = value.path + "/" + EncryptUtil.MD5(url) + ".png";
      _dowloadImg(url, path).then((value) {
        if (value) {
          //开始分享
          switch (type) {
            case 1:
              ShareUtil.shareImg(context, File(path), SharePlatform.wx);
              break;
            case 2:
              ShareUtil.shareImg(context, File(path), SharePlatform.qq);
              break;
            case 3:
              ShareUtil.shareImg(context, File(path), SharePlatform.sina);
              break;
          }
        }
      });
    });
  }
}
src/main/resources/code/flutter_module/lib/utils/jump_page.dart
@@ -1,10 +1,9 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import '../../utils/pageutils.dart';
import '../../utils/ui_utils.dart';
import 'package:flutter_boost/flutter_boost.dart';
import '../../utils/pageutils.dart';
import '../main.dart';
class JumpPageUtil {
src/main/resources/code/flutter_module/lib/utils/network_util.dart
New file
@@ -0,0 +1,74 @@
import 'package:flutter/services.dart';
typedef OnNetWorkChanged = void Function(ConnectivityResult);
List<OnNetWorkChanged> _notifyList = [];
ConnectivityResult _getNetwork(String network) {
  if (network == "1") {
    return ConnectivityResult.mobile;
  } else if (network == "2") {
    return ConnectivityResult.wifi;
  } else {
    return ConnectivityResult.none;
  }
}
class Connectivity {
  static Connectivity? _singleton;
  static final NetWorkMethodChannel _netWorkMethodChannel =
      NetWorkMethodChannel("com.yeshi.video/network");
  Connectivity._();
  factory Connectivity() {
    _singleton ??= Connectivity._();
    return _singleton!;
  }
  Future<ConnectivityResult> checkConnectivity() async {
    String network =
        await _netWorkMethodChannel.invokeMethod("getCurrentNetwork");
    print("当前网络状态$network");
    return _getNetwork(network);
  }
  OnNetWorkChanged listen(OnNetWorkChanged changed) {
    _notifyList.add(changed);
    return changed;
  }
  remove(OnNetWorkChanged changed) {
    _notifyList.remove(changed);
  }
}
class NetWorkMethodChannel extends MethodChannel {
  NetWorkMethodChannel(String name) : super(name) {
    setMethodCallHandler((call) {
      switch (call.method) {
        case "onNetworkChanged":
          {
            print("网络连接状态改变${call.arguments}");
            String network = call.arguments;
            _notifyList.forEach((element) {
              element(_getNetwork(network));
            });
          }
      }
      return Future.value();
    });
  }
}
enum ConnectivityResult {
  /// WiFi: Device connected via Wi-Fi
  wifi,
  /// Mobile: Device connected to cellular network
  mobile,
  /// None: Device not connected to any network
  none
}
src/main/resources/code/flutter_module/lib/utils/setting_util.dart
@@ -1,46 +1,47 @@
import 'package:shared_preferences/shared_preferences.dart';
import 'share_preference.dart';
class SettingUtil {
  //设置推送
  static Future<bool> setPush(bool enable) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return await prefs.setBool("setting_push", enable);
    await _setSetting("pushUnDisturb", enable);
    return true;
  }
  ///是否允许推送
  static Future<bool> isEnablePush() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    bool? result = prefs.getBool("setting_push");
    result ??= true;
    return result;
  static Future<bool?> isEnablePush() async {
    return await _getSetting("pushUnDisturb");
  }
  //设置推荐广告
  static Future<bool> setRecommendAd(bool enable) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return await prefs.setBool("setting_recommend_ad", enable);
    await _setSetting("adRecommend", enable);
    return true;
  }
  ///是否允许推荐广告
  static Future<bool> isEnableRecommendAd() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    bool? result = prefs.getBool("setting_recommend_ad");
    result ??= true;
    return result;
  static Future<bool?> isEnableRecommendAd() async {
    return await _getSetting("adRecommend");
  }
  //设置推荐广告
  static Future<bool> setLocationSpan(int second) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return await prefs.setInt("setting_location_span", second);
  //设置推荐内容
  static Future<bool> setRecommendContent(bool enable) async {
    await _setSetting("contentRecommend", enable);
    return true;
  }
  ///是否允许推荐广告
  static Future<int> getLocationSpan() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    int? result = prefs.getInt("setting_location_span");
    result ??= 30;
    return result;
  ///是否允许推荐内容
  static Future<bool?> isEnableRecommendContent() async {
    return await _getSetting("contentRecommend");
  }
}
  static _setSetting(String key, bool value) async {
    await dataMethodChannel
        .invokeMethod("setSetting", {"key": key, "value": value});
  }
  static Future<bool?> _getSetting(String key) async {
    return await dataMethodChannel.invokeMethod("getSetting", key);
  }
}
src/main/resources/code/flutter_module/lib/utils/share_utils.dart
@@ -6,10 +6,16 @@
import 'config_util.dart';
class ShareUtil {
  static shareImg(
      BuildContext context, File f, SharePlatform sharePlatform) async {
    if (Platform.isAndroid) {
      if (sharePlatform == SharePlatform.all) {
        Share.shareFiles([f.path]);
        return;
      }
      const platform = MethodChannel("com.yeshi.location/share"); //分析1
      bool result = false;
      try {
src/main/resources/code/flutter_module/lib/utils/ui_constant.dart
@@ -9,6 +9,7 @@
}
class Constant {
  static const bool NATIVE=true;
  static const String IOS_APP_ID =
      "1135798414";
@@ -32,9 +33,6 @@
  static const String APP_DOWNLOAD_LINK =
      "https://a.app.qq.com/o/simple.jsp?pkgname=com.dw.zzql";
  static const String MAP_LINK =
      "http://web.location.izzql.com/map/map.html";
}
src/main/resources/code/flutter_module/lib/utils/ui_utils.dart
@@ -18,6 +18,24 @@
MethodChannel uiMethodChannel = UIMethodChannel('com.yeshi.video/ui');
setStatusBarLight() {
  uiMethodChannel.invokeMethod("setStatusBarLight");
}
setStatusBarDark() {
  uiMethodChannel.invokeMethod("setStatusBarDark");
}
//跳转页面
jumpAppPage(String type, Map<String, dynamic>? params) {
  Map<String, dynamic> ps = {"type": type};
  if (params != null) {
    ps["params"] = params;
  }
  //跳转应用界面
  uiMethodChannel.invokeMethod("jumpAppPage", ps);
}
///包裹整个页面,下拉刷新,,上拉加载的默认配置
Widget getBasePage(Widget widget) {
  return RefreshConfiguration(
src/main/resources/code/flutter_module/lib/utils/wx_util.dart
New file
@@ -0,0 +1,65 @@
///微信授权帮助类
import 'package:flutter/cupertino.dart';
import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx;
import '../../api/http.dart';
import '../ui/widget/refresh_listview.dart';
import 'ui_utils.dart';
class WXAuthUtil {
  static init(BuildContext context, StringCallback callback) {
    fluwx
        .registerWxApi(
        appId: "wx420b62b9213e0fc9",
        universalLink: "https://your.univerallink.com/link/")
        .then((value) {
      print("微信初始化完成:$value");
      fluwx.weChatResponseEventHandler.listen((res) {
        dismissDialog(context);
        print("微信回调:${res.errCode} -  ${res.errStr}");
        if (res is fluwx.WeChatAuthResponse) {
          fluwx.WeChatAuthResponse response = res;
          print("微信获取到的code: ${response.code}");
          int errCode = response.errCode;
          if (errCode == 0) {
            String? code = response.code;
            if (code == null) {
              ToastUtil.toast("微信授权失败,请稍后再试", context);
              return;
            }
            callback(code);
          } else if (errCode == -4) {
            //showToast("用户拒绝授权");
          } else if (errCode == -2) {
            // showToast("用户取消授权");
          } else {
            ToastUtil.toast("微信授权失败,请稍后再试", context);
            return;
          }
        }
      });
    });
  }
  ///开始授权
  static startAuth(BuildContext context) async {
    bool installed = await wxInstalled();
    if (!installed) {
      ToastUtil.toast("尚未安装微信", context);
      return;
    }
    showLoading(context);
    fluwx
        .sendWeChatAuth(scope: "snsapi_userinfo", state: "wechat_sdk_demo_test")
        .then((value) {
      print("微信授权登录回调:$value");
    });
  }
  ///是否安装了微信
  static Future<bool> wxInstalled() async {
    return await fluwx.isWeChatInstalled;
  }
}
src/main/resources/code/flutter_module/pubspec.lock
@@ -64,6 +64,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.15.0"
  cookie_jar:
    dependency: transitive
    description:
      name: cookie_jar
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "3.0.1"
  cross_file:
    dependency: transitive
    description:
@@ -120,6 +127,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "4.0.4"
  dio_cookie_manager:
    dependency: "direct dev"
    description:
      name: dio_cookie_manager
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.0"
  event_bus:
    dependency: "direct dev"
    description:
@@ -127,6 +141,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.0"
  fading_edge_scrollview:
    dependency: transitive
    description:
      name: fading_edge_scrollview
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.1"
  fake_async:
    dependency: transitive
    description:
@@ -228,13 +249,20 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.8.5+1"
  fluttertoast:
    dependency: "direct dev"
    description:
      name: fluttertoast
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "8.0.9"
  fluwx_no_pay:
    dependency: "direct dev"
    description:
      name: fluwx_no_pay
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "3.8.1"
    version: "3.8.5"
  fwfh_text_style:
    dependency: transitive
    description:
@@ -319,6 +347,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.0.1"
  marquee:
    dependency: "direct dev"
    description:
      name: marquee
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.2.1"
  matcher:
    dependency: transitive
    description:
@@ -347,13 +382,6 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "1.0.1"
  oktoast:
    dependency: "direct dev"
    description:
      name: oktoast
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "3.1.5"
  package_info:
    dependency: "direct dev"
    description:
@@ -438,6 +466,13 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "3.7.0"
  pin_code_fields:
    dependency: "direct dev"
    description:
      name: pin_code_fields
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "7.4.0"
  platform:
    dependency: transitive
    description:
@@ -500,42 +535,42 @@
      name: share_plus
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "3.1.0"
    version: "4.0.4"
  share_plus_linux:
    dependency: transitive
    description:
      name: share_plus_linux
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.4"
    version: "3.0.0"
  share_plus_macos:
    dependency: transitive
    description:
      name: share_plus_macos
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.2"
    version: "3.0.0"
  share_plus_platform_interface:
    dependency: transitive
    description:
      name: share_plus_platform_interface
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.1"
    version: "3.0.2"
  share_plus_web:
    dependency: transitive
    description:
      name: share_plus_web
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.4"
    version: "3.0.0"
  share_plus_windows:
    dependency: transitive
    description:
      name: share_plus_windows
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "2.0.3"
    version: "3.0.0"
  shared_preferences:
    dependency: "direct dev"
    description:
@@ -660,13 +695,6 @@
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.4.2"
  toast:
    dependency: "direct dev"
    description:
      name: toast
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "0.1.5"
  typed_data:
    dependency: transitive
    description:
src/main/resources/code/flutter_module/pubspec.yaml
@@ -40,14 +40,13 @@
  shared_preferences: ^2.0.8
  oktoast: ^3.1.5
  dio: ^4.0.4
  dio_cookie_manager: ^2.0.0
  fluttertoast: ^8.0.8
  #轮播图插件
  flutter_swiper_null_safety: ^1.0.2
  toast: ^0.1.5
  webview_flutter: ^2.8.0
@@ -59,11 +58,11 @@
  qr_flutter: ^4.0.0
  #分享组件
  share_plus: ^3.0.4
  path_provider: ^2.0.6
  share_plus: ^4.0.4
  path_provider: ^2.0.9
  #微信登录
  fluwx_no_pay: ^3.8.1
  fluwx_no_pay: ^3.8.4
  event_bus: ^2.0.0
@@ -96,7 +95,7 @@
  cached_network_image: ^3.2.0
  #图片选择
  image_picker: ^0.8.4+9
  image_picker: ^0.8.4+11
  #图片裁剪
  image_cropper: ^1.5.0
@@ -105,6 +104,12 @@
  #保存图片到相册
  image_gallery_saver: ^1.7.1
  #跑马灯
  marquee: ^2.2.1
  #验证码输入框
  pin_code_fields: ^7.4.0
  flutter_boost:
    git:
      url: 'https://github.com/alibaba/flutter_boost.git'
src/main/resources/code/service/app/pom.xml
@@ -218,7 +218,7 @@
        <dependency>
            <groupId>com.ks</groupId>
            <artifactId>facade-push</artifactId>
            <version>0.0.2</version>
            <version>0.0.4</version>
        </dependency>
        <dependency>
@@ -244,6 +244,20 @@
        </dependency>
        <!-- 腾讯云短信 -->
        <dependency>
            <groupId>com.github.qcloudsms</groupId>
            <artifactId>qcloudsms</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>
    </dependencies>
src/main/resources/code/service/app/src/main/java/com/ks/app/Application.java
@@ -5,13 +5,17 @@
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.yeshi.utils.mq.JobThreadExecutorServiceImpl;
import org.yeshi.utils.tencentcloud.COSManager;
import org.yeshi.utils.tencentcloud.entity.COSInitParams;
import javax.servlet.MultipartConfigElement;
import java.io.File;
import java.util.Properties;
//不引入数据库
@@ -69,4 +73,19 @@
        COSManager.getInstance().init(params);
    }
    /**
     * 设置文件上传临时保存目录
     */
    @Bean
    MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        String location = System.getProperty("user.dir") + "/data/tmp";
        File tmpFile = new File(location);
        if (!tmpFile.exists()) {
            tmpFile.mkdirs();
        }
        factory.setLocation(location);
        return factory.createMultipartConfig();
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/AdminApiFilter.java
@@ -1,27 +1,23 @@
package com.ks.app.aop;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.entity.AdminUser;
import com.ks.app.utils.ApiCodeConstant;
import com.ks.app.utils.SystemInfoUtil;
import com.ks.app.vo.AcceptAdminData;
import com.ks.app.vo.AcceptData;
import net.sf.json.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
//后台接口监控
@Component
@@ -46,7 +42,22 @@
        }
        if (acceptAdminData != null) {
            HttpSession session = servletContainer.getRequest().getSession();
            acceptAdminData.setSystem(SystemInfoUtil.getAdminSelectedSystem(servletContainer.getRequest().getSession()));
            if (acceptAdminData.getSystem() == null) {
                PrintWriter out = servletContainer.getResponse().getWriter();
                out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_ERROR_IN_SERVER, "未选择系统"));
                out.close();
                return null;
            }
            //如果用户登录了将用户信息加入进去
            SecurityContext contextSession = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
            if (contextSession != null) {
                Authentication authentication = contextSession.getAuthentication();
                AdminUser adminUser = (AdminUser) authentication.getPrincipal();
                acceptAdminData.setAdminUser(adminUser);
            }
        }
src/main/resources/code/service/app/src/main/java/com/ks/app/aop/SignValidate.java
@@ -1,6 +1,5 @@
package com.ks.app.aop;
import com.ks.app.entity.APPPlatform;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.utils.ApiCodeConstant;
@@ -40,8 +39,8 @@
        PrintWriter out = null;
        ServletRequestAttributes servletContainer = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        servletContainer.getResponse().setCharacterEncoding("UTF-8");
        out = servletContainer.getResponse().getWriter();
        HttpServletRequest request = servletContainer.getRequest();
        AcceptData acceptData = null;
@@ -54,6 +53,7 @@
        }
        if (acceptData == null) {
            out = servletContainer.getResponse().getWriter();
            out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_FAIL_SIGN_ERROR, "签名错误"));
            return null;
        }
@@ -63,6 +63,7 @@
        if (isRight) {
            // 判断签名超时
            if (Math.abs((acceptData.getTimestamp() - System.currentTimeMillis())) > 1000 * 60 * 10) {
                out = servletContainer.getResponse().getWriter();
                out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_FAIL_OUT_TIME, "时间错误"));
                return null;
            }
@@ -87,11 +88,14 @@
            } catch (Throwable e) {
                e.printStackTrace();
                out = servletContainer.getResponse().getWriter();
                out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_ERROR_IN_SERVER, "服务器内部错误"));
                return null;
            }
            return obj;
        } else {
            out = servletContainer.getResponse().getWriter();
            out.print(JsonUtil.loadFalseResult(ApiCodeConstant.CODE_FAIL_SIGN_ERROR, "签名错误"));
            return null;
        }
src/main/resources/code/service/app/src/main/java/com/ks/app/config/RedisConfig.java
@@ -18,6 +18,8 @@
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.time.Duration;
@@ -99,4 +101,15 @@
        return template;
    }
    @Bean
    public JedisPool jedisPool() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(maxActive);
        poolConfig.setMaxIdle(maxIdle);
        poolConfig.setTestOnBorrow(true);
        return new JedisPool(poolConfig, addr, port, timeout, auth, database);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/config/WebSecurityConfig.java
@@ -53,6 +53,8 @@
    private final String LOGIN_PROCESSING_URL = "/admin/api/login";
    private final String LOGIN_PAGE_PATH="/7aed59d33d777100/login.html";
    //图形验证码配置
    @Bean
    public Producer captcha() {
@@ -139,7 +141,7 @@
                .and()
                .formLogin()
                //自定义登录界面
                .loginPage("/login.html")
                .loginPage(LOGIN_PAGE_PATH)
                //处理登录逻辑的url
                .loginProcessingUrl(LOGIN_PROCESSING_URL)
                //登录成功后的跳转
@@ -250,7 +252,7 @@
            if (url.contains("/admin/api/")) {
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
            } else {
                response.sendRedirect("/login.html");
                response.sendRedirect(LOGIN_PAGE_PATH);
            }
        }
    }
src/main/resources/code/service/app/src/main/java/com/ks/app/config/XXLJobConfig.java
New file
@@ -0,0 +1,50 @@
package com.ks.app.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class XXLJobConfig {
    Logger log = LoggerFactory.getLogger(XXLJobConfig.class);
    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;
    @Value("${xxl.job.executor.appname}")
    private String appName;
    @Value("${xxl.job.executor.ip}")
    private String ip;
    @Value("${xxl.job.executor.port}")
    private int port;
    @Value("${xxl.job.accessToken}")
    private String accessToken;
    @Value("${xxl.job.executor.logpath}")
    private String logPath;
    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;
    @Bean(initMethod = "start", destroyMethod = "destroy")
    public XxlJobSpringExecutor xxlJobExecutor() {
        log.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppName(appName);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
        return xxlJobSpringExecutor;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/FileController.java
New file
@@ -0,0 +1,42 @@
package com.ks.app.controller.admin;
import com.ks.app.utils.ImageUtil;
import net.sf.json.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.entity.FileUploadResult;
import org.yeshi.utils.tencentcloud.COSManager;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.InputStream;
@Controller
@RequestMapping("/admin/api/file")
public class FileController {
    @ResponseBody
    @RequestMapping("uploadImg")
    public String uploadImg(@RequestParam("file_url") MultipartFile file, String type, HttpSession session) throws IOException {
        String md5 = DigestUtils.md5Hex(file.getBytes());
        InputStream inputStream = file.getInputStream();
        String contentType = file.getContentType();
        String fileType = contentType.substring(contentType.indexOf("/") + 1);
        String key = "/imgs/" + type + "/" + md5 + "." + fileType;
        FileUploadResult result = COSManager.getInstance().uploadFile(inputStream, key);
        if (result == null) {
            return JsonUtil.loadFalseResult("上传出错");
        }
        JSONObject data = new JSONObject();
        data.put("url", ImageUtil.getCOSImageUrl(key));
        data.put("md5", result.getMd5());
        return JsonUtil.loadTrueResult(data);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/admin/config/SystemConfigAdminController.java
@@ -2,8 +2,12 @@
import com.google.gson.*;
import com.ks.app.entity.config.SystemConfig;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.entity.config.SystemConfigType;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.service.query.config.SystemConfigQuery;
import com.ks.app.vo.AcceptAdminData;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -25,15 +29,15 @@
    private SystemConfigService systemConfigService;
    private String loadPrint(String callback, String root){
          return root;
    private String loadPrint(String callback, String root) {
        return root;
    }
    @ResponseBody
    @RequestMapping("list")
    public String list(SystemConfigQuery query, int page, int limit, String callback) {
        List<SystemConfig> list = systemConfigService.list(query,page,limit);
        long count = systemConfigService.count(query);
        List<SystemConfig> list = systemConfigService.listByType(query.getType() == null ? SystemConfigType.common : query.getType());
        long count = list.size();
        JSONObject data = new JSONObject();
        Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
@@ -50,11 +54,12 @@
    @ResponseBody
    @RequestMapping("add")
    public String add(SystemConfig bean, HttpSession session, String callback) {
        try{
    public String add(SystemConfig bean, AcceptAdminData acceptAdminData, String callback) {
        try {
            bean.setSystem(acceptAdminData.getSystem());
            systemConfigService.add(bean);
            return loadPrint(callback, JsonUtil.loadTrueResult(""));
        }catch(Exception e){
        } catch (Exception e) {
            return loadPrint(callback, JsonUtil.loadFalseResult(e.getMessage()));
        }
    }
@@ -63,7 +68,7 @@
    @RequestMapping("get")
    public String get(String id, HttpSession session, String callback) {
        SystemConfig entity = systemConfigService.get(id);
        if (entity !=null){
        if (entity != null) {
            return loadPrint(callback, JsonUtil.loadTrueResult(entity));
        } else {
            return loadPrint(callback, JsonUtil.loadFalseResult("ID不存在"));
@@ -73,17 +78,33 @@
    @ResponseBody
    @RequestMapping("update")
    public String update(SystemConfig bean, HttpSession session,String callback) {
    public String update(SystemConfig bean, HttpSession session, String callback) {
        if (bean.getId() == null) {
            return loadPrint(callback, JsonUtil.loadFalseResult("ID不能为空"));
        }
        try{
        try {
            systemConfigService.update(bean);
        }catch(Exception e){
        } catch (Exception e) {
            return loadPrint(callback, JsonUtil.loadFalseResult(e.getMessage()));
        }
        return loadPrint(callback, JsonUtil.loadTrueResult(""));
    }
    @ResponseBody
    @RequestMapping("getKeyList")
    public String getKeyList(SystemConfigType type) {
        JSONArray array = new JSONArray();
        for (SystemConfigKey key : SystemConfigKey.values()) {
            if (key.getType() == (type == null ? SystemConfigType.common : type)) {
                JSONObject data = new JSONObject();
                data.put("key", key.name());
                data.put("value", key.getDesc());
                array.add(data);
            }
        }
        return JsonUtil.loadTrueResult(array);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/ConfigController.java
@@ -1,5 +1,7 @@
package com.ks.app.controller.client.api;
import com.google.gson.Gson;
import com.ks.app.dto.config.AdSourceConfig;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.vo.AcceptData;
@@ -42,7 +44,8 @@
                SystemConfigKey.course,
                SystemConfigKey.unRegister,
                SystemConfigKey.privacyComplain,
                SystemConfigKey.vipLink
                SystemConfigKey.helpLink,
                SystemConfigKey.disclaimerLink
        };
        for (SystemConfigKey config : configs) {
@@ -50,39 +53,31 @@
            data.put(config.name(), value);
        }
        //TODO 广告K接口配置
        SystemConfigKey[] ads = new SystemConfigKey[]{
                SystemConfigKey.splashAd,
                SystemConfigKey.rewardAd,
                SystemConfigKey.exitAppAd
        };
        JSONObject adConfig = new JSONObject();
        for (SystemConfigKey ad : ads) {
            String value = systemConfigService.getValueCache(acceptData.getSystem(), ad);
            JSONObject valueJSON = JSONObject.fromObject(value);
            String channel = acceptData.getChannel();
            String channel = acceptData.getChannel().toLowerCase();
            if (StringUtil.isNullOrEmpty(channel) || valueJSON.optJSONObject(channel) == null) {
                channel = "qq";
            }
            valueJSON = valueJSON.optJSONObject(channel.toLowerCase());
            if (valueJSON != null) {
                if (acceptData.getVersion() <= valueJSON.optInt("version")) {
                    String pid = valueJSON.optString("pid");
                    String type = valueJSON.optString("type");
                    valueJSON = new JSONObject();
                    valueJSON.put("pid", pid);
                    valueJSON.put("type", type);
                } else {
                    valueJSON = null;
                AdSourceConfig adSourceConfig = new Gson().fromJson(valueJSON.toString(), AdSourceConfig.class);
                if (acceptData.getVersion() <= adSourceConfig.getVersion()) {
                    adConfig.put(ad.name(), new Gson().toJson(adSourceConfig.getTypes()));
                }
            }
            if (valueJSON != null) {
                data.put(ad.name().replace("ad_", ""), valueJSON.toString());
            }
        }
        data.put("ad", adConfig);
        return JsonUtil.loadTrueResult(data);
    }
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/SMSController.java
@@ -1,5 +1,6 @@
package com.ks.app.controller.client.api;
import com.github.qcloudsms.SmsSingleSenderResult;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.service.manager.VerifyCodeManager;
@@ -56,10 +57,14 @@
            String msg = systemConfigService.getValueCache(acceptData.getSystem(), SystemConfigKey.tencentVerifySMSTemplate);
            String appId = systemConfigService.getValueCache(acceptData.getSystem(), SystemConfigKey.tencentSMSAppId);
            String appKey = systemConfigService.getValueCache(acceptData.getSystem(), SystemConfigKey.tencentSMSAppKey);
            //  SmsSingleSenderResult result=
//            TencentSMSUtil.sendSingleMsg(Integer.parseInt(appId), appKey, phone, msg.replace("{验证码}", code));
            verifyCodeManager.sendSMSSuccess(acceptData.getSystem(), phone, code);
            return JsonUtil.loadTrueResult("");
            SmsSingleSenderResult result =
                    TencentSMSUtil.sendSingleMsg(Integer.parseInt(appId), appKey, phone, msg.replace("{验证码}", code));
            if (result.result == 0) {
                verifyCodeManager.sendSMSSuccess(acceptData.getSystem(), phone, code);
                return JsonUtil.loadTrueResult("");
            } else {
                return JsonUtil.loadFalseResult("验证码发送失败,请稍后再试");
            }
        } else {
            return JsonUtil.loadFalseResult("服务器繁忙,请稍后再试");
        }
src/main/resources/code/service/app/src/main/java/com/ks/app/controller/client/api/UserController.java
@@ -1,15 +1,20 @@
package com.ks.app.controller.client.api;
import com.ks.app.dto.user.LoginInfoDTO;
import com.ks.app.entity.APPPlatform;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.entity.user.UserLoginRecord;
import com.ks.app.entity.vip.UserVIPInfo;
import com.ks.app.exception.user.LoginException;
import com.ks.app.exception.user.UserAccountException;
import com.ks.app.service.inter.user.UserAccountService;
import com.ks.app.service.inter.user.UserExtraInfoService;
import com.ks.app.service.inter.user.UserInfoService;
import com.ks.app.service.inter.vip.VIPService;
import com.ks.app.service.manager.PushManager;
import com.ks.app.service.manager.VerifyCodeManager;
import com.ks.app.utils.ApiCodeConstant;
import com.ks.app.utils.ImageUtil;
import com.ks.app.utils.annotation.UserLogin;
import com.ks.app.vo.AcceptData;
import com.ks.app.vo.user.UserInfoVO;
@@ -18,15 +23,24 @@
import com.ks.push.pojo.DO.BPushDeviceToken;
import com.ks.push.pojo.DO.PushPlatform;
import com.ks.push.service.BDeviceTokenService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.yeshi.utils.IPUtil;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.ThreadUtil;
import org.yeshi.utils.entity.FileUploadResult;
import org.yeshi.utils.tencentcloud.COSManager;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
/**
 * @author hxh
@@ -50,13 +64,17 @@
    @Resource
    private VerifyCodeManager verifyCodeManager;
    //@Reference(version = "1.0", check = false)
    private BDeviceTokenService bDeviceTokenService;
    @Resource
    private PushManager pushManager;
    @Resource
    private UserExtraInfoService userExtraInfoService;
    @ResponseBody
    @RequestMapping("loginPhone")
    public String loginPhone(AcceptData acceptData, String phone, String vcode, String token) {
    public String loginPhone(AcceptData acceptData, String phone, String vcode, String token, HttpServletRequest request) {
        LoginInfoDTO loginInfo = new LoginInfoDTO();
        loginInfo.setIpInfo(IPUtil.getRemotIP(request) + ":" + request.getRemotePort());
        loginInfo.setLoginType(UserLoginRecord.TYPE_LOGIN_PHONE);
        if (!StringUtil.isNullOrEmpty(phone)) {
            if (StringUtil.isNullOrEmpty(vcode)) {
@@ -72,6 +90,25 @@
            return JsonUtil.loadFalseResult("信息不完整");
        }
        loginInfo.setSystem(acceptData.getSystem());
        return login(loginInfo, acceptData);
    }
    @ResponseBody
    @RequestMapping("loginWX")
    public String loginWX(AcceptData acceptData, String code, HttpServletRequest request) {
        LoginInfoDTO loginInfo = new LoginInfoDTO();
        loginInfo.setIpInfo(IPUtil.getRemotIP(request) + ":" + request.getRemotePort());
        loginInfo.setLoginType(UserLoginRecord.TYPE_LOGIN_WX);
        if (StringUtil.isNullOrEmpty(code)) {
            return JsonUtil.loadFalseResult("信息不完整");
        }
        loginInfo.setWxCode(code);
        loginInfo.setSystem(acceptData.getSystem());
        return login(loginInfo, acceptData);
    }
    private String login(LoginInfoDTO loginInfo, AcceptData acceptData) {
        try {
            UserInfo userInfo = userAccountService.login(loginInfo);
            ThreadUtil.run(new Runnable() {
@@ -79,18 +116,55 @@
                public void run() {
                    try {
                        //登录成功
                        bDeviceTokenService.bindUid(acceptData.getSystem().name(), acceptData.getUtdId(), userInfo.getId() + "");
                        pushManager.bindUid(acceptData.getSystem(), userInfo.getId(), acceptData.getPlatform() == APPPlatform.ios ? acceptData.getIdfa() : acceptData.getUtdId());
                    } catch (Exception e) {
                    }
                }
            });
            return JsonUtil.loadTrueResult(JsonUtil.getApiCommonGson().toJson(userInfo));
            return outUserInfoForLogin(userInfo);
        } catch (LoginException e) {
            return JsonUtil.loadFalseResult(e.getMessage());
        }
    }
    private String outUserInfoForLogin(UserInfo userInfo) {
        UserInfoVO vo = UserInfoVO.create(userInfo, userExtraInfoService.get(userInfo.getId()));
        //是否需要填写邀请码
        vo.setHasBoss(false);
        return JsonUtil.loadTrueResult(JsonUtil.getSimpleGson().toJson(vo));
    }
    @UserLogin(uid = "#uid")
    @ResponseBody
    @RequestMapping("bindWX")
    public String bindWX(AcceptData acceptData, Long uid, String code) {
        try {
            userAccountService.bindWX(uid, code);
        } catch (UserAccountException e) {
            e.printStackTrace();
            return JsonUtil.loadFalseResult(e.getMsg());
        }
        return JsonUtil.loadTrueResult("");
    }
    @UserLogin(uid = "#uid")
    @ResponseBody
    @RequestMapping("bindPhone")
    public String bindPhone(AcceptData acceptData, Long uid, String phone, String vcode, String token) {
        try {
            userAccountService.bindPhone(uid, phone, vcode, token);
        } catch (UserAccountException e) {
            e.printStackTrace();
            return JsonUtil.loadFalseResult(e.getMsg());
        }
        return JsonUtil.loadTrueResult("");
    }
    @UserLogin(uid = "#uid")
@@ -99,7 +173,7 @@
    public String logout(AcceptData acceptData, Long uid) {
        try {
            //解绑UID
            bDeviceTokenService.unBindUid(acceptData.getSystem().name(), acceptData.getUtdId());
            pushManager.unBind(acceptData.getSystem(), acceptData.getPlatform() == APPPlatform.ios ? acceptData.getIdfa() : acceptData.getUtdId());
        } catch (Exception e) {
            e.printStackTrace();
        }
@@ -166,32 +240,76 @@
        return JsonUtil.loadTrueResult(vo);
    }
    @UserLogin(uid = "#uid")
    @ResponseBody
    @RequestMapping("updateUserInfo")
    public String updateUserInfo(AcceptData acceptData, Long uid, String nickName, @Nullable @RequestParam("portrait") MultipartFile portrait, String portraitMD5) {
        UserInfo user = userInfoService.get(uid);
        if (user == null) {
            return JsonUtil.loadFalseResult("用户不存在");
        }
        UserInfo update = new UserInfo();
        update.setId(uid);
        if (!StringUtil.isNullOrEmpty(nickName)) {
            update.setNickName(nickName);
        }
        if (portrait != null) {
            if (StringUtil.isNullOrEmpty(portraitMD5)) {
                return JsonUtil.loadFalseResult("头像文件加密值为空");
            }
            try {
                String md5 = DigestUtils.md5Hex(portrait.getBytes());
                if (!portraitMD5.equalsIgnoreCase(md5)) {
                    return JsonUtil.loadFalseResult("头像文件加密值错误");
                }
                InputStream inputStream = portrait.getInputStream();
                String contentType = portrait.getContentType();
                String key = String.format("/imgs/portrait/%s_%s.png", uid, md5);
                FileUploadResult result = COSManager.getInstance().uploadFile(inputStream, key);
                if (result == null) {
                    return JsonUtil.loadFalseResult("上传出错");
                }
                update.setPortrait(ImageUtil.getCOSImageUrl(key));
            } catch (Exception e) {
                return JsonUtil.loadFalseResult("头像修改出错");
            }
        }
        userInfoService.update(update);
        if (portrait != null) {
            //删除原来的头像
            if (!user.getPortrait().contains("default")) {
                try {
                    COSManager.getInstance().deleteFileByKey(ImageUtil.getUrlKey(user.getPortrait()));
                } catch (Exception e) {
                }
            }
        }
        return JsonUtil.loadTrueResult("");
    }
    @ResponseBody
    @RequestMapping("uploadPushRegId")
    public String uploadPushRegId(AcceptData acceptData, Long uid, String regId) {
        BPushDeviceToken deviceToken = new BPushDeviceToken();
        deviceToken.setAppCode(acceptData.getSystem().name());
        deviceToken.setDeviceId(acceptData.getUtdId());
        deviceToken.setBuildModel(acceptData.getDeviceType());
        deviceToken.setBuildVersion(acceptData.getOsVersion());
        deviceToken.setToken(regId);
        deviceToken.setType(PushPlatform.jpush);
        if (uid != null) {
            deviceToken.setUid(uid + "");
        }
        deviceToken.setVersionCode(acceptData.getVersion());
        try {
            bDeviceTokenService.save(deviceToken);
            pushManager.saveToken(acceptData, uid, regId);
            return JsonUtil.loadTrueResult("");
        } catch (BPushDeviceTokenException e) {
            return JsonUtil.loadTrueResult(e.getMessage());
            return JsonUtil.loadFalseResult(e.getCode(), "业务出错");
        } catch (ParamsException e) {
            return JsonUtil.loadTrueResult(e.getMessage());
            return JsonUtil.loadFalseResult(e.getCode(), "参数错误");
        }
    }
src/main/resources/code/service/app/src/main/java/com/ks/app/dao/config/SystemConfigDao.java
@@ -17,80 +17,89 @@
@Repository
public class SystemConfigDao extends MongodbBaseDao<SystemConfig>{
public class SystemConfigDao extends MongodbBaseDao<SystemConfig> {
  public void updateSelective(SystemConfig bean) {
    public void updateSelective(SystemConfig bean) {
        Query query = new Query();
        Update update=new Update();
        Update update = new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if(bean.getName() != null) {
        if (bean.getName() != null) {
            update.set("name", bean.getName());
        }
        if(bean.getKey() != null) {
        if (bean.getKey() != null) {
            update.set("key", bean.getKey());
        }
        if(bean.getSystem() != null) {
        if (bean.getSystem() != null) {
            update.set("system", bean.getSystem());
        }
        if(bean.getValue() != null) {
        if (bean.getValue() != null) {
            update.set("value", bean.getValue());
        }
        if(bean.getRemarks() != null) {
        if (bean.getRemarks() != null) {
            update.set("remarks", bean.getRemarks());
        }
        if(bean.getCreateTime() != null) {
        if (bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
  }
    }
  public List<SystemConfig> list(DaoQuery daoQuery){
    public List<SystemConfig> list(DaoQuery daoQuery) {
        Query query = getQuery(daoQuery);
        if (daoQuery.sortList!=null && daoQuery.sortList.size()>0){
        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);
    public long count(DaoQuery daoQuery) {
        Query query = getQuery(daoQuery);
        return count(query);
  }
    }
  private Query getQuery(DaoQuery daoQuery){
        List<Criteria> andList=new ArrayList<>();
        if(daoQuery.name!=null){
    private Query getQuery(DaoQuery daoQuery) {
        List<Criteria> andList = new ArrayList<>();
        if (daoQuery.name != null) {
            andList.add(Criteria.where("name").regex(daoQuery.name));
        }
        if(daoQuery.key!=null){
        if (daoQuery.key != null) {
            andList.add(Criteria.where("key").is(daoQuery.key));
        }
        if(daoQuery.system!=null){
        if (daoQuery.keyList != null) {
            Criteria[] keys = new Criteria[daoQuery.keyList.size()];
            for (int i = 0; i < daoQuery.keyList.size(); i++) {
                keys[i] = Criteria.where("key").is(daoQuery.keyList.get(i));
            }
            andList.add(new Criteria().orOperator(keys));
        }
        if (daoQuery.system != null) {
            andList.add(Criteria.where("system").is(daoQuery.system));
        }
        if(daoQuery.value!=null){
        if (daoQuery.value != null) {
            andList.add(Criteria.where("value").regex(daoQuery.value));
        }
        Query query=new Query();
        Criteria[]  ands=new Criteria[andList.size()];
        Query query = new Query();
        Criteria[] ands = new Criteria[andList.size()];
        andList.toArray(ands);
        if(ands.length>0){
        if (ands.length > 0) {
            query.addCriteria(new Criteria().andOperator(ands));
        }
        return query;
  }
    }
  public static class DaoQuery{
    public static class DaoQuery {
        public String name;
        public SystemConfigKey key;
        public List<SystemConfigKey> keyList;
        public SystemEnum system;
        public String value;
        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/UserExtraInfoDao.java
New file
@@ -0,0 +1,75 @@
package com.ks.app.dao.user;
import com.ks.app.entity.user.UserExtraInfo;
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 UserExtraInfoDao extends MongodbBaseDao<UserExtraInfo> {
    public void updateSelective(UserExtraInfo bean) {
        Query query = new Query();
        Update update = new Update();
        query.addCriteria(Criteria.where("id").is(bean.getId()));
        if (bean.getInviteCode() != null) {
            update.set("inviteCode", bean.getInviteCode());
        }
        if (bean.getUnReadMsgCount() != null) {
            update.set("unReadMsgCount", bean.getUnReadMsgCount());
        }
        if (bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
    }
    public List<UserExtraInfo> 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.inviteCode != null) {
            andList.add(Criteria.where("inviteCode").is(daoQuery.inviteCode));
        }
        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 String inviteCode;
        public int start;
        public int count;
        public List<Sort.Order> sortList;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/config/AdSourceConfig.java
New file
@@ -0,0 +1,51 @@
package com.ks.app.dto.config;
import java.util.List;
/**
 * @author hxh
 * @title: AdSourceConfig
 * @description: 广告来源配置
 * @date 2022/5/5 15:46
 */
public class AdSourceConfig {
    private int version;
    private List<TypeProbability> types;
    static class TypeProbability {
        String type;
        int weight;
        public String getType() {
            return type;
        }
        public void setType(String type) {
            this.type = type;
        }
        public int getWeight() {
            return weight;
        }
        public void setWeight(int weight) {
            this.weight = weight;
        }
    }
    public int getVersion() {
        return version;
    }
    public void setVersion(int version) {
        this.version = version;
    }
    public List<TypeProbability> getTypes() {
        return types;
    }
    public void setTypes(List<TypeProbability> types) {
        this.types = types;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/config/AlipayConfig.java
New file
@@ -0,0 +1,79 @@
package com.ks.app.dto.config;
import org.yeshi.utils.annotation.Map;
public class AlipayConfig {
    @Map("appId")
    private String appId;
    @Map("private_key")
    private String privateKey;
    @Map("public_key")
    private String publicKey;
    @Map("account_name")
    private String accountName;
    @Map("app_cert_path")
    private String appCertPath;
    @Map("alipay_root_cert_path")
    private String alipayRootCertPath ;
    @Map("alipay_cert_path")
    private String alipayCertPath ;
    public String getAppCertPath() {
        return appCertPath;
    }
    public void setAppCertPath(String appCertPath) {
        this.appCertPath = appCertPath;
    }
    public String getAlipayRootCertPath() {
        return alipayRootCertPath;
    }
    public void setAlipayRootCertPath(String alipayRootCertPath) {
        this.alipayRootCertPath = alipayRootCertPath;
    }
    public String getAlipayCertPath() {
        return alipayCertPath;
    }
    public void setAlipayCertPath(String alipayCertPath) {
        this.alipayCertPath = alipayCertPath;
    }
    public String getAppId() {
        return appId;
    }
    public void setAppId(String appId) {
        this.appId = appId;
    }
    public String getPrivateKey() {
        return privateKey;
    }
    public void setPrivateKey(String privateKey) {
        this.privateKey = privateKey;
    }
    public String getAccountName() {
        return accountName;
    }
    public void setAccountName(String accountName) {
        this.accountName = accountName;
    }
    public String getPublicKey() {
        return publicKey;
    }
    public void setPublicKey(String publicKey) {
        this.publicKey = publicKey;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/config/WXTransferConfig.java
New file
@@ -0,0 +1,46 @@
package com.ks.app.dto.config;
import org.yeshi.utils.annotation.Map;
public class WXTransferConfig {
    @Map("mchId")
    private String mchId;
    @Map("key")
    private String key;
    @Map("certPwd")
    private String certPwd;
    @Map("certPath")
    private String certPath;
    public String getMchId() {
        return mchId;
    }
    public void setMchId(String mchId) {
        this.mchId = mchId;
    }
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getCertPwd() {
        return certPwd;
    }
    public void setCertPwd(String certPwd) {
        this.certPwd = certPwd;
    }
    public String getCertPath() {
        return certPath;
    }
    public void setCertPath(String certPath) {
        this.certPath = certPath;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/dto/mq/TestMQMsg.java
New file
@@ -0,0 +1,13 @@
package com.ks.app.dto.mq;
/**
 * @author hxh
 * @title: TestMsg
 * @description: TODO
 * @date 2022/5/12 12:02
 */
public class TestMQMsg {
    private Long createTime;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/AdminUser.java
@@ -19,9 +19,22 @@
    private String name;
    /**
     * 邮箱
     **/
    private String email;
    private Date createTime;
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getAccount() {
        return account;
    }
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/AppJumpType.java
New file
@@ -0,0 +1,28 @@
package com.ks.app.entity.config;
/**
 * @author hxh
 * @title: JumpType
 * @description: 应用跳转类型
 * @date 2022/4/2 14:10
 */
public enum AppJumpType {
    //消息
    msg,
    //邀请
    invite,
    //短视频
    drawVideo,
    //资讯
    news,
    //小说
    novel,
    //提现
    extract,
    //签到
    signIn,
    //网页
    web,
    //百川
    baichuan;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/AppName.java
New file
@@ -0,0 +1,80 @@
package com.ks.app.entity.config;
import com.yeshi.makemoney.app.entity.SystemEnum;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.Date;
/**
 * @author hxh
 * @title: AppName
 * @description: 应用名称(分渠道)
 * @date 2022/4/2 14:18
 */
@Document(collection = "appName")
public class AppName {
    @Id
    private String id;
    @Indexed
    private SystemEnum system;
    @Indexed
    private String channel;
    private String name;
    private Date createTime;
    private Date updateTime;
    public String toId() {
        return system.name() + "-" + channel;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public SystemEnum getSystem() {
        return system;
    }
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
    public String getChannel() {
        return channel;
    }
    public void setChannel(String channel) {
        this.channel = channel;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfig.java
@@ -3,7 +3,6 @@
import com.ks.app.entity.SystemEnum;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.yeshi.utils.generater.annotation.admin.DaoQueryCondition;
import java.io.Serializable;
import java.util.Date;
@@ -18,13 +17,9 @@
public class SystemConfig implements Serializable {
    @Id
    private String id;
    @DaoQueryCondition(queryType = DaoQueryCondition.QueryType.contains)
    private String name;
    @DaoQueryCondition
    private SystemConfigKey key;
    @DaoQueryCondition
    private SystemEnum system;
    @DaoQueryCondition(queryType = DaoQueryCondition.QueryType.contains)
    private String value;
    private String remarks;
    private Date createTime;
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfigKey.java
@@ -8,32 +8,57 @@
 */
public enum SystemConfigKey {
    signKey("签名Key"),
    defaultPortrait("默认头像"),
    defaultNickNamePrefix("默认昵称前缀"),
    wxAppId("微信开放平台APPId"),
    wxAppSecret("微信开放平台APPSecret"),
    aliyunOneKeyAuthAcessKey("阿里云一键登录appId"),
    aliyunOneKeyAuthAcessSecret("阿里云一键登录appSecret"),
    tencentSMSAppId("腾讯云短信APPID"),
    tencentSMSAppKey("腾讯云短信APPKey"),
    tencentVerifySMSTemplate("腾讯云验证码短信模板"),
    testAccount("测试账号"),
    signKey(SystemConfigType.system, "签名Key"),
    defaultPortrait(SystemConfigType.system, "默认头像"),
    defaultNickNamePrefix(SystemConfigType.system, "默认昵称前缀"),
    wxAppId(SystemConfigType.system, "微信开放平台APPId"),
    wxAppSecret(SystemConfigType.system, "微信开放平台APPSecret"),
    aliyunOneKeyAuthAcessKey(SystemConfigType.system, "阿里云一键登录appId"),
    aliyunOneKeyAuthAcessSecret(SystemConfigType.system, "阿里云一键登录appSecret"),
    tencentSMSAppId(SystemConfigType.system, "腾讯云短信APPID"),
    tencentSMSAppKey(SystemConfigType.system, "腾讯云短信APPKey"),
    tencentVerifySMSTemplate(SystemConfigType.system, "腾讯云验证码短信模板"),
    testAccount(SystemConfigType.system, "测试账号"),
    emailSender(SystemConfigType.system, "发送邮件的账号与密码"),
    appLink(SystemConfigType.system, "应用二合一链接"),
    androidPushAppCode(SystemConfigType.system, "android推送应用编码"),
    androidPushActivity(SystemConfigType.system, "android推送落地页Activity"),
    //返回给前端的数据
    kefu("客服链接"),
    course("教程链接"),
    unRegister("注销链接"),
    privacyComplain("隐私投诉链接"),
    vipLink("会员链接");
    kefu(SystemConfigType.common, "客服链接"),
    course(SystemConfigType.common, "教程链接"),
    unRegister(SystemConfigType.common, "注销链接"),
    privacyComplain(SystemConfigType.common, "隐私投诉链接"),
    helpLink(SystemConfigType.common, "帮助中心链接"),
    disclaimerLink(SystemConfigType.common, "免责声明链接"),
    //广告配置
    splashAd(SystemConfigType.ad, "开屏广告"),
    rewardAd(SystemConfigType.ad, "激励视频广告"),
    exitAppAd(SystemConfigType.ad, "退出应用广告"),
    //资金相关配置
    extractConfig(SystemConfigType.extract, "提现配置"),
    ;
    private String desc;
    private SystemConfigType type;
    public String getDesc() {
        return desc;
    }
    private SystemConfigKey(String desc) {
    public SystemConfigType getType() {
        return type;
    }
    private SystemConfigKey(SystemConfigType type, String desc) {
        this.type = type;
        this.desc = desc;
    }
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/config/SystemConfigType.java
New file
@@ -0,0 +1,25 @@
package com.ks.app.entity.config;
/**
 * @author hxh
 * @title: SystemConfigType
 * @description: 系统配置分类
 * @date 2022/4/2 15:15
 */
public enum SystemConfigType {
    common("通用"),
    system("系統相关"),
    extract("提现"),
    ad("广告")
    ;
    private String name;
    private SystemConfigType(String name) {
    }
    public String getName() {
        return name;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/entity/user/UserExtraInfo.java
New file
@@ -0,0 +1,75 @@
package com.ks.app.entity.user;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.Date;
/**
 * @author hxh
 * @title: UserExtraInfo
 * @description: 附加信息
 * @date 2022/4/2 14:14
 */
@Document(collection = "userExtraInfo")
public class UserExtraInfo {
    @Id
    private Long id;
    /**
     * 邀请码
     **/
    @Indexed
    private String inviteCode;
    /**
     * 未读消息的数量
     **/
    private Integer unReadMsgCount;
    private Date createTime;
    private Date updateTime;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getInviteCode() {
        return inviteCode;
    }
    public void setInviteCode(String inviteCode) {
        this.inviteCode = inviteCode;
    }
    public Integer getUnReadMsgCount() {
        return unReadMsgCount;
    }
    public void setUnReadMsgCount(Integer unReadMsgCount) {
        this.unReadMsgCount = unReadMsgCount;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/user/UserAccountException.java
New file
@@ -0,0 +1,31 @@
package com.ks.app.exception.user;
import com.ks.lib.common.exception.BaseException;
/**
 * @author hxh
 * @title: LoginException
 * @description: 账户异常
 * @date 2021/11/16 18:23
 */
public class UserAccountException extends BaseException {
    //已经绑定
    public final static int CODE_ALREAD_BIND = 201;
    //微信信息出错
    public final static int CODE_ERROR_WX_INFO = 102;
    //电话号码出错
    public final static int CODE_ERROR_PHONE = 103;
    //用户错误
    public final static int CODE_USER_ERROR = 101;
    public UserAccountException(int code, String msg) {
        super(code, msg);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/user/UserExtraInfoException.java
New file
@@ -0,0 +1,11 @@
package com.ks.app.exception.user;
import com.ks.lib.common.exception.BaseException;
public class UserExtraInfoException extends BaseException{
    public UserExtraInfoException(int code, String msg) {
        super(code, msg);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/exception/user/UserInfoException.java
New file
@@ -0,0 +1,20 @@
package com.ks.app.exception.user;
import com.ks.lib.common.exception.BaseException;
/**
 * @author hxh
 * @title: UserInfoException
 * @description: 用户信息异常
 * @date 2022/4/6 18:10
 */
public class UserInfoException extends BaseException {
    //没有邀请码
    public final static int CODE_NO_INVITE_CODE = 1001;
    public UserInfoException(int code, String msg) {
        super(code, msg);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/config/SystemConfigServiceImpl.java
@@ -5,15 +5,18 @@
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.config.SystemConfig;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.entity.config.SystemConfigType;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.service.query.config.SystemConfigQuery;
import org.springframework.cache.annotation.Cacheable;
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.StringUtil;
import org.yeshi.utils.bean.BeanUtil;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -35,6 +38,19 @@
            return null;
        }
        return list.get(0).getValue();
    }
    @Override
    public SystemConfig getByKey(SystemEnum system, SystemConfigKey key) {
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.system = system;
        daoQuery.key = key;
        daoQuery.count = 1;
        List<SystemConfig> list = systemConfigDao.list(daoQuery);
        if (list == null || list.size() == 0) {
            return null;
        }
        return list.get(0);
    }
    @Override
@@ -62,6 +78,23 @@
    }
    @Override
    public List<SystemConfig> listByType(SystemConfigType type) {
        List<SystemConfigKey> keyList = new ArrayList<>();
        for (SystemConfigKey key : SystemConfigKey.values()) {
            if (key.getType() == type) {
                keyList.add(key);
            }
        }
        DaoQuery daoQuery = new DaoQuery();
        daoQuery.keyList = keyList;
        daoQuery.start = 0;
        daoQuery.count = keyList.size();
        return systemConfigDao.list(daoQuery);
    }
    @Override
    public SystemConfig get(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
@@ -75,6 +108,10 @@
            systemConfig.setId(systemConfig.getSystem().name() + "-" + systemConfig.getKey().name());
        }
        if (StringUtil.isNullOrEmpty(systemConfig.getName())) {
            systemConfig.setName(systemConfig.getKey().getDesc());
        }
        //查询主键ID是否存在
        if (systemConfigDao.get(systemConfig.getId()) != null) {
src/main/resources/code/service/app/src/main/java/com/ks/app/service/impl/user/UserAccountServiceImpl.java
@@ -1,11 +1,13 @@
package com.ks.app.service.impl.user;
import com.ks.app.dto.user.LoginInfoDTO;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.entity.user.UserLoginRecord;
import com.ks.app.entity.user.WXUserInfo;
import com.ks.app.exception.user.LoginException;
import com.ks.app.exception.user.UserAccountException;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.service.inter.user.*;
import com.ks.app.service.manager.VerifyCodeManager;
@@ -62,7 +64,7 @@
                } else {
                    //验证码登录
                    if (!verifyCodeManager.isPhoneCodeRight(loginInfo.getSystem(), loginInfo.getPhone(), loginInfo.getVcode())) {
                        throw new LoginException("验证码出错");
                        throw new LoginException("验证码错误");
                    }
                }
                //执行登录操作
@@ -99,8 +101,11 @@
                //保存微信用户信息
                WXUserInfo wxUserInfo = null;
                try {
                    wxUserInfo = wxUserInfoService.save(WXUserInfo.create(weiXinUser));
                    WXUserInfo temp = WXUserInfo.create(weiXinUser);
                    temp.setSystem(loginInfo.getSystem());
                    wxUserInfo = wxUserInfoService.save(temp);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new LoginException("保存微信授权信息失败");
                }
                wxUserInfo.setSystem(loginInfo.getSystem());
@@ -111,7 +116,11 @@
                    newUser.setWxUser(wxUserInfo);
                    newUser.setSystem(loginInfo.getSystem());
                    newUser.setNickName(wxUserInfo.getNickName());
                    newUser.setPortrait(wxUserInfo.getHeadImgUrl());
                    if (StringUtil.isNullOrEmpty(wxUserInfo.getHeadImgUrl())) {
                        newUser.setPortrait(systemConfigService.getValueCache(loginInfo.getSystem(), SystemConfigKey.defaultPortrait));
                    } else {
                        newUser.setPortrait(wxUserInfo.getHeadImgUrl());
                    }
                    try {
                        userInfoService.add(newUser);
                    } catch (Exception e) {
@@ -146,7 +155,7 @@
        }
        loginSuccess(user.getId(), loginInfo);
        return null;
        return user;
    }
    @Override
@@ -157,6 +166,77 @@
        userInfoService.update(update);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void bindWX(Long uid, String code) throws UserAccountException {
        UserInfo user = userInfoService.get(uid);
        if (user == null) {
            throw new UserAccountException(UserAccountException.CODE_USER_ERROR, "用户不存在");
        }
        SystemEnum system = user.getSystem();
        String appId = systemConfigService.getValueCache(system, SystemConfigKey.wxAppId);
        String appSecret = systemConfigService.getValueCache(system, SystemConfigKey.wxAppSecret);
        WeiXinUser weiXinUser = WXAppLoginUtil.getWeiXinUser(code, appId, appSecret);
        if (weiXinUser == null) {
            throw new UserAccountException(UserAccountException.CODE_ERROR_WX_INFO, "微信授权信息获取失败");
        }
        //保存微信用户信息
        WXUserInfo wxUserInfo = null;
        try {
            WXUserInfo temp = WXUserInfo.create(weiXinUser);
            temp.setSystem(system);
            wxUserInfo = wxUserInfoService.save(temp);
        } catch (Exception e) {
            throw new UserAccountException(UserAccountException.CODE_ERROR_WX_INFO, "保存微信授权信息失败");
        }
        UserInfo u = userInfoService.selectByWXIdAndSystemAndStatus(wxUserInfo.getId(), system, UserInfo.STATUS_NORMAL);
        if (u != null) {
            throw new UserAccountException(UserAccountException.CODE_ALREAD_BIND, "微信已绑定其他账号");
        }
        //绑定到用户
        UserInfo update = new UserInfo();
        update.setId(uid);
        update.setWxUser(wxUserInfo);
        userInfoService.update(update);
    }
    @Override
    public void bindPhone(Long uid, String phone, String vcode, String token) throws UserAccountException {
        UserInfo user = userInfoService.get(uid);
        if (user == null) {
            throw new UserAccountException(UserAccountException.CODE_USER_ERROR, "用户不存在");
        }
        SystemEnum system = user.getSystem();
        if (!StringUtil.isNullOrEmpty(token)) {
            //一键登录
            //获取电话号码
            String mobile = AliyunOneKeyLoginUtil.getMobile(token, UUID.randomUUID().toString(), systemConfigService.getValueCache(system, SystemConfigKey.aliyunOneKeyAuthAcessKey), systemConfigService.getValueCache(system, SystemConfigKey.aliyunOneKeyAuthAcessSecret));
            if (StringUtil.isNullOrEmpty(mobile)) {
                throw new UserAccountException(UserAccountException.CODE_ERROR_PHONE, "电话号码获取失败");
            }
            phone = mobile;
        } else {
            //验证码登录
            if (!verifyCodeManager.isPhoneCodeRight(system, phone, vcode)) {
                throw new UserAccountException(UserAccountException.CODE_ERROR_PHONE, "验证码错误");
            }
        }
        UserInfo u = userInfoService.selectByPhoneAndSystemAndStatus(phone, system, UserInfo.STATUS_NORMAL);
        if (u != null) {
            throw new UserAccountException(UserAccountException.CODE_ALREAD_BIND, "手机号已绑定其他账号");
        }
        //绑定到用户
        UserInfo update = new UserInfo();
        update.setId(uid);
        update.setPhone(phone);
        userInfoService.update(update);
    }
    /**
     * @return void
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/config/SystemConfigService.java
@@ -6,8 +6,11 @@
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.entity.config.SystemConfigType;
import org.yeshi.utils.bean.BeanUtil;
import java.util.List;
import com.ks.app.entity.config.SystemConfig;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.service.query.config.SystemConfigQuery;
@@ -16,56 +19,69 @@
public interface SystemConfigService {
    /**
     * @author hxh
     * @description 获取缓存值
     * @date 11:50 2021/11/16
     * @param: system
     * @param: key
     * @return java.lang.String
     **/
    public String getValueCache(SystemEnum system, SystemConfigKey key);
    /**
     * @return java.lang.String
     * @author hxh
     * @description 获取缓存值
     * @date 11:50 2021/11/16
     * @param: system
     * @param: key
     **/
    public String getValueCache(SystemEnum system, SystemConfigKey key);
    /**
     * 获取列表
     * @param systemConfigQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<SystemConfig> list(SystemConfigQuery systemConfigQuery, int page, int pageSize) ;
     * @return java.lang.String
     * @author hxh
     * @description 根据Key值获取对象
     * @date 11:50 2021/11/16
     * @param: system
     * @param: key
     **/
    public SystemConfig getByKey(SystemEnum system, SystemConfigKey key);
    /**
     *
     */
    public long count(SystemConfigQuery systemConfigQuery) ;
     * 获取列表
     *
     * @param systemConfigQuery
     * @param page
     * @param pageSize
     * @return
     */
    public List<SystemConfig> list(SystemConfigQuery systemConfigQuery, int page, int pageSize);
    /**
     *
     */
    public SystemConfig get(String id) ;
     *
     */
    public long count(SystemConfigQuery systemConfigQuery);
    public List<SystemConfig> listByType(SystemConfigType type);
    /**
     *
     */
    public void add(SystemConfig systemConfig)  throws Exception;
    public void save(SystemConfig config);
     *
     */
    public SystemConfig get(String id);
    /**
     *
     */
    public void update(SystemConfig systemConfig) ;
     *
     */
    public void add(SystemConfig systemConfig) throws Exception;
    public void save(SystemConfig config);
    /**
     *
     */
    public void delete(List<String> idList) ;
     *
     */
    public void update(SystemConfig systemConfig);
    /**
     *
     */
    public void delete(List<String> idList);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserAccountService.java
@@ -3,6 +3,7 @@
import com.ks.app.dto.user.LoginInfoDTO;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.exception.user.LoginException;
import com.ks.app.exception.user.UserAccountException;
/**
 * @author hxh
@@ -16,13 +17,34 @@
    /**
     * @return void
     * @description 主注销
     * @date 13:56 2021/12/6
     * @param: uid
     * @return void
     **/
    public void unRegister(Long uid);
    /**
     * @return void
     * @author hxh
     * @description 绑定微信
     * @date 14:37 2022/4/22
     * @param: uid
     * @param: code
     **/
    public void bindWX(Long uid, String code) throws UserAccountException;
    /**
     * @return void
     * @author hxh
     * @description 绑定电话号码
     * @date 14:37 2022/4/22
     * @param: uid
     * @param: phone
     **/
    public void bindPhone(Long uid,String phone, String vcode, String token) throws UserAccountException;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/inter/user/UserExtraInfoService.java
New file
@@ -0,0 +1,75 @@
package com.ks.app.service.inter.user;
import com.ks.app.entity.user.UserExtraInfo;
public interface UserExtraInfoService {
    public UserExtraInfo get(Long uid);
    public UserExtraInfo init(Long uid);
    /**
     * @return void
     * @author hxh
     * @description 增加未读消息的数量
     * @date 15:15 2022/4/8
     * @param: uid
     * @param: count
     **/
    public void addUnReadMsgCount(Long uid, int count);
    /**
     * @author hxh
     * @description 读所有消息
     * @date 15:22 2022/4/8
     * @param: uid
     * @return void
     **/
    public void setMsgRead(Long uid);
    /**
     * @return void
     * @author hxh
     * @description 设置邀请码
     * @date 15:16 2022/4/8
     * @param: uid
     * @param: code
     **/
    public void setInviteCode(Long uid, String code);
    /**
     * @author hxh
     * @description 根据邀请码查询用户ID
     * @date 11:55 2022/4/20
     * @param: inviteCode
     * @return java.lang.Long
     **/
    public Long selectUidByInviteCode(String inviteCode);
    /**
     * @author hxh
     * @description 设置签到自动提醒
     * @date 15:22 2022/4/21
     * @param: uid
     * @param: notify
     * @return void
     **/
    public void setSignInNotify(Long uid, boolean notify);
    /**
     * @author hxh
     * @description 获取签到自动提醒
     * @date 15:23 2022/4/21
     * @param: uid
     * @return boolean
     **/
    public boolean getSignInNotify(Long uid);
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/manager/PushManager.java
New file
@@ -0,0 +1,171 @@
package com.ks.app.service.manager;
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.config.AppJumpType;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.vo.AcceptData;
import com.ks.lib.common.exception.ParamsException;
import com.ks.push.exception.BPushDeviceTokenException;
import com.ks.push.exception.BPushTaskException;
import com.ks.push.pojo.DO.*;
import com.ks.push.service.BDeviceTokenService;
import com.ks.push.service.BPushTaskService;
import com.ks.push.utils.JPushUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @author hxh
 * @title: PushManager
 * @description: 推送管理器
 * @date 2022/4/29 17:33
 */
@Component
public class PushManager {
    @Reference(version = "1.0", check = false)
    private BDeviceTokenService bdeviceTokenService;
    @Reference(version = "1.0", check = false)
    private BPushTaskService bPushTaskService;
    @Resource
    private SystemConfigService systemConfigService;
    /**
     * @return void
     * @author hxh
     * @description 保存token
     * @date 17:36 2022/4/29
     * @param: acceptData
     * @param: uid
     * @param: regId
     **/
    public void saveToken(AcceptData acceptData, Long uid, String regId) throws BPushDeviceTokenException, ParamsException {
        BPushDeviceToken token = new BPushDeviceToken();
        if (uid != null) {
            token.setUid(uid + "");
        }
        token.setType(PushPlatform.jpush);
        token.setAppCode(systemConfigService.getValueCache(acceptData.getSystem(), SystemConfigKey.androidPushAppCode));
        token.setVersionCode(acceptData.getVersion());
        token.setToken(regId);
        token.setDeviceId(acceptData.getUtdId());
        token.setBuildVersion(acceptData.getOsVersion());
        token.setBuildModel(acceptData.getDeviceType());
        token.setCreateTime(new Date());
        bdeviceTokenService.save(token);
    }
    /**
     * @return void
     * @author hxh
     * @description 绑定用户ID
     * @date 17:40 2022/4/29
     * @param: system
     * @param: uid
     * @param: deviceId
     **/
    public void bindUid(SystemEnum system, Long uid, String deviceId) {
        bdeviceTokenService.bindUid(systemConfigService.getValueCache(system, SystemConfigKey.androidPushAppCode), deviceId, uid + "");
    }
    /**
     * @return void
     * @author hxh
     * @description 解绑用户ID
     * @date 17:41 2022/4/29
     * @param: system
     * @param: deviceId
     **/
    public void unBind(SystemEnum system, String deviceId) {
        bdeviceTokenService.unBindUid(systemConfigService.getValueCache(system, SystemConfigKey.androidPushAppCode), deviceId);
    }
    /**
     * @return void
     * @author hxh
     * @description 推送签到
     * @date 16:40 2022/5/7
     * @param: system
     * @param: uid
     **/
    public void pushSignIn(SystemEnum system, List<Long> uidList) throws BPushTaskException {
        if (uidList == null || uidList.size() == 0) {
            return;
        }
        Map<String, String> extras = new HashMap<>();
        extras.put("type", AppJumpType.signIn.name());
        String title = "签到提醒";
        String content = "今日你还未签到,签到最高可领150金币!";
        push(system, uidList, title, content, extras);
    }
    /**
     * @return void
     * @author hxh
     * @description 推送金币结算
     * @date 16:41 2022/5/7
     * @param: system
     * @param: uid
     * @param: goldCorn
     * @param: money
     **/
    public void pushGoldCornSettle(SystemEnum system, Long uid, int goldCorn, BigDecimal money) throws BPushTaskException {
        Map<String, String> extras = new HashMap<>();
        extras.put("type", AppJumpType.extract.name());
        String title = "到账提醒";
        String content = String.format("昨日金币折算成功,入账%s元", money.setScale(2).toString());
        push(system, Arrays.asList(new Long[]{uid}), title, content, extras);
    }
    /**
     * @return void
     * @author hxh
     * @description 推送内容
     * @date 16:55 2022/5/7
     * @param: system
     * @param: uid
     * @param: title
     * @param: content
     * @param: extras
     **/
    private void push(SystemEnum system, List<Long> uidList, String title, String content, Map<String, String> extras) throws BPushTaskException {
        BPushTask bPushTask = new BPushTask();
        BPushMessage message = new BPushMessage();
        message.setMessage(false);
        message.setExtras(extras);
        message.setAndroidActivity(getPushIntent(system));
        message.setTitle(title);
        message.setContent(content);
        bPushTask.setMessage(message);
        bPushTask.setAppCode(systemConfigService.getValueCache(system, SystemConfigKey.androidPushAppCode));
        BPushFilter filter = new BPushFilter();
        if (uidList == null || uidList.size() == 0) {
            //推送30天内还活跃的用户
            filter.setMinActiveTime(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24L * 30));
        } else {
            filter.setUidList(uidList.stream().map(item -> item + "").collect(Collectors.toList()));
        }
        bPushTask.setFilter(filter);
        String taskId = bPushTaskService.createTask(bPushTask);
        bPushTaskService.startPush(taskId);
    }
    private String getPushIntent(SystemEnum system) {
        return JPushUtil.createIntent(systemConfigService.getValueCache(system, SystemConfigKey.androidPushActivity), system.getPackageName());
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/manager/VerifyCodeManager.java
@@ -3,6 +3,7 @@
import com.ks.app.entity.SystemEnum;
import com.ks.app.entity.config.SystemConfigKey;
import com.ks.app.service.inter.config.SystemConfigService;
import com.ks.app.utils.Constant;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.yeshi.utils.StringUtil;
@@ -62,7 +63,9 @@
     * @param: code
     **/
    public boolean isPhoneCodeRight(SystemEnum system, String phone, String code) {
        if (!Constant.VERIFY_VCODE) {
            return true;
        }
        String value = systemConfigService.getValueCache(system, SystemConfigKey.testAccount);
        //测试账号
        if (!StringUtil.isNullOrEmpty(value)) {
@@ -75,7 +78,6 @@
        String oldCode = redisTemplate.opsForValue().get(String.format("vcp-%s-%s", system.name(), phone));
        return oldCode != null && oldCode.equalsIgnoreCase(code);
//        return true;
    }
    /**
@@ -90,6 +92,4 @@
        Object oldCode = redisTemplate.opsForValue().get("v-c-e-" + StringUtil.Md5(email));
        return oldCode != null && oldCode.toString().equalsIgnoreCase(code);
    }
}
}
src/main/resources/code/service/app/src/main/java/com/ks/app/service/query/config/SystemConfigQuery.java
@@ -1,15 +1,17 @@
package com.ks.app.service.query.config;
public class SystemConfigQuery {
    //搜索关键词
    private String kw;
import com.ks.app.entity.config.SystemConfigType;
    private String getKw(){
        return kw;
public class SystemConfigQuery {
    //类型
    private SystemConfigType type;
    public SystemConfigType getType() {
        return type;
    }
    private void setKw(String kw){
        this.kw = kw;
    public void setType(SystemConfigType type) {
        this.type = type;
    }
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/Constant.java
@@ -1,5 +1,11 @@
package com.ks.app.utils;
import com.ks.app.dto.config.AlipayConfig;
import com.ks.app.dto.config.WXTransferConfig;
import org.yeshi.utils.annotation.MapUtil;
import java.util.Properties;
/**
 * @author hxh
 * @title: Constant
@@ -8,7 +14,30 @@
 */
public class Constant {
    public final static int PAGE_SIZE=20;
    //是否需要验证验证码
    public final static boolean VERIFY_VCODE = true;
    public static AlipayConfig alipayConfig;
    public static WXTransferConfig wxTransferConfig;
    static {
        if (alipayConfig == null) {
            Properties ps = org.yeshi.utils.PropertiesUtil
                    .getProperties(Constant.class.getClassLoader().getResourceAsStream("alipay.properties"));
            alipayConfig = (AlipayConfig) MapUtil.parseMapByJson(AlipayConfig.class, ps, null);
        }
        if (wxTransferConfig == null) {
            Properties ps = org.yeshi.utils.PropertiesUtil
                    .getProperties(Constant.class.getClassLoader().getResourceAsStream("wx_transfer.properties"));
            wxTransferConfig = (WXTransferConfig) MapUtil.parseMapByJson(WXTransferConfig.class, ps, null);
        }
    }
    public final static int PAGE_SIZE = 20;
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/ImageUtil.java
New file
@@ -0,0 +1,43 @@
package com.ks.app.utils;
import java.util.Properties;
/**
 * @author hxh
 * @title: ImageUtil
 * @description: 图片帮助类
 * @date 2022/4/9 14:15
 */
public class ImageUtil {
    private static String domain;
    private static String getVisitDomain() {
        if (domain == null) {
            Properties ps = org.yeshi.utils.PropertiesUtil
                    .getProperties(ImageUtil.class.getClassLoader().getResourceAsStream("cos.properties"));
            domain = ps.getProperty("domain");
        }
        return domain;
    }
    /**
     * @author hxh
     * @description 获取cos的图片访问路径
     * @date 14:17 2022/4/9
     * @param: key
     * @return java.lang.String
     **/
    public static String getCOSImageUrl(String key) {
        return getVisitDomain() + key;
    }
    public static String getUrlKey(String imgUrl) {
        String url = imgUrl.replace("http://", "").replace("https://", "");
        String key = url.substring(url.indexOf("/"));
        return key;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/JedisUtil.java
New file
@@ -0,0 +1,42 @@
package com.ks.app.utils;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import javax.annotation.Resource;
/**
 * @author hxh
 * @title: JedisUtil
 * @description: Jedis工具类
 * @date 2022/5/9 11:53
 */
@Component
public class JedisUtil {
    @Resource
    private JedisPool jedisPool;
    /**
     * 执行
     *
     * @param jedisExcuter
     */
    public void excute(JedisExcuter jedisExcuter) throws Exception {
        Jedis jedis = jedisPool.getResource();
        try {
            if (jedisExcuter != null) {
                jedisExcuter.execute(jedis);
            }
        } finally {
            jedis.close();
        }
    }
    public interface JedisExcuter {
        public void execute(Jedis jedis) throws Exception;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/ValidatorUtils.java
New file
@@ -0,0 +1,34 @@
package com.ks.app.utils;
import com.ks.lib.common.exception.ParamsException;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;
/**
 * @author hxh
 * @title: ValidatorUtils
 * @description: 验证工具
 * @date 2022/5/10 16:37
 */
public class ValidatorUtils {
    private static Validator validator;
    static {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }
    public static void validateEntity(Object object, Class<?>... groups) throws ParamsException {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty()) {
            for (ConstraintViolation<Object> o : constraintViolations) {
                throw new ParamsException(ParamsException.CODE_PARAMS_NOT_ENOUGH, o.getMessage());
            }
        }
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/factory/AppJumpParamsFactory.java
New file
@@ -0,0 +1,30 @@
package com.ks.app.utils.factory;
import net.sf.json.JSONObject;
import org.yeshi.utils.StringUtil;
/**
 * @author hxh
 * @title: AppJumpParamsUtil
 * @description: 参数factory
 * @date 2022/4/2 14:27
 */
public class AppJumpParamsFactory {
    public static String createWeb(String url, String title) {
        JSONObject params = new JSONObject();
        params.put("url", url);
        if (!StringUtil.isNullOrEmpty(title)) {
            params.put("title", title);
        }
        return params.toString();
    }
    public static String createBaiChuan(String url) {
        JSONObject params = new JSONObject();
        params.put("url", url);
        return params.toString();
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/mq/CMQManager.java
New file
@@ -0,0 +1,85 @@
package com.ks.app.utils.mq;
import com.google.gson.Gson;
import com.ks.app.dto.mq.TestMQMsg;
import com.qcloud.cmq.Message;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.mq.TDMQUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author hxh
 * @title: CMQManager
 * @description: MQ
 * @date 2022/4/1 17:06
 */
public class CMQManager {
    private static String secretId = "AKIDTlpgJhLjOozvd6QI2XnpfGbgV4NQJk25";
    private static String secretKey = "xhCSUHo55oHUQ6XicFcmfIgspX0EEzWo";
    private static CMQManager cmqManager;
    private static TDMQUtil tdmqUtil;
    //TODO 设置队列
    public static String QUEUE_EXTRACT_RESULT = "xxxx";
    static {
        TDMQUtil.getInstance().init(secretId, secretKey, true);
        tdmqUtil = TDMQUtil.getInstance();
        tdmqUtil.createQueue(QUEUE_EXTRACT_RESULT);
    }
    public static CMQManager getInstance() {
        if (cmqManager == null) {
            cmqManager = new CMQManager();
        }
        return cmqManager;
    }
    /**
     * 添加提现结果消息
     *
     * @param msg
     */
    public void addExtractResultMsg(TestMQMsg msg) {
        String content = new Gson().toJson(msg);
        tdmqUtil.sendMsg(QUEUE_EXTRACT_RESULT, content);
    }
    /**
     * 消费提现结果消息
     *
     * @param count
     * @return
     */
    public Map<String, TestMQMsg> consumeExtractResultMsg(int count) {
        List<Message> list = tdmqUtil.recieveMsg(count, QUEUE_EXTRACT_RESULT);
        Map<String, TestMQMsg> map = new HashMap<>();
        if (list != null) {
            for (Message msg : list) {
                String result = msg.msgBody;
                if (!StringUtil.isNullOrEmpty(result)) {
                    TestMQMsg resultMQMsg = new Gson().fromJson(result,
                            TestMQMsg.class);
                    map.put(msg.receiptHandle, resultMQMsg);
                }
            }
        }
        return map;
    }
    /**
     * 删除提现结果消息
     *
     * @param receiptHandle
     */
    public void deleteExtractResultMsg(String receiptHandle) {
        tdmqUtil.deleteMsg(QUEUE_EXTRACT_RESULT, receiptHandle);
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/pay/AlipayUtil.java
New file
@@ -0,0 +1,93 @@
package com.ks.app.utils.pay;
import com.alipay.api.AlipayApiException;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.ks.app.utils.Constant;
import net.sf.json.JSONObject;
import org.yeshi.utils.exception.AlipayTransferException;
import java.math.BigDecimal;
public class AlipayUtil {
    private static DefaultAlipayClient alipayClient = null;
    static {
        String privateKey = Constant.alipayConfig.getPrivateKey();
        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
        certAlipayRequest.setAppId(Constant.alipayConfig.getAppId());
        certAlipayRequest.setPrivateKey(privateKey);
        certAlipayRequest.setFormat("json");
        certAlipayRequest.setCharset("GBK");
        certAlipayRequest.setSignType("RSA2");
        certAlipayRequest.setCertPath(
                AlipayUtil.class.getClassLoader().getResource(Constant.alipayConfig.getAppCertPath()).getPath());
        certAlipayRequest.setAlipayPublicCertPath(
                AlipayUtil.class.getClassLoader().getResource(Constant.alipayConfig.getAlipayCertPath()).getPath());
        certAlipayRequest.setRootCertPath(
                AlipayUtil.class.getClassLoader().getResource(Constant.alipayConfig.getAlipayRootCertPath()).getPath());
        try {
            alipayClient = new DefaultAlipayClient(certAlipayRequest);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
    }
    public static AlipayFundTransUniTransferResponse transfer(String outBizNo, String account, String name,
            BigDecimal money, String orderTitle, String mark)
            throws AlipayApiException, NumberFormatException, AlipayTransferException {
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        JSONObject json = new JSONObject();
        json.put("out_biz_no", outBizNo);
        json.put("trans_amount", money.toString());
        json.put("product_code", "TRANS_ACCOUNT_NO_PWD");
        json.put("order_title", orderTitle);
        JSONObject payee_info = new JSONObject();
        payee_info.put("identity", account);
        payee_info.put("identity_type", "ALIPAY_LOGON_ID");
        payee_info.put("name", name);
        json.put("payee_info", payee_info);
        json.put("remark", mark);
        json.put("biz_scene", "DIRECT_TRANSFER");
        request.setBizContent(json.toString());
        AlipayFundTransUniTransferResponse response = null;
        response = alipayClient.certificateExecute(request);
        // 成功转账
        if (response != null && response.isSuccess() && "10000".equals(response.getCode())) {
            return response;
        } else// 转账失败
        {
            throw new AlipayTransferException(Integer.parseInt(response.getCode()), response.getSubCode(),
                    response.getSubMsg());
        }
    }
    public static AlipayFundTransUniTransferResponse transferNoThrowException(String outBizNo, String account, String name,
            BigDecimal money, String orderTitle, String mark) throws AlipayApiException{
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        JSONObject json = new JSONObject();
        json.put("out_biz_no", outBizNo);
        json.put("trans_amount", money.toString());
        json.put("product_code", "TRANS_ACCOUNT_NO_PWD");
        json.put("order_title", orderTitle);
        JSONObject payee_info = new JSONObject();
        payee_info.put("identity", account);
        payee_info.put("identity_type", "ALIPAY_LOGON_ID");
        payee_info.put("name", name);
        json.put("payee_info", payee_info);
        json.put("remark", mark);
        json.put("biz_scene", "DIRECT_TRANSFER");
        request.setBizContent(json.toString());
        AlipayFundTransUniTransferResponse response = null;
        response = alipayClient.certificateExecute(request);
        return response;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/user/InviteCodeUtil.java
New file
@@ -0,0 +1,44 @@
package com.ks.app.utils.user;
import java.math.BigDecimal;
/**
 * @author hxh
 * @title: InviteCodeUtil
 * @description: 邀请码工具类
 * @date 2022/4/18 15:25
 */
public class InviteCodeUtil {
    public static String createInviteCode(Long uid) {
        return createInviteCode((int) (Math.random() * 10 + 1), uid);
    }
    public static String createInviteCode(int base, Long uid) {
        long num = base * 100000000L + uid;
        return convert10To36(num);
    }
    private static String convert10To36(Long num) {
        String numbers = "YE9VFA3N6KG7JZH4LD5IO2RBS0QTMPU1WC8X";
        BigDecimal numBig = new BigDecimal(num);
        int ge = numBig.divideAndRemainder(new BigDecimal(36))[1].intValue();
        int n = 1;
        String result = "";
        result += numbers.charAt(ge);
        while (numBig.divideAndRemainder(new BigDecimal(36).pow(n))[0].compareTo(new BigDecimal(0)) > 0) {
            int w = numBig.divideAndRemainder(new BigDecimal(36).pow(n))[0].divideAndRemainder(new BigDecimal(36))[1]
                    .intValue();
            result = numbers.charAt(w) + result;
            n++;
        }
        return result;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/utils/user/UserVOUtil.java
New file
@@ -0,0 +1,24 @@
package com.ks.app.utils.user;
/**
 * @author hxh
 * @title: UserVOUtil
 * @description: TODO
 * @date 2022/4/18 15:45
 */
public class UserVOUtil {
    public static String getCoverPhone(String phone) {
        if (phone == null) {
            return phone;
        }
        if (phone.length() >= 5) {
            String st = phone.substring(0, 3);
            st += "******";
            st += phone.substring(phone.length() - 2, phone.length());
            return st;
        }
        return phone;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/AcceptAdminData.java
@@ -1,6 +1,7 @@
package com.ks.app.vo;
import com.ks.app.entity.APPPlatform;
import com.ks.app.entity.AdminUser;
import com.ks.app.entity.SystemEnum;
/**
@@ -11,6 +12,7 @@
 */
public class AcceptAdminData {
    private SystemEnum system;
    private AdminUser adminUser;
    public SystemEnum getSystem() {
        return system;
@@ -19,4 +21,12 @@
    public void setSystem(SystemEnum system) {
        this.system = system;
    }
    public AdminUser getAdminUser() {
        return adminUser;
    }
    public void setAdminUser(AdminUser adminUser) {
        this.adminUser = adminUser;
    }
}
src/main/resources/code/service/app/src/main/java/com/ks/app/vo/user/UserInfoVO.java
@@ -1,5 +1,10 @@
package com.ks.app.vo.user;
import com.ks.app.entity.user.UserExtraInfo;
import com.ks.app.entity.user.UserInfo;
import com.ks.app.entity.user.WXUserInfo;
import com.ks.app.utils.user.UserVOUtil;
/**
 * @author hxh
 * @title: UserInfoVO
@@ -10,8 +15,47 @@
    private String id;
    private String nickName;
    private String portrait;
    private String phone;
    private String wxNickName;
    private String inviteCode;
    private Boolean hasBoss;
    private Integer unReadMsgCount;
    //VIP到期时间
    private Long vipExpireTime;
    public static UserInfoVO create(UserInfo user) {
        UserInfoVO vo = new UserInfoVO();
        vo.setId(user.getId() + "");
        vo.setNickName(user.getNickName());
        vo.setPortrait(user.getPortrait());
        vo.setPhone(UserVOUtil.getCoverPhone(user.getPhone()));
        return vo;
    }
    public static UserInfoVO create(UserInfo user, UserExtraInfo extraInfo) {
        UserInfoVO vo = create(user);
        vo.setInviteCode(extraInfo.getInviteCode());
        if (extraInfo.getUnReadMsgCount() == null) {
            vo.setUnReadMsgCount(0);
        } else {
            vo.setUnReadMsgCount(extraInfo.getUnReadMsgCount());
        }
        return vo;
    }
    public static UserInfoVO create(UserInfo user, UserExtraInfo extraInfo, WXUserInfo wxUserInfo) {
        UserInfoVO vo = create(user, extraInfo);
        if (wxUserInfo != null) {
            vo.setWxNickName(wxUserInfo.getNickName());
        }
        return vo;
    }
    public String getId() {
        return id;
@@ -44,4 +88,44 @@
    public void setVipExpireTime(Long vipExpireTime) {
        this.vipExpireTime = vipExpireTime;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getWxNickName() {
        return wxNickName;
    }
    public void setWxNickName(String wxNickName) {
        this.wxNickName = wxNickName;
    }
    public String getInviteCode() {
        return inviteCode;
    }
    public void setInviteCode(String inviteCode) {
        this.inviteCode = inviteCode;
    }
    public Boolean getHasBoss() {
        return hasBoss;
    }
    public void setHasBoss(Boolean hasBoss) {
        this.hasBoss = hasBoss;
    }
    public Integer getUnReadMsgCount() {
        return unReadMsgCount;
    }
    public void setUnReadMsgCount(Integer unReadMsgCount) {
        this.unReadMsgCount = unReadMsgCount;
    }
}
src/main/resources/code/service/app/src/main/resources/alipay.properties
@@ -1,3 +1,8 @@
app_id=2021002122664142
private_key=MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCobx3dj48eJ8xg9twd0Yo2j/t0UzawGHcCJ5lmA+LR3ZJHKud2/YhsekN5ZXR9BgJ3DZNTlZfRK3/DyW2CxEJmpCU9tNAM8WapkaXobQOaBqVhcfj9YevygcGYfAK0vPYNuGwCOW93Cl0Lm9SWIZQZIv3w8mWQBX9+7csAt9K46hk7QCJG/YyHORgTFWeHLATbj+j8JywyFpd5ZSrGFUj/bC5Z1v2Gx7lXOLF5VnAjY7slPdElYe93MHnLh901NQPI/IoqJupEJhHgV2Qi3Z+7PXXNTa/tWAew3rlYdEtfRojFPhqB5rNF3inIKLryMfxBcbVTG13QGFWo3gJZ9BdbAgMBAAECggEBAJkaiBdBy2Ip4wmw21zvf6chMf0HNwrS8jqvLC0jEyaZNcIjKctronqYmITcyAptUAhP+r9bl2i3FagujLD1HTaXtpJkrUlWlW9FyX2Aumlj6SiupRoNzJ/fes7UytDngvHt1aAf/UZD0VggChl95FUFDbfbXp6PoNkL5h98+LrD9eKrRd2Oeclpnet5E3benQogLLtW+n10PB2PTrBJg+HGk+M5J5t5O4fEZ4mCpEPl2Pq6g5KVR7Hbb5n0x7K5Uo8WXU79OIdMt8zy6a8BHx3VPYjkqr9VjMCEfgKBngMJ1ezFJGQ6rc3xJD9DoSR7/YXuFeHKQao8tX6UmUGjRUECgYEA4amyumywa37lmDtkmHXXgJHcpvejxM+A7F8DBw/uUBekVSCq3rU/kPsnXCr+/pL91ulEcJduCmPIbfkvTmAthD5IqDhQYnnYX+ulhX1C8Aj6zulkGqfa8sevuPjaLelLNZxvXXIYNik4+z5o7CSIgOrCjBhAWCKAgb/45BEwpIMCgYEAvxPb/ib7MMdEbWBmvqtauPPi170GOT9IiIcXQwyhcfj5/+0E83bjoEj0GOUH2X8qT0liSmj1LJqny4K00qnG05zijL+vna/pn3zFTKrRVtCmRDtYSJtzcCju7RdkNQ8WXASTmjaSinuEdg+aTI9G+oOMyIYGEQVZ8o+w2KzaukkCgYEAkPH+Ie5UNwewE2L6z07J2ARYlUp0/6JE7g5tFGkwKnO1ExTDi/8hUE9xzaq0VPI3Z4Y3dpZdkQDcqX6n2xC9y7Zx1tMtFsOqrpnenGqDx0gNST/yE4kDgnOutAHrqheyPkI36e6yDH/X4NEKdbtVjnC7+15MXg/zOOQEywEbnF8CgYAqcSHTYRs4aXqUhO4teehL3rhLTUw9mQXmdYNAPGT76N627xHDdmv3JV06zlyg/fMK63TurEORJcURmjXJ+TYVuOpFcypx7yoIZ/F3JxYan3ve+gORFR5eEmmHtkNm2bQQul+CyI5iPi9c/fg6+zQ73s59l+9vBm5FR49zgWmQKQKBgQCmq14mUPPe5LF3W342qZTKSKtwF82XYmuJ0EtjYxlt+D70fSvaB8Dtj/XanL0FRMVZsJaIM1pjdnMIqRN2AGOXLRt8DV9lTELqBfq2aI7f9vscc28T4ySUTkWVbZYwC6iDlPBha3MUwGGiO/rNbnIY7GB3BUSpgazo02lvzd0vsw==
alipay_public_key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHWEgMOlGb/VbN5pcSXv+DLX2EJ43p93zP9eyao8ghj1LcBSf5Sx4gYpuySKZ0oimILb+ErOAlDzcXwvMxcVTK0W2M6UaUW0Vh71vOorqggOGqMJsSDpV1hvYrUSCYu1Qe5KtV85w+Kw4dImC3fayIaxUMhwySuniQ/uQtezRHn/vwXrGigu3Y2tRgPMUptqA14EYEfhpm3KjLXsqWdJBO6ziiqILHJtow65QzkeoLM2ZHpYH6oYy2rIj/iSIpos18MKWvr4XrqSptJYIQp+G3dwqjlt2kk4bpgAXQSR6wKAtGTkAYvlOSpkQXVqI3tIGZO3ZM9bFQurMBoJFX790wIDAQAB
appId=2018120462438303
private_key=MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+x9VLP7eZ0sHVjkgNYMnqEP2CrDI+BdW7Il2o1e5Wp0o3GoJBkJH29SpUPQoWUDM3JoILzXPnlS6QeCzfPG3ROJyXlWjp7vNzGs7oWGCbsYac/bweV9DsxnEO5xqYRKUInLL+SoqepxUPYTFxroh5E4ZVWLWBHC0bFCZxiwy9jZhpbNcTAAp/WRJoCpbV0YAw+4pZQmV99HvzwfNKZtUWQWnyKglI3RogYJphFhB91e0X+phZzuE5WzgT2mGOGqw2w3DVK7YDgIX5nAI73Z8zlkDfSys3tB3KibuVMuR6/3yt+G867vhjfebonTHyqKpCJSuyFRfR/WR4lMx4+3aZAgMBAAECggEBAIudAeJHhrzzFxaJQQFJS3oXZO4zxbDN5FNGGvRrWjffxNf+dkQ04Byx3YA4CyG5H0HE1HZ+q8tVyPXAfFYBivwJSc9Eb7qCO3aIr9IomspVaAWLSheKfEJKFoKpbTTxRzS+N98P/dGMxES1A9IFv6mbODtM58bML9YZMOj2sSQlK+g0TKW5SipjWwnmSlEXDDYLMKWRR3zec1FBOB2DR+6Ajkz0+ml4gmlbQe6WNRGPZ7mhW+VLjIbZNd8UYwnRttCJ8G/vWP0xdsyB0wZ5jFhVQsZuqlxCL+LJjsB7o16MsH6r9L8QkGADeo0aICFhsFYmujX4pTBQB6oOQoj07YECgYEA//fOPwTN1hsvUHblXWChn0p5e7Z3S2hxhpnbL0og4Mx+TTQMQ5XgzUCwwFacV5Ctk/lxOepgu8+X928+IeJjPAFZzxLLb4iMpfwzxYhbRli32blNQEH2aXPwnGreXJPAjRAjDx5WbdYOcVyWQRk2MpWSI3eFzxSXS/uaSf6P9LUCgYEAvs3w0Ab9jal7awPMmEKT2+CIbUKTLXsRikxXMX8UsIKYo/5zeqMKwXDjE63agkTNLAUqaYuIA5SFDYbgpXuF5nta2gflgFw8k1mkBdPEhUFYeNmh7tSJgAtObWKOaiDO4/DdmUYd50GIbSGsbUPZ9/PZcju9eJqcf5peaI/m7NUCgYEAgQhdet0kGjN4BXr6IrlMoCz90oRn3KaY2/6BRHR84HWVkbuUFxndyfo7X6oJhAbVyYtsLYLeIq8Cb2QvkQs7dQtFR6K01NOj+ySIwKH9SRf+Dg5gR+04l24vs9oXn9mHrlSdJ8jmTtYiT7kZsVVRQeyuT5y34m0B2/bIj1Z5ISUCgYBXmSTd3Ne7mfvXfb8IiEhpwgPgZZg8YSwEWlgNmVJeVxbM850AyKm/dZxLBJ41AHFRrG10V2LygdU0CKBKWRN4ZVmoj8eFztLgs17ibf7jTsTXdtMpWtpltssi3QSVJMrXS1XxcId6DFQeBj+rSmNfuswx7ctm+1SuIKkHSEm0oQKBgCPwgwsEw4J5yN5J0UEcXbZt9eCNfG43e3NcvsUITxueH05IiHACMw4e6STdgqPMSaiDWb7/d6OTG0Ps1JjuWE4/2i1OeVA/ytznskDw/Y7AH+6Z12x1NPeDYJHOH04K9cV1JQvQoCoQ03ffhHsIU7c7K3pLmLwlHc9IU6tkkcU1
public_key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvsfVSz+3mdLB1Y5IDWDJ6hD9gqwyPgXVuyJdqNXuVqdKNxqCQZCR9vUqVD0KFlAzNyaCC81z55UukHgs3zxt0Ticl5Vo6e7zcxrO6Fhgm7GGnP28HlfQ7MZxDucamESlCJyy/kqKnqcVD2Exca6IeROGVVi1gRwtGxQmcYsMvY2YaWzXEwAKf1kSaAqW1dGAMPuKWUJlffR788HzSmbVFkFp8ioJSN0aIGCaYRYQfdXtF/qYWc7hOVs4E9phjhqsNsNw1Su2A4CF+ZwCO92fM5ZA30srN7Qdyom7lTLkev98rfhvOu74Y33m6J0x8qiqQiUrshUX0f1keJTMePt2mQIDAQAB
account_name=重庆快省科技有限公司
app_cert_path=alipay/appCertPublicKey_2018120462438303.crt
alipay_root_cert_path=alipay/alipayRootCert.crt
alipay_cert_path=alipay/alipayCertPublicKey_RSA2.crt
src/main/resources/code/service/app/src/main/resources/application-dev.yml
@@ -85,11 +85,11 @@
      addresses: http://1.14.235.17:9000/xxl-job-admin
#buddo配置参数
#dubbo:
#  application:
#    name: app-consumer
#  registry:
#    protocol: zookeeper
#    address: zookeeper://172.16.16.46:2181 # 134.175.68.214   134.175.68.214:2181
#    client: curator
dubbo:
  application:
    name: app-consumer
  registry:
    protocol: zookeeper
    address: zookeeper://193.112.35.168:2182 # 134.175.68.214   134.175.68.214:2181
    client: curator
src/main/resources/code/service/app/src/main/resources/application-pro.yml
@@ -84,10 +84,10 @@
    admin:
      addresses: http://1.14.235.17:9000/xxl-job-admin
#dubbo:
#  application:
#    name: app-consumer
#  registry:
#    protocol: zookeeper
#    address: zookeeper://172.16.16.46:2181 # 134.175.68.214   134.175.68.214:2181
#    client: curator
dubbo:
  application:
    name: app-consumer
  registry:
    protocol: zookeeper
    address: zookeeper://172.16.16.46:2181 # 134.175.68.214   134.175.68.214:2181
    client: curator
src/main/resources/code/service/app/src/main/resources/cos.properties
@@ -2,4 +2,6 @@
secretId =AKIDTlpgJhLjOozvd6QI2XnpfGbgV4NQJk25
secretKey =xhCSUHo55oHUQ6XicFcmfIgspX0EEzWo
bucketName =xxxx
region=ap-nanjing
region=ap-nanjing
#图片访问域名
domain=http://img.mm.yeshitv.com
src/main/resources/code/service/app/src/main/resources/mapper/UserInfoMapper.xml
@@ -34,26 +34,26 @@
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user where id = #{id, jdbcType=BIGINT}
        from mm_user where id = #{id, jdbcType=BIGINT}
    </select>
    <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user where id = #{id,jdbcType=BIGINT} for update
        from mm_user where id = #{id,jdbcType=BIGINT} for update
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
        delete from
        lt_user where id = #{id,jdbcType=BIGINT}
        mm_user where id = #{id,jdbcType=BIGINT}
    </delete>
    <insert id="insert"
            parameterType="com.ks.app.entity.user.UserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into
        lt_user
        mm_user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            system,
            nick_name,
@@ -88,7 +88,7 @@
    <insert id="insertSelective"
            parameterType="com.ks.app.entity.user.UserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into lt_user
        insert into mm_user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,</if>
            <if test="system != null">system,</if>
@@ -121,7 +121,7 @@
    </insert>
    <update id="updateByPrimaryKey"
            parameterType="com.ks.app.entity.user.UserInfo">
        update lt_user
        update mm_user
        <set>
            <if test="id != null">id = #{id,jdbcType=BIGINT},</if>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
@@ -140,7 +140,7 @@
    </update>
    <update id="updateByPrimaryKeySelective"
            parameterType="com.ks.app.entity.user.UserInfo">
        update lt_user
        update mm_user
        <set>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">nick_name = #{nickName,jdbcType=VARCHAR},</if>
@@ -158,7 +158,6 @@
    </update>
    <sql id="listWhere">
        <if test="query.system!=null">
            and system = #{query.system}
        </if>
@@ -180,6 +179,7 @@
        <if test="query.email!=null">
            and email = #{query.email}
        </if>
        <if test="query.maxCreateTime!=null">
            and create_time <![CDATA[<]]> #{query.maxCreateTime}
        </if>
@@ -188,13 +188,13 @@
        </if>
        <if test="query.status!=null">
            and status >= #{query.status}
            and status = #{query.status}
        </if>
    </sql>
    <select id="list"
            resultMap="BaseResultMap">
        SELECT * FROM lt_user
        SELECT * FROM mm_user
        <where>
            <include refid="listWhere">
            </include>
@@ -210,7 +210,7 @@
    <select id="listByUids"
            resultMap="BaseResultMap">
        SELECT * FROM lt_user
        SELECT * FROM mm_user
        <foreach collection="uidList" open=" where " separator=" or " item="uid">
            id= #{uid}
        </foreach>
@@ -219,7 +219,7 @@
    <select id="count"
            resultType="java.lang.Long">
        SELECT count(*) FROM lt_user
        SELECT count(*) FROM mm_user
        <where>
            <include refid="listWhere">
            </include>
@@ -230,7 +230,7 @@
    <select id="statisticByCreateTime"
            resultMap="com.ks.app.mapper.basemapper.Statistic_Number_BaseResultMap">
        SELECT DATE_FORMAT(l.`create_time`,'${timeQuery.timeFormat}') AS time,COUNT(*) AS number FROM lt_user l WHERE
        SELECT DATE_FORMAT(l.`create_time`,'${timeQuery.timeFormat}') AS time,COUNT(*) AS number FROM mm_user l WHERE
        l.`create_time`>#{timeQuery.startTime} AND #{timeQuery.endTime}>l.`create_time`
        <if test="system!=null">
            and system=#{system}
src/main/resources/code/service/app/src/main/resources/mapper/WXUserInfoMapper.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.mapper.user.WXUserInfoMapper">
<mapper namespace="com.ks.app.dao.user.WXUserInfoMapper">
    <resultMap id="BaseResultMap"
               type="com.ks.app.entity.user.WXUserInfo">
        <id column="id" property="id" jdbcType="BIGINT"/>
@@ -28,26 +28,26 @@
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user_wx where id = #{id, jdbcType=BIGINT}
        from mm_user_wx where id = #{id, jdbcType=BIGINT}
    </select>
    <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap"
            parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List"/>
        from lt_user_wx where id = #{id,jdbcType=BIGINT} for update
        from mm_user_wx where id = #{id,jdbcType=BIGINT} for update
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
        delete from
        lt_user_wx where id = #{id,jdbcType=BIGINT}
        mm_user_wx where id = #{id,jdbcType=BIGINT}
    </delete>
    <insert id="insert"
            parameterType="com.ks.app.entity.user.WXUserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into
        lt_user_wx
        mm_user_wx
        <trim prefix="(" suffix=")" suffixOverrides=",">
            system,
            nick_name,
@@ -82,7 +82,7 @@
    <insert id="insertSelective"
            parameterType="com.ks.app.entity.user.WXUserInfo"
            useGeneratedKeys="true" keyProperty="id">
        insert into lt_user_wx
        insert into mm_user_wx
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,</if>
            <if test="system != null">system,</if>
@@ -115,7 +115,7 @@
    </insert>
    <update id="updateByPrimaryKey"
            parameterType="com.ks.app.entity.user.WXUserInfo">
        update lt_user_wx
        update mm_user_wx
        <set>
            <if test="id != null">id = #{id,jdbcType=BIGINT},</if>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
@@ -134,7 +134,7 @@
    </update>
    <update id="updateByPrimaryKeySelective"
            parameterType="com.ks.app.entity.user.WXUserInfo">
        update lt_user_wx
        update mm_user_wx
        <set>
            <if test="system != null">system = #{system,jdbcType=VARCHAR},</if>
            <if test="nickName != null">nick_name = #{nickName,jdbcType=VARCHAR},</if>
@@ -153,18 +153,18 @@
    <sql id="listWhere">
        <if test="query.system!=null">
            system=#{query.system}
            and system=#{query.system}
        </if>
        <if test="query.unionId!=null">
            union_id=#{query.unionId}
            and union_id=#{query.unionId}
        </if>
    </sql>
    <select id="list"
            resultMap="BaseResultMap">
        SELECT * FROM lt_user_wx
        SELECT * FROM mm_user_wx
        <where>
            <include refid="listWhere">
            </include>
@@ -180,7 +180,7 @@
    <select id="count"
            resultType="java.lang.Long">
        SELECT count(*) FROM lt_user_wx
        SELECT count(*) FROM mm_user_wx
        <where>
            <include refid="listWhere">
            </include>
src/main/resources/code/service/app/src/main/resources/static/config/system_config_add.html
@@ -26,42 +26,42 @@
    <div class="layui-row">
        <form class="layui-form" lay-filter="add">
                <div class="layui-form-item">
                    <label for="L_appCode" class="layui-form-label">
                        名称</label>
                     <div class="layui-input-block">
                          <input type="text" name="name"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                    </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    名称</label>
                <div class="layui-input-block">
                    <input type="text" name="name" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
                <div class="layui-form-item">
                    <label for="L_appCode" class="layui-form-label">
                        关键字</label>
                     <div class="layui-input-block">
                          <input type="text" name="key"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                    </div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    关键字</label>
                <div class="layui-input-block">
                    <select type="text" name="key" placeholder="" autocomplete="off"
                            class="layui-input"></select>
                </div>
                <div class="layui-form-item">
                    <label for="L_appCode" class="layui-form-label">
                        内容</label>
                     <div class="layui-input-block">
                          <input type="text" name="value"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                    </div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    内容</label>
                <div class="layui-input-block">
                    <textarea type="text" rows="5" name="value" lay-verify="" placeholder="" autocomplete="off"
                              class="layui-textarea"></textarea>
                </div>
                <div class="layui-form-item">
                    <label for="L_appCode" class="layui-form-label">
                        备注</label>
                     <div class="layui-input-block">
                          <input type="text" name="remarks"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                    </div>
            </div>
            <div class="layui-form-item">
                <label for="L_appCode" class="layui-form-label">
                    备注</label>
                <div class="layui-input-block">
                      <textarea type="text" name="remarks" lay-verify="" placeholder="" autocomplete="off" rows="5"
                                class="layui-textarea"></textarea>
                </div>
            </div>
            <div class="layui-form-item">
                <label for="L_remarks" class="layui-form-label"></label>
@@ -100,8 +100,8 @@
    layui.use(['form', 'layer', 'jquery', 'upload'], function () {
        $ = layui.jquery;
        var form = layui.form,
                layer = layui.layer,
                upload = layui.upload;
            layer = layui.layer,
            upload = layui.upload;
        var verify = {};
        //自定义验证规则
@@ -110,46 +110,70 @@
        //渲染上传控件
        uploadTool.init(upload);
        var params = {};
        var type = ksapp.getQueryParam("type");
        if (type != null && type.length > 0) {
            params["type"] = type;
        }
        ksapp.post('/admin/api/config/getKeyList', params, function (res) {
            if (res.code == 0) {
                //填充数据
                $("select[name=key]").empty();
                for (var i = 0; i < res.data.length; i++) {
                    var html = "<option value='" + res.data[i].key + "'>";
                    html += res.data[i].value + "</option>";
                    $("select[name=key]").append(html);
                }
                //重新渲染表单
                form.render();
            } else {
                layer.msg(res.msg);
            }
        }, function (res) {
        });
        //监听提交
        form.on('submit(add)',
                function (data) {
                    console.log(data.field);
                    //转换json对象
                    for (key in data.field) {
                        if (key.indexOf(".") > -1) {
                            var value = data.field[key];
                            delete data.field[key];
                            var onkeys = key.split(".");
                            //创建对象
                            if (data.field[onkeys[0]] == undefined) {
                                data.field[onkeys[0]] = {};
                            }
                            data.field[onkeys[0]][onkeys[1]] = value;
            function (data) {
                console.log(data.field);
                //转换json对象
                for (key in data.field) {
                    if (key.indexOf(".") > -1) {
                        var value = data.field[key];
                        delete data.field[key];
                        var onkeys = key.split(".");
                        //创建对象
                        if (data.field[onkeys[0]] == undefined) {
                            data.field[onkeys[0]] = {};
                        }
                        data.field[onkeys[0]][onkeys[1]] = value;
                    }
                    uploadTool.upload(function(){
                        //发异步,把数据提交给php
                        ksapp.post('/admin/api/config/add', data.field, function (res) {
                            if (res.code == 0) {
                                layer.alert("增加成功", {
                                            icon: 6
                                        },
                                        function () {
                                            //关闭当前frame
                                            xadmin.close();
                                            // 可以对父窗口进行刷新
                                            // xadmin.father_reload();
                                        });
                            } else {
                                layer.msg(res.msg);
                            }
                }
                uploadTool.upload(function () {
                    //发异步,把数据提交给php
                    ksapp.post('/admin/api/config/add', data.field, function (res) {
                        if (res.code == 0) {
                            layer.alert("增加成功", {
                                    icon: 6
                                },
                                function () {
                                    //关闭当前frame
                                    xadmin.close();
                                    // 可以对父窗口进行刷新
                                    // xadmin.father_reload();
                                });
                        } else {
                            layer.msg(res.msg);
                        }
                        }, function (res) {
                        });
                    }, function (res) {
                    });
                    return false;
                });
                return false;
            });
        //请求select的数据API
    })
    ;
src/main/resources/code/service/app/src/main/resources/static/config/system_config_list.html
@@ -43,7 +43,7 @@
                    <form class="layui-form layui-col-space5">
                        <div class="layui-inline layui-show-xs-block">
                            <input type="text" name="kw"  lay-verify=""  placeholder="请输入名称" autocomplete="off"
                            <input type="text" name="kw" lay-verify="" placeholder="请输入名称" autocomplete="off"
                                   class="layui-input">
                        </div>
@@ -64,7 +64,7 @@
</body>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn" onclick="xadmin.open('添加系统配置信息','system_config_add.html',500,580)"><i
        <button class="layui-btn" onclick="xadmin.open('添加系统配置信息','system_config_add.html?type='+  ksapp.getQueryParam('type'),500,580)"><i
                class="layui-icon"></i>添加
        </button>
    </div>
@@ -72,7 +72,8 @@
<script type="text/html" id="optContainer">
    <div class="layui-btn-container">
        <a title="修改" onclick="xadmin.open('修改系统配置信息','system_config_update.html?id={{d.id}}',500,580)" href="javascript:;">
        <a title="修改" onclick="xadmin.open('修改系统配置信息','system_config_update.html?id={{d.id}}',500,580)"
           href="javascript:;">
            <i class="layui-icon">&#xe642;</i>
        </a>
    </div>
@@ -101,7 +102,7 @@
<script type="text/html" id="imgshow">
    <!-- 这里的checked的状态只是演示 -->
    <img  src="{{d.}}"/>
    <img src="{{d.}}"/>
    <input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="女|男" lay-filter="sexDemo" {{ d.id==
           10003 ? 'checked': ''}} >
</script>
@@ -138,8 +139,8 @@
                    //初始化
                    layui.use(['laydate', 'form', 'table'], function () {
                        var laydate = layui.laydate,
                                form = layui.form,
                                table = layui.table;
                            form = layui.form,
                            table = layui.table;
                        //渲染日期输入框
                        //搜索条件
                        form.on('submit(search)', function (data) {
@@ -153,19 +154,21 @@
                            toolbar: "#toolbar",
                            totalRow: true,
                            cols: [[{type: 'checkbox', title: "ID"},
                                    {field: 'name', width: 200, sort: false, title: "名称"},
                                    {field: 'key', width: 120, sort: false, title: "关键字"},
                                    {field: 'value', width: 400, sort: false, title: "内容",templet:function(res){
                                        if("object"== typeof res.value){
                                {field: 'name', width: 200, sort: false, title: "名称"},
                                {field: 'key', width: 120, sort: false, title: "关键字"},
                                {
                                    field: 'value', width: 400, sort: false, title: "内容", templet: function (res) {
                                        if ("object" == typeof res.value) {
                                            return JSON.stringify(res.value);
                                        }else{
                                        } else {
                                            return res.value;
                                        }
                                        }},
                                    {field: 'remarks', width: 120, sort: false, title: "备注"},
                                    {field: 'createTime', width: 120, sort: false, title: "创建时间"},
                                    {field: 'updateTime', width: 120, sort: false, title: "修改时间"},
                                    }
                                },
                                {field: 'remarks', width: 120, sort: false, title: "备注"},
                                {field: 'createTime', width: 120, sort: false, title: "创建时间"},
                                {field: 'updateTime', width: 120, sort: false, title: "修改时间"},
                                {fixed: 'right', width: 80, title: "操作", toolbar: '#optContainer'}]],
                            page: true,
                            parseData: function (res) { //res 即为原始返回的数据
@@ -189,31 +192,32 @@
                        //头工具栏事件
                        table.on('toolbar(app)',
                                function (obj) {
                                    var checkStatus = table.checkStatus(obj.config.id);
                                    switch (obj.event) {
                                        case 'delete':
                                            var data = checkStatus.data;
                                            if (data == null || data.length == 0) {
                                                layer.msg("未选择选项");
                                                return;
                                            }
                                            var ids = new Array();
                                            for (var i = 0; i < data.length; i++)
                                                ids.push(data[i].id);
                                            layer.confirm('确认要删除吗?', function (index) {
                                                //发异步删除数据
                                                app.deleteList(ids, function () {
                                                    layer.msg("删除成功");
                                                    $("form").submit();
                                                });
                            function (obj) {
                                var checkStatus = table.checkStatus(obj.config.id);
                                switch (obj.event) {
                                    case 'delete':
                                        var data = checkStatus.data;
                                        if (data == null || data.length == 0) {
                                            layer.msg("未选择选项");
                                            return;
                                        }
                                        var ids = new Array();
                                        for (var i = 0; i < data.length; i++)
                                            ids.push(data[i].id);
                                        layer.confirm('确认要删除吗?', function (index) {
                                            //发异步删除数据
                                            app.deleteList(ids, function () {
                                                layer.msg("删除成功");
                                                $("form").submit();
                                            });
                                        });
                                            break;
                                    };
                                });
                                        break;
                                }
                                ;
                            });
                        //请求搜索表单中需要的数据
                          $('#search').trigger("click");
                        $('#search').trigger("click");
                    });
                },
@@ -236,6 +240,15 @@
                    });
                },
                search: function (params) {
                    params["type"] = ksapp.getQueryParam("type");
                    var ps = {};
                    for (var key in params) {
                        if (params[key] != null && params[key].length > 0) {
                            ps[key] = params[key];
                        }
                    }
                    //数据重载
                    tableIns.reload({
                        where: params,
@@ -245,8 +258,8 @@
                    });
                },
            }
    });
    app.init();
        });
        app.init();
    });
</script>
src/main/resources/code/service/app/src/main/resources/static/config/system_config_update.html
@@ -48,8 +48,8 @@
                    <label for="L_appCode" class="layui-form-label">
                        内容</label>
                    <div class="layui-input-block">
                          <input type="text" name="value"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                          <textarea type="text" rows="5" name="value" lay-verify="" placeholder="" autocomplete="off"
                                    class="layui-textarea"></textarea>
                    </div>
                </div>
@@ -57,8 +57,8 @@
                    <label for="L_appCode" class="layui-form-label">
                        备注</label>
                    <div class="layui-input-block">
                          <input type="text" name="remarks"  lay-verify=""  placeholder="" autocomplete="off"
                               class="layui-input">
                            <textarea type="text" name="remarks" lay-verify="" placeholder="" autocomplete="off" rows="5"
                                      class="layui-textarea"></textarea>
                    </div>
                </div>
src/main/resources/code/service/app/src/main/resources/static/index.html
@@ -138,11 +138,23 @@
                    <i class="iconfont nav_right">&#xe697;</i></a>
                <ul class="sub-menu">
                    <li>
                        <a onclick="xadmin.add_tab('系统参数','config/system_config_list.html')">
                        <a onclick="xadmin.add_tab('系统参数','config/system_config_list.html?type=system')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>系统参数</cite></a>
                    </li>
                    <li>
                        <a onclick="xadmin.add_tab('客户端参数','config/system_config_list.html?type=common')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>客户端参数</cite></a>
                    </li>
                    <li>
                        <a onclick="xadmin.add_tab('广告配置','config/system_config_list.html?type=ad')">
                            <i class="iconfont">&#xe6a7;</i>
                            <cite>广告配置</cite></a>
                    </li>
                </ul>
            </li>
        </ul>
src/main/resources/code/service/app/src/main/resources/static/welcome.html
@@ -15,7 +15,7 @@
    <!-- <link rel="stylesheet" href="./css/theme5.css"> -->
    <script type="text/javascript" src="js/xadmin.js"></script>
    <script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/http.js" type="text/javascript" charset="utf-8"></script>
    <script src="lib/layui/layui.js" charset="utf-8"></script>
@@ -23,6 +23,7 @@
    <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <script type="text/javascript" src="js/xadmin.js"></script>
    <![endif]-->
    <script>
        // 是否开启刷新记忆tab功能
@@ -41,33 +42,33 @@
            border-left: none;
        }
        .time-psan {
        .time-span {
            height: 25px;
            display: flex;
            margin: 20px 0;
        }
        .time-psan div {
        .time-span div {
            width: 50px;
            height: 100%;
            text-align: center;
            line-height:25px;
            line-height: 25px;
            font-size: 12px;
            background: #F5F5F5;
            color: #666;
            cursor: pointer;
        }
        .time-psan .active {
        .time-span .active {
            background: #DDDDDD;
        }
        .time-psan :first-child {
        .time-span :first-child {
            border-top-left-radius: 8px;
            border-bottom-left-radius: 8px;
        }
        .time-psan :last-child {
        .time-span :last-child {
            border-top-right-radius: 8px;
            border-bottom-right-radius: 8px;
        }
@@ -78,140 +79,183 @@
</head>
<body>
<div class="layui-card">
    <div class="layui-card-body">
        <blockquote class="layui-elem-quote">
            新增用户统计
        </blockquote>
        <form class="layui-form layui-col-space5">
            <div class="layui-inline layui-show-xs-block">
                <input type="text" name="date" lay-verify="" placeholder="" autocomplete="off"
                       class="layui-input">
            </div>
            <div class="layui-inline layui-show-xs-block">
                <button id="search" class="layui-btn" lay-submit="" lay-filter="search">
                    <i class="layui-icon">&#xe615;</i></button>
            </div>
        </form>
        <div class="time-psan">
            <div key="hour">小时</div>
            <div key="day" class="active">天</div>
            <div key="month">月</div>
<div id="content">
    <div class="layui-card" v-for="item,index in charts" :id="item.type" :data-index="index">
        <div class="layui-card-body">
            <blockquote class="layui-elem-quote">
                {{item.title}}
            </blockquote>
            <form class="layui-form layui-col-space5">
                <div class="layui-inline layui-show-xs-block">
                    <input type="text" name="date" lay-verify="" placeholder="" autocomplete="off"
                           class="layui-input">
                </div>
                <div class="layui-inline layui-show-xs-block">
                    <!-- :lay-filter="'search-'+item.type" -->
                    <button class="search" class="layui-btn" lay-submit="" :lay-filter="'search-'+item.type">
                        <i class="layui-icon">&#xe615;</i></button>
                </div>
                <input type="hidden" :value="index" name="index">
            </form>
            <div class="time-span">
                <div data-key="hour" @click="changeSpan(index,$event)">小时</div>
                <div data-key="day" class="active" @click="changeSpan(index,$event)">天</div>
                <div data-key="month" @click="changeSpan(index,$event)">月</div>
            </div>
            <canvas :id="'chart-'+item.type" width="100%" height="25"></canvas>
        </div>
        <canvas id="myChart" width="100%" height="25"></canvas>
    </div>
</div>
</body>
<script>
    $(function () {
        var app = new Vue({
            el: "#content",
            data: {
                charts: [
                    {
                        type: 'user',
                        url: '/admin/api/user/statisticRegisterUser',
                        title: '新增用户统计'
                    }
                ],
                chartsCanvas: {}
            },
            mounted: function () {
                setTimeout(function () {
                    app.init();
                }, 10);
        //时间间隔点击事件
        $(".time-psan div").click(function () {
            if (!$(this).hasClass("active")) {
                $(".time-psan div").removeClass("active");
                $(this).addClass("active");
                $("#search").click();
            },
            methods: {
                init: function () {
                    var $this = this;
                    layui.use(['laydate', 'form'], function () {
                        var laydate = layui.laydate,
                            form = layui.form;
                        for (var i = 0; i < $this.charts.length; i++) {
                            var chartConfig = $this.charts[i];
                            console.log("初始化 ", chartConfig.type, i);
                            //渲染日期输入框
                            var d = new Date();
                            var nowDay = d.format('yyyy-MM-dd');
                            laydate.render({
                                elem: "#" + chartConfig.type + " input[name=date]" //指定元素
                                ,
                                index: i,
                                type: 'date'
                                ,
                                trigger: 'click'
                                //,lang: 'en'
                                //,theme: 'grid'
                                ,
                                range: true //开启日期范围,默认使用“-”分割
                                // ,min: '2020-01-01'
                                //,max: '2021-5-9'
                                //,value: '2021-05-09 12:06:09'
                                ,
                                value: new Date(d.getTime() - 1000 * 60 * 60 * 24 * 7).format('yyyy-MM-dd') + " - " + nowDay
                                ,
                                done: function (value, date, endDate) {
                                    console.log(value, date, endDate, this.index);
                                    $("#" + $this.charts[this.index].type + " .search").click();
                                },
                                change: function (value, date, endDate) {
                                }
                            });
                            //搜索条件
                            form.on("submit(search-" + chartConfig.type + ")", function (data) {
                                var index = parseInt(data.field.index);
                                var span = $("#" + $this.charts[index].type + " .time-span .active").attr("data-key");
                                var config = $this.charts[index];
                                app.requestData(config.url, data.field.date, span, function (labels, values) {
                                    $this.draw(labels, values, $this.getLineChart(config));
                                });
                                return false;
                            });
                            //查询
                            $("#" + chartConfig.type + " .search").click();
                        }
                        // $("#search-user").click();
                    });
                },
                requestData: function (url, dateValue, span, callback) {
                    var date = dateValue.split(" - ");
                    //"/admin/api/user/statisticRegisterUser"
                    ksapp.post(url, {
                        startTime: new Date(date[0]).getTime() - 1000 * 60 * 60 * 8,
                        endTime: new Date(date[1]).getTime() - 1000 * 60 * 60 * 8 + 1000 * 60 * 60 * 24 - 1,
                        span: span
                    }, function (res) {
                        if (res.code == 0) {
                            var labels = new Array();
                            var values = new Array();
                            for (var i = 0; i < res.data.list.length; i++) {
                                labels.push(res.data.list[i].time);
                                values.push(res.data.list[i].number);
                            }
                            callback(labels, values);
                        } else {
                            layer.msg(res.msg);
                        }
                    }, function (res) {
                    });
                },
                getLineChart: function (config) {
                    if (this.chartsCanvas[config.type] == null) {
                        var ctx = document.getElementById("chart-" + config.type).getContext('2d');
                        this.chartsCanvas[config.type] = new Chart(ctx, {
                            type: 'line',
                            data: {
                                labels: [],
                                datasets: [{
                                    label: config.title,
                                    data: [],
                                    backgroundColor: 'rgba(255, 99, 132, 0.2)',
                                    borderColor: 'rgba(54, 162, 235, 1)',
                                    borderWidth: 3
                                }]
                            },
                            options: {
                                scales: {
                                    yAxes: [{
                                        ticks: {
                                            beginAtZero: true
                                        }
                                    }]
                                }
                            }
                        });
                    }
                    return this.chartsCanvas[config.type];
                },
                draw: function (labels, data, chart) {
                    console.log("绘图", chart);
                    chart.data.labels = labels;
                    chart.data.datasets[0].data = data;
                    chart.update();
                },
                changeSpan: function (index, event) {
                    var el = event.currentTarget;
                    if (!$(el).hasClass("active")) {
                        $(el).parent().find("div").removeClass("active");
                        $(el).addClass("active");
                        console.log("点击:" + ("#" + this.charts[index].type + " .search"));
                        $("#" + this.charts[index].type + " .search").click();
                    }
                }
            }
        });
        layui.use(['laydate', 'form'], function () {
            var laydate = layui.laydate,
                form = layui.form;
            //渲染日期输入框
            var d = new Date();
            var nowDay = d.format('yyyy-MM-dd');
            laydate.render({
                elem: 'input[name=date]' //指定元素
                , type: 'date'
                , trigger: 'click'
                //,lang: 'en'
                //,theme: 'grid'
                , range: true //开启日期范围,默认使用“-”分割
                // ,min: '2020-01-01'
                //,max: '2021-5-9'
                //,value: '2021-05-09 12:06:09'
                , value: nowDay + " - " + nowDay
                , done: function (value, date, endDate) {
                    console.log(value, date, endDate);
                    requestData(value);
                }
                , change: function (value, date, endDate) {
                }
            });
            //搜索条件
            form.on('submit(search)', function (data) {
                requestData(data.field.date);
                return false;
            });
            $("#search").click();
        });
        function requestData(value) {
            var date = value.split(" - ");
            ksapp.post("/admin/api/user/statisticRegisterUser", {
                startTime: new Date(date[0]).getTime()-1000*60*60*8,
                endTime: new Date(date[1]).getTime()-1000*60*60*8+1000*60*60*24-1,
                span: $(".time-psan .active").attr("key")
            }, function (res) {
                if (res.code == 0) {
                    var labels = new Array();
                    var values = new Array();
                    for (var i = 0; i < res.data.list.length; i++) {
                        labels.push(res.data.list[i].time);
                        values.push(res.data.list[i].number);
                    }
                    draw(labels, values);
                } else {
                    layer.msg(res.msg);
                }
            }, function (res) {
            });
        }
    });
</script>
<script>
    var ctx = document.getElementById("myChart").getContext('2d');
    var myChar = null;
    function draw(labels, data) {
        if (myChar == null) {
            myChar = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: labels,
                    datasets: [{
                        label: '新增用户数',
                        data: data,
                        backgroundColor: 'rgba(255, 99, 132, 0.2)',
                        borderColor: 'rgba(54, 162, 235, 1)',
                        borderWidth: 3
                    }]
                },
                options: {
                    scales: {
                        yAxes: [{
                            ticks: {
                                beginAtZero: true
                            }
                        }]
                    }
                }
            });
        } else {
            myChar.data.labels = labels;
            myChar.data.datasets[0].data = data;
            myChar.update();
        }
    }
</script>
src/main/resources/code/service/app/src/main/resources/wx/apiclient_cert.p12
Binary files differ
src/main/resources/code/service/app/src/main/resources/wx_transfer.properties
New file
@@ -0,0 +1,4 @@
mchId=1520950211
key=XYJkJ2018FAfaodCCx899mLl138rfGVd
certPwd=1520950211
certPath=wx/apiclient_cert.p12
src/main/resources/code/service/pom.xml
@@ -149,8 +149,6 @@
        <!--</dependency>-->
        <!-- Redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
@@ -160,7 +158,7 @@
        <dependency>
            <groupId>com.yeshi</groupId>
            <artifactId>utils</artifactId>
            <version>0.3.2</version>
            <version>0.3.8</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.data</groupId>
@@ -175,9 +173,13 @@
            </exclusions>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>
</project>