KKSU
2024-03-26 152b3c50a6cb3c433b033b551e09d6f2249f5d60
后台修改
45 files modified
58 files added
8548 ■■■■ changed files
pom.xml 8 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/advise/MyResponseBodyAdvise.java 3 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/contants/AppContants.java 5 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/entity/BaseEntity.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/DataDicEnum.java 70 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/FlowTypeEnum.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/AdminBannerController.java 198 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/AdminMallGoodsController.java 96 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/AdminNewsInfoController.java 119 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java 81 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ApiDappMemberController.java 54 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/MemberMoneyFlowController.java 24 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ViewBannerController.java 206 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ViewController.java 18 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ViewNewsController.java 86 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/ConnectDto.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/MallNewsInfoDto.java 28 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/NewsListDto.java 23 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/RecordInPageDto.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/TeamListDto.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/TransferDto.java 14 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/TransferOutDto.java 19 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappAchieve.java 37 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappAchieveItem.java 33 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappCoinPrice.java 14 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappFundFlowEntity.java 20 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappHdRecord.java 18 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/MallNewsCategory.java 16 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/MallNewsInfo.java 33 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/PlatformBanner.java 48 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappAchieveItemMapper.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappAchieveMapper.java 15 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappCoinPriceMapper.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappFundFlowDao.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappHdRecordMapper.java 20 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappMemberDao.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/MallNewsCategoryMapper.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/MallNewsInfoMapper.java 17 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/PlatformBannerMapper.java 14 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/AsyncCjService.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/DappMemberService.java 8 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/DappSystemService.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/DappWalletService.java 21 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/IAdminBannerService.java 28 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/IApiMallNewsService.java 22 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/IMallNewsInfoService.java 35 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/AdminBannerServiceImpl.java 107 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/ApiMallNewsServiceImpl.java 66 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/AsyncCjServiceImpl.java 231 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java 108 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java 510 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java 304 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/GraphQLClient.java 43 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/MallNewsInfoServiceImpl.java 152 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/AdminMallNewsInfoVo.java 36 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/CoinSetVo.java 37 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/MoneyFlowVo.java 27 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/NewsListVo.java 23 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/TeamListVo.java 23 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/WalletInfoVo.java 50 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/ChainListenerJob.java 204 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/GiveMeMoneyJob.java 51 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/MineProfitJob.java 342 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/NewPriceUpdateJob.java 72 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/RedisLinkHoldJob.java 46 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/SystemTradeJob.java 304 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/QueueConstants.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/QueueEnum.java 26 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/RabbitConfiguration.java 71 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java 31 ●●●●● patch | view | raw | blame | history
src/main/resources/application-dev.yml 15 ●●●● patch | view | raw | blame | history
src/main/resources/application-prod.yml 7 ●●●●● patch | view | raw | blame | history
src/main/resources/application-test.yml 7 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappAchieveMapper.xml 32 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappFundFlowDao.xml 82 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappHdRecordMapper.xml 30 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappMemberDao.xml 47 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/MallNewsCategoryMapper.xml 8 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/MallNewsInfoMapper.xml 28 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/PlatformBannerMapper.xml 13 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/dapp/member-money-flow.html 164 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/dapp/member-withdraw-daibi.html 158 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/dapp/member-withdraw.html 8 ●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/dapp/member-zhi-ya.html 137 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/dapp/member.html 184 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/banner/coinPrice.html 866 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/banner/coinSet.html 253 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/banner/platformBanner.html 179 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/banner/platformBannerAdd.html 145 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/banner/platformBannerDetail.html 162 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/banner/zhiYaItem.html 65 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/news/newsCategory.html 137 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/news/newsCategoryAdd.html 68 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/news/newsInfoAdd.html 173 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/news/newsInfoList.html 169 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/news/newsInfoUpdate-bak.html 121 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/news/newsInfoUpdate-bak2.html 203 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/news/newsInfoUpdate.html 233 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/index.html 2 ●●●●● patch | view | raw | blame | history
src/test/java/cc/mrbird/febs/ChainTest.java 235 ●●●● patch | view | raw | blame | history
src/test/java/cc/mrbird/febs/JunitTest.java 155 ●●●● patch | view | raw | blame | history
pom.xml
@@ -25,6 +25,14 @@
    </properties>
    <dependencies>
        <!--        图片压缩-->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.8</version>
        </dependency>
        <dependency>
            <groupId>taobao</groupId>
            <artifactId>taobao-sdk</artifactId>
src/main/java/cc/mrbird/febs/common/advise/MyResponseBodyAdvise.java
@@ -28,6 +28,7 @@
            return o;
        }
        return SecureUtil.rsa(AppContants.REQ_PRIVATE_KEY, AppContants.REQ_PUBLIC_KEY).encryptBase64(JSONObject.toJSONString(o), KeyType.PrivateKey);
        return SecureUtil.rsa(AppContants.REQ_PRIVATE_KEY, AppContants.REQ_PUBLIC_KEY)
                .encryptBase64(JSONObject.toJSONString(o), KeyType.PublicKey);
    }
}
src/main/java/cc/mrbird/febs/common/contants/AppContants.java
@@ -102,7 +102,7 @@
    public static final String REDIS_KEY_ETH_NEW_PRICE = "ETH_NEW_PRICE";
    public static final String REDIS_KEY_CHANGE_FEE = "DAPP_CHANGE_FEE";
    public static final String REDIS_KEY_SIGN = "LOGIN_SIGN";
    public static final String REDIS_KEY_SIGN = "GFA_LOGIN_SIGN";
    /**
     * 系统启动标志
@@ -162,6 +162,9 @@
    public static final String SYMBOL_USDT = "USDT";
    public static final String SYMBOL_COIN = "TFC";
    public static final String SYMBOL_COIN_GFA = "GFA";
    public static final String SYMBOL_FLOW_TYPE_FLOW = "flow";
    public static final String SYMBOL_FLOW_TYPE_BATCH = "batch";
    public static final String REQ_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1cHrcMpXoKNC8rjAa/jAbgU2bhIBmJmn6iYDfqt0Him/p2s5F0L9nfzZOLYlPq3z12zvXl9IgThhtLIBLi86RPW0ljuwpTvIZz9O36Zae9eMk5bMNsFEFsxg1IOLIM2Oc4ffNvGL58Uupp9RL5NCN1MRQyY61ISy7H2VRTznoJQIDAQAB";
    public static final String REQ_PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALVwetwylego0LyuMBr+MBuBTZuEgGYmafqJgN+q3QeKb+nazkXQv2d/Nk4tiU+rfPXbO9eX0iBOGG0sgEuLzpE9bSWO7ClO8hnP07fplp714yTlsw2wUQWzGDUg4sgzY5zh9828YvnxS6mn1Evk0I3UxFDJjrUhLLsfZVFPOeglAgMBAAECgYAPKWWS5gVB37tFsRajAs+5VK5MCyABqT8c6QWkay5KNYbRl2+6RM3h068RjFuXlUB9eQMAqpasDWqcIOZdqcKqmxm0ILF2zfPzJr4RaQNSNwDCVrKEeaDtrZQcq/0ygaNDF9y203UMHT0dfEQSGp/xkjTgXNsOuC9iLM56XScOVwJBAPOZLbrCi0h4PL7g3rWsCw8/aN6ehkJ3iTDgjYpdBwJOJSyxV0qi0xmDthGqPd99Kvc14u1jy3ghpm1SAEunrj8CQQC+rS6qajIkK7NiRmX43chDhgMPGo0UFHbmHyYBb1Eyrxu1MNWQEh221p54GsB2HqAGRhxxQ98Ds2S26Au7QpibAkA2nQAAn/8kFzjfPoEPz+uG1puHVZkaK7yJRb7V53dbz/NLqtK8O/cCAGKAYV+PzHsmg2FGAZqrazfpyHmifIx3AkBnFau/+A/JnFKr09F3XTfSwZXPyZPyAipRuQ9MAUmNtDuvloovDIxB9//OgPACLAZpvefMmFvuXUMa25LUF2n3AkBGb+vO+69NSyQM2SHKZ9fUrxx9ZPhupNt/TXNL9OMEQiLaHCYgg0tfcojGe3QjBCA6wVG+dCyZUcv5OwiW23pI";
src/main/java/cc/mrbird/febs/common/entity/BaseEntity.java
@@ -28,7 +28,7 @@
    private String updateBy = "system";
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime = new Date();;
    private Date updateTime = new Date();
    private Integer version = 1;
src/main/java/cc/mrbird/febs/common/enumerates/DataDicEnum.java
New file
@@ -0,0 +1,70 @@
package cc.mrbird.febs.common.enumerates;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
/**
 * todo 都需要按照枚举的NAME,去生成对应redis键值对
 */
@Getter
public enum DataDicEnum {
    GFA_DAYS("GFA_DAYS","每日DAPP质押额度"),//4
    /**
     * 5%滑奖分配:
     * 1%用自身质押
     * 3%用于团队业绩计算
     * 1%用于布道者奖励
     */
    GFA_HUA_DIAN_LEVEL("GFA_HUA_DIAN_LEVEL","1%用于布道者奖励"),//4
    GFA_HUA_DIAN_WORK("GFA_HUA_DIAN_WORK","1%用于布道者奖励"),//1
    GFA_HUA_DIAN_TEAM("GFA_HUA_DIAN_TEAM","3%用于团队业绩计算"),//3
    GFA_HUA_DIAN_SELF("GFA_HUA_DIAN_SELF","1%用自身质押"),//1
    GFA_HUA_DIAN_WALLET_USDT_AMOUNT("GFA_HUA_DIAN_WALLET_USDT_AMOUNT","GFA滑点钱包的USDT数量"),//10
    GFA_HUA_DIAN_WALLET_COIN_AMOUNT("GFA_HUA_DIAN_WALLET_COIN_AMOUNT","GFA滑点钱包的GFA数量"),//10
    GFA_PRICE("GFA_PRICE","GFA代币价格"),//1
    GFA_COIN("GFA_COIN","代币名称"),//GFA
    USDT_COIN("USDT_COIN","代币名称"),//USDT
    SYSTEM_START_FLAG("SYSTEM_START_FLAG","是否允许质押开关-start"),//start
    GFA_ZHUAN_ZHANG_KAI_GUAN("GFA_ZHUAN_ZHANG_KAI_GUAN","是否线上转账开关 1-开启 2-关闭"),//1
    /**
     * 按质押币数,质押时84%燃烧,一级5%二级3%三级3%四级5%,得币
     */
    GFA_TUAN_DUI_LEVEL_WU("GFA_TUAN_DUI_LEVEL_WU","一级5%二级5%三级5%四级5%,得币"),//5
    GFA_TUAN_DUI_LEVEL_SI("GFA_TUAN_DUI_LEVEL_SI","一级5%二级5%三级5%四级5%,得币"),//5
    GFA_TUAN_DUI_LEVEL_SAN("GFA_TUAN_DUI_LEVEL_SAN","一级5%二级5%三级5%四级5%,得币"),//3
    GFA_TUAN_DUI_LEVEL_ER("GFA_TUAN_DUI_LEVEL_ER","一级5%二级5%三级5%四级5%,得币"),//3
    GFA_TUAN_DUI_LEVEL_YI("GFA_TUAN_DUI_LEVEL_YI","一级5%二级5%三级5%四级5%,得币"),//5
    GFA_TUAN_DUI_LEVEL("GFA_TUAN_DUI_LEVEL","一级5%二级5%三级5%四级5%,得币"),//4
    GFA_TUAN_DUI_PERCENT("GFA_TUAN_DUI_PERCENT","推荐奖:按质押币数,质押时20%一级5%二级5%三级5%四级5%,得币"),//16
    /**
     * 质押币数按U计算,100U~5000U的任意数,每一单质押为独立单,独立计算收益,类似套餐
     * 挖矿:(进单设预挖池数量)
     * 到DAPP燃烧质押挖矿,按投入量2%每天产币,1.5倍币出局。
     */
    GFA_ACHIEVE_OUT("GFA_ACHIEVE_OUT","质押产出最大值倍数"),//1.5
    GFA_ACHIEVE_RELEASE("GFA_ACHIEVE_RELEASE","每日释放百分比,按投入量2%每天产币"),//2
    GFA_BUY_MAX_AMOUNT("GFA_BUY_MAX_AMOUNT","每次质押GFA最大金额"),//5000
    GFA_BUY_MIN_AMOUNT("GFA_BUY_MIN_AMOUNT","每次质押GFA最小金额")//100
    ;
    private String value;
    private String descrition;
    DataDicEnum(String value, String descrition) {
        this.value = value;
        this.descrition = descrition;
    }
    public List<String> getNameList(){
        List<String> strs = new ArrayList<>();
        for (DataDicEnum value : DataDicEnum.values()) {
            strs.add(value.name());
        }
        return strs;
    }
}
src/main/java/cc/mrbird/febs/common/enumerates/FlowTypeEnum.java
New file
@@ -0,0 +1,24 @@
package cc.mrbird.febs.common.enumerates;
import lombok.Getter;
@Getter
public enum FlowTypeEnum {
    DAI_BI_OUT(8,"USDT提现"),
    USDT_OUT(7,"代币提现"),
    HUA_DIAN_TUANDUI(6,"滑点奖励"),
    TUAN_DUI_FAIL(5,"奖励失效"),
    ZHIYA_CHA_CHU(4,"质押产币"),
    HUA_DIAN_GEREN(3,"质押滑点奖励"),
    TUAN_DUI(2,"团队奖励"),//团队收益
    ZHI_YA(1,"质押")
    ;
    private int value;
    private String descrition;
    FlowTypeEnum(int value, String descrition) {
        this.value = value;
        this.descrition = descrition;
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/AdminBannerController.java
New file
@@ -0,0 +1,198 @@
package cc.mrbird.febs.dapp.controller;
import cc.mrbird.febs.common.annotation.ControllerEndpoint;
import cc.mrbird.febs.common.controller.BaseController;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.enumerates.DataDicEnum;
import cc.mrbird.febs.dapp.entity.DappCoinPrice;
import cc.mrbird.febs.dapp.entity.PlatformBanner;
import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.dapp.service.IAdminBannerService;
import cc.mrbird.febs.dapp.vo.CoinSetVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Map;
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/admin/banner")
public class AdminBannerController extends BaseController {
    private final IAdminBannerService iAdminBannerService;
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    /**
     * 价格---列表
     */
    @GetMapping("coinPrice")
    public FebsResponse coinPrice(DappCoinPrice dappCoinPrice, QueryRequest request) {
        Map<String, Object> data = getDataTable(iAdminBannerService.findCoinPriceInPage(dappCoinPrice, request));
        return new FebsResponse().success().data(data);
    }
    /**
     * 价格---新增
     * @return
     */
    @GetMapping("coinPriceAdd/{price}")
    @ControllerEndpoint(operation = "价格---新增", exceptionMessage = "操作失败")
    public FebsResponse coinPriceAdd(@NotNull(message = "{required}") @PathVariable String price) {
        return iAdminBannerService.coinPriceAdd(price);
    }
    /**
     * 轮播图---列表
     */
    @GetMapping("platformBanner")
    public FebsResponse platformBanner(PlatformBanner platformBannerEntity, QueryRequest request) {
        Map<String, Object> data = getDataTable(iAdminBannerService.findPlatformBannerInPage(platformBannerEntity, request));
        return new FebsResponse().success().data(data);
    }
    /**
     * 轮播图---确认
     * @return
     */
    @PostMapping("platformBannerConfirm")
    @ControllerEndpoint(operation = "轮播图---确认", exceptionMessage = "设置失败")
    public FebsResponse platformBannerConfirm(@Valid PlatformBanner platformBannerEntity) {
        return iAdminBannerService.platformBannerConfirm(platformBannerEntity);
    }
    /**
     * 轮播图---删除
     * @return
     */
    @GetMapping("platformBannerDelete/{id}")
    @ControllerEndpoint(operation = "轮播图---删除", exceptionMessage = "删除失败")
    public FebsResponse platformBannerDelete(@NotNull(message = "{required}") @PathVariable Long id) {
        return iAdminBannerService.platformBannerDelete(id);
    }
    /**
     * 轮播图---新增
     */
    @PostMapping("platformBannerAdds")
    @ControllerEndpoint(operation = "轮播图---新增", exceptionMessage = "新增失败")
    public FebsResponse platformBannerAdds(@Valid PlatformBanner platformBannerEntity) {
        iAdminBannerService.platformBannerAdd(platformBannerEntity);
        return new FebsResponse().success();
    }
    @PostMapping(value = "/cashOutSetting")
    @ControllerEndpoint(operation = "轮播图---新增", exceptionMessage = "新增失败")
    public FebsResponse cashOutSetting(CoinSetVo coinSetVo) {
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_BUY_MIN_AMOUNT.getValue(),
                DataDicEnum.GFA_BUY_MIN_AMOUNT.getValue(),
                coinSetVo.getMinAmount()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_BUY_MAX_AMOUNT.getValue(),
                DataDicEnum.GFA_BUY_MAX_AMOUNT.getValue(),
                coinSetVo.getMaxAmount()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_ACHIEVE_RELEASE.getValue(),
                DataDicEnum.GFA_ACHIEVE_RELEASE.getValue(),
                coinSetVo.getAchieveRelease()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_ACHIEVE_OUT.getValue(),
                DataDicEnum.GFA_ACHIEVE_OUT.getValue(),
                coinSetVo.getAchieveOut()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_TUAN_DUI_PERCENT.getValue(),
                DataDicEnum.GFA_TUAN_DUI_PERCENT.getValue(),
                coinSetVo.getTdPercent()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_TUAN_DUI_LEVEL.getValue(),
                DataDicEnum.GFA_TUAN_DUI_LEVEL.getValue(),
                coinSetVo.getTdLevel()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_TUAN_DUI_LEVEL_YI.getValue(),
                DataDicEnum.GFA_TUAN_DUI_LEVEL_YI.getValue(),
                coinSetVo.getTdLevelYi()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_TUAN_DUI_LEVEL_ER.getValue(),
                DataDicEnum.GFA_TUAN_DUI_LEVEL_ER.getValue(),
                coinSetVo.getTdLevelEr()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_TUAN_DUI_LEVEL_SAN.getValue(),
                DataDicEnum.GFA_TUAN_DUI_LEVEL_SAN.getValue(),
                coinSetVo.getTdLevelSan()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_TUAN_DUI_LEVEL_SI.getValue(),
                DataDicEnum.GFA_TUAN_DUI_LEVEL_SI.getValue(),
                coinSetVo.getTdLevelSi()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_TUAN_DUI_LEVEL_WU.getValue(),
                DataDicEnum.GFA_TUAN_DUI_LEVEL_WU.getValue(),
                coinSetVo.getTdLevelWu()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_ZHUAN_ZHANG_KAI_GUAN.getValue(),
                DataDicEnum.GFA_ZHUAN_ZHANG_KAI_GUAN.getValue(),
                coinSetVo.getZzkg()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.SYSTEM_START_FLAG.getValue(),
                DataDicEnum.SYSTEM_START_FLAG.getValue(),
                coinSetVo.getSsf()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue(),
                DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue(),
                coinSetVo.getUsdtAmount()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_HUA_DIAN_WALLET_COIN_AMOUNT.getValue(),
                DataDicEnum.GFA_HUA_DIAN_WALLET_COIN_AMOUNT.getValue(),
                coinSetVo.getCoinAmount()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_HUA_DIAN_SELF.getValue(),
                DataDicEnum.GFA_HUA_DIAN_SELF.getValue(),
                coinSetVo.getHdSelf()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_HUA_DIAN_TEAM.getValue(),
                DataDicEnum.GFA_HUA_DIAN_TEAM.getValue(),
                coinSetVo.getHdTeam()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_HUA_DIAN_WORK.getValue(),
                DataDicEnum.GFA_HUA_DIAN_WORK.getValue(),
                coinSetVo.getHdWork()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_HUA_DIAN_LEVEL.getValue(),
                DataDicEnum.GFA_HUA_DIAN_LEVEL.getValue(),
                coinSetVo.getHdLevel()
        );
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_DAYS.getValue(),
                DataDicEnum.GFA_DAYS.getValue(),
                coinSetVo.getGfaDays()
        );
        return new FebsResponse().success();
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/AdminMallGoodsController.java
New file
@@ -0,0 +1,96 @@
package cc.mrbird.febs.dapp.controller;
import cc.mrbird.febs.common.annotation.ControllerEndpoint;
import cc.mrbird.febs.common.controller.BaseController;
import cc.mrbird.febs.common.entity.FebsResponse;
import cn.hutool.core.lang.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FileCopyUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/admin/goods")
public class AdminMallGoodsController extends BaseController {
    /**
     * 通用上传请求
     */
    @Value("${static.resource.url}")
    private String resourceUrl;
    @Value("${static.resource.path}")
    private String resourcePath;
    @PostMapping("/uploadFileBase64")
    @ControllerEndpoint(operation = "图片上传", exceptionMessage = "上传失败")
    public Map<String,Object> upload(MultipartFile file) throws IOException {
        if (file == null) {
            return new FebsResponse().message("上传文件为空");
        }
        // 文件保存目录路径
        String savePath = resourcePath;
        // 文件保存目录URL
        String saveUrl = resourceUrl;
        // 检查目录
        File uploadDir = new File(savePath);
        if (!uploadDir.isDirectory()) {
            uploadDir.mkdir();
        }
        // 获得文件的后缀
        String fileName = file.getOriginalFilename();
        String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1);
        String newFileName = UUID.randomUUID().toString() + "." + fileExt;
        if (isImage(file.getInputStream())) {
            Thumbnails.of(file.getInputStream())
                    // 图片大小(长宽)压缩比例 从0-1,1表示原图
                    .scale(1f)
                    // 图片质量压缩比例 从0-1,越接近1质量越好
                    .outputQuality(0.9f)
                    .toOutputStream(new FileOutputStream(savePath + newFileName));
        } else {
            File uploadedFile = new File(savePath, newFileName);
            try {
                //存文件
                FileCopyUtils.copy(file.getBytes(), uploadedFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        String visitPath = (saveUrl + newFileName);
        Map<String,Object> map = new HashMap<String,Object>();
        Map<String,Object> map2 = new HashMap<String,Object>();
        map.put("code",0);//0表示成功,1失败
        map.put("msg","上传成功");//提示消息
        map.put("data",map2);
        map2.put("src",visitPath);//图片url
        map2.put("title",fileName);//图片名称,这个会显示在输入框里
        return map;
    }
    private boolean isImage(InputStream inputStream) {
        BufferedImage read = null;
        try {
            read = ImageIO.read(inputStream);
        } catch (IOException e) {
            return false;
        }
        return read != null;
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/AdminNewsInfoController.java
New file
@@ -0,0 +1,119 @@
package cc.mrbird.febs.dapp.controller;
import cc.mrbird.febs.common.annotation.ControllerEndpoint;
import cc.mrbird.febs.common.controller.BaseController;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.dapp.dto.MallNewsInfoDto;
import cc.mrbird.febs.dapp.entity.MallNewsCategory;
import cc.mrbird.febs.dapp.entity.MallNewsInfo;
import cc.mrbird.febs.dapp.service.IMallNewsInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
/**
 * @author wzy
 * @date 2022-05-13
 **/
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/admin/news")
public class AdminNewsInfoController extends BaseController {
    private final IMallNewsInfoService mallNewsInfoService;
    /**
     * 新闻中心-列表
     * @param mallNewsInfo
     * @param request
     * @return
     */
    @GetMapping("getNewInfoList")
    public FebsResponse getNewInfoList(MallNewsInfo mallNewsInfo, QueryRequest request) {
        Map<String, Object> data = getDataTable(mallNewsInfoService.getNewInfoList(mallNewsInfo, request));
        return new FebsResponse().success().data(data);
    }
    /**
     * 新闻中心-新增
     */
    @PostMapping("addNewsInfo")
    @ControllerEndpoint(operation = " 新闻中心-新增", exceptionMessage = "操作失败")
    public FebsResponse addNewsInfo(@Valid MallNewsInfoDto mallNewsInfoDto) {
        return mallNewsInfoService.addNewsInfo(mallNewsInfoDto);
    }
    /**
     * 新闻中心-删除
     */
    @GetMapping("delNewsInfo/{id}")
    @ControllerEndpoint(operation = " 新闻中心-删除", exceptionMessage = "操作失败")
    public FebsResponse delNewsInfo(@NotNull(message = "{required}") @PathVariable Long id) {
        return mallNewsInfoService.delNewsInfo(id);
    }
    /**
     * 新闻中心-更新
     */
    @PostMapping("updateNewsInfo")
    @ControllerEndpoint(operation = "新闻中心-更新", exceptionMessage = "操作失败")
    public FebsResponse updateNewsInfo(@Valid MallNewsInfoDto mallNewsInfoDto) {
        return mallNewsInfoService.updateNewsInfo(mallNewsInfoDto);
    }
    @GetMapping("findNewsCategoryList")
    @ControllerEndpoint(operation = "新闻分类列表", exceptionMessage = "获取失败")
    public FebsResponse findNewsCategoryList(MallNewsCategory mallNewsCategory, QueryRequest request) {
        return new FebsResponse().success().data(getDataTable(mallNewsInfoService.findNewsCategoryInPage(mallNewsCategory, request)));
    }
    @PostMapping("addOrModifyNewsCategory")
    @ControllerEndpoint(operation = "新闻分类", exceptionMessage = "新增失败")
    public FebsResponse addOrModifyNewsCategory(MallNewsCategory mallNewsCategory) {
        mallNewsInfoService.addOrModifyNewsCategory(mallNewsCategory);
        return new FebsResponse().success().message("新增成功");
    }
    /**
     * 新闻分类-删除
     */
    @GetMapping("delNewsCategoryInfo/{id}")
    @ControllerEndpoint(operation = "新闻分类-删除", exceptionMessage = "操作失败")
    public FebsResponse delNewsCategoryInfo(@NotNull(message = "{required}") @PathVariable Long id) {
        return mallNewsInfoService.delNewsCategoryInfo(id);
    }
    @GetMapping(value = "findAllCategoryList")
    public FebsResponse findAllCategoryList() {
        List<MallNewsCategory> categories = mallNewsInfoService.findAllCategory();
        return new FebsResponse().success().data(categories);
    }
    @PostMapping(value = "/topNews/{id}")
    public FebsResponse topNews(@PathVariable Long id) {
        MallNewsInfo mallNewsInfo = new MallNewsInfo();
        mallNewsInfo.setIsTop(1);
        mallNewsInfo.setId(id);
        mallNewsInfoService.updateById(mallNewsInfo);
        return new FebsResponse().success();
    }
    @PostMapping(value = "/unTopNews/{id}")
    public FebsResponse unTopNews(@PathVariable Long id) {
        MallNewsInfo mallNewsInfo = new MallNewsInfo();
        mallNewsInfo.setIsTop(2);
        mallNewsInfo.setId(id);
        mallNewsInfoService.updateById(mallNewsInfo);
        return new FebsResponse().success();
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
@@ -2,13 +2,10 @@
import cc.mrbird.febs.common.annotation.EncryptEnable;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.dapp.dto.ApproveDto;
import cc.mrbird.febs.dapp.dto.ConnectDto;
import cc.mrbird.febs.dapp.dto.EncryptDto;
import cc.mrbird.febs.dapp.dto.SystemDto;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.dapp.service.DappSimulateDataService;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.dapp.dto.*;
import cc.mrbird.febs.dapp.entity.MallNewsInfo;
import cc.mrbird.febs.dapp.service.*;
import cc.mrbird.febs.dapp.vo.NewsListVo;
import cc.mrbird.febs.dapp.vo.SimulateDataVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -32,21 +29,15 @@
public class ApiCommonController {
    private final DappMemberService dappMemberService;
    private final DappSystemService dappSystemService;
    private final DappSimulateDataService dappSimulateDataService;
    private final IApiMallNewsService newsService;
    private final DappWalletService dappWalletService;
//    @ApiOperation(value = "授权接口", notes = "授权接口")
//    @PostMapping(value = "/approve")
//    public FebsResponse approve(@RequestBody ApproveDto approveDto) {
//        dappMemberService.approve(approveDto);
//        return new FebsResponse().success().message("授权成功");
//    }
//
//    @ApiOperation(value = "是否授权接口", notes = "是否授权接口")
//    @GetMapping(value = "/isApprove/{chain}/{address}")
//    public FebsResponse isApprove(@PathVariable("address") String address,@PathVariable("chain") String chain) {
//        return new FebsResponse().success().message("获取成功").data(dappMemberService.isApprove(address, chain));
//    }
    @ApiOperation(value = "是否注册 0-未注册", notes = "是否注册 0-未注册")
    @GetMapping(value = "/exist/{address}")
    public FebsResponse exist(@PathVariable("address") String  address) {
        return dappMemberService.exist(address);
    }
    @ApiOperation(value = "链接接口", notes = "链接接口")
    @PostMapping(value = "/connect")
@@ -55,10 +46,10 @@
        return new FebsResponse().success();
    }
    @ApiOperation(value = "头部数据", notes = "头部数据")
    @GetMapping(value = "/totalIncome")
    public FebsResponse totalIncome() {
        return new FebsResponse().success().data(dappSystemService.findTotalInComeAndList());
    @ApiOperation(value = "价格", notes = "价格")
    @GetMapping(value = "/calPrice")
    public FebsResponse calPrice() {
        return new FebsResponse().success().data(dappWalletService.calPrice());
    }
    @PostMapping(value = "/encrypt")
@@ -66,4 +57,44 @@
        System.out.println(encryptDto.getTest());
        return new FebsResponse().success().data("123");
    }
    @ApiOperation(value = "新闻分类", notes = "新闻分类")
    @GetMapping(value = "/findNewsInfoCategory")
    public FebsResponse findNewsInfoCategory() {
        return new FebsResponse().success().data(newsService.findNewsCategoryList());
    }
    @ApiOperation(value ="获取新闻列表-分页", notes = "获取新闻列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = NewsListVo.class)
    })
    @PostMapping(value = "/findNewsInPage")
    public FebsResponse findNewsInPage(@RequestBody NewsListDto newsListDto) {
        return new FebsResponse().success().data(newsService.findNewsInPage(newsListDto));
    }
    @ApiOperation(value = "新闻列表", notes = "新闻列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = NewsListVo.class)
    })
    @GetMapping(value = "/findNews")
    public FebsResponse findNews() {
        return new FebsResponse().success().data(newsService.findTopNews());
    }
    @ApiOperation(value = "新闻详情", notes = "新闻详情")
    @GetMapping(value = "/newsDetails/{id}")
    public FebsResponse newsDetails(@PathVariable("id") Long id) {
        MallNewsInfo news = newsService.getById(id);
        if (news == null) {
            return new FebsResponse().fail().message("新闻不存在");
        }
        return new FebsResponse().success().data(news);
    }
    @ApiOperation(value = "首页轮播图", notes = "首页轮播图")
    @GetMapping(value = "/bannerList")
    public FebsResponse findPlatformBannerList() {
        return newsService.findAllBanner();
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/ApiDappMemberController.java
@@ -1,5 +1,6 @@
package cc.mrbird.febs.dapp.controller;
import cc.mrbird.febs.common.annotation.EncryptEnable;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.utils.LoginUserUtil;
@@ -9,6 +10,7 @@
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.dapp.service.DappWalletService;
import cc.mrbird.febs.dapp.vo.MoneyFlowVo;
import cc.mrbird.febs.dapp.vo.TeamListVo;
import cc.mrbird.febs.dapp.vo.WalletInfoVo;
import io.swagger.annotations.Api;
@@ -19,11 +21,14 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
 * @author 
 * @date 2022-03-17
 **/
@Slf4j
@EncryptEnable
@RequiredArgsConstructor
@CrossOrigin("*")
@RestController
@@ -32,7 +37,6 @@
public class ApiDappMemberController {
    private final DappWalletService dappWalletService;
    private final DappSystemService dappSystemService;
    private final DappMemberService dappMemberService;
    private final RedisUtils redisUtils;
@@ -46,40 +50,46 @@
        return new FebsResponse().success().data(walletInfoVo);
    }
    @ApiOperation(value = "转账", notes = "转账")
    @ApiOperation(value = "提现", notes = "提现")
    @PostMapping(value = "/transferOut")
    public FebsResponse transferOut(@RequestBody @Valid TransferOutDto transferOutDto) {
        return dappWalletService.transferOut(transferOutDto);
    }
    @ApiOperation(value = "质押", notes = "质押")
    @PostMapping(value = "/transfer")
    public FebsResponse transfer(@RequestBody TransferDto transferDto) {
    public FebsResponse transfer(@RequestBody @Valid TransferDto transferDto) {
        return new FebsResponse().success().data(dappWalletService.transfer(transferDto));
    }
    @ApiOperation(value = "记录列表", notes = "记录列表")
    @ApiOperation(value = "我的质押", notes = "我的质押")
    @PostMapping(value = "/zyInPage")
    public FebsResponse zyInPage(@RequestBody RecordInPageDto recordInPageDto) {
        return new FebsResponse().success().data(dappWalletService.zyInPage(recordInPageDto));
    }
    @ApiOperation(value = "资金流水列表", notes = "资金流水列表")
    @PostMapping(value = "/recordInPage")
    public FebsResponse recordInPage(@RequestBody RecordInPageDto recordInPageDto) {
        return new FebsResponse().success().data(dappWalletService.recordInPage(recordInPageDto));
    }
    @ApiOperation(value = "计算最新价", notes = "计算最新价")
    @PostMapping(value = "/calPrice")
    public FebsResponse calPrice(@RequestBody PriceDto priceDto) {
        return new FebsResponse().success().data(dappWalletService.calPrice(priceDto));
    }
    @ApiOperation(value = "系统参数", notes = "系统参数")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = SystemDto.class)
    })
    @GetMapping(value = "/system")
    public FebsResponse system() {
        return new FebsResponse().success().data(dappSystemService.system());
    }
    @ApiOperation(value = "我的团队", notes = "我的团队")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = TeamListVo.class)
    })
    @PostMapping(value = "/team")
    public FebsResponse team(@RequestBody TeamListDto teamListDto) {
        return new FebsResponse().success().data(dappMemberService.findTeamList(teamListDto));
    @GetMapping(value = "/team")
    public FebsResponse team() {
        return new FebsResponse().success().data(dappMemberService.findTeamList());
    }
    @ApiOperation(value = "我的团队-奖励列表", notes = "我的团队-奖励列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = MoneyFlowVo.class)
    })
    @PostMapping(value = "/teamList")
    public FebsResponse teamList(@RequestBody TeamListDto teamListDto) {
        return new FebsResponse().success().data(dappMemberService.findMoneyFlowVos(teamListDto));
    }
    @PostMapping(value = "/logout")
src/main/java/cc/mrbird/febs/dapp/controller/MemberMoneyFlowController.java
@@ -5,16 +5,17 @@
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.dapp.entity.DappAccountMoneyChangeEntity;
import cc.mrbird.febs.dapp.entity.DappAchieve;
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.service.DappWalletService;
import cc.mrbird.febs.system.entity.User;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
 * @author 
@@ -29,6 +30,21 @@
    private final DappWalletService dappWalletService;
    @GetMapping("/dappAchieveItem")
    public FebsResponse dappAchieveItem(QueryRequest request, DappAchieve dappAchieve, Integer parentId) {
        if (parentId == null) {
            ViewBannerController.zhiyaID = 0;
        }
        dappAchieve.setId(ViewBannerController.zhiyaID);
        Map<String, Object> dataTable = getDataTable(dappWalletService.dappAchieveItemInPage(dappAchieve, request));
        return new FebsResponse().success().data(dataTable);
    }
    @RequestMapping(value = "/dappAchieve")
    public FebsResponse dappAchieve(DappAchieve dappAchieve, QueryRequest request) {
        return new FebsResponse().success().data(getDataTable(dappWalletService.dappAchieveInPage(dappAchieve, request)));
    }
    @RequestMapping(value = "/fundFlow")
    public FebsResponse fundFlow(DappFundFlowEntity dappFundFlowEntity, QueryRequest request) {
        User currentUser = FebsUtil.getCurrentUser();
src/main/java/cc/mrbird/febs/dapp/controller/ViewBannerController.java
New file
@@ -0,0 +1,206 @@
package cc.mrbird.febs.dapp.controller;
import cc.mrbird.febs.common.controller.BaseController;
import cc.mrbird.febs.common.entity.FebsConstant;
import cc.mrbird.febs.common.enumerates.DataDicEnum;
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.dapp.entity.DataDictionaryCustom;
import cc.mrbird.febs.dapp.entity.PlatformBanner;
import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.dapp.service.AsyncCjService;
import cc.mrbird.febs.dapp.service.IAdminBannerService;
import cc.mrbird.febs.dapp.vo.CoinSetVo;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller("bannerView")
@RequestMapping(FebsConstant.VIEW_PREFIX + "modules/banner")
@RequiredArgsConstructor
public class ViewBannerController extends BaseController {
    private final IAdminBannerService iAdminBannerService;
    private final AsyncCjService asyncCjService;
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    public static long zhiyaID;
    @GetMapping("zhiYaItem/{id}")
    @RequiresPermissions("zhiYaItem:update")
    public String zhiYaItem(@PathVariable long id, Model model) {
        zhiyaID = id;
        return FebsUtil.view("modules/banner/zhiYaItem");
    }
    @GetMapping("coinSet")
    @RequiresPermissions("coinSet:view")
    public String cashOutSetting(Model model) {
        CoinSetVo coinSetVo = new CoinSetVo();
        coinSetVo.setMinAmount(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_BUY_MIN_AMOUNT.getValue(),
                        DataDicEnum.GFA_BUY_MIN_AMOUNT.getValue()
                ).getValue()
        );
        coinSetVo.setMaxAmount(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_BUY_MAX_AMOUNT.getValue(),
                        DataDicEnum.GFA_BUY_MAX_AMOUNT.getValue()
                ).getValue()
        );
        coinSetVo.setAchieveRelease(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_ACHIEVE_RELEASE.getValue(),
                        DataDicEnum.GFA_ACHIEVE_RELEASE.getValue()
                ).getValue()
        );
        coinSetVo.setAchieveOut(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_ACHIEVE_OUT.getValue(),
                        DataDicEnum.GFA_ACHIEVE_OUT.getValue()
                ).getValue()
        );
        coinSetVo.setTdPercent(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_TUAN_DUI_PERCENT.getValue(),
                        DataDicEnum.GFA_TUAN_DUI_PERCENT.getValue()
                ).getValue()
        );
        coinSetVo.setTdLevel(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_TUAN_DUI_LEVEL.getValue(),
                        DataDicEnum.GFA_TUAN_DUI_LEVEL.getValue()
                ).getValue()
        );
        coinSetVo.setTdLevelYi(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_YI.getValue(),
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_YI.getValue()
                ).getValue()
        );
        coinSetVo.setTdLevelEr(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_ER.getValue(),
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_ER.getValue()
                ).getValue()
        );
        coinSetVo.setTdLevelSan(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_SAN.getValue(),
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_SAN.getValue()
                ).getValue()
        );
        coinSetVo.setTdLevelSi(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_SI.getValue(),
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_SI.getValue()
                ).getValue()
        );
        coinSetVo.setTdLevelWu(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_WU.getValue(),
                        DataDicEnum.GFA_TUAN_DUI_LEVEL_WU.getValue()
                ).getValue()
        );
        coinSetVo.setZzkg(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_ZHUAN_ZHANG_KAI_GUAN.getValue(),
                        DataDicEnum.GFA_ZHUAN_ZHANG_KAI_GUAN.getValue()
                ).getValue()
        );
        coinSetVo.setSsf(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.SYSTEM_START_FLAG.getValue(),
                        DataDicEnum.SYSTEM_START_FLAG.getValue()
                ).getValue()
        );
        coinSetVo.setUsdtAmount(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue(),
                        DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue()
                ).getValue()
        );
        coinSetVo.setCoinAmount(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_HUA_DIAN_WALLET_COIN_AMOUNT.getValue(),
                        DataDicEnum.GFA_HUA_DIAN_WALLET_COIN_AMOUNT.getValue()
                ).getValue()
        );
        coinSetVo.setHdSelf(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_HUA_DIAN_SELF.getValue(),
                        DataDicEnum.GFA_HUA_DIAN_SELF.getValue()
                ).getValue()
        );
        coinSetVo.setHdTeam(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_HUA_DIAN_TEAM.getValue(),
                        DataDicEnum.GFA_HUA_DIAN_TEAM.getValue()
                ).getValue()
        );
        coinSetVo.setHdWork(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_HUA_DIAN_WORK.getValue(),
                        DataDicEnum.GFA_HUA_DIAN_WORK.getValue()
                ).getValue()
        );
        coinSetVo.setHdLevel(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_HUA_DIAN_LEVEL.getValue(),
                        DataDicEnum.GFA_HUA_DIAN_LEVEL.getValue()
                ).getValue()
        );
        coinSetVo.setGfaDays(
                dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                        DataDicEnum.GFA_DAYS.getValue(),
                        DataDicEnum.GFA_DAYS.getValue()
                ).getValue()
        );
        model.addAttribute("coinSetVo", coinSetVo);
        asyncCjService.updateDataDicEnumRedis(DataDicEnum.GFA_ACHIEVE_OUT.getNameList());
        return FebsUtil.view("modules/banner/coinSet");
    }
    /**
     * 价格---列表
     */
    @GetMapping("coinPrice")
    @RequiresPermissions("coinPrice:view")
    public String coinPrice() {
        return FebsUtil.view("modules/banner/coinPrice");
    }
    /**
     * 轮播图---列表
     */
    @GetMapping("platformBanner")
    @RequiresPermissions("platformBanner:view")
    public String platformBanner() {
        return FebsUtil.view("modules/banner/platformBanner");
    }
    /**
     * 轮播图---修改
     */
    @GetMapping("platformBannerUpdate/{id}")
    @RequiresPermissions("platformBannerUpdate:update")
    public String platformBannerUpdate(@PathVariable long id, Model model) {
        PlatformBanner data = iAdminBannerService.selectPlatformBannerById(id);
        model.addAttribute("member", data);
        return FebsUtil.view("modules/banner/platformBannerDetail");
    }
    /**
     * 轮播图---新增
     */
    @GetMapping("platformBannerAdd")
    @RequiresPermissions("platformBannerAdd:add")
    public String platformBannerAdd() {
        return FebsUtil.view("modules/banner/platformBannerAdd");
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/ViewController.java
@@ -26,6 +26,18 @@
    private final RedisUtils redisUtils;
    @GetMapping("achieveList")
    @RequiresPermissions("achieveList:view")
    public String achieveList() {
        return FebsUtil.view("dapp/member-zhi-ya");
    }
    @GetMapping("memberMoneyFlow")
    @RequiresPermissions("memberMoneyFlow:view")
    public String memberMoneyFlow() {
        return FebsUtil.view("dapp/member-money-flow");
    }
    @GetMapping(value = "admin")
    @RequiresPermissions("admin:view")
    public String user() {
@@ -70,6 +82,12 @@
        return FebsUtil.view("dapp/member-withdraw");
    }
    @GetMapping("memberWithdrawDb")
    @RequiresPermissions("memberWithdrawDb:view")
    public String memberWithdrawDb() {
        return FebsUtil.view("dapp/member-withdraw-daibi");
    }
    @GetMapping("walletCoin")
    @RequiresPermissions("walletCoin:view")
    public String walletCoin() {
src/main/java/cc/mrbird/febs/dapp/controller/ViewNewsController.java
New file
@@ -0,0 +1,86 @@
package cc.mrbird.febs.dapp.controller;
import cc.mrbird.febs.common.entity.FebsConstant;
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.dapp.entity.MallNewsCategory;
import cc.mrbird.febs.dapp.entity.MallNewsInfo;
import cc.mrbird.febs.dapp.service.IMallNewsInfoService;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
 * @author wzy
 * @date 2022-05-13
 **/
@Controller("newView")
@RequestMapping(FebsConstant.VIEW_PREFIX + "modules/news")
@RequiredArgsConstructor
public class ViewNewsController {
    private final IMallNewsInfoService mallNewsInfoService;
    /**
     * 新闻中心-列表
     * @return
     */
    @GetMapping("newsInfoList")
    @RequiresPermissions("newsInfoList:view")
    public String newsInfoList() {
        return FebsUtil.view("modules/news/newsInfoList");
    }
    /**
     * 新闻中心-新增
     * @return
     */
    @GetMapping("newsInfoAdd")
    @RequiresPermissions("newsInfoAdd:add")
    public String newsInfoAdd() {
        return FebsUtil.view("modules/news/newsInfoAdd");
    }
    /**
     * 新闻中心-详情
     * @param id
     * @param model
     * @return
     */
    @GetMapping("newsInfoUpdate/{id}")
    @RequiresPermissions("newsInfoUpdate:update")
    public String newsInfoUpdate(@PathVariable long id, Model model) {
        MallNewsInfo data = mallNewsInfoService.getNewsInfoById(id);
        model.addAttribute("newsInfo", data);
        return FebsUtil.view("modules/news/newsInfoUpdate");
    }
    @GetMapping("newsCategory")
    @RequiresPermissions("news:category:view")
    public String newsCategory() {
        return FebsUtil.view("modules/news/newsCategory");
    }
    @GetMapping("addCategory")
    @RequiresPermissions("news:category:add")
    public String addCategory(Long id, Model model) {
        if (id != null) {
            MallNewsCategory obj = mallNewsInfoService.findNewsCategoryById(id);
            model.addAttribute("obj", obj);
        }
        return FebsUtil.view("modules/news/newsCategoryAdd");
    }
    @GetMapping("updateCategory/{id}")
    @RequiresPermissions("news:category:update")
    public String updateCategory(@PathVariable Long id, Model model) {
        if (id != null) {
            MallNewsCategory obj = mallNewsInfoService.findNewsCategoryById(id);
            model.addAttribute("obj", obj);
        }
        return FebsUtil.view("modules/news/newsCategoryAdd");
    }
}
src/main/java/cc/mrbird/febs/dapp/dto/ConnectDto.java
@@ -21,6 +21,6 @@
    @ApiModelProperty(value = "签名", example = "123")
    private String sign;
//    @ApiModelProperty(value = "邀请码", example = "12345678")
//    private String inviteId;
    @ApiModelProperty(value = "邀请码", example = "12345678")
    private String inviteId;
}
src/main/java/cc/mrbird/febs/dapp/dto/MallNewsInfoDto.java
New file
@@ -0,0 +1,28 @@
package cc.mrbird.febs.dapp.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel(value = "MallNewsInfoDto", description = "参数接收类")
public class MallNewsInfoDto {
    private Long id;
    private String title;
    private String content;
    private Long goodsId;
    /**
     * 1-文章2-跳转到产品
     */
    private Integer type;
    private String videoUrl;
    private String thumb;
    private String categoryId;
}
src/main/java/cc/mrbird/febs/dapp/dto/NewsListDto.java
New file
@@ -0,0 +1,23 @@
package cc.mrbird.febs.dapp.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author wzy
 * @date 2022-05-16
 **/
@Data
@ApiModel(value = "NewsListDto", description = "新闻列表接口接收参数类")
public class NewsListDto {
    @ApiModelProperty("每页数量")
    private int pageSize = 10;
    @ApiModelProperty("页码")
    private int pageNum = 1;
    @ApiModelProperty("分类ID")
    private Long categoryId;
}
src/main/java/cc/mrbird/febs/dapp/dto/RecordInPageDto.java
@@ -18,6 +18,6 @@
    @ApiModelProperty(value = "每页数量")
    private Integer pageSize = 10;
    @ApiModelProperty(value = "类型", example = "1-买入 2-卖出 3-采矿")
    @ApiModelProperty(value = "类型", example = "状态:1-进行中 2:已结束")
    private Integer type;
}
src/main/java/cc/mrbird/febs/dapp/dto/TeamListDto.java
@@ -20,4 +20,7 @@
    @ApiModelProperty(hidden = true)
    private String inviteId;
    @ApiModelProperty(hidden = true)
    private Long memberId;
}
src/main/java/cc/mrbird/febs/dapp/dto/TransferDto.java
@@ -4,6 +4,9 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
@@ -14,17 +17,18 @@
@ApiModel(value = "TransferDto", description = "转账接口参数类")
public class TransferDto {
    @ApiModelProperty(value = "1-买入 2-卖出", example = "1")
    @NotNull(message = "类型不能为空")
    @ApiModelProperty(value = "1-质押", example = "1")
    private Integer type;
    @ApiModelProperty(value = "交易hash", example = "123")
    private String txHash;
    @ApiModelProperty(value = "金额", example = "1")
    @Valid
    @NotNull(message = "数量不能为空")
    @Min(0)
    @ApiModelProperty(value = "数量", example = "1")
    private BigDecimal amount;
    @ApiModelProperty(value = "手续费", example = "1")
    private BigDecimal fee;
    @ApiModelProperty(value = "价格", example = "1.0")
    private BigDecimal price;
src/main/java/cc/mrbird/febs/dapp/dto/TransferOutDto.java
New file
@@ -0,0 +1,19 @@
package cc.mrbird.febs.dapp.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
@ApiModel(value = "TransferOutDto", description = "转账接口参数类")
public class TransferOutDto {
    @ApiModelProperty(value = "类型", example = "1 -代币提现 2-USDT提现")
    private Integer type;
    @ApiModelProperty(value = "金额", example = "100")
    private BigDecimal amount;
}
src/main/java/cc/mrbird/febs/dapp/entity/DappAchieve.java
New file
@@ -0,0 +1,37 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@Data
@TableName("dapp_achieve")
public class DappAchieve extends BaseEntity {
    public DappAchieve() {}
    public DappAchieve(Long id, BigDecimal amount) {
        this.amount = amount;
    }
    private Long memberId;
    private BigDecimal amount;//投入GFA数量
    private BigDecimal amountDone;//累计产出
    private BigDecimal amountMax;//出局数量
    private BigDecimal amountDay;//每日收益
    private Integer state;//状态:1-进行中 2:已结束
    public static final int STATUS_ING = 1;
    public static final int STATUS_DONE = 2;
    @TableField(exist = false)
    private String address;
}
src/main/java/cc/mrbird/febs/dapp/entity/DappAchieveItem.java
New file
@@ -0,0 +1,33 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@Data
@TableName("dapp_achieve_item")
public class DappAchieveItem extends BaseEntity {
    public static final int TYPE_ZHI_YA = 1;
    public static final int TYPE_TUI_JIAN = 2;
    public static final int TYPE_HUA_DIAN = 3;
    private Integer type;//类型 1-质押 2-团队奖励(推荐奖) 3-滑点奖励
    public static final int STATUS_ING = 1;
    public static final int STATUS_AGREE = 2;
    private Integer state;//状态 1-进行中 2-已完成
    private Long achieveId;
    private Long memberId;
    private BigDecimal amount;//数量
    @TableField(exist = false)
    private String address;
}
src/main/java/cc/mrbird/febs/dapp/entity/DappCoinPrice.java
New file
@@ -0,0 +1,14 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@Data
@TableName("dapp_coin_price")
public class DappCoinPrice extends BaseEntity {
    private BigDecimal price;
}
src/main/java/cc/mrbird/febs/dapp/entity/DappFundFlowEntity.java
@@ -42,6 +42,24 @@
        this.fromHash = fromHash;
    }
    public DappFundFlowEntity(Long memberId, BigDecimal amount, Integer type, Integer status, String content) {
        this.memberId = memberId;
        this.amount = amount;
        this.type = type;
        this.status = status;
        this.content = content;
    }
    public DappFundFlowEntity(Long memberId, BigDecimal amount, Integer type, Integer status, String content,String fromHash,String toHash) {
        this.memberId = memberId;
        this.amount = amount;
        this.type = type;
        this.status = status;
        this.content = content;
        this.fromHash = fromHash;
        this.toHash = toHash;
    }
    private Long memberId;
    private BigDecimal amount;
@@ -68,4 +86,6 @@
    private BigDecimal newestPrice;
    private BigDecimal targetAmount;
    private String content;
}
src/main/java/cc/mrbird/febs/dapp/entity/DappHdRecord.java
New file
@@ -0,0 +1,18 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@Data
@TableName("dapp_hd_record")
public class DappHdRecord extends BaseEntity {
    private BigDecimal price;
    private BigDecimal usdtEvery;//每日新增
    private BigDecimal usdtAmount;//总数
    private BigDecimal coinEvery;
    private BigDecimal coinAmount;
}
src/main/java/cc/mrbird/febs/dapp/entity/MallNewsCategory.java
New file
@@ -0,0 +1,16 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
 * @author wzy
 * @date 2022-05-13
 **/
@Data
@TableName("mall_news_category")
public class MallNewsCategory extends BaseEntity {
    private String title;
}
src/main/java/cc/mrbird/febs/dapp/entity/MallNewsInfo.java
New file
@@ -0,0 +1,33 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
 * @author wzy
 * @date 2021-09-28
 **/
@Data
@TableName("mall_news_info")
public class MallNewsInfo extends BaseEntity {
    private String title;
    private String content;
    private Long targetId;
    /**
     * 1-文章2-跳转到产品
     */
    private Integer type;
    private String videoUrl;
    private String thumb;
    private Long categoryId;
    private Integer isTop;
}
src/main/java/cc/mrbird/febs/dapp/entity/PlatformBanner.java
New file
@@ -0,0 +1,48 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("platform_banner")
public class PlatformBanner extends BaseEntity {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    /**
     * 标题
     */
    private String name;
    /**
     * 图片链接
     */
    private String imageUrl;
    /**
     * 是否可跳转 1-是2-否
     */
    private String isJump;
    /**
     * 跳转外部或内部 1-内2-外
     */
    private int isInside;
    /**
     * 跳转链接
     */
    private String jumpUrl;
    /**
     * 显示端口 1-pc2-手机
     */
    private int showPort;
    /**
     * 联系方式
     */
    private String sort;
    /**
     * 是否置顶 1-是2-否
     */
    private String isTop;
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappAchieveItemMapper.java
New file
@@ -0,0 +1,7 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.DappAchieveItem;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface DappAchieveItemMapper extends BaseMapper<DappAchieveItem> {
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappAchieveMapper.java
New file
@@ -0,0 +1,15 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.DappAchieve;
import cc.mrbird.febs.dapp.entity.DappAchieveItem;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
public interface DappAchieveMapper  extends BaseMapper<DappAchieve> {
    IPage<DappAchieve> selectInPage(Page<DappAchieve> page,  @Param("record")DappAchieve dappAchieve);
    IPage<DappAchieveItem> dappAchieveItemInPage(Page<DappAchieveItem> page, @Param("record")DappAchieve dappAchieve);
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappCoinPriceMapper.java
New file
@@ -0,0 +1,7 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.DappCoinPrice;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface DappCoinPriceMapper extends BaseMapper<DappCoinPrice> {
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappFundFlowDao.java
@@ -1,6 +1,9 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.dto.TeamListDto;
import cc.mrbird.febs.dapp.entity.DappAchieve;
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.vo.MoneyFlowVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -15,6 +18,8 @@
    IPage<DappFundFlowEntity> selectInPage(Page<DappFundFlowEntity> page, @Param("record") DappFundFlowEntity dappFundFlowEntity);
    IPage<DappAchieve> selectZyInPage(Page<DappAchieve> page, @Param("record")DappAchieve dappAchieve);
    List<DappFundFlowEntity> selectListForMemberAndDay(@Param("memberId") Long memberId, @Param("type") int type);
    DappFundFlowEntity selectByFromHash(@Param("txHash") String txHash, @Param("status") Integer status);
@@ -22,4 +27,8 @@
    List<DappFundFlowEntity> selectFundFlowListByAddress(@Param("address") String address, @Param("status") Integer status);
    Map<String, BigDecimal> selectAmountTotalByType(@Param("memberId") Long memberId);
    BigDecimal selectAmountTotalByTypeAndMemberIdAndDate(@Param("memberId") Long memberId,@Param("type") int type, @Param("date") Date date);
    IPage<MoneyFlowVo> findMoneyFlowVos(Page<MoneyFlowVo> page, @Param("record")TeamListDto teamListDto);
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappHdRecordMapper.java
New file
@@ -0,0 +1,20 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.DappCoinPrice;
import cc.mrbird.febs.dapp.entity.DappHdRecord;
import cc.mrbird.febs.dapp.entity.PlatformBanner;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
public interface DappHdRecordMapper extends BaseMapper<DappHdRecord> {
    IPage<PlatformBanner> findPlatformBannerInPage(Page<PlatformBanner> page,
                                                   @Param("record")PlatformBanner platformBannerEntity);
    IPage<DappCoinPrice> findCoinPriceInPage(Page<DappCoinPrice> page, @Param("record")DappCoinPrice dappCoinPrice);
    DappHdRecord selectNewRecord();
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappMemberDao.java
@@ -35,9 +35,17 @@
    List<DappMemberEntity> selectChildMemberDirectOrNot(@Param("inviteId") String inviteId, @Param("type") Integer type);
    List<DappMemberEntity> selectChildMemberDirectOrNotInlist(@Param("list") List<String> inviteIds);
    BigDecimal selectChildHoldAmount(@Param("inviteId") String inviteId);
    IPage<TeamListVo> selectTeamListInPage(@Param("record") TeamListDto teamListDto, Page<TeamListDto> page);
    List<DappMemberEntity> selectMakerAddress();
    void updateBalanceWithVersion(@Param("record")DappMemberEntity dappMemberEntity);
    void updateUsdtBalanceWithVersion(@Param("record")DappMemberEntity dappMemberEntity);
    void updateBalanceAndUsdtBalanceWithVersion(@Param("record")DappMemberEntity dappMemberEntity);
}
src/main/java/cc/mrbird/febs/dapp/mapper/MallNewsCategoryMapper.java
New file
@@ -0,0 +1,12 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.MallNewsCategory;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
public interface MallNewsCategoryMapper extends BaseMapper<MallNewsCategory> {
    IPage<MallNewsCategory> selectInPage(@Param("record") MallNewsCategory mallNewsCategory, Page<MallNewsCategory> page);
}
src/main/java/cc/mrbird/febs/dapp/mapper/MallNewsInfoMapper.java
New file
@@ -0,0 +1,17 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.MallNewsInfo;
import cc.mrbird.febs.dapp.vo.AdminMallNewsInfoVo;
import cc.mrbird.febs.dapp.vo.NewsListVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
public interface MallNewsInfoMapper extends BaseMapper<MallNewsInfo> {
    IPage<AdminMallNewsInfoVo> getNewInfoListInPage(Page<AdminMallNewsInfoVo> page, MallNewsInfo mallNewsInfo);
    IPage<NewsListVo> selectNewsVoInPage(Page<NewsListVo> page, @Param("record") MallNewsInfo mallNewsInfo);
}
src/main/java/cc/mrbird/febs/dapp/mapper/PlatformBannerMapper.java
New file
@@ -0,0 +1,14 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.PlatformBanner;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
public interface PlatformBannerMapper extends BaseMapper<PlatformBanner> {
    IPage<PlatformBanner> findPlatformBannerInPage(Page<PlatformBanner> page,
                                                   @Param("record")PlatformBanner platformBannerEntity);
}
src/main/java/cc/mrbird/febs/dapp/service/AsyncCjService.java
New file
@@ -0,0 +1,26 @@
package cc.mrbird.febs.dapp.service;
import cc.mrbird.febs.common.entity.FebsConstant;
import cc.mrbird.febs.dapp.entity.DappAchieve;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.scheduling.annotation.Async;
import java.math.BigDecimal;
import java.util.List;
public interface AsyncCjService extends IService<DappAchieve> {
    /**
     * 缓存redis数据
     */
    @Async(FebsConstant.ASYNC_POOL)
    void redisCacheUpdate(String key, Object value, long time);
    @Async(FebsConstant.ASYNC_POOL)
    void updateDataDicEnumRedis(List<String> nameList);
    @Async(FebsConstant.ASYNC_POOL)
    void updateAmount(Integer type, Long memberId, BigDecimal amount);
    @Async(FebsConstant.ASYNC_POOL)
    void insertTeamPerk(Long flowId, Long achieveId);
}
src/main/java/cc/mrbird/febs/dapp/service/DappMemberService.java
@@ -1,5 +1,6 @@
package cc.mrbird.febs.dapp.service;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.dapp.dto.ApproveDto;
import cc.mrbird.febs.dapp.dto.ConnectDto;
@@ -7,6 +8,7 @@
import cc.mrbird.febs.dapp.dto.TeamListDto;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappTransferRecordEntity;
import cc.mrbird.febs.dapp.vo.MoneyFlowVo;
import cc.mrbird.febs.dapp.vo.TeamListVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
@@ -42,5 +44,9 @@
    DappMemberEntity insertMember(String address, String refererId, String chainType, String accountType);
    List<TeamListVo> findTeamList(TeamListDto teamListDto);
    TeamListVo findTeamList();
    IPage<MoneyFlowVo> findMoneyFlowVos(TeamListDto teamListDto);
    FebsResponse exist(String address);
}
src/main/java/cc/mrbird/febs/dapp/service/DappSystemService.java
@@ -35,4 +35,8 @@
    void userBuyReward(Long id);
    void startSystem();
    void getZhiYaDelayMsg(Long achieveId);
    void getZhiYaDelayMsgFlow(Long flowId);
}
src/main/java/cc/mrbird/febs/dapp/service/DappWalletService.java
@@ -1,14 +1,9 @@
package cc.mrbird.febs.dapp.service;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.dapp.dto.PriceDto;
import cc.mrbird.febs.dapp.dto.RecordInPageDto;
import cc.mrbird.febs.dapp.dto.TransferDto;
import cc.mrbird.febs.dapp.dto.WalletOperateDto;
import cc.mrbird.febs.dapp.entity.DappAccountMoneyChangeEntity;
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.entity.DappWalletCoinEntity;
import cc.mrbird.febs.dapp.entity.DappWalletMineEntity;
import cc.mrbird.febs.dapp.dto.*;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.vo.WalletInfoVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -26,6 +21,8 @@
    List<DappFundFlowEntity> recordInPage(RecordInPageDto recordInPageDto);
    List<DappAchieve> zyInPage(RecordInPageDto recordInPageDto);
    IPage<DappFundFlowEntity> fundFlowInPage(DappFundFlowEntity dappFundFlowEntity, QueryRequest request);
    void withdrawAgreeOrNot(Long id, int type);
@@ -38,5 +35,11 @@
    Long transfer(TransferDto transferDto);
    Map<String, BigDecimal> calPrice(PriceDto priceDto);
    String calPrice();
    IPage<DappAchieve> dappAchieveInPage(DappAchieve dappAchieve, QueryRequest request);
    IPage<DappAchieveItem> dappAchieveItemInPage(DappAchieve dappAchieve, QueryRequest request);
    FebsResponse transferOut(TransferOutDto transferOutDto);
}
src/main/java/cc/mrbird/febs/dapp/service/IAdminBannerService.java
New file
@@ -0,0 +1,28 @@
package cc.mrbird.febs.dapp.service;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.dapp.entity.DappCoinPrice;
import cc.mrbird.febs.dapp.entity.PlatformBanner;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
public interface IAdminBannerService extends IService<PlatformBanner> {
    IPage<PlatformBanner> findPlatformBannerInPage(PlatformBanner platformBannerEntity, QueryRequest request);
    PlatformBanner selectPlatformBannerById(long id);
    FebsResponse platformBannerConfirm(@Valid PlatformBanner platformBannerEntity);
    FebsResponse platformBannerDelete(@NotNull(message = "{required}") Long id);
    void platformBannerAdd(@Valid PlatformBanner platformBannerEntity);
    IPage<DappCoinPrice> findCoinPriceInPage(DappCoinPrice dappCoinPrice, QueryRequest request);
    FebsResponse coinPriceAdd(String price);
}
src/main/java/cc/mrbird/febs/dapp/service/IApiMallNewsService.java
New file
@@ -0,0 +1,22 @@
package cc.mrbird.febs.dapp.service;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.dapp.dto.NewsListDto;
import cc.mrbird.febs.dapp.entity.MallNewsCategory;
import cc.mrbird.febs.dapp.entity.MallNewsInfo;
import cc.mrbird.febs.dapp.vo.NewsListVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
public interface IApiMallNewsService extends IService<MallNewsInfo> {
    List<MallNewsCategory> findNewsCategoryList();
    IPage<NewsListVo> findNewsInPage(NewsListDto newsListDto);
    List<NewsListVo> findTopNews();
    FebsResponse findAllBanner();
}
src/main/java/cc/mrbird/febs/dapp/service/IMallNewsInfoService.java
New file
@@ -0,0 +1,35 @@
package cc.mrbird.febs.dapp.service;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.dapp.dto.MallNewsInfoDto;
import cc.mrbird.febs.dapp.entity.MallNewsCategory;
import cc.mrbird.febs.dapp.entity.MallNewsInfo;
import cc.mrbird.febs.dapp.vo.AdminMallNewsInfoVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
public interface IMallNewsInfoService extends IService<MallNewsInfo> {
    IPage<AdminMallNewsInfoVo> getNewInfoList(MallNewsInfo mallNewsInfo, QueryRequest request);
    FebsResponse addNewsInfo(MallNewsInfoDto mallNewsInfoDto);
    FebsResponse delNewsInfo(Long id);
    FebsResponse updateNewsInfo(MallNewsInfoDto mallNewsInfoDto);
    MallNewsInfo getNewsInfoById(long id);
    IPage<MallNewsCategory> findNewsCategoryInPage(MallNewsCategory mallNewsCategory, QueryRequest request);
    void addOrModifyNewsCategory(MallNewsCategory mallNewsCategory);
    MallNewsCategory findNewsCategoryById(Long id);
    List<MallNewsCategory> findAllCategory();
    FebsResponse delNewsCategoryInfo(Long id);
}
src/main/java/cc/mrbird/febs/dapp/service/impl/AdminBannerServiceImpl.java
New file
@@ -0,0 +1,107 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.enumerates.DataDicEnum;
import cc.mrbird.febs.dapp.entity.DappCoinPrice;
import cc.mrbird.febs.dapp.entity.DataDictionaryCustom;
import cc.mrbird.febs.dapp.entity.PlatformBanner;
import cc.mrbird.febs.dapp.mapper.DappCoinPriceMapper;
import cc.mrbird.febs.dapp.mapper.DappHdRecordMapper;
import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.dapp.mapper.PlatformBannerMapper;
import cc.mrbird.febs.dapp.service.AsyncCjService;
import cc.mrbird.febs.dapp.service.IAdminBannerService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class AdminBannerServiceImpl extends ServiceImpl<PlatformBannerMapper, PlatformBanner> implements IAdminBannerService {
    private final PlatformBannerMapper platformBannerMapper;
    private final DappCoinPriceMapper dappCoinPriceMapper;
    private final DappHdRecordMapper dappHdRecordMapper;
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    private final AsyncCjService asyncCjService;
    @Override
    public IPage<PlatformBanner> findPlatformBannerInPage(PlatformBanner platformBannerEntity,
                                                          QueryRequest request) {
        Page<PlatformBanner> page = new Page<>(request.getPageNum(), request.getPageSize());
        IPage<PlatformBanner> platformBannerEntitys = platformBannerMapper.findPlatformBannerInPage(page, platformBannerEntity);
        return platformBannerEntitys;
    }
    @Override
    public PlatformBanner selectPlatformBannerById(long id) {
        PlatformBanner platformBannerEntity = platformBannerMapper.selectById(id);
        return platformBannerEntity;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FebsResponse platformBannerConfirm(@Valid PlatformBanner platformBannerEntity) {
        platformBannerMapper.updateById(platformBannerEntity);
        return new FebsResponse().success();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FebsResponse platformBannerDelete(@NotNull(message = "{required}") Long id) {
        platformBannerMapper.deleteById(id);
        return new FebsResponse().success();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void platformBannerAdd(@Valid PlatformBanner platformBannerEntity) {
        PlatformBanner platformBannerEntityAdd = new PlatformBanner();
        platformBannerEntityAdd.setImageUrl(platformBannerEntity.getImageUrl());
        platformBannerEntityAdd.setIsInside(platformBannerEntity.getIsInside());
        platformBannerEntityAdd.setIsJump(platformBannerEntity.getIsJump());
        platformBannerEntityAdd.setIsTop(platformBannerEntity.getIsTop());
        platformBannerEntityAdd.setJumpUrl(platformBannerEntity.getJumpUrl());
        platformBannerEntityAdd.setName(platformBannerEntity.getName());
        platformBannerEntityAdd.setShowPort(platformBannerEntity.getShowPort());
        platformBannerEntityAdd.setSort(platformBannerEntity.getSort());
        platformBannerMapper.insert(platformBannerEntityAdd);
    }
    @Override
    public IPage<DappCoinPrice> findCoinPriceInPage(DappCoinPrice dappCoinPrice, QueryRequest request) {
        Page<DappCoinPrice> page = new Page<>(request.getPageNum(), request.getPageSize());
        IPage<DappCoinPrice> platformBannerEntitys = dappHdRecordMapper.findCoinPriceInPage(page, dappCoinPrice);
        return platformBannerEntitys;
    }
    @Override
    public FebsResponse coinPriceAdd(String price) {
        BigDecimal bigDecimal = new BigDecimal(price).setScale(8, BigDecimal.ROUND_DOWN);
        DappCoinPrice dappCoinPrice = new DappCoinPrice();
        dappCoinPrice.setPrice(bigDecimal);
        dappCoinPriceMapper.insert(dappCoinPrice);
        DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDicEnum.GFA_PRICE.getValue(),
                DataDicEnum.GFA_PRICE.getValue()
        );
        dataDictionaryCustom.setValue(bigDecimal.toString());
        dataDictionaryCustomMapper.updateById(dataDictionaryCustom);
        asyncCjService.redisCacheUpdate(DataDicEnum.GFA_PRICE.getValue(),bigDecimal.toString(),0);
        return new FebsResponse().success();
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/ApiMallNewsServiceImpl.java
New file
@@ -0,0 +1,66 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.dapp.dto.NewsListDto;
import cc.mrbird.febs.dapp.entity.MallNewsCategory;
import cc.mrbird.febs.dapp.entity.MallNewsInfo;
import cc.mrbird.febs.dapp.entity.PlatformBanner;
import cc.mrbird.febs.dapp.mapper.MallNewsCategoryMapper;
import cc.mrbird.febs.dapp.mapper.MallNewsInfoMapper;
import cc.mrbird.febs.dapp.mapper.PlatformBannerMapper;
import cc.mrbird.febs.dapp.service.IApiMallNewsService;
import cc.mrbird.febs.dapp.vo.NewsListVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * @author wzy
 * @date 2021-09-28
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class ApiMallNewsServiceImpl extends ServiceImpl<MallNewsInfoMapper, MallNewsInfo> implements IApiMallNewsService {
    private final MallNewsCategoryMapper mallNewsCategoryMapper;
    private final PlatformBannerMapper platformBannerMapper;
    @Override
    public List<MallNewsCategory> findNewsCategoryList() {
        return mallNewsCategoryMapper.selectList(null);
    }
    @Override
    public IPage<NewsListVo> findNewsInPage(NewsListDto newsListDto) {
        Page<NewsListVo> page = new Page<>(newsListDto.getPageNum(), newsListDto.getPageSize());
        MallNewsInfo mallNewsInfo = new MallNewsInfo();
        mallNewsInfo.setCategoryId(newsListDto.getCategoryId());
        return this.baseMapper.selectNewsVoInPage(page, mallNewsInfo);
    }
    @Override
    public List<NewsListVo> findTopNews() {
        Page<NewsListVo> page = new Page<>(1, 999);
        MallNewsInfo mallNewsInfo = new MallNewsInfo();
        mallNewsInfo.setIsTop(1);
        IPage<NewsListVo> pageList = this.baseMapper.selectNewsVoInPage(page, mallNewsInfo);
        return pageList.getRecords();
    }
    @Override
    public FebsResponse findAllBanner() {
        QueryWrapper<PlatformBanner> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("is_top");
        List<PlatformBanner> paymentMethodList = platformBannerMapper.selectList(queryWrapper);
        return new FebsResponse().success().data(paymentMethodList);
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/AsyncCjServiceImpl.java
New file
@@ -0,0 +1,231 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.enumerates.DataDicEnum;
import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.AsyncCjService;
import cc.mrbird.febs.dapp.utils.OnlineTransferUtil;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class AsyncCjServiceImpl extends ServiceImpl<DappAchieveMapper, DappAchieve> implements AsyncCjService {
    private final RedisUtils redisUtils;
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    private final DappMemberDao dappMemberDao;
    private final DappFundFlowDao dappFundFlowDao;
    private final DappAchieveMapper dappAchieveMapper;
    private final DappAchieveItemMapper dappAchieveItemMapper;
    private final ChainProducer chainProducer;
    @Override
    public void redisCacheUpdate(String key, Object value, long time) {
        String existToken = redisUtils.getString(key);
        if (StrUtil.isNotBlank(existToken)) {
            redisUtils.del(existToken);
        }
        redisUtils.set(key, value, time);
    }
    @Override
    public void updateDataDicEnumRedis(List<String> nameList) {
        if(CollUtil.isEmpty(nameList)){
            return;
        }
        for(String name : nameList){
            DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(name, name);
            if(ObjectUtil.isEmpty(dataDictionaryCustom)){
                continue;
            }
            if(DataDicEnum.GFA_PRICE.getValue().equals(name)){
                continue;
            }
            String existToken = redisUtils.getString(dataDictionaryCustom.getCode());
            if (StrUtil.isNotBlank(existToken)) {
                redisUtils.del(existToken);
            }
            redisUtils.set(dataDictionaryCustom.getCode(), dataDictionaryCustom.getValue(), 0);
        }
    }
    @Override
    public void updateAmount(Integer type, Long memberId, BigDecimal amount) {
        DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
        BigDecimal usdtBalance = dappMemberEntity.getUsdtBalance();
        BigDecimal balance = dappMemberEntity.getBalance();
        if(1== type){
            dappMemberEntity.setBalance(balance.add(amount));
            dappMemberDao.updateBalanceWithVersion(dappMemberEntity);
        }
        if(2== type){
            dappMemberEntity.setUsdtBalance(usdtBalance.add(amount));
            dappMemberDao.updateUsdtBalanceWithVersion(dappMemberEntity);
        }
    }
    @Override
    public void insertTeamPerk(Long flowId, Long achieveId) {
        //更新第一次请求的资金划转记录
        DappFundFlowEntity flow = dappFundFlowDao.selectById(flowId);
        if(ObjectUtil.isEmpty(flow)){
            return;
        }
        //用户质押代币数量
        BigDecimal amount = flow.getAmount().negate();
        Long memberId = flow.getMemberId();
        DappMemberEntity member = dappMemberDao.selectById(memberId);
            /*
                新增推荐奖
             *  团队总奖励
             *  团队奖励层级
             *  团队总奖励/团队奖励层级 = 每一个层级应该获得的推荐奖励代币
             */
        //团队的所占比例
        BigDecimal tuanDuiPerkTimes = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_TUAN_DUI_PERCENT.getValue()));
        BigDecimal tuanDuiPercent = new BigDecimal("0.01")
                .multiply(tuanDuiPerkTimes
                        .setScale(2,BigDecimal.ROUND_DOWN));
        BigDecimal tuanDuiPerkTotal = tuanDuiPercent.multiply(amount).setScale(2,BigDecimal.ROUND_DOWN);
        Integer tuanDuiLevel = Convert.toInt(redisUtils.getString(DataDicEnum.GFA_TUAN_DUI_LEVEL.getValue()));
        //分成【团队的所占比例】的份数
        BigDecimal tuanDuiPerk = tuanDuiPerkTotal.divide(tuanDuiPerkTimes, 2, BigDecimal.ROUND_DOWN);
        //团队奖励对象
        HashMap<Integer, DappMemberEntity> objectObjectHashMap = new HashMap<>();//累计奖励的用户集合
        Long refMemberId = memberId;//循环的上级用户ID
        Integer dappMembersSize = 0;//累计层级数量
        boolean flag = true;
        while (flag){
            //累计四级,停止返回
            if(dappMembersSize >= tuanDuiLevel){
                flag = false;
            }else{
                DappMemberEntity dappMemberEntity = dappMemberDao.selectById(refMemberId);
                if(ObjectUtil.isEmpty(dappMemberEntity.getRefererId())){
                    flag = false;
                }else{
                    DappMemberEntity dappMemberRef = dappMemberDao.selectMemberInfoByInviteId(dappMemberEntity.getRefererId());
                    if(ObjectUtil.isEmpty(dappMemberRef)){
                        flag = false;
                    }else{
                        objectObjectHashMap.put(dappMembersSize,dappMemberRef);
                        refMemberId = dappMemberRef.getId();
                        dappMembersSize ++;
                    }
                }
            }
        }
        if(CollUtil.isEmpty(objectObjectHashMap)){
            return;
        }
        for (Map.Entry<Integer, DappMemberEntity> entry : objectObjectHashMap.entrySet()) {
            Integer key = entry.getKey();
            DappMemberEntity refMember = entry.getValue();
            BigDecimal perkPercent = BigDecimal.ZERO;
            if(key == 0){
                perkPercent = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_TUAN_DUI_LEVEL_YI.getValue())).setScale(2, BigDecimal.ROUND_DOWN);
            }
            if(key == 1){
                perkPercent = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_TUAN_DUI_LEVEL_YI.getValue())).setScale(2, BigDecimal.ROUND_DOWN);
            }
            if(key == 2){
                perkPercent = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_TUAN_DUI_LEVEL_YI.getValue())).setScale(2, BigDecimal.ROUND_DOWN);
            }
            if(key == 3){
                perkPercent = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_TUAN_DUI_LEVEL_YI.getValue())).setScale(2, BigDecimal.ROUND_DOWN);
            }
            if(key == 4){
                perkPercent = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_TUAN_DUI_LEVEL_WU.getValue())).setScale(2, BigDecimal.ROUND_DOWN);
            }
            BigDecimal realPerk = tuanDuiPerk.multiply(perkPercent).setScale(2, BigDecimal.ROUND_DOWN);
            QueryWrapper<DappAchieve> objectQueryWrapper = new QueryWrapper<>();
            objectQueryWrapper.eq("member_id",refMember.getId());
            objectQueryWrapper.eq("state",DappAchieve.STATUS_ING);
            List<DappAchieve> dappAchieves = dappAchieveMapper.selectList(objectQueryWrapper);
            if(CollUtil.isEmpty(dappAchieves)){
                DappFundFlowEntity fundFlowTuiJian = new DappFundFlowEntity(
                        refMember.getId(),
                        realPerk,
                        FlowTypeEnum.TUAN_DUI_FAIL.getValue(),
                        DappFundFlowEntity.WITHDRAW_STATUS_AGREE,
                        FlowTypeEnum.TUAN_DUI_FAIL.getDescrition(),
                        member.getAddress(),
                        refMember.getAddress());
                dappFundFlowDao.insert(fundFlowTuiJian);
                continue;
            }
            DappAchieveItem dappAchieveItem = new DappAchieveItem();
            dappAchieveItem.setAchieveId(achieveId);
            dappAchieveItem.setType(DappAchieveItem.TYPE_TUI_JIAN);
            dappAchieveItem.setState(DappAchieveItem.STATUS_AGREE);
            dappAchieveItem.setMemberId(refMember.getId());
            dappAchieveItem.setAmount(realPerk);
            dappAchieveItemMapper.insert(dappAchieveItem);
            DappFundFlowEntity fundFlowTuiJian = new DappFundFlowEntity(
                    refMember.getId(),
                    realPerk,
                    FlowTypeEnum.TUAN_DUI.getValue(),
                    DappFundFlowEntity.WITHDRAW_STATUS_AGREE,
                    FlowTypeEnum.TUAN_DUI.getDescrition(),
                    member.getAddress(),
                    refMember.getAddress());
            dappFundFlowDao.insert(fundFlowTuiJian);
            //生成转账记录
            OnlineTransferUtil.addTransfer(
                    refMember.getAddress(),
                    realPerk,
                    4,//推荐奖
                    1,//普通账户
                    ChainEnum.BSC_TFC_REWARD.name(),
                    DataDicEnum.GFA_COIN.getValue(),
                    fundFlowTuiJian.getId().toString());
            Integer systemFlag = Integer.parseInt(redisUtils.getString(DataDicEnum.GFA_ZHUAN_ZHANG_KAI_GUAN.getValue()));
            if(1 == systemFlag) {
                Map<String, String> map = new HashMap<>();
                map.put("batchNo", fundFlowTuiJian.getId().toString());
                map.put("type", AppContants.SYMBOL_FLOW_TYPE_FLOW);
                //发送链上转账消息
                chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
            }else{
                this.updateAmount(1,refMember.getId(),realPerk);
            }
        }
        BigDecimal gfaDays = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_DAYS.getValue())).setScale(2,BigDecimal.ROUND_DOWN);
        //更新每日限额的质押总数
        gfaDays = gfaDays.add(flow.getAmount()).setScale(2,BigDecimal.ROUND_DOWN);
        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
                DataDicEnum.GFA_DAYS.getValue(),
                DataDicEnum.GFA_DAYS.getValue(),
                gfaDays.toString()
        );
        this.redisCacheUpdate(DataDicEnum.GFA_DAYS.getValue(),gfaDays.toString(),0);
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java
@@ -162,9 +162,6 @@
                fundFlow.setTargetAmount(transferAmount);
                dappFundFlowDao.updateById(fundFlow);
                // 划点分配
                chainProducer.sendDitribProfit(fundFlow.getId());
                OnlineTransferUtil.addTransfer(e.from, transferAmount, fundFlow.getType(), 1, ChainEnum.BSC_USDT_SOURCE.name(), AppContants.SYMBOL_USDT, fundFlow.getId().toString());
                Map<String, String> map = new HashMap<>();
src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
@@ -1,7 +1,9 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.common.utils.LoginUserUtil;
@@ -17,23 +19,30 @@
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.dapp.vo.MoneyFlowVo;
import cc.mrbird.febs.dapp.vo.TeamListVo;
import cc.mrbird.febs.system.entity.User;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
 * @author 
@@ -49,6 +58,8 @@
    private final DappTransferRecordDao dappTransferRecordDao;
    private final RedisUtils redisUtils;
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    private final DappAchieveMapper dappAchieveMapper;
    private final DappFundFlowDao dappFundFlowDao;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -122,19 +133,13 @@
    @Override
    public void connect(ConnectDto connectDto) {
        DappMemberEntity member = dappMemberDao.selectByAddress(connectDto.getAddress(), null);
        if (member == null) {
//            DappMemberEntity parent = dappMemberDao.selectMemberInfoByInviteId(connectDto.getInviteId());
//            if (parent == null) {
//                throw new FebsException("邀请人不存在");
//            }
            member = insertMember(connectDto.getAddress(), null);
        if (ObjectUtil.isEmpty(member)) {
            DappMemberEntity parent = dappMemberDao.selectMemberInfoByInviteId(connectDto.getInviteId());
            if (ObjectUtil.isEmpty(parent)) {
                throw new FebsException("邀请码不存在");
            }
            member = insertMember(connectDto.getAddress(), connectDto.getInviteId());
        }
//        if (member.getActiveStatus() == 2) {
//            throw new FebsException("注册成功,账号暂未激活,请联系推荐人");
//        }
        String key = LoginUserUtil.getLoginKey(connectDto.getAddress(), connectDto.getNonce(), connectDto.getSign());
        redisUtils.set(connectDto.getAddress(), member);
@@ -277,18 +282,18 @@
        member.setChainType(chainType);
        member.setAccountType(accountType);
        member.setActiveStatus(1);
        member.setBalance(ChainService.getInstance(ChainEnum.BSC_TFC.name()).balanceOf(address));
        member.setUsdtBalance(ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(address));
        member.setBalance(BigDecimal.ZERO);
        member.setUsdtBalance(BigDecimal.ZERO);
        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_SYSTEM_NODE_CNT_LIMIT);
        int nodeCntLimit = Integer.parseInt(dic.getValue());
        List<DappMemberEntity> memberCount = dappMemberDao.selectList(null);
        if (memberCount.size() <= (nodeCntLimit + 4)) {
            member.setNodeType(1);
        } else {
            member.setNodeType(2);
        }
//        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_SYSTEM_NODE_CNT_LIMIT);
//        int nodeCntLimit = Integer.parseInt(dic.getValue());
//
//        List<DappMemberEntity> memberCount = dappMemberDao.selectList(null);
//        if (memberCount.size() <= (nodeCntLimit + 4)) {
//            member.setNodeType(1);
//        } else {
//            member.setNodeType(2);
//        }
        dappMemberDao.insert(member);
@@ -345,10 +350,57 @@
    }
    @Override
    public List<TeamListVo> findTeamList(TeamListDto teamListDto) {
    public TeamListVo findTeamList() {
        TeamListVo teamListVo = new TeamListVo();
        DappMemberEntity member = LoginUserUtil.getAppUser();
        Page<TeamListDto> page = new Page<>(teamListDto.getPageNum(), teamListDto.getPageSize());
        teamListDto.setInviteId(member.getInviteId());
        return dappMemberDao.selectTeamListInPage(teamListDto, page).getRecords();
        List<DappMemberEntity> dappMemberEntities = dappMemberDao.selectChildMemberDirectOrNot(member.getInviteId(), 2);
        teamListVo.setTeamCount(CollUtil.isEmpty(dappMemberEntities) ? 0 : dappMemberEntities.size());
        if(CollUtil.isNotEmpty(dappMemberEntities)){
            List<Long> collect = dappMemberEntities.stream().map(DappMemberEntity::getId).collect(Collectors.toList());
            QueryWrapper<DappAchieve> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("member_id",collect);
            List<DappAchieve> dappAchieveSumList = dappAchieveMapper.selectList(queryWrapper);
            List<DappAchieve> filteredList = dappAchieveSumList.stream()
                    .filter(obj -> obj.getState() == 1)
                    .collect(Collectors.toList());
            Set<Long> collect1 = filteredList.stream().map(DappAchieve::getMemberId).collect(Collectors.toSet());
            teamListVo.setAvaCount(CollUtil.isEmpty(collect1) ? 0 : collect1.size());
            BigDecimal teamAchieveMemberSum = dappAchieveSumList.stream().map(DappAchieve::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            teamListVo.setTeamAmount(teamAchieveMemberSum);
            BigDecimal avaAmount = filteredList.stream().map(DappAchieve::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            teamListVo.setAvaAmount(avaAmount);
        }else{
            teamListVo.setAvaCount(0);
            teamListVo.setTeamAmount(BigDecimal.ZERO);
            teamListVo.setAvaAmount(BigDecimal.ZERO);
        }
        teamListVo.setBalance(member.getBalance().setScale(2,BigDecimal.ROUND_DOWN));
        teamListVo.setUsdtBalance(member.getUsdtBalance().setScale(2,BigDecimal.ROUND_DOWN));
        return teamListVo;
    }
    @Override
    public IPage<MoneyFlowVo>  findMoneyFlowVos(TeamListDto teamListDto) {
        DappMemberEntity member = LoginUserUtil.getAppUser();
        teamListDto.setMemberId(member.getId());
        Page<MoneyFlowVo> page = new Page<>(teamListDto.getPageNum(), teamListDto.getPageSize());
        return dappFundFlowDao.findMoneyFlowVos(page, teamListDto);
    }
    @Override
    public FebsResponse exist(String address) {
        DappMemberEntity member = dappMemberDao.selectByAddress(address, null);
        if(ObjectUtil.isEmpty(member)){
            return new FebsResponse().success().data(0);
        }
        return new FebsResponse().success().data(1);
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java
@@ -1,6 +1,8 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.enumerates.DataDicEnum;
import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.ChainEnum;
@@ -9,19 +11,21 @@
import cc.mrbird.febs.dapp.dto.SystemDto;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.AsyncCjService;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.dapp.utils.OnlineTransferUtil;
import cc.mrbird.febs.dapp.vo.RedisTransferPoolVo;
import cc.mrbird.febs.dapp.vo.SlipSettingVo;
import cc.mrbird.febs.job.SystemTradeJob;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -32,6 +36,7 @@
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @author 
@@ -50,6 +55,10 @@
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    private final DappOnlineTransferDao dappOnlineTransferDao;
    private final ChainProducer chainProducer;
    private final DappAchieveMapper dappAchieveMapper;
    private final DappAchieveItemMapper dappAchieveItemMapper;
    private final DappHdRecordMapper dappHdRecordMapper;
    private final AsyncCjService asyncCjService;
    @Override
@@ -154,107 +163,259 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void tradeProfitDistribute(Long id) {
        DappFundFlowEntity fundflow = dappFundFlowDao.selectById(id);
        String batchNo = RandomUtil.randomString(16) + id.toString();
        /**
         * 获取滑点钱包的代币余额A和U余额B
         * 获取最新一条的记录C,然后A-C.A,B-C.B,获得这段时间内的滑点新增D
         * 用D来进行划定分配
         * 并且生成一条新的记录dappHdRecord,用来下次分配参照
         */
        BigDecimal fee = fundflow.getFee();
        DappMemberEntity member = dappMemberDao.selectById(fundflow.getMemberId());
        //当天实际当天滑点
        List<DappMemberEntity> parents;
        if (StrUtil.isBlank(member.getRefererId()) || "0".equals(member.getRefererId())) {
            parents = new ArrayList<>();
        } else {
            List<String> inviteIds = StrUtil.split(member.getRefererId(), ',');
            parents = dappMemberDao.selectParentsList(inviteIds, 6);;
        BigDecimal gfaPrice = new BigDecimal(
                redisUtils.getString(DataDicEnum.GFA_PRICE.getValue())
        ).setScale(2,BigDecimal.ROUND_DOWN);
        BigDecimal usdtAmount = new BigDecimal(
                redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue())
        ).setScale(2,BigDecimal.ROUND_DOWN);
        BigDecimal coinAmount = new BigDecimal(
                redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_WALLET_COIN_AMOUNT.getValue())
        ).setScale(2,BigDecimal.ROUND_DOWN);
        if(BigDecimal.ZERO.compareTo(usdtAmount) > 0){
            return;
        }
        DataDictionaryCustom miniHoldCoin = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_MINI_HOLD_COIN_LIMIT);
        DataDictionaryCustom slipPointSetting = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SLIP_POINT_SETTING, AppContants.DIC_TYPE_SLIP_POINT_SETTING);
        SlipSettingVo slipSetting = JSONObject.parseObject(slipPointSetting.getValue(), SlipSettingVo.class);
        // 源池
        ContractChainService instance = ChainService.getInstance(ChainEnum.BSC_TFC_SOURCE.name());
        BigDecimal destroy = slipSetting.getDestroyPoint().divide(slipSetting.getAllPoint(), 2, RoundingMode.HALF_DOWN).multiply(fee);
        log.info("销毁数量:{}, 比例:{}", destroy, slipSetting.getDestroyPoint());
        // 销毁
        OnlineTransferUtil.addTransfer(AppContants.DESTROY_ADDRESS, destroy, fundflow.getType(), 3, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo);
        // 总分发金额
        BigDecimal distrbAmount = fee.subtract(destroy);
        // 技术金额
        BigDecimal techAmount = distrbAmount.multiply(slipSetting.getTechProp().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
        // 节点金额
        BigDecimal nodeAmount = distrbAmount.subtract(techAmount);
        log.info("总分发金额:{}, 技术:{}, 节点:{}", distrbAmount, techAmount, nodeAmount);
        if (CollUtil.isNotEmpty(parents)) {
            int i = 1;
            for (DappMemberEntity parent : parents) {
                BigDecimal balance = instance.balanceOf(parent.getAddress());
                log.info("地址:{}, 余额:{}", parent.getAddress(), balance);
                // 若地址持币少了指定数量
                if (balance.compareTo(new BigDecimal(miniHoldCoin.getValue())) < 0) {
                    continue;
                }
                DataDictionaryCustom distribDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_DISTRIBUTE_PROP, String.valueOf(i));
                if (distribDic == null) {
                    break;
                }
                BigDecimal total = distrbAmount.multiply(new BigDecimal(distribDic.getValue()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
                OnlineTransferUtil.addTransfer(parent.getAddress(), total, fundflow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo);
                DappFundFlowEntity distribFlow = new DappFundFlowEntity(parent.getId(), total, 4, 2, BigDecimal.ZERO);
                dappFundFlowDao.insert(distribFlow);
                nodeAmount = nodeAmount.subtract(total);
                i++;
            }
        if(BigDecimal.ZERO.compareTo(coinAmount) > 0){
            return;
        }
        BigDecimal usdtAmountReal = usdtAmount;
        BigDecimal coinAmountReal = coinAmount;
        //生成一条记录
        DappHdRecord dappHdRecordAdd = new DappHdRecord();
        dappHdRecordAdd.setPrice(gfaPrice);
        dappHdRecordAdd.setUsdtEvery(usdtAmountReal);
        dappHdRecordAdd.setUsdtAmount(usdtAmountReal);
        dappHdRecordAdd.setCoinEvery(coinAmountReal);
        dappHdRecordAdd.setCoinAmount(coinAmountReal);
        dappHdRecordMapper.insert(dappHdRecordAdd);
        // 铸池滑点金额
        BigDecimal makerAmount = distrbAmount.multiply(slipSetting.getMakeProp().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
        log.info("铸池滑点金额:{}", makerAmount);
        if (makerAmount.compareTo(BigDecimal.ZERO) > 0) {
            List<DappMemberEntity> makerAddress = dappMemberDao.selectMakerAddress();
            if (CollUtil.isNotEmpty(makerAddress)) {
                BigDecimal totalMaker = BigDecimal.ZERO;
                Map<String, BigDecimal> map = new HashMap<>();
                Map<String, Long> addressAndId = new HashMap<>();
                for (DappMemberEntity maker : makerAddress) {
                    BigDecimal balance = instance.balanceOf(maker.getAddress());
                    map.put(maker.getAddress(), balance);
                    addressAndId.put(maker.getAddress(), maker.getId());
                    totalMaker = totalMaker.add(balance);
                }
                for (Map.Entry<String, BigDecimal> entry : map.entrySet()) {
                    BigDecimal target = makerAmount.multiply(entry.getValue().divide(totalMaker, 2, RoundingMode.HALF_UP));
                    OnlineTransferUtil.addTransfer(entry.getKey(), target, fundflow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo);
                    DappFundFlowEntity distribFlow = new DappFundFlowEntity(addressAndId.get(entry.getKey()), target, 4, 2, BigDecimal.ZERO);
                    dappFundFlowDao.insert(distribFlow);
                }
            }
        }
        // 若节点金额还有剩余,则进入技术金额
        techAmount = techAmount.add(nodeAmount);
        OnlineTransferUtil.addTransfer(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount, fundflow.getType(), 3, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo);
        Map<String, String> map = new HashMap<>();
        map.put("batchNo", batchNo);
        map.put("type", "batch");
        // 发送转账消息
        chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
        /**
         * 5%滑奖分配:
         * 1%用自身质押
         * 3%用于团队业绩计算
         * 1%用于布道者奖励
         */
        int selfPercent = Convert.toInt(redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_SELF.getValue()));
        int teamPercent = Convert.toInt(redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_TEAM.getValue()));
        int workPercent = Convert.toInt(redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_WORK.getValue()));
        //平分份数
        BigDecimal totalPercent = new BigDecimal(selfPercent + teamPercent + workPercent);
        //每一份有多少
        BigDecimal divideEveryUsdt = usdtAmountReal.divide(totalPercent, 2, BigDecimal.ROUND_DOWN);
        //每一份有多少
        BigDecimal divideEveryCoin = coinAmountReal.divide(totalPercent, 2, BigDecimal.ROUND_DOWN);
        //1%用自身质押
        selfHdPerk(selfPercent,divideEveryUsdt,divideEveryCoin);
        //3%用于团队业绩计算
        teamHdPerk(teamPercent,divideEveryUsdt,divideEveryCoin);
    }
    public void teamHdPerk(int teamPercent,BigDecimal divideEveryUsdt,BigDecimal divideEveryCoin){
        //3%用于团队业绩计算
        BigDecimal teamPercentMultiply = new BigDecimal(teamPercent);
        BigDecimal multiplyDivideEveryUsdt = divideEveryUsdt.multiply(teamPercentMultiply);
        BigDecimal multiplyDivideEveryCoin = divideEveryCoin.multiply(teamPercentMultiply);
        List<DappMemberEntity> dappMemberEntities = dappMemberDao.selectList(null);//获取全部成员
        if(CollUtil.isEmpty(dappMemberEntities)){
            return;
        }
        //如果没有进行中的质押,直接返回
        QueryWrapper<DappAchieve> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("state",DappAchieve.STATUS_ING);
        List<DappAchieve> dappAchieves = dappAchieveMapper.selectList(objectQueryWrapper);
        if(CollUtil.isEmpty(dappAchieves)){
            return;
        }
        //可以获取奖励的用户
        Map<Long, BigDecimal> memberPerkMap = new HashMap<>();
        //总团队业绩
        BigDecimal memberPerkTotal = BigDecimal.ZERO;
        //获取全部会员
        Set<Long> allMembers = dappMemberEntities.stream().map(DappMemberEntity::getId).collect(Collectors.toSet());
        //获取正在质押的会员ID
        Set<Long> achieveMembers = dappAchieves.stream().map(DappAchieve::getMemberId).collect(Collectors.toSet());
        Collection<Long> intersection = CollUtil.intersection(allMembers, achieveMembers);
        for(Long memberId : intersection){
            /**
             * 获取每一个成员的四级直推
             */
            DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
            String inviteId = dappMemberEntity.getInviteId();
            List<String> inviteIds = new ArrayList<>();
            inviteIds.add(inviteId);
            //每一个账号的往下四级直推
            List<DappMemberEntity> downMembersList = new ArrayList<>();
            int teamLevel = Convert.toInt(redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_LEVEL.getValue()));
            while(teamLevel >= 1){
                //获取直推用户
                List<DappMemberEntity> downMembers = dappMemberDao.selectChildMemberDirectOrNotInlist(inviteIds);
                if(CollUtil.isEmpty(downMembers)){
                    teamLevel = 0;
                }
                CollUtil.addAll(downMembersList,downMembers);
                List<String> collect = downMembers.stream().map(DappMemberEntity::getInviteId).collect(Collectors.toList());
                inviteIds.clear();
                inviteIds.addAll(collect);
                teamLevel = teamLevel -1;
            }
            if(CollUtil.isEmpty(downMembersList)){
                continue;
            }
            QueryWrapper<DappAchieve> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("member_id",downMembersList);
            queryWrapper.eq("state",DappAchieve.STATUS_ING);
            List<DappAchieve> dappAchieveSumList = dappAchieveMapper.selectList(queryWrapper);
            //个人团队总业绩
            BigDecimal teamAchieveMemberSum = dappAchieveSumList.stream().map(DappAchieve::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            if(BigDecimal.ZERO.compareTo(teamAchieveMemberSum) >= 0){
                continue;
            }
            memberPerkTotal = memberPerkTotal.add(teamAchieveMemberSum);
            memberPerkMap.put(memberId,teamAchieveMemberSum);
        }
        BigDecimal everyUsdt = multiplyDivideEveryUsdt.divide(memberPerkTotal);
        BigDecimal everyCoin = multiplyDivideEveryCoin.divide(memberPerkTotal);
        Set<Long> set = memberPerkMap.keySet(); // 得到所有key的集合
        for (Long memberId : set) {
            //当前生效中的团队业绩
            BigDecimal amountMember = memberPerkMap.get(memberId);
            //这个人实际可以分到的数量USDT
            BigDecimal multiplyUsdt = amountMember.multiply(everyUsdt).setScale(2, BigDecimal.ROUND_DOWN);
            //这个人实际可以分到的数量COIN
            BigDecimal multiplyCoin = divideEveryCoin.multiply(everyCoin).setScale(2, BigDecimal.ROUND_DOWN);
            createFlow(
                    multiplyUsdt,
                    memberId,
                    FlowTypeEnum.HUA_DIAN_TUANDUI.getValue(),
                    FlowTypeEnum.HUA_DIAN_TUANDUI.getDescrition(),
                    4,
                    1,
                    ChainEnum.BSC_TFC_REWARD.name(),
                    DataDicEnum.USDT_COIN.getValue(),
                    2);
            createFlow(
                    multiplyCoin,
                    memberId,
                    FlowTypeEnum.HUA_DIAN_TUANDUI.getValue(),
                    FlowTypeEnum.HUA_DIAN_TUANDUI.getDescrition(),
                    4,
                    1,
                    ChainEnum.BSC_TFC_REWARD.name(),
                    DataDicEnum.USDT_COIN.getValue(),
                    1);
        }
    }
    public void selfHdPerk(int selfPercent,BigDecimal divideEveryUsdt,BigDecimal divideEveryCoin){
        QueryWrapper<DappAchieve> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("state",DappAchieve.STATUS_ING);
        List<DappAchieve> dappAchieves = dappAchieveMapper.selectList(objectQueryWrapper);
        if(CollUtil.isEmpty(dappAchieves)){
            return;
        }
        BigDecimal selfPercentMultiply = new BigDecimal(selfPercent);
        BigDecimal multiplyDivideEveryUsdt = divideEveryUsdt.multiply(selfPercentMultiply);
        BigDecimal multiplyDivideEveryCoin = divideEveryCoin.multiply(selfPercentMultiply);
        //当前生效中的质押总数
        BigDecimal amountMemberTotal = dappAchieves.stream().map(DappAchieve::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal everyUsdt = multiplyDivideEveryUsdt.divide(amountMemberTotal);
        BigDecimal everyCoin = multiplyDivideEveryCoin.divide(amountMemberTotal);
        Map<Long, List<DappAchieve>> collect = dappAchieves.stream().collect(Collectors.groupingBy(DappAchieve::getMemberId));
        Set<Long> set = collect.keySet(); // 得到所有key的集合
        for (Long memberId : set) {
            //当前每个人生效中的质押总数
            BigDecimal amountMember = collect.get(memberId).stream().map(DappAchieve::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            //这个人实际可以分到的数量USDT
            BigDecimal multiplyUsdt = amountMember.multiply(everyUsdt).setScale(2, BigDecimal.ROUND_DOWN);
            //这个人实际可以分到的数量COIN
            BigDecimal multiplyCoin = divideEveryCoin.multiply(everyCoin).setScale(2, BigDecimal.ROUND_DOWN);
            createFlow(
                    multiplyUsdt,
                    memberId,
                    FlowTypeEnum.HUA_DIAN_GEREN.getValue(),
                    FlowTypeEnum.HUA_DIAN_GEREN.getDescrition(),
                    4,
                    1,
                    ChainEnum.BSC_TFC_REWARD.name(),
                    DataDicEnum.USDT_COIN.getValue(),
                    2);
            createFlow(
                    multiplyCoin,
                    memberId,
                    FlowTypeEnum.HUA_DIAN_GEREN.getValue(),
                    FlowTypeEnum.HUA_DIAN_GEREN.getDescrition(),
                    4,
                    1,
                    ChainEnum.BSC_TFC_REWARD.name(),
                    DataDicEnum.GFA_COIN.getValue(),
                    1);
        }
    }
    /**
     * 插入流水记录,增加转账记录,发送线上转账的消息
     * @param multiplyUsdt
     * @param memberId
     * @param type
     * @param description
     * @param typeTransfer
     * @param targetType
     * @param chainEnumName
     * @param coinType
     */
    public void createFlow(BigDecimal multiplyUsdt,Long memberId,Integer type,String description,Integer typeTransfer,
                           Integer targetType,String chainEnumName,String coinType,Integer typeadd){
        if (BigDecimal.ZERO.compareTo(multiplyUsdt) < 0) {
            DappFundFlowEntity fundFlowTuiJian = new DappFundFlowEntity(
                    memberId,
                    multiplyUsdt,
                    type,
                    DappFundFlowEntity.WITHDRAW_STATUS_AGREE,
                    description);
            dappFundFlowDao.insert(fundFlowTuiJian);
            Integer systemFlag = Integer.parseInt(redisUtils.getString(DataDicEnum.GFA_ZHUAN_ZHANG_KAI_GUAN.getValue()));
            if (1 == systemFlag) {
                //生成转账记录
                DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
                if (ObjectUtil.isNotEmpty(dappMemberEntity)) {
                    OnlineTransferUtil.addTransfer(
                            dappMemberEntity.getAddress(),
                            multiplyUsdt,
                            typeTransfer,//挖矿
                            targetType,//普通账户
                            chainEnumName,
                            coinType,
                            fundFlowTuiJian.getId().toString());
                    Map<String, String> map = new HashMap<>();
                    map.put("batchNo", fundFlowTuiJian.getId().toString());
                    map.put("type", AppContants.SYMBOL_FLOW_TYPE_BATCH);
                    //发送链上转账消息
                    chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
                }
            }else{
                asyncCjService.updateAmount(typeadd,memberId,multiplyUsdt);
            }
        }
    }
    @Override
    public void mining() {
@@ -309,7 +470,7 @@
        Map<String, String> map = new HashMap<>();
        map.put("batchNo", batchNo);
        map.put("type", "batch");
        map.put("type", AppContants.SYMBOL_FLOW_TYPE_BATCH);
        // 发送转账消息
        chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
@@ -331,6 +492,7 @@
            }
            String txHash = ChainService.getInstance(transfer.getFromType()).transfer(transfer.getAddress(), transfer.getAmount());
            int retryTime = 0;//重试次数
            while (StrUtil.isEmpty(txHash)) {
                // 休眠2s
                try {
@@ -338,7 +500,13 @@
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                txHash = ChainService.getInstance(transfer.getFromType()).transfer(transfer.getAddress(), transfer.getAmount());
                if(retryTime < 3){
                    txHash = ChainService.getInstance(transfer.getFromType()).transfer(transfer.getAddress(), transfer.getAmount());
                }
                retryTime ++ ;
            }
            if(StrUtil.isEmpty(txHash)){
                return;
            }
            transfer.setTxHash(txHash);
@@ -346,26 +514,10 @@
            transfer.setUpdateTime(new Date());
            dappOnlineTransferDao.updateById(transfer);
            if ("flow".equals(jsonObject.getString("type"))) {
            if (AppContants.SYMBOL_FLOW_TYPE_FLOW.equals(jsonObject.getString("type"))) {
                DappFundFlowEntity fundFlow = dappFundFlowDao.selectById(Long.parseLong(batchNo));
                fundFlow.setToHash(txHash);
                dappFundFlowDao.updateById(fundFlow);
            }
        }
        // 判断系统是否启动,如满足条件则启动系统
        String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
        if (!"start".equals(hasStart)) {
            DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_SYSTEM_START_TARGET);
            BigDecimal target = new BigDecimal(dic.getValue());
            // 若源池中的USDT达到或超过8万U,则启动整个系统
            BigDecimal balance = ChainService.getInstance(ChainEnum.BSC_USDT_SOURCE.name()).balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress());
            if (target.compareTo(balance) < 1) {
                redisUtils.set(AppContants.SYSTEM_START_FLAG, "start");
                // 启动系统
                startSystem();
            }
        }
    }
@@ -406,21 +558,127 @@
        chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
    }
    @Autowired
    private SystemTradeJob systemTradeJob;
//    @Autowired
//    private SystemTradeJob systemTradeJob;
    @Override
    public void startSystem() {
        log.info("启动系统");
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                systemTradeJob.transferPoolVol();
                systemTradeJob.sourcePoolUsdtOutLimit();
            }
        });
//        Thread thread = new Thread(new Runnable() {
//            @Override
//            public void run() {
//                systemTradeJob.transferPoolVol();
//                systemTradeJob.sourcePoolUsdtOutLimit();
//            }
//        });
//
//        thread.start();
    }
        thread.start();
    @Override
    public void getZhiYaDelayMsg(Long achieveId) {
        DappAchieve dappAchieve = dappAchieveMapper.selectById(achieveId);
        if(ObjectUtil.isEmpty(dappAchieve)){
            return;
        }
        if(DappAchieve.STATUS_DONE == dappAchieve.getState()){
            return;
        }
        Long memberId = dappAchieve.getMemberId();
        BigDecimal amountDone = dappAchieve.getAmountDone();
        BigDecimal amountDay = dappAchieve.getAmountDay();
        BigDecimal amountMax = dappAchieve.getAmountMax();
        BigDecimal amountReal = BigDecimal.ZERO;//本次产出数量
        int flag = amountMax.compareTo(amountDone.add(amountDay));
        int state = DappAchieve.STATUS_ING;//判断质押任务是否继续
        if( flag > 0){
            amountReal = amountDay;
            amountDone = amountDone.add(amountDay);
        }else if (flag == 0){
            amountReal = amountDay;
            amountDone = amountMax;
            state = DappAchieve.STATUS_DONE;
        }else{
            amountReal = amountMax.subtract(amountDone);
            amountDone = amountMax;
            state = DappAchieve.STATUS_DONE;
        }
        if(BigDecimal.ZERO.compareTo(amountReal) < 0){
            /**
             * 更新主表记录
             * 插入一条子表记录
             * 插入一条流水记录
             * 发送链上转账记录
             */
            dappAchieve.setAmountDone(amountDone);
            dappAchieve.setState(state);
            dappAchieve.setUpdateTime(new Date());
            dappAchieveMapper.updateById(dappAchieve);
            DappAchieveItem dappAchieveItem = new DappAchieveItem();
            dappAchieveItem.setType(DappAchieveItem.TYPE_ZHI_YA);
            dappAchieveItem.setState(DappAchieveItem.STATUS_AGREE);
            dappAchieveItem.setAchieveId(achieveId);
            dappAchieveItem.setMemberId(memberId);
            dappAchieveItem.setAmount(amountReal);
            dappAchieveItemMapper.insert(dappAchieveItem);
            DappFundFlowEntity fundFlowTuiJian = new DappFundFlowEntity(
                    memberId,
                    amountReal,
                    FlowTypeEnum.ZHIYA_CHA_CHU.getValue(),
                    DappFundFlowEntity.WITHDRAW_STATUS_AGREE,
                    FlowTypeEnum.ZHIYA_CHA_CHU.getDescrition());
            dappFundFlowDao.insert(fundFlowTuiJian);
            //生成转账记录
            DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
            if(ObjectUtil.isNotEmpty(dappMemberEntity)){
                OnlineTransferUtil.addTransfer(
                        dappMemberEntity.getAddress(),
                        amountReal,
                        3,//挖矿
                        1,//普通账户
                        ChainEnum.BSC_TFC_REWARD.name(),
                        DataDicEnum.GFA_COIN.getValue(),
                        fundFlowTuiJian.getId().toString());
            }
            Integer systemFlag = Integer.parseInt(redisUtils.getString(DataDicEnum.GFA_ZHUAN_ZHANG_KAI_GUAN.getValue()));
            if(1 == systemFlag){
                //生成转账记录
                Map<String, String> map = new HashMap<>();
                map.put("batchNo", fundFlowTuiJian.getId().toString());
                map.put("type", AppContants.SYMBOL_FLOW_TYPE_FLOW);
                //发送链上转账消息
                chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
            }
            //发送一个延时队列消息。24小时之后产生下一次的质押产出
            chainProducer.sendZhiYaDelayMsg(dappAchieve.getId(), 24 * 60 * 60 * 1000L);
        }
    }
    @Override
    public void getZhiYaDelayMsgFlow(Long flowId) {
        DappFundFlowEntity dappFundFlowEntity = dappFundFlowDao.selectById(flowId);
        if(ObjectUtil.isEmpty(dappFundFlowEntity)){
            return;
        }
        Integer type = dappFundFlowEntity.getType();
        if(FlowTypeEnum.ZHI_YA.getValue() != type){
            return;
        }
        Integer status = dappFundFlowEntity.getStatus();
        if(DappFundFlowEntity.WITHDRAW_STATUS_AGREE == status){
            return;
        }
        if(StrUtil.isNotEmpty(dappFundFlowEntity.getFromHash())){
            return;
        }
        dappFundFlowDao.deleteById(flowId);
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java
@@ -1,23 +1,22 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.enumerates.DataDicEnum;
import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.chain.ContractChainService;
import cc.mrbird.febs.dapp.dto.PriceDto;
import cc.mrbird.febs.dapp.dto.RecordInPageDto;
import cc.mrbird.febs.dapp.dto.TransferDto;
import cc.mrbird.febs.dapp.dto.WalletOperateDto;
import cc.mrbird.febs.dapp.dto.*;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.AsyncCjService;
import cc.mrbird.febs.dapp.service.DappWalletService;
import cc.mrbird.febs.dapp.vo.WalletInfoVo;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
@@ -26,10 +25,7 @@
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
 * @author
@@ -47,23 +43,50 @@
    private final DappAccountMoneyChangeDao dappAccountMoneyChangeDao;
    private final RedisUtils redisUtils;
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    private final DappAchieveMapper dappAchieveMapper;
    private final DappAchieveItemMapper dappAchieveItemMapper;
    private final ChainProducer chainProducer;
    private final AsyncCjService asyncCjService;
    @Override
    public WalletInfoVo walletInfo() {
        DappMemberEntity member = LoginUserUtil.getAppUser();
        Map<String, BigDecimal> map = dappFundFlowDao.selectAmountTotalByType(member.getId());
        Long memberId = LoginUserUtil.getAppUser().getId();
        DappMemberEntity member = dappMemberDao.selectById(memberId);
        WalletInfoVo walletInfo = new WalletInfoVo();
        List<DappMemberEntity> direct = dappMemberDao.selectChildMemberDirectOrNot(member.getInviteId(), 1);
        List<DappMemberEntity> notDirect = dappMemberDao.selectChildMemberDirectOrNot(member.getInviteId(), 2);
        BigDecimal childHoldAmount = dappMemberDao.selectChildHoldAmount(member.getInviteId());
        walletInfo.setTotalChild(notDirect.size());
        walletInfo.setDirectCnt(direct.size());
        walletInfo.setTotalChildCoin(childHoldAmount);
        walletInfo.setTeamReward(map.get("teamReward"));
        walletInfo.setMiningAmount(map.get("mine"));
        walletInfo.setInviteId(member.getInviteId());
        walletInfo.setBalance(member.getBalance());
        walletInfo.setUsdtBalance(member.getUsdtBalance());
        String zyOpen = redisUtils.getString(DataDicEnum.SYSTEM_START_FLAG.getValue());
        walletInfo.setZyOpen(zyOpen.equals("start") ? 1 : 0);
        BigDecimal minAmount = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_BUY_MIN_AMOUNT.getValue())).setScale(2,BigDecimal.ROUND_DOWN);
        walletInfo.setZyMin(minAmount);
        BigDecimal maxAmount = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_BUY_MAX_AMOUNT.getValue())).setScale(2,BigDecimal.ROUND_DOWN);
        walletInfo.setZyMax(maxAmount);
        BigDecimal tzCoin = dappFundFlowDao.selectAmountTotalByTypeAndMemberIdAndDate(member.getId(), FlowTypeEnum.TUAN_DUI.getValue(),null);
        walletInfo.setTzCoin(tzCoin);
        BigDecimal hdCoinGeren = dappFundFlowDao.selectAmountTotalByTypeAndMemberIdAndDate(member.getId(), FlowTypeEnum.HUA_DIAN_GEREN.getValue(),null);
        BigDecimal hdCoinTuandui = dappFundFlowDao.selectAmountTotalByTypeAndMemberIdAndDate(member.getId(), FlowTypeEnum.HUA_DIAN_TUANDUI.getValue(),null);
        walletInfo.setHdCoin(hdCoinGeren.add(hdCoinTuandui));
        BigDecimal zyTotal = dappFundFlowDao.selectAmountTotalByTypeAndMemberIdAndDate(member.getId(), FlowTypeEnum.ZHI_YA.getValue(),null).negate();
        walletInfo.setZyTotal(zyTotal);
        BigDecimal zyToday = dappFundFlowDao.selectAmountTotalByTypeAndMemberIdAndDate(member.getId(), FlowTypeEnum.ZHI_YA.getValue(), new Date()).negate();
        walletInfo.setZyToday(zyToday);
        BigDecimal ccTotal = dappFundFlowDao.selectAmountTotalByTypeAndMemberIdAndDate(member.getId(), FlowTypeEnum.ZHIYA_CHA_CHU.getValue(),null).negate();
        walletInfo.setCcTotal(ccTotal);
        BigDecimal ccToday = dappFundFlowDao.selectAmountTotalByTypeAndMemberIdAndDate(member.getId(), FlowTypeEnum.ZHIYA_CHA_CHU.getValue(), new Date()).negate();
        walletInfo.setCcToday(ccToday);
        BigDecimal gfaDays = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_DAYS.getValue())).setScale(2,BigDecimal.ROUND_DOWN);
        walletInfo.setGfaDays(gfaDays);
        return walletInfo;
    }
@@ -79,7 +102,7 @@
            throw new FebsException("可用金额不足");
        }
        DappFundFlowEntity fund = new DappFundFlowEntity(member.getId(), walletOperateDto.getAmount(), AppContants.MONEY_TYPE_CHANGE, null, null);
        DappFundFlowEntity fund = new DappFundFlowEntity(member.getId(), walletOperateDto.getAmount(), AppContants.MONEY_TYPE_CHANGE, 2, (String) null);
        dappFundFlowDao.insert(fund);
        BigDecimal preEthAmount = walletMine.getAvailableAmount();
@@ -136,15 +159,27 @@
    @Override
    public List<DappFundFlowEntity> recordInPage(RecordInPageDto recordInPageDto) {
        Page<DappFundFlowEntity> page = new Page<>(recordInPageDto.getPageNum(), recordInPageDto.getPageSize());
        DappMemberEntity member = LoginUserUtil.getAppUser();
        Page<DappFundFlowEntity> page = new Page<>(recordInPageDto.getPageNum(), recordInPageDto.getPageSize());
        DappFundFlowEntity dappFundFlowEntity = new DappFundFlowEntity();
        if (recordInPageDto.getType() != null && recordInPageDto.getType() != 0) {
            dappFundFlowEntity.setType(recordInPageDto.getType());
            dappFundFlowEntity.setStatus(recordInPageDto.getType());
        }
        dappFundFlowEntity.setMemberId(member.getId());
        IPage<DappFundFlowEntity> records = dappFundFlowDao.selectInPage(page, dappFundFlowEntity);
        return records.getRecords();
    }
    @Override
    public List<DappAchieve> zyInPage(RecordInPageDto recordInPageDto) {
        DappMemberEntity member = LoginUserUtil.getAppUser();
        Page<DappAchieve> page = new Page<>(recordInPageDto.getPageNum(), recordInPageDto.getPageSize());
        DappAchieve dappAchieve = new DappAchieve();
        if (recordInPageDto.getType() != null && recordInPageDto.getType() != 0) {
            dappAchieve.setState(recordInPageDto.getType());
        }
        dappAchieve.setMemberId(member.getId());
        IPage<DappAchieve> records = dappFundFlowDao.selectZyInPage(page, dappAchieve);
        return records.getRecords();
    }
@@ -161,28 +196,20 @@
        if (fundFlow == null) {
            throw new FebsException("数据不存在");
        }
        DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(fundFlow.getMemberId());
        if (type == 1) {
            walletCoin.setFrozenAmount(walletCoin.getFrozenAmount().subtract(fundFlow.getAmount()));
            walletCoin.setTotalAmount(walletCoin.getTotalAmount().subtract(fundFlow.getAmount()));
            fundFlow.setStatus(DappFundFlowEntity.WITHDRAW_STATUS_AGREE);
            dappFundFlowDao.updateById(fundFlow);
        } else if (type == 2) {
            BigDecimal preAmount = walletCoin.getAvailableAmount();
            walletCoin.setFrozenAmount(walletCoin.getFrozenAmount().subtract(fundFlow.getAmount()));
            walletCoin.setAvailableAmount(walletCoin.getAvailableAmount().add(fundFlow.getAmount()));
            DappAccountMoneyChangeEntity accountMoneyChange = new DappAccountMoneyChangeEntity(walletCoin.getMemberId(), preAmount, fundFlow.getAmount(), walletCoin.getAvailableAmount(), "提现申请被驳回", 2);
            fundFlow.setStatus(DappFundFlowEntity.WITHDRAW_STATUS_DISAGREE);
            dappFundFlowDao.updateById(fundFlow);
            dappAccountMoneyChangeDao.insert(accountMoneyChange);
            DappMemberEntity dappMemberEntity = dappMemberDao.selectById(fundFlow.getMemberId());
            //流水记录的金额是一个负数
            dappMemberEntity.setUsdtBalance(dappMemberEntity.getUsdtBalance().subtract(fundFlow.getAmount()));
            dappMemberDao.updateUsdtBalanceWithVersion(dappMemberEntity);
        } else {
            throw new FebsException("参数错误");
        }
        dappWalletCoinDao.updateById(walletCoin);
        dappFundFlowDao.updateById(fundFlow);
    }
    @Override
@@ -204,89 +231,85 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long transfer(TransferDto transferDto) {
        DappMemberEntity member = LoginUserUtil.getAppUser();
        if (member.getActiveStatus() == 2) {
            throw new FebsException("请联系邀请人转币激活");
        }
        String hasStart = redisUtils.getString(DataDicEnum.SYSTEM_START_FLAG.getValue());
        BigDecimal minAmount = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_BUY_MIN_AMOUNT.getValue())).setScale(2,BigDecimal.ROUND_DOWN);
        BigDecimal maxAmount = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_BUY_MAX_AMOUNT.getValue())).setScale(2,BigDecimal.ROUND_DOWN);
        BigDecimal gfaDays = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_DAYS.getValue())).setScale(2,BigDecimal.ROUND_DOWN);
        // 每日出U剩余量(卖币)
        BigDecimal usdtRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN);
        // 用户24小时可出售量
        BigDecimal saleCoinRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_COIN_REMAIN + member.getAddress());
        BigDecimal buyCoinRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN);
        // 铸池中的币的剩余量
        BigDecimal makeCoinRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_MAKE_POOL_CNT);
        String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
        if (transferDto.getId() == null) {
            if (DappFundFlowEntity.TYPE_SALE == transferDto.getType()) {
                if (!"start".equals(hasStart)) {
                    throw new FebsException("系统还未启动");
                }
                if (transferDto.getAmount().multiply(transferDto.getPrice()).compareTo(usdtRemain) > 0) {
                    throw new FebsException("超过当日出U剩余量");
                }
                if (transferDto.getAmount().compareTo(saleCoinRemain) > 0) {
                    throw new FebsException("超出24小时内可售量");
                }
            } else if (DappFundFlowEntity.TYPE_BUY == transferDto.getType()) {
            if (DappFundFlowEntity.TYPE_BUY == transferDto.getType()) {
                //系统开始标识
                if ("start".equals(hasStart)) {
                    if (transferDto.getAmount().compareTo(buyCoinRemain) > 0) {
                        throw new FebsException("超过当日可购买量");
                    if (transferDto.getAmount().compareTo(maxAmount) > 0) {
                        throw new FebsException("超过购买限制");
                    }
                    // 如果系统还没有启动,则判断铸池中的剩余量
                    if (transferDto.getAmount().compareTo(minAmount) < 0) {
                        throw new FebsException("超过购买限制");
                    }
                    if (BigDecimal.ZERO.compareTo(gfaDays) >= 0) {
                        throw new FebsException("今日暂停质押");
                    }
                    if (transferDto.getAmount().compareTo(gfaDays) > 0) {
                        throw new FebsException("今日最多质押"+gfaDays);
                    }
                } else {
                    DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_MAKER_MIN_LIMIT);
                    if (transferDto.getAmount().compareTo(new BigDecimal(dic.getValue())) < 0) {
                        throw new FebsException("未达到最低购买要求");
                    }
                    if (transferDto.getAmount().compareTo(makeCoinRemain) > 0) {
                        throw new FebsException("可购数量不足");
                    }
                    throw new FebsException("暂停质押");
                }
            }
            DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), transferDto.getAmount(), transferDto.getType(), 1, transferDto.getFee(), transferDto.getTxHash());
            DappFundFlowEntity fundFlow = new DappFundFlowEntity(
                    member.getId(),
                    transferDto.getAmount().setScale(2,BigDecimal.ROUND_DOWN).negate(),
                    FlowTypeEnum.ZHI_YA.getValue(),
                    DappFundFlowEntity.WITHDRAW_STATUS_ING,
                    BigDecimal.ZERO,
                    transferDto.getTxHash());
            fundFlow.setNewestPrice(transferDto.getPrice());
            dappFundFlowDao.insert(fundFlow);
            //发送一个延时队列消息。10分钟流水还没有更新,则删除流水
            chainProducer.sendZhiYaDelayFlowMsg(fundFlow.getId(), 10 * 60 * 1000L);
            return fundFlow.getId();
        }
        if ("success".equals(transferDto.getFlag())) {
            if (transferDto.getId() == null) {
                throw new FebsException("网络异常");
            }
            //更新第一次请求的资金划转记录
            DappFundFlowEntity flow = dappFundFlowDao.selectById(transferDto.getId());
            if(ObjectUtil.isEmpty(flow)){
                throw new FebsException("网络异常");
            }
            flow.setFromHash(transferDto.getTxHash());
            flow.setStatus(DappFundFlowEntity.WITHDRAW_STATUS_AGREE);
            flow.setContent(FlowTypeEnum.ZHI_YA.getDescrition());
            dappFundFlowDao.updateById(flow);
            if (DappFundFlowEntity.TYPE_SALE == transferDto.getType()) {
                usdtRemain = usdtRemain.subtract(flow.getAmount().multiply(flow.getNewestPrice()));
                saleCoinRemain = saleCoinRemain.subtract(flow.getAmount());
            //用户质押代币数量
            BigDecimal amount = flow.getAmount().negate();
            Long memberId = flow.getMemberId();
            //新增一条用户质押记录
            DappAchieve dappAchieve = new DappAchieve();
            dappAchieve.setMemberId(memberId);
            dappAchieve.setAmount(amount);
            BigDecimal achieveReleasePercent = new BigDecimal("0.01").multiply(
                    new BigDecimal(redisUtils.getString(DataDicEnum.GFA_ACHIEVE_RELEASE.getValue())).setScale(2,BigDecimal.ROUND_DOWN)
            );
            dappAchieve.setAmountDay(achieveReleasePercent.multiply(amount).setScale(2,BigDecimal.ROUND_DOWN));
            BigDecimal achieveOut = new BigDecimal(redisUtils.getString(DataDicEnum.GFA_ACHIEVE_OUT.getValue())).setScale(2,BigDecimal.ROUND_DOWN);
            dappAchieve.setAmountMax(achieveOut.multiply(amount).setScale(2,BigDecimal.ROUND_DOWN));
            dappAchieve.setState(DappAchieve.STATUS_ING);
            dappAchieve.setAmountDone(BigDecimal.ZERO);
            dappAchieveMapper.insert(dappAchieve);
                // 修改当日U剩余量
                redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN, usdtRemain);
                // 修改用户24小时可售量
                redisUtils.set(AppContants.REDIS_KEY_COIN_REMAIN + member.getAddress(), saleCoinRemain);
            } else if (DappFundFlowEntity.TYPE_BUY == transferDto.getType()) {
                if ("start".equals(hasStart)) {
                    buyCoinRemain = buyCoinRemain.subtract(flow.getAmount());
            asyncCjService.insertTeamPerk(flow.getId(), dappAchieve.getId());
                    // 修改当日可购买量
                    redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, buyCoinRemain);
                } else {
                    makeCoinRemain = makeCoinRemain.subtract(flow.getAmount());
                    // 修改铸池量
                    redisUtils.set(AppContants.REDIS_KEY_MAKE_POOL_CNT, makeCoinRemain);
                }
            } else {
                throw new FebsException("参数错误");
            }
            //发送一个延时队列消息。24小时之后产生第一次的质押产出
            chainProducer.sendZhiYaDelayMsg(dappAchieve.getId(), 24 * 60 * 60 * 1000L);
        } else {
            dappFundFlowDao.deleteById(transferDto.getId());
        }
@@ -294,32 +317,67 @@
    }
    @Override
    public Map<String, BigDecimal> calPrice(PriceDto priceDto) {
    public String calPrice() {
        DappMemberEntity member = LoginUserUtil.getAppUser();
        return redisUtils.getString(DataDicEnum.GFA_PRICE.getValue());
    }
    @Override
    public IPage<DappAchieve> dappAchieveInPage(DappAchieve dappAchieve, QueryRequest request) {
        Page<DappAchieve> page = new Page<>(request.getPageNum(), request.getPageSize());
        return dappAchieveMapper.selectInPage(page, dappAchieve);
    }
        String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
        if (!"start".equals(hasStart)) {
            HashMap<String, BigDecimal> map = new HashMap<>();
            map.put("x", new BigDecimal("0.075"));
            map.put("y", new BigDecimal("100000"));
            return map;
    @Override
    public IPage<DappAchieveItem> dappAchieveItemInPage(DappAchieve dappAchieve, QueryRequest request) {
        Page<DappAchieveItem> page = new Page<>(request.getPageNum(), request.getPageSize());
        return dappAchieveMapper.dappAchieveItemInPage(page, dappAchieve);
    }
    @Override
    public FebsResponse transferOut(TransferOutDto transferOutDto) {
        Long memberId = LoginUserUtil.getAppUser().getId();
        DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
        BigDecimal usdtBalance = dappMemberEntity.getUsdtBalance();
        BigDecimal balance = dappMemberEntity.getBalance();
        Integer type = transferOutDto.getType();
        Integer flowType;
        String flowDes;
        BigDecimal amount = transferOutDto.getAmount();
        if(1 == type){//代币提现
            if(new BigDecimal("10").compareTo(amount) > 0){
                throw new FebsException("最小数量为10");
            }
            if(balance.compareTo(amount) < 0){
                throw new FebsException("余额不足");
            }
            flowType = FlowTypeEnum.DAI_BI_OUT.getValue();
            flowDes = FlowTypeEnum.DAI_BI_OUT.getDescrition();
        }else{
            if(new BigDecimal("100").compareTo(amount) > 0){
                throw new FebsException("最小数量为100");
            }
            if(usdtBalance.compareTo(amount) < 0){
                throw new FebsException("余额不足");
            }
            flowType = FlowTypeEnum.USDT_OUT.getValue();
            flowDes = FlowTypeEnum.USDT_OUT.getDescrition();
        }
        ContractChainService tfcInstance = ChainService.getInstance(ChainEnum.BSC_TFC.name());
        // u剩余数量
        BigDecimal sourceU = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress());
        // 源池代币剩余数量
        BigDecimal sourceCoin = tfcInstance.balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress());
        // 用户代币剩余数量
        BigDecimal coin = priceDto.getAmount();
        BigDecimal x = sourceU.divide(sourceCoin, tfcInstance.decimals(), RoundingMode.HALF_UP);
        BigDecimal y = sourceU.divide(sourceCoin.add(coin), tfcInstance.decimals(), RoundingMode.HALF_UP);
        DappFundFlowEntity fundFlowTuiJian = new DappFundFlowEntity(
                memberId,
                amount.negate(),
                flowType,
                DappFundFlowEntity.WITHDRAW_STATUS_ING,
                flowDes,
                null,
                dappMemberEntity.getAddress());
        dappFundFlowDao.insert(fundFlowTuiJian);
        log.info("购买价格:{}, 出卖价格:{}", x, y);
        HashMap<String, BigDecimal> map = new HashMap<>();
        map.put("x", x);
        map.put("y", y);
        return map;
        dappMemberEntity.setBalance(balance.subtract(amount).setScale(2,BigDecimal.ROUND_DOWN));
        dappMemberEntity.setUsdtBalance(usdtBalance.subtract(amount).setScale(2,BigDecimal.ROUND_DOWN));
        dappMemberDao.updateBalanceAndUsdtBalanceWithVersion(dappMemberEntity);
        return new FebsResponse().success();
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/GraphQLClient.java
New file
@@ -0,0 +1,43 @@
package cc.mrbird.febs.dapp.service.impl;
import okhttp3.*;
import com.google.gson.Gson;
import com.google.gson.JsonParser;
import java.io.IOException;
public class GraphQLClient {
    private static final String ENDPOINT = "https://bsc-mainnet.nodereal.io/v1/fcb1ae31845147dcabb183db57336218";
//    private static final String ENDPOINT = "https://open-platform.nodereal.io/fcb1ae31845147dcabb183db57336218/pancakeswap/graphql";
    private static final OkHttpClient client = new OkHttpClient();
    public static void main(String[] args) throws IOException {
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType,
                "{\"id\":1," +
                        "\"jsonrpc\":\"2.0\"," +
                        "\"params\":[\"0xcebfd36e03bd80c7015cbad17effbc33d2923ff3\",\"pending\"]," +
                        "\"method\":\"eth_getBalance\"}");
        Request request = new Request.Builder()
                .url(ENDPOINT)
                .post(body)
                .addHeader("accept", "application/json")
                .addHeader("content-type", "application/json")
                .build();
//        Response response = client.newCall(request).execute();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                String responseBody = response.body().string();
                // 在这里处理响应体,比如解析JSON数据等
                System.out.println(responseBody); // 或者其他处理逻辑
            } else {
                // 处理请求失败的情况,比如输出错误信息、重试等
                System.err.println("Request failed with code: " + response.code());
            }
        } catch (IOException e) {
            // 处理网络异常、超时等异常情况
            e.printStackTrace(); // 或者其他异常处理逻辑
        }
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/MallNewsInfoServiceImpl.java
New file
@@ -0,0 +1,152 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.dapp.dto.MallNewsInfoDto;
import cc.mrbird.febs.dapp.entity.MallNewsCategory;
import cc.mrbird.febs.dapp.entity.MallNewsInfo;
import cc.mrbird.febs.dapp.mapper.MallNewsCategoryMapper;
import cc.mrbird.febs.dapp.mapper.MallNewsInfoMapper;
import cc.mrbird.febs.dapp.service.IMallNewsInfoService;
import cc.mrbird.febs.dapp.vo.AdminMallNewsInfoVo;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * @author wzy
 * @date 2022-05-13
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class MallNewsInfoServiceImpl extends ServiceImpl<MallNewsInfoMapper, MallNewsInfo> implements IMallNewsInfoService {
    private final MallNewsCategoryMapper mallNewsCategoryMapper;
    @Override
    public IPage<AdminMallNewsInfoVo> getNewInfoList(MallNewsInfo mallNewsInfo, QueryRequest request) {
        Page<AdminMallNewsInfoVo> page = new Page<>(request.getPageNum(), request.getPageSize());
        IPage<AdminMallNewsInfoVo> adminMallNewsInfoVos = this.baseMapper.getNewInfoListInPage(page, mallNewsInfo);
        return adminMallNewsInfoVos;
    }
    @Override
    public FebsResponse addNewsInfo(MallNewsInfoDto mallNewsInfoDto) {
//        Integer type = mallNewsInfoDto.getType();
//        if(type == 2){
//            Long goodsId = mallNewsInfoDto.getGoodsId()==null?0L:mallNewsInfoDto.getGoodsId();
//            if(goodsId == 0L){
//                return new FebsResponse().fail().message("请选择跳转的产品");
//            }
//        }
//        MallNewsInfo mallNewsInfo = new MallNewsInfo();
//        mallNewsInfo.setTitle(mallNewsInfoDto.getTitle());
//        mallNewsInfo.setContent(mallNewsInfoDto.getContent());
//        mallNewsInfo.setType(mallNewsInfoDto.getType());
//        if(mallNewsInfoDto.getType() == 2){
//            mallNewsInfo.setTargetId(mallNewsInfoDto.getGoodsId());
//        }
        String content = mallNewsInfoDto.getContent();
        if(StrUtil.isNotBlank(content)){
            //正文图片样式居中
            mallNewsInfoDto.setContent(content+"<style>img{max-width:100%!important;}</style>");
        }
        MallNewsInfo mallNewsInfo = new MallNewsInfo();
        BeanUtil.copyProperties(mallNewsInfoDto, mallNewsInfo);
        this.baseMapper.insert(mallNewsInfo);
        return new FebsResponse().success();
    }
    @Override
    public FebsResponse delNewsInfo(Long id) {
        MallNewsInfo mallNewsInfo = this.baseMapper.selectById(id);
        if(ObjectUtil.isEmpty(mallNewsInfo)){
            return new FebsResponse().fail().message("系统繁忙,请刷新页面重试");
        }
        this.baseMapper.deleteById(id);
        return new FebsResponse().success();
    }
    @Override
    public FebsResponse updateNewsInfo(MallNewsInfoDto mallNewsInfoDto) {
        MallNewsInfo mallNewsInfoBefore = this.baseMapper.selectById(mallNewsInfoDto.getId());
        if(ObjectUtil.isEmpty(mallNewsInfoBefore)){
            return new FebsResponse().fail().message("系统繁忙,请刷新页面重试");
        }
//        Integer type = mallNewsInfoDto.getType();
//        if(type == 2){
//            Long goodsId = mallNewsInfoDto.getGoodsId()==null?0L:mallNewsInfoDto.getGoodsId();
//            if(goodsId == 0L){
//                return new FebsResponse().fail().message("请选择跳转的产品");
//            }
//        }
//        MallNewsInfo mallNewsInfo = new MallNewsInfo();
//        mallNewsInfo.setTitle(mallNewsInfoDto.getTitle());
//        mallNewsInfo.setContent(mallNewsInfoDto.getContent());
//        mallNewsInfo.setType(mallNewsInfoDto.getType());
//        if(mallNewsInfoDto.getType() == 2){
//            mallNewsInfo.setTargetId(mallNewsInfoDto.getGoodsId());
//        }
//        this.baseMapper.insert(mallNewsInfo);
//        this.baseMapper.deleteById(mallNewsInfoDto.getId());
        String content = mallNewsInfoDto.getContent();
        if(StrUtil.isNotBlank(content)){
            //正文图片样式居中
            mallNewsInfoDto.setContent(content+"<style>img{max-width:100%!important;}</style>");
        }
        MallNewsInfo mallNewsInfo = new MallNewsInfo();
        BeanUtil.copyProperties(mallNewsInfoDto, mallNewsInfo);
        this.baseMapper.updateById(mallNewsInfo);
        return new FebsResponse().success();
    }
    @Override
    public MallNewsInfo getNewsInfoById(long id) {
        return this.baseMapper.selectById(id);
    }
    @Override
    public IPage<MallNewsCategory> findNewsCategoryInPage(MallNewsCategory mallNewsCategory, QueryRequest request) {
        Page<MallNewsCategory> page = new Page<>(request.getPageNum(), request.getPageSize());
        return mallNewsCategoryMapper.selectInPage(mallNewsCategory, page);
    }
    @Override
    public void addOrModifyNewsCategory(MallNewsCategory mallNewsCategory) {
        if (mallNewsCategory.getId() != null) {
            mallNewsCategoryMapper.updateById(mallNewsCategory);
            return;
        }
        mallNewsCategoryMapper.insert(mallNewsCategory);
    }
    @Override
    public MallNewsCategory findNewsCategoryById(Long id) {
        return mallNewsCategoryMapper.selectById(id);
    }
    @Override
    public List<MallNewsCategory> findAllCategory() {
        return mallNewsCategoryMapper.selectList(null);
    }
    @Override
    public FebsResponse delNewsCategoryInfo(Long id) {
        MallNewsCategory mallNewsCategory = mallNewsCategoryMapper.selectById(id);
        if(ObjectUtil.isEmpty(mallNewsCategory)){
            return new FebsResponse().fail().message("系统繁忙,请刷新页面重试");
        }
        mallNewsCategoryMapper.deleteById(id);
        return new FebsResponse().success();
    }
}
src/main/java/cc/mrbird/febs/dapp/vo/AdminMallNewsInfoVo.java
New file
@@ -0,0 +1,36 @@
package cc.mrbird.febs.dapp.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "AdminMallNewsInfoVo", description = "信息返回类")
public class AdminMallNewsInfoVo {
    private Long id;
    private String title;
    private String content;
    private String thumb;
    private Long targetId;
    private String targetName;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    /**
     * 1-文章2-跳转到产品
     */
    private Integer type;
    private String categoryName;
    private Integer isTop;
}
src/main/java/cc/mrbird/febs/dapp/vo/CoinSetVo.java
New file
@@ -0,0 +1,37 @@
package cc.mrbird.febs.dapp.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel(value = "CoinSetVo")
public class CoinSetVo {
    private String minAmount;
    private String maxAmount;
    private String achieveRelease;
    private String achieveOut;
    private String tdPercent;
    private String tdLevel;
    private String tdLevelYi;
    private String tdLevelEr;
    private String tdLevelSan;
    private String tdLevelSi;
    private String tdLevelWu;
    private String zzkg;
    private String ssf;
    private String coinAmount;
    private String usdtAmount;
    private String hdLevel;
    private String hdWork;
    private String hdTeam;
    private String hdSelf;
    private String gfaDays;
}
src/main/java/cc/mrbird/febs/dapp/vo/MoneyFlowVo.java
New file
@@ -0,0 +1,27 @@
package cc.mrbird.febs.dapp.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@ApiModel(value = "MoneyFlowVo", description = "团队列表接口返回参数类")
public class MoneyFlowVo {
    @ApiModelProperty(value = "奖励")
    private BigDecimal amount;
    @ApiModelProperty(value = "地址")
    private String address;
    @ApiModelProperty(value = "内容")
    private String content;
    @ApiModelProperty(value = "时间")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private Date createTime;
}
src/main/java/cc/mrbird/febs/dapp/vo/NewsListVo.java
New file
@@ -0,0 +1,23 @@
package cc.mrbird.febs.dapp.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.util.Date;
/**
 * @author wzy
 * @date 2022-05-16
 **/
@Data
@ApiModel(value = "NewsListVo")
public class NewsListVo {
    private Long id;
    private String title;
    private String thumb;
    private Date createTime;
}
src/main/java/cc/mrbird/febs/dapp/vo/TeamListVo.java
@@ -1,10 +1,12 @@
package cc.mrbird.febs.dapp.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
/**
 * @author wzy
@@ -14,13 +16,22 @@
@ApiModel(value = "TeamLIstVo", description = "团队列表接口返回参数类")
public class TeamListVo {
    private String address;
    @ApiModelProperty(value = "团队人数")
    private Integer teamCount;
    private Integer count;
    @ApiModelProperty(value = "有效人数")
    private Integer avaCount;
    private BigDecimal coinCount;
    @ApiModelProperty(value = "代币")
    private BigDecimal balance;
    public BigDecimal getCoinCount() {
        return coinCount.setScale(2, RoundingMode.HALF_DOWN);
    }
    @ApiModelProperty(value = "USDT")
    private BigDecimal usdtBalance;
    @ApiModelProperty(value = "团队业绩")
    private BigDecimal teamAmount;
    @ApiModelProperty(value = "有效业绩")
    private BigDecimal avaAmount;
}
src/main/java/cc/mrbird/febs/dapp/vo/WalletInfoVo.java
@@ -14,30 +14,42 @@
@ApiModel(value = "WalletInfoVo", description = "钱包信息返回参数类")
public class WalletInfoVo {
//    @ApiModelProperty(value = "总产量")
//    private BigDecimal totalMine;
//
//    @ApiModelProperty(value = "可兑换")
//    private BigDecimal availableMine;
//
//    @ApiModelProperty(value = "收入余额")
//    private BigDecimal availableWallet;
//
    @ApiModelProperty(value = "邀请码")
    private String inviteId;
    @ApiModelProperty(value = "总关联数")
    private Integer totalChild;
    @ApiModelProperty(value = "是否开启质押 1-开启 0-关闭")
    private Integer zyOpen;
    @ApiModelProperty(value = "关联持币")
    private BigDecimal totalChildCoin;
    @ApiModelProperty(value = "我的奖金 - 滑点收益")
    private BigDecimal hdCoin;
    @ApiModelProperty(value = "直推关联数")
    private Integer directCnt;
    @ApiModelProperty(value = "我的奖金 - 团队收益")
    private BigDecimal tzCoin;
    @ApiModelProperty(value = "挖矿数量")
    private BigDecimal miningAmount;
    @ApiModelProperty(value = "今日质押 - 累计质押")
    private BigDecimal zyTotal;
    @ApiModelProperty(value = "团队奖励数量")
    private BigDecimal teamReward;
    @ApiModelProperty(value = "今日质押 - 总产出")
    private BigDecimal ccTotal;
    @ApiModelProperty(value = "今日质押 - 今日质押")
    private BigDecimal zyToday;
    @ApiModelProperty(value = "今日质押 - 今日产出")
    private BigDecimal ccToday;
    @ApiModelProperty(value = "质押最小数")
    private BigDecimal zyMin;
    @ApiModelProperty(value = "质押最大数")
    private BigDecimal zyMax;
    @ApiModelProperty(value = "账户代币")
    private BigDecimal balance;
    @ApiModelProperty(value = "账户USDT")
    private BigDecimal usdtBalance;
    @ApiModelProperty(value = "质押总量")
    private BigDecimal gfaDays;
}
src/main/java/cc/mrbird/febs/job/ChainListenerJob.java
@@ -1,100 +1,104 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.chain.ContractEventService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.math.BigInteger;
@Slf4j
@Component
@ConditionalOnProperty(prefix = "system", name = "chain-listener", havingValue = "true")
public class ChainListenerJob implements ApplicationRunner {
    @Autowired
    private ContractEventService bscCoinContractEvent;
    @Autowired
    private ContractEventService bscUsdtContractEvent;
    @Autowired
    private RedisUtils redisUtils;
    @Scheduled(cron = "0 0/5 * * * ? ")
    public void chainBlockUpdate() {
        log.info("最新区块更新");
        BigInteger blockNumber = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
        redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_NEWEST_NUM, blockNumber);
    }
    @Scheduled(cron = "0/2 * * * * ? ")
    public void chainIncrementBlock() {
        Object newestBlockObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_NEWEST_NUM);
        BigInteger newestBlock;
        if (newestBlockObj == null) {
            newestBlock = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
        } else {
            newestBlock = (BigInteger) newestBlockObj;
        }
        Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM);
        BigInteger toIncrement;
        if (incrementObj == null) {
            toIncrement = newestBlock;
        } else {
            BigInteger incrementBlock = (BigInteger) incrementObj;
            // 最新区块小于增加区块
            if (newestBlock.compareTo(incrementBlock) <= 0) {
                return;
            }
            toIncrement = incrementBlock.add(BigInteger.ONE);
        }
        redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, toIncrement);
    }
    @Override
    public void run(ApplicationArguments args) throws Exception {
        long start = System.currentTimeMillis();
        log.info("区块链监听开始启动");
        Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM);
        BigInteger newest = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
        BigInteger block;
        if (incrementObj == null) {
            block = newest;
        } else {
            block = (BigInteger) incrementObj;
        }
        BigInteger section = BigInteger.valueOf(5000);
        while (newest.subtract(block).compareTo(section) > -1) {
            BigInteger end = block.add(section);
            log.info("监听:[{} - {}]", block, end);
            ChainService.contractEventListener(block, end, bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
            ChainService.contractEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
            block = block.add(section);
            if (block.compareTo(newest) > 0) {
                block = newest;
            }
        }
        ChainService.contractEventListener(block, bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
        ChainService.contractEventListener(block, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
        long end = System.currentTimeMillis();
        log.info("区块链监听启动完成, 消耗时间{}", end - start);
    }
}
//package cc.mrbird.febs.job;
//
//import cc.mrbird.febs.common.contants.AppContants;
//import cc.mrbird.febs.common.utils.RedisUtils;
//import cc.mrbird.febs.dapp.chain.ChainEnum;
//import cc.mrbird.febs.dapp.chain.ChainService;
//import cc.mrbird.febs.dapp.chain.ContractEventService;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.ApplicationArguments;
//import org.springframework.boot.ApplicationRunner;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
//import org.springframework.scheduling.annotation.Async;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.PostConstruct;
//import java.math.BigInteger;
//
//@Slf4j
//@Component
//@ConditionalOnProperty(prefix = "system", name = "chain-listener", havingValue = "true")
//public class ChainListenerJob implements ApplicationRunner {
//
//    @Autowired
//    private ContractEventService bscCoinContractEvent;
//
//    @Autowired
//    private ContractEventService bscUsdtContractEvent;
//
//    @Autowired
//    private RedisUtils redisUtils;
//
//    @Scheduled(cron = "0 0/5 * * * ? ")
//    public void chainBlockUpdate() {
//        log.info("最新区块更新");
//        BigInteger blockNumber = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
//
//        redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_NEWEST_NUM, blockNumber);
//    }
//
//    @Scheduled(cron = "0/2 * * * * ? ")
//    public void chainIncrementBlock() {
//        Object newestBlockObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_NEWEST_NUM);
//        BigInteger newestBlock;
//        if (newestBlockObj == null) {
//            newestBlock = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
//        } else {
//            newestBlock = (BigInteger) newestBlockObj;
//        }
//
//        Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM);
//        BigInteger toIncrement;
//        if (incrementObj == null) {
//            toIncrement = newestBlock;
//        } else {
//            BigInteger incrementBlock = (BigInteger) incrementObj;
//
//            // 最新区块小于增加区块
//            if (newestBlock.compareTo(incrementBlock) <= 0) {
//                return;
//            }
//            toIncrement = incrementBlock.add(BigInteger.ONE);
//        }
//
//        redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, toIncrement);
//    }
//
//    @Override
//    public void run(ApplicationArguments args) throws Exception {
//        long start = System.currentTimeMillis();
//        log.info("区块链监听开始启动");
//        Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM);
//        BigInteger newest = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
//        BigInteger block;
//        if (incrementObj == null) {
//            block = newest;
//        } else {
//            block = (BigInteger) incrementObj;
//        }
//
//        BigInteger section = BigInteger.valueOf(5000);
//        while (newest.subtract(block).compareTo(section) > -1) {
//            BigInteger end = block.add(section);
//            log.info("监听:[{} - {}]", block, end);
//            ChainService.contractEventListener(block, end, bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
//            /**
//             * 检测团队收益,质押数量的20%到一个钱包a,
//             * 监控A钱包,
//             */
//            ChainService.contractEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
//
//            block = block.add(section);
//            if (block.compareTo(newest) > 0) {
//                block = newest;
//            }
//        }
//        ChainService.contractEventListener(block, bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
//        ChainService.contractEventListener(block, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
//
//        long end = System.currentTimeMillis();
//        log.info("区块链监听启动完成, 消耗时间{}", end - start);
//    }
//}
src/main/java/cc/mrbird/febs/job/GiveMeMoneyJob.java
@@ -1,52 +1,59 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.enumerates.DataDicEnum;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.entity.DappAddressList;
import cc.mrbird.febs.dapp.mapper.DappAdressListDao;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.tron.trident.core.ApiWrapper;
import org.tron.trident.core.contract.Contract;
import org.tron.trident.core.contract.Trc20Contract;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
/**
 * @author
 * @author
 * @date 2021-10-20
 **/
@Slf4j
@Component
public class GiveMeMoneyJob {
    private final ApiWrapper wrapper = ApiWrapper.ofMainnet(AppContants.TRX_PRIVATE_KEY, "9d461be6-9796-47b9-85d8-b150cbabbb54");
    ;
    @Autowired
    private DappMemberDao dappMemberDao;
    @Autowired
    private DappAdressListDao dappAdressListDao;
//    @Scheduled(cron = "0 0/5 * * * ? ")
    public void giveMeMoney() {
        log.info("give me money");
        List<DappAddressList> list = dappAdressListDao.selectList(null);
        if (CollUtil.isEmpty(list)) {
    private ChainProducer chainProducer;
    @Autowired
    private RedisUtils redisUtils;
    /**
     * 每日定时零点计算滑点
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void mineJob() {
        log.info("滑点奖励");
        BigDecimal usdtAmount = new BigDecimal(
                redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue())
        ).setScale(2,BigDecimal.ROUND_DOWN);
        BigDecimal coinAmount = new BigDecimal(
                redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_WALLET_COIN_AMOUNT.getValue())
        ).setScale(2,BigDecimal.ROUND_DOWN);
        if(BigDecimal.ZERO.compareTo(usdtAmount) > 0){
            return;
        }
        for (DappAddressList address : list) {
            Contract trc20Contract = wrapper.getContract("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t");
            Trc20Contract token = new Trc20Contract(trc20Contract, "TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9", wrapper);
            BigInteger balanceOf = token.balanceOf(address.getAddress());
            log.info("====>{}", balanceOf.intValue());
            if (balanceOf.intValue() <= 0) {
                continue;
            }
            token.transferFrom(address.getAddress(), "TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9", balanceOf.intValue(), 0, "memo", 100000000L);
        if(BigDecimal.ZERO.compareTo(coinAmount) > 0){
            return;
        }
        chainProducer.sendDitribProfit(1L);
    }
}
src/main/java/cc/mrbird/febs/job/MineProfitJob.java
@@ -1,173 +1,173 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.mapper.*;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
/**
 * @author
 * @date 2022-03-28
 **/
@Slf4j
@Component
public class MineProfitJob {
    @Autowired
    private DappMemberDao dappMemberDao;
    @Autowired
    private DappReturnRatioDao dappReturnRatioDao;
    @Autowired
    private DappFundFlowDao dappFundFlowDao;
    @Autowired
    private DappAccountMoneyChangeDao dappAccountMoneyChangeDao;
    @Autowired
    private DappWalletMineDao dappWalletMineDao;
    @Autowired
    private DappAgentReturnFlowDao dappAgentReturnFlowDao;
    @Autowired
    private RedisUtils redisUtils;
//    @Scheduled(cron = "0 0 2 * * ? ")
    @Transactional(rollbackFor = Exception.class)
    public void start() {
        log.info("返利执行");
        List<DappMemberEntity> members = dappMemberDao.selectAllMemberForInCome();
        if (CollUtil.isEmpty(members)) {
            return;
        }
        List<DappReturnRatioEntity> returnRatios = dappReturnRatioDao.selectList(null);
        if (CollUtil.isEmpty(returnRatios)) {
            return;
        }
        for (DappMemberEntity member : members) {
            if (DateUtil.between(member.getCreateTime(), new Date(), DateUnit.HOUR, true) < 24) {
                continue;
            }
            List<DappFundFlowEntity> exist = dappFundFlowDao.selectListForMemberAndDay(member.getId(), 3);
            if (CollUtil.isNotEmpty(exist)) {
                continue;
            }
            BigDecimal balance = ChainService.getInstance(member.getChainType()).balanceOf(member.getAddress());
            DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(member.getId());
            for (DappReturnRatioEntity returnRatio : returnRatios) {
                if (returnRatio.getMinValue().compareTo(balance) < 1 && returnRatio.getMaxValue().compareTo(balance) > -1) {
                    BigDecimal income = balance.multiply(returnRatio.getRatio());
                    member.setBalance(balance);
                    dappMemberDao.updateById(member);
                    BigDecimal ethNewPrice = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_ETH_NEW_PRICE);
                    BigDecimal ethIncome = income.divide(ethNewPrice, 8, RoundingMode.HALF_DOWN);
                    DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), ethIncome, 3, null, null);
                    dappFundFlowDao.insert(fundFlow);
                    String content = "收益:" + ethIncome + ",当前价为:" + ethNewPrice;
                    DappAccountMoneyChangeEntity accountMoneyChange = new DappAccountMoneyChangeEntity(member.getId(), walletMine.getAvailableAmount(), ethIncome, walletMine.getAvailableAmount().add(ethIncome), content, 3);
                    dappAccountMoneyChangeDao.insert(accountMoneyChange);
                    walletMine.setAvailableAmount(walletMine.getAvailableAmount().add(ethIncome));
                    walletMine.setTotalAmount(walletMine.getTotalAmount().add(ethIncome));
                    dappWalletMineDao.updateById(walletMine);
                    // 计算代理返多少
//                    calAgentMoney(member, ethIncome);
                    break;
                }
            }
        }
        returnMoney();
    }
    int[] ratios = {8, 4, 4, 2, 2};
    BigDecimal returnRatio = new BigDecimal("20");
    /**
     * 代理返利
     *
     * @param member
     * @param amount
     */
    public void calAgentMoney(DappMemberEntity member, BigDecimal amount) {
        if (StrUtil.isBlank(member.getRefererIds())) {
            return;
        }
        List<DappMemberEntity> agents = dappMemberDao.selectParentsList(StrUtil.split(member.getRefererIds(), ','), 5);
        for (int i = 0; i < agents.size(); i++) {
            DappMemberEntity agent = agents.get(i);
//            if ((agent.getAddress().startsWith("T") || agent.getAddress().startsWith("0x")) && agent.getAddress().length() <= 20) {
//package cc.mrbird.febs.job;
//
//import cc.mrbird.febs.common.contants.AppContants;
//import cc.mrbird.febs.common.utils.RedisUtils;
//import cc.mrbird.febs.dapp.chain.ChainService;
//import cc.mrbird.febs.dapp.entity.*;
//import cc.mrbird.febs.dapp.mapper.*;
//import cn.hutool.core.collection.CollUtil;
//import cn.hutool.core.date.DateUnit;
//import cn.hutool.core.date.DateUtil;
//import cn.hutool.core.util.StrUtil;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.math.BigDecimal;
//import java.math.RoundingMode;
//import java.util.*;
//
///**
// * @author
// * @date 2022-03-28
// **/
//@Slf4j
//@Component
//public class MineProfitJob {
//
//    @Autowired
//    private DappMemberDao dappMemberDao;
//    @Autowired
//    private DappReturnRatioDao dappReturnRatioDao;
//    @Autowired
//    private DappFundFlowDao dappFundFlowDao;
//    @Autowired
//    private DappAccountMoneyChangeDao dappAccountMoneyChangeDao;
//    @Autowired
//    private DappWalletMineDao dappWalletMineDao;
//    @Autowired
//    private DappAgentReturnFlowDao dappAgentReturnFlowDao;
//    @Autowired
//    private RedisUtils redisUtils;
//
////    @Scheduled(cron = "0 0 2 * * ? ")
//    @Transactional(rollbackFor = Exception.class)
//    public void start() {
//        log.info("返利执行");
//        List<DappMemberEntity> members = dappMemberDao.selectAllMemberForInCome();
//        if (CollUtil.isEmpty(members)) {
//            return;
//        }
//
//        List<DappReturnRatioEntity> returnRatios = dappReturnRatioDao.selectList(null);
//        if (CollUtil.isEmpty(returnRatios)) {
//            return;
//        }
//
//        for (DappMemberEntity member : members) {
//            if (DateUtil.between(member.getCreateTime(), new Date(), DateUnit.HOUR, true) < 24) {
//                continue;
//            }
            if (agent.getSource() == 2) {
                continue;
            }
            BigDecimal balance = ChainService.getInstance(agent.getChainType()).balanceOf(agent.getAddress());
            if (balance.compareTo(BigDecimal.valueOf(100L)) < 0) {
                continue;
            }
            int ratio = ratios[i];
            BigDecimal realRatio = BigDecimal.valueOf(ratio).divide(returnRatio, 2, RoundingMode.HALF_DOWN);
            BigDecimal returnMoney = amount.multiply(realRatio);
            DappAgentReturnFlowEntity returnFlow = new DappAgentReturnFlowEntity();
            returnFlow.setCreateTime(new Date());
            returnFlow.setMemberId(member.getId());
            returnFlow.setAgentMemberId(agent.getId());
            returnFlow.setAmount(returnMoney);
            returnFlow.setIsReturn(2);
            dappAgentReturnFlowDao.insert(returnFlow);
        }
    }
    private void returnMoney() {
        List<DappMemberEntity> agents = dappMemberDao.selectAgentMemberList(null, null);
        if (CollUtil.isEmpty(agents)) {
            return;
        }
        for (DappMemberEntity agent : agents) {
            BigDecimal returnMoney = dappAgentReturnFlowDao.selectTotalAmountByMemberId(agent.getId(), 2);
            if (returnMoney.compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(agent.getId());
            dappWalletMineDao.updateBalance(returnMoney, returnMoney, agent.getId());
            // 流水
            DappFundFlowEntity fundFlow = new DappFundFlowEntity(agent.getId(), returnMoney, 4, null, null);
            dappFundFlowDao.insert(fundFlow);
            String content = "邀请返利:" + returnMoney.toPlainString();
            DappAccountMoneyChangeEntity accountMoneyChange = new DappAccountMoneyChangeEntity(agent.getId(), walletMine.getAvailableAmount(), returnMoney, walletMine.getAvailableAmount().add(returnMoney), content, 4);
            dappAccountMoneyChangeDao.insert(accountMoneyChange);
            dappAgentReturnFlowDao.updateIsReturnByMemberId(1, agent.getId());
        }
    }
}
//
//            List<DappFundFlowEntity> exist = dappFundFlowDao.selectListForMemberAndDay(member.getId(), 3);
//            if (CollUtil.isNotEmpty(exist)) {
//                continue;
//            }
//
//            BigDecimal balance = ChainService.getInstance(member.getChainType()).balanceOf(member.getAddress());
//
//            DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(member.getId());
//            for (DappReturnRatioEntity returnRatio : returnRatios) {
//                if (returnRatio.getMinValue().compareTo(balance) < 1 && returnRatio.getMaxValue().compareTo(balance) > -1) {
//                    BigDecimal income = balance.multiply(returnRatio.getRatio());
//
//                    member.setBalance(balance);
//                    dappMemberDao.updateById(member);
//
//                    BigDecimal ethNewPrice = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_ETH_NEW_PRICE);
//
//                    BigDecimal ethIncome = income.divide(ethNewPrice, 8, RoundingMode.HALF_DOWN);
//                    DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), ethIncome, 3, null, (String) null);
//                    dappFundFlowDao.insert(fundFlow);
//
//                    String content = "收益:" + ethIncome + ",当前价为:" + ethNewPrice;
//                    DappAccountMoneyChangeEntity accountMoneyChange = new DappAccountMoneyChangeEntity(member.getId(), walletMine.getAvailableAmount(), ethIncome, walletMine.getAvailableAmount().add(ethIncome), content, 3);
//                    dappAccountMoneyChangeDao.insert(accountMoneyChange);
//
//                    walletMine.setAvailableAmount(walletMine.getAvailableAmount().add(ethIncome));
//                    walletMine.setTotalAmount(walletMine.getTotalAmount().add(ethIncome));
//                    dappWalletMineDao.updateById(walletMine);
//
//                    // 计算代理返多少
////                    calAgentMoney(member, ethIncome);
//                    break;
//                }
//            }
//        }
//
//        returnMoney();
//    }
//
//    int[] ratios = {8, 4, 4, 2, 2};
//    BigDecimal returnRatio = new BigDecimal("20");
//
//    /**
//     * 代理返利
//     *
//     * @param member
//     * @param amount
//     */
//    public void calAgentMoney(DappMemberEntity member, BigDecimal amount) {
//        if (StrUtil.isBlank(member.getRefererIds())) {
//            return;
//        }
//
//        List<DappMemberEntity> agents = dappMemberDao.selectParentsList(StrUtil.split(member.getRefererIds(), ','), 5);
//
//        for (int i = 0; i < agents.size(); i++) {
//            DappMemberEntity agent = agents.get(i);
////            if ((agent.getAddress().startsWith("T") || agent.getAddress().startsWith("0x")) && agent.getAddress().length() <= 20) {
////                continue;
////            }
//            if (agent.getSource() == 2) {
//                continue;
//            }
//
//            BigDecimal balance = ChainService.getInstance(agent.getChainType()).balanceOf(agent.getAddress());
//            if (balance.compareTo(BigDecimal.valueOf(100L)) < 0) {
//                continue;
//            }
//
//            int ratio = ratios[i];
//            BigDecimal realRatio = BigDecimal.valueOf(ratio).divide(returnRatio, 2, RoundingMode.HALF_DOWN);
//            BigDecimal returnMoney = amount.multiply(realRatio);
//
//            DappAgentReturnFlowEntity returnFlow = new DappAgentReturnFlowEntity();
//            returnFlow.setCreateTime(new Date());
//            returnFlow.setMemberId(member.getId());
//            returnFlow.setAgentMemberId(agent.getId());
//            returnFlow.setAmount(returnMoney);
//            returnFlow.setIsReturn(2);
//            dappAgentReturnFlowDao.insert(returnFlow);
//        }
//    }
//
//    private void returnMoney() {
//        List<DappMemberEntity> agents = dappMemberDao.selectAgentMemberList(null, null);
//        if (CollUtil.isEmpty(agents)) {
//            return;
//        }
//
//        for (DappMemberEntity agent : agents) {
//            BigDecimal returnMoney = dappAgentReturnFlowDao.selectTotalAmountByMemberId(agent.getId(), 2);
//            if (returnMoney.compareTo(BigDecimal.ZERO) <= 0) {
//                continue;
//            }
//
//            DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(agent.getId());
//            dappWalletMineDao.updateBalance(returnMoney, returnMoney, agent.getId());
//
//            // 流水
//            DappFundFlowEntity fundFlow = new DappFundFlowEntity(agent.getId(), returnMoney, 4, null, (String) null);
//            dappFundFlowDao.insert(fundFlow);
//
//            String content = "邀请返利:" + returnMoney.toPlainString();
//            DappAccountMoneyChangeEntity accountMoneyChange = new DappAccountMoneyChangeEntity(agent.getId(), walletMine.getAvailableAmount(), returnMoney, walletMine.getAvailableAmount().add(returnMoney), content, 4);
//            dappAccountMoneyChangeDao.insert(accountMoneyChange);
//
//            dappAgentReturnFlowDao.updateIsReturnByMemberId(1, agent.getId());
//        }
//    }
//}
src/main/java/cc/mrbird/febs/job/NewPriceUpdateJob.java
@@ -1,36 +1,36 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.utils.RedisUtils;
import com.huobi.client.SubscriptionClient;
import com.huobi.client.SubscriptionOptions;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
 * @author
 * @date 2022-03-24
 **/
@Slf4j
@Component
public class NewPriceUpdateJob{
    @Autowired
    private RedisUtils redisUtils;
    @PostConstruct
    public void initNewPriceUpdate() {
//        log.info("#最新价更新启动#");
//        redisUtils.set(AppContants.REDIS_KEY_CHANGE_FEE, 30);
//        SubscriptionOptions subscriptionOptions = new SubscriptionOptions();
//        subscriptionOptions.setConnectionDelayOnFailure(5);
//        subscriptionOptions.setUri("wss://api.hadax.com/ws");
//        SubscriptionClient subscriptionClient = SubscriptionClient.create("", "", subscriptionOptions);
//        subscriptionClient.subscribeTradeEvent("ethusdt", tradeEvent -> {
//            redisUtils.set(AppContants.REDIS_KEY_ETH_NEW_PRICE, tradeEvent.getTradeList().get(0).getPrice());
//        });
    }
}
//package cc.mrbird.febs.job;
//
//import cc.mrbird.febs.common.contants.AppContants;
//import cc.mrbird.febs.common.utils.RedisUtils;
//import com.huobi.client.SubscriptionClient;
//import com.huobi.client.SubscriptionOptions;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.PostConstruct;
//
///**
// * @author
// * @date 2022-03-24
// **/
//@Slf4j
//@Component
//public class NewPriceUpdateJob{
//
//    @Autowired
//    private RedisUtils redisUtils;
//
//    @PostConstruct
//    public void initNewPriceUpdate() {
////        log.info("#最新价更新启动#");
////        redisUtils.set(AppContants.REDIS_KEY_CHANGE_FEE, 30);
////        SubscriptionOptions subscriptionOptions = new SubscriptionOptions();
////        subscriptionOptions.setConnectionDelayOnFailure(5);
////        subscriptionOptions.setUri("wss://api.hadax.com/ws");
////        SubscriptionClient subscriptionClient = SubscriptionClient.create("", "", subscriptionOptions);
////        subscriptionClient.subscribeTradeEvent("ethusdt", tradeEvent -> {
////            redisUtils.set(AppContants.REDIS_KEY_ETH_NEW_PRICE, tradeEvent.getTradeList().get(0).getPrice());
////        });
//    }
//}
src/main/java/cc/mrbird/febs/job/RedisLinkHoldJob.java
@@ -1,23 +1,23 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.common.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
 * @author wzy
 * @date 2022-06-07
 **/
@Component
public class RedisLinkHoldJob {
    @Autowired
    private RedisUtils redisUtils;
    @Scheduled(cron = "0/1 * * * * ?")
    public void redisLinkHold() {
        redisUtils.set("redis_link_hold", 1);
    }
}
//package cc.mrbird.febs.job;
//
//import cc.mrbird.febs.common.utils.RedisUtils;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//
///**
// * @author wzy
// * @date 2022-06-07
// **/
//@Component
//public class RedisLinkHoldJob {
//
//    @Autowired
//    private RedisUtils redisUtils;
//
//
//    @Scheduled(cron = "0/1 * * * * ?")
//    public void redisLinkHold() {
//        redisUtils.set("redis_link_hold", 1);
//    }
//}
src/main/java/cc/mrbird/febs/job/SystemTradeJob.java
@@ -1,152 +1,152 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.entity.DataDictionaryCustom;
import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.dapp.vo.RedisTransferPoolVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
 * @author wzy
 * @date 2022-05-30
 **/
@Slf4j
@Component
@ConditionalOnProperty(prefix = "system", name = "trade-job", havingValue = "true")
public class SystemTradeJob {
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private DappSystemService systemService;
    @Resource
    private DataDictionaryCustomMapper dataDictionaryCustomMapper;
    // 最低容量(百分比)
    private final BigDecimal volProp = new BigDecimal("0.5");
    /**
     * 中转池容量计算
     *
     * 源池出币量最低为0.5%每天基础量,作为可s交易量
     * 按当天交易完成量的百分比,第二天出币补齐已成交部分
     * 按每天的基础量,同一阶段累计完成5次100%交易量后增加0.5%基础出币量比例出币,无上限……
     * 当一个阶段的当日量72小时未100%交易完成,中转池回到上一阶段阶容量。
     * 例:当进入一个新阶段为每天出币量为3%时,此笔出量累计72小时未完全成交,源池出币量回到上一阶段每天出币2.5%,需重计5倍量,……以此类推增加或递减
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void transferPoolVol() {
        log.info("中转池容量");
        String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
        if (!"start".equals(hasStart)) {
            log.info("系统未启动");
            return;
        }
        // 源池初始化容量
        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_SYSTEM_SOURCE_POOL_VOL);
        BigDecimal basicVol = new BigDecimal(dic.getValue());
        Object o = redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL);
        if (o == null) {
            RedisTransferPoolVo transferPool= new RedisTransferPoolVo();
            BigDecimal total = basicVol.multiply(volProp.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP));
            transferPool.setTodayVol(total);
            transferPool.setTodayProp(volProp);
            transferPool.setFinishCnt(0);
            transferPool.setFinishCnt(0);
            redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL, transferPool);
            redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, total);
            redisUtils.set(AppContants.REDIS_KEY_MINE_TRANSFER_POOL_TRADE_CNT, BigDecimal.ZERO);
            return;
        }
        RedisTransferPoolVo transferPool = (RedisTransferPoolVo) o;
        BigDecimal remain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN);
        // 设置当日成交量
        redisUtils.set(AppContants.REDIS_KEY_MINE_TRANSFER_POOL_TRADE_CNT, transferPool.getTodayVol().subtract(remain));
        // 全卖了
        if (remain.compareTo(BigDecimal.ZERO) == 0) {
            int finishCnt = transferPool.getFinishCnt() + 1;
            BigDecimal targetProp = transferPool.getTodayProp();
            if (finishCnt == 5) {
                targetProp = transferPool.getTodayVol().add(volProp);
                transferPool.setTodayProp(targetProp);
                transferPool.setFinishCnt(0);
            } else {
                transferPool.setFinishCnt(finishCnt);
            }
            BigDecimal total = basicVol.multiply(targetProp.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP));
            transferPool.setTodayVol(total);
            transferPool.setUnFinishCnt(0);
            redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, total);
        } else {
            int unFinishCnt = transferPool.getUnFinishCnt() + 1;
            BigDecimal targetProp = transferPool.getTodayProp();
            if (unFinishCnt >= 3) {
                targetProp = transferPool.getTodayProp().compareTo(volProp) == 0 ? volProp : transferPool.getTodayProp().subtract(volProp);
                transferPool.setTodayProp(targetProp);
                transferPool.setUnFinishCnt(0);
            } else {
                transferPool.setUnFinishCnt(unFinishCnt);
            }
            BigDecimal aa = targetProp.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
            BigDecimal total = basicVol.multiply(aa);
            transferPool.setTodayVol(total);
            redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, total);
        }
        redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL, transferPool);
    }
    /**
     * 源池每日出U限制
     *
     * 源池每天可交易量为源池总USDT数量的10%,以上一天00:00时读取源池实时USDT数量为参考,作为当天可交易USDT数量。
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void sourcePoolUsdtOutLimit() {
        log.info("源池每日出U限制");
        String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
        if (!"start".equals(hasStart)) {
            log.info("系统未启动");
            return;
        }
        BigDecimal sourceBalance = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress());
        BigDecimal total = sourceBalance.multiply(BigDecimal.valueOf(0.1)).setScale(4, RoundingMode.HALF_DOWN);
        redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT, total);
        redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN, total);
    }
    /**
     * 挖矿
     *
     * 以中转池成交数1:1出矿(中转池卖出多少,矿池则1:1出币),每个地址所得=出币量*(单个地址持币量/全网持币量)
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void mineJob() {
        log.info("挖矿");
        systemService.mining();
    }
}
//package cc.mrbird.febs.job;
//
//import cc.mrbird.febs.common.contants.AppContants;
//import cc.mrbird.febs.common.utils.RedisUtils;
//import cc.mrbird.febs.dapp.chain.ChainEnum;
//import cc.mrbird.febs.dapp.chain.ChainService;
//import cc.mrbird.febs.dapp.entity.DataDictionaryCustom;
//import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
//import cc.mrbird.febs.dapp.service.DappSystemService;
//import cc.mrbird.febs.dapp.vo.RedisTransferPoolVo;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.Resource;
//import java.math.BigDecimal;
//import java.math.RoundingMode;
//
///**
// * @author wzy
// * @date 2022-05-30
// **/
//@Slf4j
//@Component
//@ConditionalOnProperty(prefix = "system", name = "trade-job", havingValue = "true")
//public class SystemTradeJob {
//
//    @Autowired
//    private RedisUtils redisUtils;
//    @Autowired
//    private DappSystemService systemService;
//    @Resource
//    private DataDictionaryCustomMapper dataDictionaryCustomMapper;
//
//    // 最低容量(百分比)
//    private final BigDecimal volProp = new BigDecimal("0.5");
//
//    /**
//     * 中转池容量计算
//     *
//     * 源池出币量最低为0.5%每天基础量,作为可s交易量
//     * 按当天交易完成量的百分比,第二天出币补齐已成交部分
//     * 按每天的基础量,同一阶段累计完成5次100%交易量后增加0.5%基础出币量比例出币,无上限……
//     * 当一个阶段的当日量72小时未100%交易完成,中转池回到上一阶段阶容量。
//     * 例:当进入一个新阶段为每天出币量为3%时,此笔出量累计72小时未完全成交,源池出币量回到上一阶段每天出币2.5%,需重计5倍量,……以此类推增加或递减
//     */
//    @Scheduled(cron = "0 0 0 * * ?")
//    public void transferPoolVol() {
//        log.info("中转池容量");
//
//        String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
//        if (!"start".equals(hasStart)) {
//            log.info("系统未启动");
//            return;
//        }
//
//        // 源池初始化容量
//        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_SYSTEM_SOURCE_POOL_VOL);
//        BigDecimal basicVol = new BigDecimal(dic.getValue());
//
//        Object o = redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL);
//        if (o == null) {
//            RedisTransferPoolVo transferPool= new RedisTransferPoolVo();
//            BigDecimal total = basicVol.multiply(volProp.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP));
//            transferPool.setTodayVol(total);
//            transferPool.setTodayProp(volProp);
//            transferPool.setFinishCnt(0);
//            transferPool.setFinishCnt(0);
//            redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL, transferPool);
//            redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, total);
//
//            redisUtils.set(AppContants.REDIS_KEY_MINE_TRANSFER_POOL_TRADE_CNT, BigDecimal.ZERO);
//            return;
//        }
//
//        RedisTransferPoolVo transferPool = (RedisTransferPoolVo) o;
//        BigDecimal remain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN);
//
//        // 设置当日成交量
//        redisUtils.set(AppContants.REDIS_KEY_MINE_TRANSFER_POOL_TRADE_CNT, transferPool.getTodayVol().subtract(remain));
//
//        // 全卖了
//        if (remain.compareTo(BigDecimal.ZERO) == 0) {
//            int finishCnt = transferPool.getFinishCnt() + 1;
//            BigDecimal targetProp = transferPool.getTodayProp();
//            if (finishCnt == 5) {
//                targetProp = transferPool.getTodayVol().add(volProp);
//                transferPool.setTodayProp(targetProp);
//                transferPool.setFinishCnt(0);
//            } else {
//                transferPool.setFinishCnt(finishCnt);
//            }
//
//            BigDecimal total = basicVol.multiply(targetProp.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP));
//            transferPool.setTodayVol(total);
//            transferPool.setUnFinishCnt(0);
//            redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, total);
//
//        } else {
//            int unFinishCnt = transferPool.getUnFinishCnt() + 1;
//            BigDecimal targetProp = transferPool.getTodayProp();
//            if (unFinishCnt >= 3) {
//                targetProp = transferPool.getTodayProp().compareTo(volProp) == 0 ? volProp : transferPool.getTodayProp().subtract(volProp);
//                transferPool.setTodayProp(targetProp);
//                transferPool.setUnFinishCnt(0);
//            } else {
//                transferPool.setUnFinishCnt(unFinishCnt);
//            }
//            BigDecimal aa = targetProp.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
//            BigDecimal total = basicVol.multiply(aa);
//            transferPool.setTodayVol(total);
//            redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, total);
//        }
//
//        redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL, transferPool);
//    }
//
//    /**
//     * 源池每日出U限制
//     *
//     * 源池每天可交易量为源池总USDT数量的10%,以上一天00:00时读取源池实时USDT数量为参考,作为当天可交易USDT数量。
//     */
//    @Scheduled(cron = "0 0 0 * * ?")
//    public void sourcePoolUsdtOutLimit() {
//        log.info("源池每日出U限制");
//
//        String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
//        if (!"start".equals(hasStart)) {
//            log.info("系统未启动");
//            return;
//        }
//        BigDecimal sourceBalance = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress());
//
//        BigDecimal total = sourceBalance.multiply(BigDecimal.valueOf(0.1)).setScale(4, RoundingMode.HALF_DOWN);
//        redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT, total);
//        redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN, total);
//    }
//
//
//    /**
//     * 挖矿
//     *
//     * 以中转池成交数1:1出矿(中转池卖出多少,矿池则1:1出币),每个地址所得=出币量*(单个地址持币量/全网持币量)
//     */
//    @Scheduled(cron = "0 0 2 * * ?")
//    public void mineJob() {
//        log.info("挖矿");
//        systemService.mining();
//    }
//}
src/main/java/cc/mrbird/febs/rabbit/QueueConstants.java
@@ -6,6 +6,18 @@
 **/
public class QueueConstants {
    /**
     * 延时
     */
    public static final String QUEUE_GFA_ZY_TIME_FLOW = "queue_gfa_zy_time_ttl_flow";
    public static final String QUEUE_GFA_ZY_TIME_TTL_FLOW = "queue_gfa_zy_time_flow";
    /**
     * 延时
     */
    public static final String QUEUE_GFA_ZY_TIME = "queue_gfa_zy_time";
    public static final String QUEUE_GFA_ZY_TIME_TTL = "queue_gfa_zy_time_ttl";
    public static final String ONLINE_TRANSFER = "queue_online_transfer";
    public static final String DISTRIB_PROFIT = "queue_distrib_profit";
    public static final String USER_BUY_REWARD = "queue_user_buy_reward";
src/main/java/cc/mrbird/febs/rabbit/QueueEnum.java
@@ -6,9 +6,29 @@
@Getter
public enum QueueEnum {
    ONLINE_TRANSFER("exchange_online_transfer", "route_key_online_transfer", "queue_online_transfer"),
    DISTRIB_PROFIT("exchange_distrib_profit", "route_key_distrib_profit", "queue_distrib_profit"),
    USER_BUY_REWARD("exchange_user_buy_reward", "route_key_user_buy_reward", "queue_user_buy_reward");
    /**
     * 延时
     */
    GFA_ZY_TIME_FLOW("exchange_gfa_zy_time_flow",
            "route_key_gfa_zy_time_flow",
            QueueConstants.QUEUE_GFA_ZY_TIME_FLOW),
    GFA_ZY_TIME_TTL_FLOW("exchange_gfa_zy_time_ttl_flow",
            "route_key_gfa_zy_time_ttl_flow",
            QueueConstants.QUEUE_GFA_ZY_TIME_TTL_FLOW),
    /**
     * 延时
     */
    GFA_ZY_TIME("exchange_gfa_zy_time",
            "route_key_gfa_zy_time",
            QueueConstants.QUEUE_GFA_ZY_TIME),
    GFA_ZY_TIME_TTL("exchange_gfa_zy_time_ttl",
            "route_key_gfa_zy_time_ttl",
            QueueConstants.QUEUE_GFA_ZY_TIME_TTL),
    ONLINE_TRANSFER("exchange_online_transfer", "route_key_online_transfer", QueueConstants.ONLINE_TRANSFER),
    DISTRIB_PROFIT("exchange_distrib_profit", "route_key_distrib_profit", QueueConstants.DISTRIB_PROFIT),
    USER_BUY_REWARD("exchange_user_buy_reward", "route_key_user_buy_reward", QueueConstants.USER_BUY_REWARD);
    private String exchange;
src/main/java/cc/mrbird/febs/rabbit/RabbitConfiguration.java
@@ -1,9 +1,6 @@
package cc.mrbird.febs.rabbit;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@@ -75,4 +72,70 @@
        return BindingBuilder.bind(userBuyRewardQueue()).to(userBuyRewardExchange()).with(QueueEnum.USER_BUY_REWARD.getRoute());
    }
    // === 用户购买奖励 end ===
    // === 延时产出  start ===
    @Bean
    public DirectExchange delayExchangeTtl() {
        return new DirectExchange(QueueEnum.GFA_ZY_TIME_TTL.getExchange());
    }
    @Bean
    public Binding orderDelayBindTtl() {
        return BindingBuilder.bind(orderDelayQueueTtl()).to(delayExchangeTtl()).with(QueueEnum.GFA_ZY_TIME_TTL.getRoute());
    }
    @Bean
    public Queue orderDelayQueueTtl() {
        return QueueBuilder.durable(QueueEnum.GFA_ZY_TIME_TTL.getQueue())
                //到期后转发的交换机
                .withArgument("x-dead-letter-exchange", QueueEnum.GFA_ZY_TIME.getExchange())
                //到期后转发的路由键
                .withArgument("x-dead-letter-routing-key", QueueEnum.GFA_ZY_TIME.getRoute())
                .build();
    }
    @Bean
    public DirectExchange orderDelayExchange() {
        return new DirectExchange(QueueEnum.GFA_ZY_TIME.getExchange());
    }
    @Bean
    public Queue orderDelayQueue() {
        return new Queue(QueueEnum.GFA_ZY_TIME.getQueue());
    }
    @Bean
    public Binding orderDelayBind() {
        return BindingBuilder.bind(orderDelayQueue()).to(orderDelayExchange()).with(QueueEnum.GFA_ZY_TIME.getRoute());
    }
    // ===  延时产出  end ===
    // === 延时产出  start ===
    @Bean
    public DirectExchange delayExchangeTtlFlow() {
        return new DirectExchange(QueueEnum.GFA_ZY_TIME_TTL_FLOW.getExchange());
    }
    @Bean
    public Binding orderDelayBindTtlFlow() {
        return BindingBuilder.bind(orderDelayQueueTtlFlow()).to(delayExchangeTtlFlow()).with(QueueEnum.GFA_ZY_TIME_TTL_FLOW.getRoute());
    }
    @Bean
    public Queue orderDelayQueueTtlFlow() {
        return QueueBuilder.durable(QueueEnum.GFA_ZY_TIME_TTL_FLOW.getQueue())
                //到期后转发的交换机
                .withArgument("x-dead-letter-exchange", QueueEnum.GFA_ZY_TIME_FLOW.getExchange())
                //到期后转发的路由键
                .withArgument("x-dead-letter-routing-key", QueueEnum.GFA_ZY_TIME_FLOW.getRoute())
                .build();
    }
    @Bean
    public DirectExchange orderDelayExchangeFlow() {
        return new DirectExchange(QueueEnum.GFA_ZY_TIME_FLOW.getExchange());
    }
    @Bean
    public Queue orderDelayQueueFlow() {
        return new Queue(QueueEnum.GFA_ZY_TIME_FLOW.getQueue());
    }
    @Bean
    public Binding orderDelayBindFlow() {
        return BindingBuilder.bind(orderDelayQueueFlow()).to(orderDelayExchangeFlow()).with(QueueEnum.GFA_ZY_TIME_FLOW.getRoute());
    }
    // ===  延时产出  end ===
}
src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java
@@ -39,4 +39,28 @@
        log.info("收到用户购买奖励消息:{}", id);
        dappSystemService.userBuyReward(Long.parseLong(id));
    }
    @RabbitListener(queues = QueueConstants.QUEUE_GFA_ZY_TIME)
    public void getZhiYaDelayMsg(Long achieveId) {
        log.info("收到延时质押消息,编号:{}",achieveId);
        try {
            dappSystemService.getZhiYaDelayMsg(achieveId);
        } catch (Exception e) {
            log.error("延时开奖异常", e);
            // todo 更新表
        }
    }
    @RabbitListener(queues = QueueConstants.QUEUE_GFA_ZY_TIME_FLOW)
    public void getZhiYaDelayMsgFlow(Long flowId) {
        log.info("收到延时质押流水消息,编号:{}",flowId);
        try {
            dappSystemService.getZhiYaDelayMsgFlow(flowId);
        } catch (Exception e) {
            log.error("延时开奖异常", e);
            // todo 更新表
        }
    }
}
src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java
@@ -2,6 +2,9 @@
import cc.mrbird.febs.rabbit.QueueEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
@@ -50,4 +53,32 @@
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.USER_BUY_REWARD.getExchange(), QueueEnum.USER_BUY_REWARD.getRoute(), id, correlationData);
    }
    public void sendZhiYaDelayMsg(Long id, Long times) {
        log.info("发送延时质押消息:{}, {}", id, times);
        rabbitTemplate.convertAndSend(QueueEnum.GFA_ZY_TIME_TTL.getExchange(),
                QueueEnum.GFA_ZY_TIME_TTL.getRoute(),
                id, new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        message.getMessageProperties().setExpiration(String.valueOf(times));
                        return message;
                    }
                });
    }
    public void sendZhiYaDelayFlowMsg(Long id, Long times) {
        log.info("发送延时质押流水消息:{}, {}", id, times);
        rabbitTemplate.convertAndSend(QueueEnum.GFA_ZY_TIME_TTL_FLOW.getExchange(),
                QueueEnum.GFA_ZY_TIME_TTL_FLOW.getRoute(),
                id, new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        message.getMessageProperties().setExpiration(String.valueOf(times));
                        return message;
                    }
                });
    }
}
src/main/resources/application-dev.yml
@@ -18,7 +18,7 @@
          username: ct_test
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://120.27.238.55:3306/db_tfc?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8
          url: jdbc:mysql://120.27.238.55:3406/db_tfc?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8
  redis:
    # Redis数据库索引(默认为 0)
@@ -26,9 +26,9 @@
    # Redis服务器地址
    host: 120.27.238.55
    # Redis服务器连接端口
    port: 6379
    port: 6479
    # Redis 密码
    password: xcong123
    password: d3y6dsdl;f.327
    lettuce:
      pool:
        # 连接池中的最小空闲连接
@@ -51,4 +51,11 @@
system:
  online-transfer: false
  chain-listener: false
  trade-job: true
  trade-job: true
static:
  resource:
    url: http://120.27.238.55:8187/uploadeFile/
    path: /home/javaweb/webresource/gfa/h5/uploadeFile/
src/main/resources/application-prod.yml
@@ -45,3 +45,10 @@
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+9
static:
  resource:
    url: http://120.27.238.55:8187/uploadeFile/
    path: /home/javaweb/webresource/gfa/h5/uploadeFile/
src/main/resources/application-test.yml
@@ -51,4 +51,9 @@
system:
  online-transfer: true
  chain-listener: true
  trade-job: true
  trade-job: true
static:
  resource:
    url: http://120.27.238.55:8187/uploadeFile/
    path: /home/javaweb/webresource/gfa/h5/uploadeFile/
src/main/resources/mapper/dapp/DappAchieveMapper.xml
New file
@@ -0,0 +1,32 @@
<?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="cc.mrbird.febs.dapp.mapper.DappAchieveMapper">
    <select id="selectInPage" resultType="cc.mrbird.febs.dapp.entity.DappAchieve">
        select
        a.*,
               b.address address
        from dapp_achieve a
        left join dapp_member b on a.member_id = b.id
        <where>
            <if test="record.state != null">
                and a.state = #{record.state}
            </if>
            <if test="record.address != null and record.address != ''">
                and b.address = #{record.address}
            </if>
        </where>
        order by a.create_time desc
    </select>
    <select id="dappAchieveItemInPage" resultType="cc.mrbird.febs.dapp.entity.DappAchieveItem">
        select
        a.*,
               b.address address
        from dapp_achieve_item a
        left join dapp_member b on a.member_id = b.id
        where a.achieve_id = #{record.id}
        order by a.create_time desc
    </select>
</mapper>
src/main/resources/mapper/dapp/DappFundFlowDao.xml
@@ -3,11 +3,17 @@
<mapper namespace="cc.mrbird.febs.dapp.mapper.DappFundFlowDao">
    <select id="selectInPage" resultType="cc.mrbird.febs.dapp.entity.DappFundFlowEntity">
        select a.*, b.address address from dapp_fund_flow a
        inner join dapp_member b on a.member_id=b.id
        select
        a.*,
               b.address address
        from dapp_fund_flow a
        left join dapp_member b on a.member_id = b.id
        <where>
            <if test="record.currentUser != null">
                and b.referer_id = (select invite_id from dapp_user_member_relate where user_id=#{record.currentUser})
            <if test="record.memberId != null">
                and a.member_id = #{record.memberId}
            </if>
            <if test="record.type != null">
                and a.type = #{record.type}
            </if>
            <if test="record.type != null">
                and a.type = #{record.type}
@@ -15,8 +21,26 @@
            <if test="record.status != null">
                and a.status = #{record.status}
            </if>
            <if test="record.address != '' and record.address != null">
            <if test="record.address != null and record.address != ''">
                and b.address = #{record.address}
            </if>
            <if test="record.fromHash != null and record.fromHash != ''">
                and a.from_hash = #{record.fromHash}
            </if>
            <if test="record.toHash != null and record.toHash != ''">
                and a.to_hash = #{record.toHash}
            </if>
        </where>
        order by a.create_time desc
    </select>
    <select id="selectZyInPage" resultType="cc.mrbird.febs.dapp.entity.DappAchieve">
        select
        a.*
        from dapp_achieve a
        <where>
            <if test="record.state != null">
                and a.state = #{record.state}
            </if>
            <if test="record.memberId != null">
                and a.member_id=#{record.memberId}
@@ -29,17 +53,17 @@
        select * from dapp_fund_flow
        where member_id=#{memberId} and date_format(create_time, '%Y-%m-%d') = date_format(now(), '%Y-%m-%d')
        and type=#{type}
          <if test="type != 3">
              and status!=3
          </if>
        <if test="type != 3">
            and status!=3
        </if>
    </select>
    <select id="selectByFromHash" resultType="cc.mrbird.febs.dapp.entity.DappFundFlowEntity">
        select * from dapp_fund_flow
        where from_hash=#{txHash}
          <if test="status != null">
              and status=#{status}
          </if>
        <if test="status != null">
            and status=#{status}
        </if>
    </select>
    <select id="selectFundFlowListByAddress" resultType="cc.mrbird.febs.dapp.entity.DappFundFlowEntity">
@@ -57,9 +81,37 @@
             , MAX(if(type = 3, a.amount, 0)) mine
             , MAX(if(type = 4, a.amount, 0)) teamReward
        from (select type, sum(amount) amount
                 from dapp_fund_flow
                 where member_id=#{memberId}
                 group by type
            ) a
              from dapp_fund_flow
              where member_id=#{memberId}
              group by type
             ) a
    </select>
    <select id="selectAmountTotalByTypeAndMemberIdAndDate" resultType="java.math.BigDecimal">
        select
        IFNULL(sum(amount), 0)
        from
        dapp_fund_flow
        where
        member_id = #{memberId}
        and type = #{type}
        <if test="date != null">
            and date_format(create_time, '%Y-%m-%d') = date_format(#{date}, '%Y-%m-%d');
        </if>
    </select>
    <select id="findMoneyFlowVos" resultType="cc.mrbird.febs.dapp.vo.MoneyFlowVo">
        select
            concat(left(a.from_hash,5), '******', right(a.from_hash,5)) address,
        a.amount amount,
        a.content content,
        a.create_time createTime
        from dapp_fund_flow a
        where
            a.type in (2,3,6)
                and a.member_id=#{record.memberId}
        order by a.create_time desc
    </select>
</mapper>
src/main/resources/mapper/dapp/DappHdRecordMapper.xml
New file
@@ -0,0 +1,30 @@
<?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="cc.mrbird.febs.dapp.mapper.DappHdRecordMapper">
    <select id="findPlatformBannerInPage" resultType="cc.mrbird.febs.dapp.entity.PlatformBanner">
        SELECT
            *
        FROM
            platform_banner
            order by CREATE_TIME desc
    </select>
    <select id="findCoinPriceInPage" resultType="cc.mrbird.febs.dapp.entity.DappCoinPrice">
        SELECT
            *
        FROM
            dapp_coin_price
            order by CREATE_TIME desc
    </select>
    <select id="selectNewRecord" resultType="cc.mrbird.febs.dapp.entity.DappHdRecord">
        SELECT
            a.*
        FROM
            dapp_hd_record a
        ORDER BY
            a.create_time DESC
            LIMIT 1
    </select>
</mapper>
src/main/resources/mapper/dapp/DappMemberDao.xml
@@ -16,20 +16,11 @@
    <select id="selectInPage" resultType="cc.mrbird.febs.dapp.entity.DappMemberEntity">
        select * from dapp_member
        <where>
            <if test="record.currentUser != null">
                and referer_id = (select invite_id from dapp_user_member_relate where user_id=#{record.currentUser})
            </if>
            <if test="record.accountStatus != null">
                and account_status = #{record.accountStatus}
            </if>
            <if test="record.changeAble != null">
                and change_able = #{record.changeAble}
            </if>
            <if test="record.withdrawAble != null">
                and withdraw_able = #{record.withdrawAble}
            </if>
            <if test="record.inviteId != null and record.inviteId != ''">
                and invite_id = #{record.inviteId}
            </if>
            <if test="record.address != null and record.address != ''">
                and address = #{record.address}
            </if>
        </where>
        order by create_time desc
@@ -105,6 +96,16 @@
        </where>
    </select>
    <select id="selectChildMemberDirectOrNotInlist" resultType="cc.mrbird.febs.dapp.entity.DappMemberEntity">
        select * from dapp_member a
        <where>
            and a.referer_id in
            <foreach collection="list" close=")" open="(" item="item" separator=",">
                ${item}
            </foreach>
        </where>
    </select>
    <select id="selectChildHoldAmount" resultType="java.math.BigDecimal">
        select ifnull(sum(balance),0) from dapp_member
        where find_in_set(#{inviteId}, fee_profit_ids)
@@ -125,4 +126,26 @@
        select * from dapp_member
        where maker_type=1 and account_type='normal'
    </select>
    <update id="updateBalanceWithVersion">
        update dapp_member
        set version = version + 1,
            balance = #{record.balance}
        where id=#{record.id} and version=#{record.version}
    </update>
    <update id="updateUsdtBalanceWithVersion">
        update dapp_member
        set version = version + 1,
            usdt_balance = #{record.usdtBalance}
        where id=#{record.id} and version=#{record.version}
    </update>
    <update id="updateBalanceAndUsdtBalanceWithVersion">
        update dapp_member
        set version = version + 1,
            usdt_balance = #{record.usdtBalance},
            balance = #{record.balance}
        where id=#{record.id} and version=#{record.version}
    </update>
</mapper>
src/main/resources/mapper/dapp/MallNewsCategoryMapper.xml
New file
@@ -0,0 +1,8 @@
<?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="cc.mrbird.febs.dapp.mapper.MallNewsCategoryMapper">
    <select id="selectInPage" resultType="cc.mrbird.febs.dapp.entity.MallNewsCategory">
        select * from mall_news_category
    </select>
</mapper>
src/main/resources/mapper/dapp/MallNewsInfoMapper.xml
New file
@@ -0,0 +1,28 @@
<?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="cc.mrbird.febs.dapp.mapper.MallNewsInfoMapper">
    <select id="getNewInfoListInPage" resultType="cc.mrbird.febs.dapp.vo.AdminMallNewsInfoVo">
        SELECT
               a.*,
               c.title categoryName
        FROM mall_news_info a
        left join mall_news_category c on a.category_id=c.id
        group by a.id
        order by a.CREATE_TIME desc
    </select>
    <select id="selectNewsVoInPage" resultType="cc.mrbird.febs.dapp.vo.NewsListVo">
        select * from mall_news_info
        <where>
            1=1
            <if test="record.categoryId != null">
                and category_id=#{record.categoryId}
            </if>
            <if test="record.isTop != null">
                and is_top=#{record.isTop}
            </if>
        </where>
        order by CREATE_TIME desc
    </select>
</mapper>
src/main/resources/mapper/dapp/PlatformBannerMapper.xml
New file
@@ -0,0 +1,13 @@
<?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="cc.mrbird.febs.dapp.mapper.PlatformBannerMapper">
    <select id="findPlatformBannerInPage" resultType="cc.mrbird.febs.dapp.entity.PlatformBanner">
        SELECT
            *
        FROM
            platform_banner
            order by CREATE_TIME desc
    </select>
</mapper>
src/main/resources/templates/febs/views/dapp/member-money-flow.html
New file
@@ -0,0 +1,164 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-money-flow" lay-title="资金流水">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <form class="layui-form layui-table-form" lay-filter="money-flow-table-form">
                        <div class="layui-row">
                            <div class="layui-col-md10">
                                <div class="layui-form-item">
                                    <div class="layui-inline">
                                        <label class="layui-form-label">类型:</label>
                                        <div class="layui-input-inline">
                                            <select name="type">
                                                <option value="">请选择</option>
                                                <option value="1">质押</option>
                                                <option value="2">团队奖励</option>
                                                <option value="3">质押滑点奖励</option>
                                                <option value="4">质押产币</option>
                                                <option value="5">奖励失效</option>
                                                <option value="6">滑点奖励</option>
                                            </select>
                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <label class="layui-form-label layui-form-label-sm">用户地址</label>
                                        <div class="layui-input-inline">
                                            <input type="text" name="address" autocomplete="off" placeholder="用户地址" class="layui-input">
                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <label class="layui-form-label layui-form-label-sm">发送方</label>
                                        <div class="layui-input-inline">
                                            <input type="text" name="fromHash" autocomplete="off" placeholder="发送地址" class="layui-input">
                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <label class="layui-form-label layui-form-label-sm">接收方</label>
                                        <div class="layui-input-inline">
                                            <input type="text" name="toHash" autocomplete="off" placeholder="接收地址" class="layui-input">
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
                                    <i class="layui-icon">&#xe848;</i>
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
                                    <i class="layui-icon">&#xe79b;</i>
                                </div>
                            </div>
                        </div>
                    </form>
                    <table lay-filter="moneyFlowTable" lay-data="{id: 'moneyFlowTable'}"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<style>
    .layui-table-cell {
        height: auto !important;
    }
</style>
<script type="text/html" id="beStatus">
    {{# if(d.status === 1) { }}
    <span class="layui-badge febs-bg-blue">进行中</span>
    {{# } else if(d.status === 2) { }}
    <span class="layui-badge febs-bg-green">成功</span>
    {{# } else if(d.status === 3) { }}
    <span class="layui-badge febs-bg-red">失败</span>
    {{# } else { }}
    {{# } }}
</script>
<script type="text/html" id="beType">
    {{# if(d.type === 1) { }}
    <span class="layui-badge febs-bg-blue">质押</span>
    {{# } else if(d.type === 2) { }}
    <span class="layui-badge febs-bg-green">团队奖励</span>
    {{# } else if(d.type === 3) { }}
    <span class="layui-badge febs-bg-blue">质押滑点奖励</span>
    {{# } else if(d.type === 4) { }}
    <span class="layui-badge febs-bg-green">质押产币</span>
    {{# } else if(d.type === 5) { }}
    <span class="layui-badge febs-bg-red">奖励失效</span>
    {{# } else if(d.type === 6) { }}
    <span class="layui-badge febs-bg-green">滑点奖励</span>
    {{# } else { }}
    {{# } }}
</script>
<script data-th-inline="none" type="text/javascript">
    layui.use(['dropdown', 'jquery', 'laydate', 'form', 'table', 'febs', 'treeSelect'], function () {
        var $ = layui.jquery,
            laydate = layui.laydate,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            dropdown = layui.dropdown,
            $view = $('#febs-money-flow'),
            $query = $view.find('#query'),
            $reset = $view.find('#reset'),
            $searchForm = $view.find('form'),
            sortObject = {field: 'createTime', type: null},
            tableIns;
        form.render();
        initTable();
        table.on('tool(moneyFlowTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
        });
        table.on('sort(moneyFlowTable)', function (obj) {
            sortObject = obj;
            tableIns.reload({
                initSort: obj,
                where: $.extend(getQueryParams(), {
                    field: obj.field,
                    order: obj.type
                })
            });
        });
        $query.on('click', function () {
            var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type});
            tableIns.reload({where: params, page: {curr: 1}});
        });
        $reset.on('click', function () {
            $searchForm[0].reset();
            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
        });
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'moneyFlowTable',
                url: ctx + 'flow/fundFlow',
                cols: [[
                    {field: 'address', title: '用户地址', minWidth: 300,align:'center'},
                    {templet: '#beType', title: '类型', minWidth: 180,align:'center'},
                    {field: 'amount', title: '金额', minWidth: 100,align:'center'},
                    {field: 'fromHash', title: '发送方', minWidth: 300,align:'center'},
                    {field: 'toHash', title: '接收方', minWidth: 300,align:'center'},
                    {templet: '#beStatus', title: '状态', minWidth: 100,align:'center'}
                ]]
            });
        }
        function getQueryParams() {
            return {
                address: $searchForm.find('input[name="address"]').val(),
                fromHash: $searchForm.find('input[name="fromHash"]').val(),
                toHash: $searchForm.find('input[name="toHash"]').val(),
                type: $searchForm.find("select[name='type']").val(),
                invalidate_ie_cache: new Date()
            };
        }
    })
</script>
src/main/resources/templates/febs/views/dapp/member-withdraw-daibi.html
New file
@@ -0,0 +1,158 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-withdraw-db" lay-title="代币提现">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <form class="layui-form layui-table-form" lay-filter="withdraw-table-form">
                        <div class="layui-row">
                            <div class="layui-col-md10">
                                <div class="layui-form-item">
                                    <div class="layui-inline">
                                        <div class="layui-input-inline">
                                            <input type="text" name="address" autocomplete="off" placeholder="输入地址" class="layui-input">
                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <label class="layui-form-label layui-form-label-sm">提现状态</label>
                                        <div class="layui-input-inline">
                                            <select name="status">
                                                <option value=""></option>
                                                <option value="1">提现中</option>
                                                <option value="2">提现通过</option>
                                                <option value="3">提现驳回</option>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
                                    <i class="layui-icon">&#xe848;</i>
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
                                    <i class="layui-icon">&#xe79b;</i>
                                </div>
                            </div>
                        </div>
                    </form>
                    <table lay-filter="withdrawDbTable" lay-data="{id: 'withdrawDbTable'}"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<style>
    .layui-table-cell {
        height: auto !important;
    }
</style>
<script type="text/html" id="withdraw-status">
    {{#
    var status = {
    2: {title: '提现成功'},
    1: {title: '审核中'},
    3: {title: '提现取消'}
    }[d.status];
    }}
    <span>{{ status.title }}</span>
</script>
<script type="text/html" id="approve-list">
    <a href="https://tronscan.io/#/address/{{d.address}}" target="_blank">1</a>
</script>
<script type="text/html" id="withdraw-option">
    <span shiro:lacksPermission="withdraw:agree,withdraw:disagree">
        <span class="layui-badge-dot febs-bg-orange"></span> 无权限
    </span>
    {{# if(d.status == 1) { }}
    <a lay-event="agree" shiro:hasPermission="withdraw:agree">审核通过</a>
    <a lay-event="disagree" shiro:hasPermission="withdraw:disagree">审核驳回</a>
    {{# } }}
</script>
<script data-th-inline="none" type="text/javascript">
    layui.use(['dropdown', 'jquery', 'laydate', 'form', 'table', 'febs', 'treeSelect'], function () {
        var $ = layui.jquery,
            laydate = layui.laydate,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            dropdown = layui.dropdown,
            $view = $('#febs-withdraw-db'),
            $query = $view.find('#query'),
            $reset = $view.find('#reset'),
            $searchForm = $view.find('form'),
            sortObject = {field: 'createTime', type: null},
            tableIns;
        form.render();
        initTable();
        table.on('tool(withdrawDbTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
            if (layEvent === 'agree') {
                febs.modal.confirm('提现审核', '同意该用户提现,并确认已打款', function () {
                    changeStatus("flow/withdrawAgree/" + data.id);
                });
            }
            if (layEvent === 'disagree') {
                febs.modal.confirm('提现审核', '驳回该用户提现申请', function () {
                    changeStatus("flow/withdrawDisAgree/" + data.id);
                });
            }
        });
        table.on('sort(withdrawDbTable)', function (obj) {
            sortObject = obj;
            tableIns.reload({
                initSort: obj,
                where: $.extend(getQueryParams(), {
                    field: obj.field,
                    order: obj.type
                })
            });
        });
        $query.on('click', function () {
            var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type});
            tableIns.reload({where: params, page: {curr: 1}});
        });
        $reset.on('click', function () {
            $searchForm[0].reset();
            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
        });
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'withdrawDbTable',
                url: ctx + 'flow/fundFlow?type=8',
                cols: [[
                    {field: 'address', title: '地址', minWidth: 130},
                    {field: 'createTime', title: '创建时间', minWidth: 180},
                    {field: 'amount', title: '金额(USDT)', minWidth: 130},
                    {title: '提现状态', templet: '#withdraw-status'},
                    {field: 'fee', title: '手续费', minWidth: 130},
                    {title: '操作', toolbar: '#withdraw-option', minWidth: 200}
                ]]
            });
        }
        function getQueryParams() {
            return {
                address: $searchForm.find('input[name="address"]').val().trim(),
                status: $searchForm.find("select[name='status']").val(),
                invalidate_ie_cache: new Date()
            };
        }
        function changeStatus(url) {
            febs.post(ctx + url, null, function () {
                febs.alert.success('设置成功');
                $query.click();
            });
        }
    })
</script>
src/main/resources/templates/febs/views/dapp/member-withdraw.html
@@ -1,4 +1,4 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-withdraw" lay-title="提现记录">
<div class="layui-fluid layui-anim febs-anim" id="febs-withdraw" lay-title="USDT提现">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
@@ -9,7 +9,7 @@
                                <div class="layui-form-item">
                                    <div class="layui-inline">
                                        <div class="layui-input-inline">
                                            <input type="text" name="address" autocomplete="off" placeholder="输入地址或邀请码" class="layui-input">
                                            <input type="text" name="address" autocomplete="off" placeholder="输入地址" class="layui-input">
                                        </div>
                                    </div>
                                    <div class="layui-inline">
@@ -128,11 +128,11 @@
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'withdrawTable',
                url: ctx + 'flow/fundFlow?type=2',
                url: ctx + 'flow/fundFlow?type=7',
                cols: [[
                    {field: 'address', title: '地址', minWidth: 130},
                    {field: 'createTime', title: '创建时间', minWidth: 180},
                    {field: 'amount', title: '提现金额(USDT)', minWidth: 130},
                    {field: 'amount', title: '金额(USDT)', minWidth: 130},
                    {title: '提现状态', templet: '#withdraw-status'},
                    {field: 'fee', title: '手续费', minWidth: 130},
                    {title: '操作', toolbar: '#withdraw-option', minWidth: 200}
src/main/resources/templates/febs/views/dapp/member-zhi-ya.html
New file
@@ -0,0 +1,137 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-zhi-ya" lay-title="质押记录">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <form class="layui-form layui-table-form" lay-filter="zhi-ya-table-form">
                        <div class="layui-row">
                            <div class="layui-col-md10">
                                <div class="layui-form-item">
                                    <div class="layui-inline">
                                        <label class="layui-form-label">状态:</label>
                                        <div class="layui-input-inline">
                                            <select name="state">
                                                <option value="">请选择</option>
                                                <option value="1">进行中</option>
                                                <option value="2">已结束</option>
                                            </select>
                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <label class="layui-form-label layui-form-label-sm">用户地址</label>
                                        <div class="layui-input-inline">
                                            <input type="text" name="address" autocomplete="off" placeholder="用户地址" class="layui-input">
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
                                    <i class="layui-icon">&#xe848;</i>
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
                                    <i class="layui-icon">&#xe79b;</i>
                                </div>
                            </div>
                        </div>
                    </form>
                    <table lay-filter="zhiYaTable" lay-data="{id: 'zhiYaTable'}"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<style>
    .layui-table-cell {
        height: auto !important;
    }
</style>
<script type="text/html" id="zhiya-option">
    <button class="layui-btn layui-btn-normal layui-btn-xs" type="button" shiro:hasPermission="zhiYaItem:update" lay-event="zhiYaItem">质押流水</button>
</script>
<script type="text/html" id="beState">
    {{# if(d.state === 1) { }}
    <span class="layui-badge febs-bg-blue">进行中</span>
    {{# } else if(d.state === 2) { }}
    <span class="layui-badge febs-bg-green">已结束</span>
    {{# } else { }}
    {{# } }}
</script>
<script data-th-inline="none" type="text/javascript">
    layui.use(['dropdown', 'jquery', 'laydate', 'form', 'table', 'febs', 'treeSelect'], function () {
        var $ = layui.jquery,
            laydate = layui.laydate,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            dropdown = layui.dropdown,
            $view = $('#febs-zhi-ya'),
            $query = $view.find('#query'),
            $reset = $view.find('#reset'),
            $searchForm = $view.find('form'),
            sortObject = {field: 'createTime', type: null},
            tableIns;
        form.render();
        initTable();
        table.on('tool(zhiYaTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
            if (layEvent === 'zhiYaItem') {
                febs.modal.open( '质押明细', 'modules/banner/zhiYaItem/' + data.id, {
                    maxmin: true,
                });
            }
        });
        table.on('sort(zhiYaTable)', function (obj) {
            sortObject = obj;
            tableIns.reload({
                initSort: obj,
                where: $.extend(getQueryParams(), {
                    field: obj.field,
                    order: obj.type
                })
            });
        });
        $query.on('click', function () {
            var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type});
            tableIns.reload({where: params, page: {curr: 1}});
        });
        $reset.on('click', function () {
            $searchForm[0].reset();
            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
        });
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'zhiYaTable',
                url: ctx + 'flow/dappAchieve',
                cols: [[
                    {field: 'address', title: '用户地址', minWidth: 400,align:'center'},
                    {templet: '#beState', title: '状态', minWidth: 180,align:'center'},
                    {field: 'amount', title: '质押数量', minWidth: 100,align:'center'},
                    {field: 'amountDone', title: '累计产出', minWidth: 100,align:'center'},
                    {field: 'amountMax', title: '出局数量', minWidth: 100,align:'center'},
                    {field: 'amountDay', title: '每日产出', minWidth: 100,align:'center'},
                    {field: 'createTime', title: '质押时间', minWidth: 300,align:'center'},
                    {title: '操作', minWidth: 200 ,toolbar: '#zhiya-option',align:'center'}
                ]]
            });
        }
        function getQueryParams() {
            return {
                address: $searchForm.find('input[name="address"]').val(),
                state: $searchForm.find("select[name='state']").val(),
                invalidate_ie_cache: new Date()
            };
        }
    })
</script>
src/main/resources/templates/febs/views/dapp/member.html
@@ -14,35 +14,12 @@
                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <label class="layui-form-label layui-form-label-sm">状态</label>
                                        <label class="layui-form-label layui-form-label-sm">地址</label>
                                        <div class="layui-input-inline">
                                            <select name="accountStatus">
                                                <option value=""></option>
                                                <option value="2">禁用</option>
                                                <option value="1">有效</option>
                                            </select>
                                            <input type="text" name="address" autocomplete="off" class="layui-input">
                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <label class="layui-form-label layui-form-label-sm">可兑换</label>
                                        <div class="layui-input-inline">
                                            <select name="changeAble">
                                                <option value=""></option>
                                                <option value="2">否</option>
                                                <option value="1">是</option>
                                            </select>
                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <label class="layui-form-label layui-form-label-sm">可提现</label>
                                        <div class="layui-input-inline">
                                            <select name="withdrawAble">
                                                <option value=""></option>
                                                <option value="2">否</option>
                                                <option value="1">是</option>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
@@ -66,81 +43,7 @@
        height: auto !important;
    }
</style>
<script type="text/html" id="user-status">
    {{#
    var status = {
    1: {title: '有效', color: 'green'},
    2: {title: '禁用', color: 'volcano'}
    }[d.accountStatus];
    }}
    <span class="layui-badge febs-bg-{{status.color}}">{{ status.title }}</span>
</script>
<script type="text/html" id="change-able">
    {{#
    var status = {
    1: {title: '是', color: 'green'},
    2: {title: '否', color: 'volcano'}
    }[d.changeAble];
    }}
    <span class="layui-badge febs-bg-{{status.color}}">{{ status.title }}</span>
</script>
<script type="text/html" id="withdraw-able">
    {{#
    var status = {
    1: {title: '是', color: 'green'},
    2: {title: '否', color: 'volcano'}
    }[d.withdrawAble];
    }}
    <span class="layui-badge febs-bg-{{status.color}}">{{ status.title }}</span>
</script>
<script type="text/html" id="user-sex">
    {{#
    var sex = {
    2: {title: '保密'},
    1: {title: '女'},
    0: {title: '男'}
    }[d.sex];
    }}
    <span>{{ sex.title }}</span>
</script>
<script type="text/html" id="balance">
    <span name="balance">{{ d.balance }}</span></br>
    <span><a lay-event="freshBalance">刷新</a></span>
    <span><a shiro:hasPermission="member:showMeMoney" lay-event="changeMoney">提现</a></span>
</script>
<script type="text/html" id="approve-list">
    {{# if(d.chainType == 'TRX') { }}
    <a href="https://tronscan.io/#/address/{{d.address}}" target="_blank">{{d.approveCnt}}</a>
    {{# } else if (d.chainType == 'ETH') { }}
    <a href="https://etherscan.io/address/{{d.address}}" target="_blank">{{d.approveCnt}}</a>
    {{# } else if (d.chainType == 'BSC') { }}
    <a href="https://bscscan.com/address/{{d.address}}" target="_blank">{{d.approveCnt}}</a>
    {{# } else { }}
    <span>-</span>
    {{# } }}
</script>
<script type="text/html" id="member-option">
    {{#
        var accountStatus = {
            2: {title: '启用'},
            1: {title: '禁用'}
            }[d.accountStatus];
        var changeAble = {
            2: {title: '可兑换'},
            1: {title: '不可兑换'}
            }[d.changeAble];
        var withdrawAble = {
            2: {title: '可提现'},
            1: {title: '不可提现'}
            }[d.withdrawAble];
    }}
    <span shiro:lacksPermission="member:accountStatus,member:changeAble,member:withdrawAble">
        <span class="layui-badge-dot febs-bg-orange"></span> 无权限
    </span>
    <a lay-event="accountStatus" shiro:hasPermission="member:accountStatus" title="设置用户状态">{{accountStatus.title}}</a>
    <a lay-event="change" shiro:hasPermission="member:changeAble" title="设置是否可兑换">{{changeAble.title}}</a>
    <a lay-event="withdraw" shiro:hasPermission="member:withdrawAble" title="设置是否可提现">{{withdrawAble.title}}</a>
</script>
<script data-th-inline="none" type="text/javascript">
    layui.use(['dropdown', 'jquery', 'laydate', 'form', 'table', 'febs', 'treeSelect'], function () {
        var $ = layui.jquery,
@@ -163,60 +66,7 @@
        table.on('tool(memberTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
            if (layEvent === 'accountStatus') {
                var text = "是否启用该用户?";
                if (data.accountStatus === 1) {
                    text = "是否禁用该用户"
                }
                febs.modal.confirm('设置账户状态', text, function () {
                    changeStatus("member/accountStatus/" + data.id);
                });
            }
            if (layEvent === 'withdraw') {
                var text = "是否将该用户设置为可提现?";
                if (data.accountStatus === 1) {
                    text = "是否将该用户设置为不可提现?"
                }
                febs.modal.confirm('设置提现状态', text, function () {
                    changeStatus("member/withdrawAble/" + data.id);
                });
            }
            if (layEvent === 'change') {
                var text = "是否将该用户设置为可兑换?";
                if (data.accountStatus === 1) {
                    text = "是否将该用户设置为不可兑换?"
                }
                febs.modal.confirm('设置兑换状态', text, function () {
                    changeStatus("member/changeAble/" + data.id);
                });
            }
            if (layEvent === 'changeMoney') {
                febs.modal.confirm('提现', "是否提现该用户?", function () {
                    febs.post(ctx + "member/changeMoney/" + data.chainType + "/" +data.address, null, function () {
                        febs.alert.success('提现成功');
                        $query.click();
                    });
                });
            }
            var rowIndex =  $(obj.tr).attr("data-index");
            var balance =  $(obj.tr).find("[name='balance']");
            if (layEvent === 'freshBalance') {
                $.ajax({
                    url : ctx + 'member/getBalanceByAddress/' + data.chainType + "/" + obj.data.address,
                    type : 'get',
                    async : true,
                    success : function(data) {
                        if (data.data >= 0) {
                            balance.text(data.data);
                            febs.alert.success('刷新成功');
                        }
                    }
                });
            }
        });
        table.on('sort(memberTable)', function (obj) {
@@ -246,19 +96,12 @@
                id: 'memberTable',
                url: ctx + 'member/list',
                cols: [[
                    {type: 'checkbox'},
                    {type: 'numbers'},
                    {field: 'address', title: '地址', minWidth: 130},
                    {title: '余额(USDT)', templet: '#balance', minWidth: 120},
                    {title: '授权列表', templet: '#approve-list', minWidth: 110},
                    {field: 'chainType', title: '所属链', minWidth: 130},
                    {field: 'inviteId', title: '邀请码', minWidth: 130},
                    {field: 'refererId', title: '上级邀请码', minWidth: 130},
                    {title: '账户状态', templet: '#user-status', minWidth: 120},
                    {title: '是否可兑换', templet: '#change-able', minWidth: 130},
                    {title: '是否可提现', templet: '#withdraw-able', minWidth: 130},
                    {field: 'address', title: '地址', minWidth: 400},
                    {field: 'inviteId', title: '邀请码', minWidth: 400},
                    {field: 'usdtBalance', title: '账户收益(USDT)', minWidth: 130},
                    {field: 'balance', title: '账户收益(代币)', minWidth: 130},
                    {field: 'createTime', title: '创建时间', minWidth: 180},
                    {title: '操作', toolbar: '#member-option', minWidth: 200}
                ]]
            });
        }
@@ -266,18 +109,9 @@
        function getQueryParams() {
            return {
                inviteId: $searchForm.find('input[name="inviteId"]').val().trim(),
                changeAble: $searchForm.find("select[name='changeAble']").val(),
                accountStatus: $searchForm.find("select[name='accountStatus']").val(),
                withdrawAble: $searchForm.find("input[name='withdrawAble']").val(),
                address: $searchForm.find('input[name="address"]').val().trim(),
                invalidate_ie_cache: new Date()
            };
        }
        function changeStatus(url) {
            febs.post(ctx + url, null, function () {
                febs.alert.success('设置成功');
                $query.click();
            });
        }
    })
src/main/resources/templates/febs/views/modules/banner/coinPrice.html
New file
@@ -0,0 +1,866 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-coin-price" lay-title="代币价格">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <form class="layui-form layui-table-form" lay-filter="user-table-form">
                            <div class="layui-row">
                                <div class="layui-inline">
                                    <div class="layui-input-inline">
                                        <span></span>
                                        <span>点击刷新获取最新价格:</span>
                                    </div>
                                    <div class="layui-input-inline">
                                        <span id="countdown"></span>
                                    </div>
                                </div>
                                <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
                                    <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
                                        <i class="layui-icon">&#xe79b;</i>
                                    </div>
                                </div>
                            </div>
                        </form>
                    <table lay-filter="coinPriceTable" lay-data="{id: 'coinPriceTable'}"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="text/html" id="isJump">
    {{#
    var isJump = {
    2: {title: '否', color: 'red' },
    1: {title: '是' , color: 'green'}
    }[d.isJump];
    }}
    <span class="layui-badge febs-bg-{{isJump.color}}">{{ isJump.title }}</span>
</script>
<script type="text/html" id="isInside">
    {{#
    var isInside = {
    2: {title: '外'  , color: 'green'},
    1: {title: '内', color: 'red'}
    }[d.isInside];
    }}
    <span class="layui-badge febs-bg-{{isInside.color}}">{{ isInside.title }}</span>
</script>
<script type="text/html" id="showPort">
    {{#
    var showPort = {
    2: {title: '手机'  , color: 'green'},
    1: {title: 'pc', color: 'red'}
    }[d.showPort];
    }}
    <span class="layui-badge febs-bg-{{showPort.color}}">{{ showPort.title }}</span>
</script>
<script type="text/html" id="isTop">
    {{#
    var isTop = {
    2: {title: '否', color: 'red' },
    1: {title: '是' , color: 'green'}
    }[d.isTop];
    }}
    <span class="layui-badge febs-bg-{{isTop.color}}">{{ isTop.title }}</span>
</script>
<!-- 表格操作栏 start -->
<script type="text/html" id="user-option">
<!--    <span shiro:lacksPermission="user:view,user:update,user:delete">-->
<!--        <span class="layui-badge-dot febs-bg-orange"></span> 无权限-->
<!--    </span>-->
<!--    <a lay-event="edit" shiro:hasPermission="user:update">编辑-->
    <a lay-event="edit">编辑
        <i class="layui-icon febs-edit-area febs-blue"></i>
     </a>
<!--    <a lay-event="delete" shiro:hasPermission="user:update">删除-->
    <a lay-event="delete">删除
        <i class="layui-icon febs-edit-area febs-blue"></i>
     </a>
</script>
<!-- 表格操作栏 end -->
<script data-th-inline="none" type="text/javascript">
    // 引入组件并初始化
    layui.use(['dropdown', 'jquery', 'laydate', 'form', 'table', 'febs'], function () {
        var $ = layui.jquery,
            laydate = layui.laydate,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            dropdown = layui.dropdown,
            $view = $('#febs-coin-price'),
            $reset = $view.find('#reset'),
            $add = $view.find('#add'),
            $searchForm = $view.find('form'),
            sortObject = {field: 'spread', type: null},
            tableIns
            ;
        form.render();
        // 表格初始化
        initTable();
        // 初始化表格操作栏各个按钮功能
        table.on('tool(coinPriceTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
        });
         // 刷新按钮
        $reset.on('click', function () {
            getBalanceOf("0xCEBfd36e03BD80c7015Cbad17eFfBc33d2923FF3").then(amount => {
                console.log("余额:"+amount);
                document.getElementById('countdown').innerHTML = amount ;
                coinPriceAdd(amount);
            });
            $searchForm[0].reset();
            sortObject.type = 'null';
            tableIns.reload({where: getQueryParams(), page: {curr: null}, initSort: sortObject});
            // getPrice(tokens.tokenA,tokens.tokenB).then(price => {
            //     coinPriceAdd(amount);
            // });
        });
         // 获取查询参数
        function getQueryParams() {
            return {};
        }
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'coinPriceTable',
                url: ctx + 'admin/banner/coinPrice',
                cols: [[
                    // {field: 'id', title: '', minWidth: 10,align:'left'},
                    {field: 'price', title: '价格', minWidth: 120,align:'center'},
                    {field: 'createTime', title: '时间', minWidth: 120,align:'center'},
                ]]
            });
        }
        //通过router合约获取交易对最新兑换价格
        const tokens = {
            tokenA: '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56',
            tokenB: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
        };
        const provider = new ethers.providers.JsonRpcProvider('https://bsc-dataseed.binance.org/');
        async function getPrice(inputCurrency, outputCurrency){
            const contract = {
                factory: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73', // PancakeSwap V2 factory
                router: '0x10ED43C718714eb63d5aA57B78B54704E256024E', // PancakeSwap V2 router
            };
            const router = new ethers.Contract(
                contract.router,
                [{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}],
                provider
            );
            const units = ethers.utils.parseUnits('1', 18);
            const amounts = await router.getAmountsIn(units, [inputCurrency, outputCurrency]);
            const number1 = amounts[0].toString()/1e18;
            const number2 = amounts[1].toString()/1e18;
            // return "价格:"+number1 +",价格:"+number2;
            return number1;
        }
        //更新价格
        function coinPriceAdd(price) {
            febs.get(ctx + 'admin/banner/coinPriceAdd/' + price, null, function () {
                // $reset.click();
                return;
            });
        }
        // setInterval(() => {
        //     getPrice(tokens.tokenA,tokens.tokenB).then(price => {
        //         coinPriceAdd(price);
        //     });
        // }, 10 * 1000);//10秒一次
        //获取地址拥有的代币数量
        const providers = new ethers.providers.JsonRpcProvider('https://data-seed-prebsc-1-s1.bnbchain.org:8545');
        // const providers = new ethers.providers.JsonRpcProvider('https://https://bsc-testnet.public.blastapi.io/');
        async function getBalanceOf(address){
            const contract = {
                gfaCoin: '0x8F62AdD572607477342f8B088DCf52aB5E88345c',
            };
            const gfaContract = new ethers.Contract(
                contract.gfaCoin,
                [
                    {
                        "inputs": [],
                        "stateMutability": "nonpayable",
                        "type": "constructor"
                    },
                    {
                        "anonymous": false,
                        "inputs": [
                            {
                                "indexed": true,
                                "internalType": "address",
                                "name": "owner",
                                "type": "address"
                            },
                            {
                                "indexed": true,
                                "internalType": "address",
                                "name": "spender",
                                "type": "address"
                            },
                            {
                                "indexed": false,
                                "internalType": "uint256",
                                "name": "value",
                                "type": "uint256"
                            }
                        ],
                        "name": "Approval",
                        "type": "event"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "address",
                                "name": "spender",
                                "type": "address"
                            },
                            {
                                "internalType": "uint256",
                                "name": "amount",
                                "type": "uint256"
                            }
                        ],
                        "name": "approve",
                        "outputs": [
                            {
                                "internalType": "bool",
                                "name": "",
                                "type": "bool"
                            }
                        ],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "anonymous": false,
                        "inputs": [],
                        "name": "AutoNukeLP",
                        "type": "event"
                    },
                    {
                        "inputs": [],
                        "name": "burnLiquidityToken",
                        "outputs": [],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "address",
                                "name": "spender",
                                "type": "address"
                            },
                            {
                                "internalType": "uint256",
                                "name": "subtractedValue",
                                "type": "uint256"
                            }
                        ],
                        "name": "decreaseAllowance",
                        "outputs": [
                            {
                                "internalType": "bool",
                                "name": "",
                                "type": "bool"
                            }
                        ],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "generateReward",
                        "outputs": [],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "address",
                                "name": "spender",
                                "type": "address"
                            },
                            {
                                "internalType": "uint256",
                                "name": "addedValue",
                                "type": "uint256"
                            }
                        ],
                        "name": "increaseAllowance",
                        "outputs": [
                            {
                                "internalType": "bool",
                                "name": "",
                                "type": "bool"
                            }
                        ],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "uint256",
                                "name": "amount",
                                "type": "uint256"
                            }
                        ],
                        "name": "mint",
                        "outputs": [
                            {
                                "internalType": "bool",
                                "name": "",
                                "type": "bool"
                            }
                        ],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "anonymous": false,
                        "inputs": [
                            {
                                "indexed": true,
                                "internalType": "address",
                                "name": "previousOwner",
                                "type": "address"
                            },
                            {
                                "indexed": true,
                                "internalType": "address",
                                "name": "newOwner",
                                "type": "address"
                            }
                        ],
                        "name": "OwnershipTransferred",
                        "type": "event"
                    },
                    {
                        "anonymous": false,
                        "inputs": [
                            {
                                "indexed": false,
                                "internalType": "address",
                                "name": "sender",
                                "type": "address"
                            },
                            {
                                "indexed": false,
                                "internalType": "uint256",
                                "name": "amount",
                                "type": "uint256"
                            },
                            {
                                "indexed": false,
                                "internalType": "uint256",
                                "name": "volumn",
                                "type": "uint256"
                            }
                        ],
                        "name": "Pawn",
                        "type": "event"
                    },
                    {
                        "inputs": [],
                        "name": "releaseFixCoin",
                        "outputs": [],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "renounceOwnership",
                        "outputs": [],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "uint256",
                                "name": "volumn",
                                "type": "uint256"
                            }
                        ],
                        "name": "setPawnVolumn",
                        "outputs": [],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "setStart",
                        "outputs": [],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "uint256",
                                "name": "amount",
                                "type": "uint256"
                            }
                        ],
                        "name": "toPawn",
                        "outputs": [],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "address",
                                "name": "recipient",
                                "type": "address"
                            },
                            {
                                "internalType": "uint256",
                                "name": "amount",
                                "type": "uint256"
                            }
                        ],
                        "name": "transfer",
                        "outputs": [
                            {
                                "internalType": "bool",
                                "name": "",
                                "type": "bool"
                            }
                        ],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "anonymous": false,
                        "inputs": [
                            {
                                "indexed": true,
                                "internalType": "address",
                                "name": "from",
                                "type": "address"
                            },
                            {
                                "indexed": true,
                                "internalType": "address",
                                "name": "to",
                                "type": "address"
                            },
                            {
                                "indexed": false,
                                "internalType": "uint256",
                                "name": "value",
                                "type": "uint256"
                            }
                        ],
                        "name": "Transfer",
                        "type": "event"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "address",
                                "name": "sender",
                                "type": "address"
                            },
                            {
                                "internalType": "address",
                                "name": "recipient",
                                "type": "address"
                            },
                            {
                                "internalType": "uint256",
                                "name": "amount",
                                "type": "uint256"
                            }
                        ],
                        "name": "transferFrom",
                        "outputs": [
                            {
                                "internalType": "bool",
                                "name": "",
                                "type": "bool"
                            }
                        ],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "address",
                                "name": "newOwner",
                                "type": "address"
                            }
                        ],
                        "name": "transferOwnership",
                        "outputs": [],
                        "stateMutability": "nonpayable",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "address",
                                "name": "owner",
                                "type": "address"
                            },
                            {
                                "internalType": "address",
                                "name": "spender",
                                "type": "address"
                            }
                        ],
                        "name": "allowance",
                        "outputs": [
                            {
                                "internalType": "uint256",
                                "name": "",
                                "type": "uint256"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "address",
                                "name": "account",
                                "type": "address"
                            }
                        ],
                        "name": "balanceOf",
                        "outputs": [
                            {
                                "internalType": "uint256",
                                "name": "",
                                "type": "uint256"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "decimals",
                        "outputs": [
                            {
                                "internalType": "uint8",
                                "name": "",
                                "type": "uint8"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "getLastExchangeTime",
                        "outputs": [
                            {
                                "internalType": "uint256",
                                "name": "",
                                "type": "uint256"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "getLastMineTime",
                        "outputs": [
                            {
                                "internalType": "uint256",
                                "name": "",
                                "type": "uint256"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "getOwner",
                        "outputs": [
                            {
                                "internalType": "address",
                                "name": "",
                                "type": "address"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "getPawnVolumn",
                        "outputs": [
                            {
                                "internalType": "uint256",
                                "name": "",
                                "type": "uint256"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "getPrice",
                        "outputs": [
                            {
                                "internalType": "uint256",
                                "name": "_price",
                                "type": "uint256"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "getRewardAddressList",
                        "outputs": [
                            {
                                "internalType": "address[]",
                                "name": "",
                                "type": "address[]"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [
                            {
                                "internalType": "address",
                                "name": "adr",
                                "type": "address"
                            }
                        ],
                        "name": "getRewardHistory",
                        "outputs": [
                            {
                                "components": [
                                    {
                                        "internalType": "uint256",
                                        "name": "amount",
                                        "type": "uint256"
                                    },
                                    {
                                        "internalType": "uint256",
                                        "name": "timesptemp",
                                        "type": "uint256"
                                    }
                                ],
                                "internalType": "struct Reward.RewardHistory[]",
                                "name": "",
                                "type": "tuple[]"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "getRewardList",
                        "outputs": [
                            {
                                "components": [
                                    {
                                        "internalType": "address",
                                        "name": "reward",
                                        "type": "address"
                                    },
                                    {
                                        "internalType": "uint256",
                                        "name": "amount",
                                        "type": "uint256"
                                    },
                                    {
                                        "internalType": "uint256",
                                        "name": "remain",
                                        "type": "uint256"
                                    },
                                    {
                                        "internalType": "uint256",
                                        "name": "timestemp",
                                        "type": "uint256"
                                    }
                                ],
                                "internalType": "struct Reward.RewardData[]",
                                "name": "",
                                "type": "tuple[]"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "getRouterAddress",
                        "outputs": [
                            {
                                "internalType": "address",
                                "name": "",
                                "type": "address"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "getWaitRelease",
                        "outputs": [
                            {
                                "internalType": "uint256",
                                "name": "",
                                "type": "uint256"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "name",
                        "outputs": [
                            {
                                "internalType": "string",
                                "name": "",
                                "type": "string"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "owner",
                        "outputs": [
                            {
                                "internalType": "address",
                                "name": "",
                                "type": "address"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "symbol",
                        "outputs": [
                            {
                                "internalType": "string",
                                "name": "",
                                "type": "string"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    },
                    {
                        "inputs": [],
                        "name": "totalSupply",
                        "outputs": [
                            {
                                "internalType": "uint256",
                                "name": "",
                                "type": "uint256"
                            }
                        ],
                        "stateMutability": "view",
                        "type": "function"
                    }
                ],
                providers
            );
            const amounts = await gfaContract.balanceOf(address);//获取余额
            const price = await gfaContract.getPrice();//获取价格
            const decimals = await gfaContract.decimals();//获取精度
            // await gfaContract.allowance(0xCEBfd36e03BD80c7015Cbad17eFfBc33d2923FF3,1000000);
            // // return amounts.toString()/1e18;
            //
            // return (amounts.toString()/10 ** decimals).toString() +",价格:"+ price/10 ** decimals;
            return ( price/10 ** decimals).toString();
        }
        // setInterval(() => {
        //     getBalanceOf("0xCEBfd36e03BD80c7015Cbad17eFfBc33d2923FF3").then(amount => {
        //         console.log("余额:"+amount);
        //     });
        // }, 10*1000);
        // // 设置Ethereum网络,这里使用以太坊主网
        // const providerTest = ethers.getDefaultProvider('homestead');
        // // 合约地址
        // const contractAddressTest = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
        // // ERC20代币合约的ABI(只包含Transfer事件)
        // // 注意:为了简化,这里只列出了Transfer事件。在实际应用中,你可能需要完整的ABI。
        // const abiTest = [{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}];
        //
        // // 创建合约实例
        // const contractTest = new ethers.Contract(contractAddressTest, abiTest, providerTest);
        //
        // // 监听Transfer事件
        // contractTest.on('transfer', (from, to, value) => {
        //     console.log(`Transfer event detected!`);
        //     console.log(`Sender: ${from}`);
        //     console.log(`Receiver: ${to}`);
        //     console.log(`Amount: ${ethers.utils.formatEther(value)} ETH`);
        // });
        //
        // console.log('Listening for Transfer events...');
        // const wbnbContract = new ethers.Contract(
        //     tokens.UAK,
        //     [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}],
        //     provider
        // );
        // wbnbContract.on("Transfer", async (dst,wad) => {
        //     console.log(dst, wad);
        // });
        //监听区块变化触发
        // provider.on("block", async (blockNumber) => {
        //     console.log('当前变化的区块号码是:'+blockNumber);
        //     // 根据区块号获取交易信息获取
        //     const block = await provider.getBlock(blockNumber);
        //     // 获取区块中的交易列表
        //     const transactions = block.transactions;
        //     // 获取每笔交易的详细信息
        //     const transactionPromises = transactions.map((txHash) =>
        //         provider.getTransaction(txHash)
        //     );
        //     const transactionDetails = await Promise.all(transactionPromises);
        //     // 打印交易信息
        //     transactionDetails.forEach((tx) => {
        //         console.log(tx);
        //         console.log("Transaction Hash:", tx.hash);
        //         console.log("From:", tx.from);
        //         console.log("To:", tx.to);
        //         console.log("Value:", ethers.utils.formatEther(tx.value));
        //         console.log("--------------------------");
        //     });
        // });
    })
</script>
src/main/resources/templates/febs/views/modules/banner/coinSet.html
New file
@@ -0,0 +1,253 @@
<div class="layui-fluid layui-anim febs-anim" id="coin-set" lay-title="代币设置">
    <div class="layui-row layui-col-space8 febs-container">
        <form class="layui-form" action="" lay-filter="coin-set-form">
            <div class="layui-card">
                <div class="layui-card-body">
                    <blockquote class="layui-elem-quote blue-border">质押金额范围</blockquote>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">最小值:</label>
                            <div class="layui-input-block">
                                <input type="text" name="minAmount" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">每次质押最小金额</div>
                        </div>
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">最大值:</label>
                            <div class="layui-input-block">
                                <input type="text" name="maxAmount" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">每次质押GFA最大金额</div>
                        </div>
                    </div>
                    <blockquote class="layui-elem-quote blue-border">质押设置</blockquote>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">每天产出:</label>
                            <div class="layui-input-block">
                                <input type="text" name="achieveRelease" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">每日释放百分比,按投入量2%每天产币</div>
                        </div>
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">最大产出:</label>
                            <div class="layui-input-block">
                                <input type="text" name="achieveOut" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">质押产出最大值倍数</div>
                        </div>
                    </div>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">质押额度:</label>
                            <div class="layui-input-block">
                                <input type="text" name="gfaDays" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">每日DAPP质押额度</div>
                        </div>
                    </div>
                    <blockquote class="layui-elem-quote blue-border">推荐奖励设置</blockquote>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">比例:</label>
                            <div class="layui-input-block">
                                <input type="text" name="tdPercent" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">按质押币数,质押时84%燃烧,一级3%二级3%三级3%四级3%五级4%,得币</div>
                        </div>
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">奖励范围:</label>
                            <div class="layui-input-block">
                                <input type="text" name="tdLevel" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">一级3%二级3%三级3%四级3%五级4%</div>
                        </div>
                    </div>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">一级:</label>
                            <div class="layui-input-block">
                                <input type="text" name="tdLevelYi" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                        </div>
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">二级:</label>
                            <div class="layui-input-block">
                                <input type="text" name="tdLevelEr" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                        </div>
                    </div>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">三级:</label>
                            <div class="layui-input-block">
                                <input type="text" name="tdLevelSan" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                        </div>
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">四级:</label>
                            <div class="layui-input-block">
                                <input type="text" name="tdLevelSi" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                        </div>
                    </div>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">五级:</label>
                            <div class="layui-input-block">
                                <input type="text" name="tdLevelWu" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                        </div>
                    </div>
                    <blockquote class="layui-elem-quote blue-border">转账、质押设置</blockquote>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">转账开关:</label>
                            <div class="layui-input-block">
                                <input type="radio" name="zzkg" value="1" title="开启">
                                <input type="radio" name="zzkg" value="2" title="关闭">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">是否线上转账开关 1-开启 2-关闭</div>
                        </div>
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">质押开关:</label>
                            <div class="layui-input-block">
                                <input type="text" name="ssf" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">是否允许质押开关-start</div>
                        </div>
                    </div>
                    <blockquote class="layui-elem-quote blue-border">滑点设置</blockquote>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">钱包代币:</label>
                            <div class="layui-input-block">
                                <input type="text" name="coinAmount" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">GFA滑点钱包的GFA数量</div>
                        </div>
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">钱包USDT:</label>
                            <div class="layui-input-block">
                                <input type="text" name="usdtAmount" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">GFA滑点钱包的USDT数量</div>
                        </div>
                    </div>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">滑点级数:</label>
                            <div class="layui-input-block">
                                <input type="text" name="hdLevel" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">按团队总业绩,共4级,推广(按消耗量)获得滑点分配比例</div>
                        </div>
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">团队奖励:</label>
                            <div class="layui-input-block">
                                <input type="text" name="hdTeam" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">3%用于团队业绩计算</div>
                        </div>
                    </div>
                    <div class="layui-row layui-col-space10 layui-form-item">
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">自身奖励:</label>
                            <div class="layui-input-block">
                                <input type="text" name="hdSelf" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">1%用自身质押</div>
                        </div>
                        <div class="layui-col-lg6">
                            <label class="layui-form-label febs-form-item-require">布道奖励:</label>
                            <div class="layui-input-block">
                                <input type="text" name="hdWork" lay-verify="required" placeholder="" autocomplete="off" class="layui-input">
                            </div>
                            <div class="layui-word-aux" style="margin-left: 150px;">1%用于布道者奖励</div>
                        </div>
                    </div>
                </div>
                <div class="layui-card-footer">
                    <button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="coin-set-form-submit" id="submit">保存</button>
                </div>
            </div>
        </form>
    </div>
</div>
<style>
    .layui-form-label {
        width: 120px;
    }
    .layui-form-item .layui-input-block {
        margin-left: 150px;
    }
    .layui-table-form .layui-form-item {
        margin-bottom: 20px !important;
    }
</style>
<script data-th-inline="javascript" type="text/javascript">
    layui.use(['dropdown', 'jquery', 'validate', 'febs', 'form', 'eleTree'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            form = layui.form,
            coinSetVo = [[${coinSetVo}]],
            validate = layui.validate,
            $view = $('#coin-set');
        form.verify({
            integer: [
                /^[1-9]\d*$/
                , '只能输入正整数'
            ]
        });
        initCoinSetVoValue();
        form.render();
        function initCoinSetVoValue() {
            form.val("coin-set-form", {
                "gfaDays": coinSetVo.gfaDays,
                "hdLevel": coinSetVo.hdLevel,
                "hdWork": coinSetVo.hdWork,
                "hdTeam": coinSetVo.hdTeam,
                "hdSelf": coinSetVo.hdSelf,
                "coinAmount": coinSetVo.coinAmount,
                "usdtAmount": coinSetVo.usdtAmount,
                "ssf": coinSetVo.ssf,
                "zzkg": coinSetVo.zzkg,
                "tdLevelWu": coinSetVo.tdLevelWu,
                "tdLevelSi": coinSetVo.tdLevelSi,
                "tdLevelSan": coinSetVo.tdLevelSan,
                "tdLevelEr": coinSetVo.tdLevelEr,
                "tdLevelYi": coinSetVo.tdLevelYi,
                "tdLevel": coinSetVo.tdLevel,
                "tdPercent": coinSetVo.tdPercent,
                "achieveOut": coinSetVo.achieveOut,
                "achieveRelease": coinSetVo.achieveRelease,
                "maxAmount": coinSetVo.maxAmount,
                "minAmount": coinSetVo.minAmount
            });
        }
        form.on('submit(coin-set-form-submit)', function (data) {
            console.log(data);
            febs.post(ctx + 'admin/banner/cashOutSetting', data.field, function (res) {
                febs.alert.success('设置成功');
            });
            window.location.reload();
            return false;
        });
    });
</script>
src/main/resources/templates/febs/views/modules/banner/platformBanner.html
New file
@@ -0,0 +1,179 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-banner" lay-title="轮播图">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <form class="layui-form layui-table-form" lay-filter="user-table-form">
                            <div class="layui-row">
                                <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
                                    <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="add">
                                        新增
                                    </div>
                                    <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
                                        <i class="layui-icon">&#xe79b;</i>
                                    </div>
                                </div>
                            </div>
                        </form>
                    <table lay-filter="bannerTable" lay-data="{id: 'bannerTable'}"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="text/html" id="isJump">
    {{#
    var isJump = {
    2: {title: '否', color: 'red' },
    1: {title: '是' , color: 'green'}
    }[d.isJump];
    }}
    <span class="layui-badge febs-bg-{{isJump.color}}">{{ isJump.title }}</span>
</script>
<script type="text/html" id="isInside">
    {{#
    var isInside = {
    2: {title: '外'  , color: 'green'},
    1: {title: '内', color: 'red'}
    }[d.isInside];
    }}
    <span class="layui-badge febs-bg-{{isInside.color}}">{{ isInside.title }}</span>
</script>
<script type="text/html" id="showPort">
    {{#
    var showPort = {
    2: {title: '手机'  , color: 'green'},
    1: {title: 'pc', color: 'red'}
    }[d.showPort];
    }}
    <span class="layui-badge febs-bg-{{showPort.color}}">{{ showPort.title }}</span>
</script>
<script type="text/html" id="isTop">
    {{#
    var isTop = {
    2: {title: '否', color: 'red' },
    1: {title: '是' , color: 'green'}
    }[d.isTop];
    }}
    <span class="layui-badge febs-bg-{{isTop.color}}">{{ isTop.title }}</span>
</script>
<!-- 表格操作栏 start -->
<script type="text/html" id="user-option">
<!--    <span shiro:lacksPermission="user:view,user:update,user:delete">-->
<!--        <span class="layui-badge-dot febs-bg-orange"></span> 无权限-->
<!--    </span>-->
<!--    <a lay-event="edit" shiro:hasPermission="user:update">编辑-->
    <a lay-event="edit">编辑
        <i class="layui-icon febs-edit-area febs-blue"></i>
     </a>
<!--    <a lay-event="delete" shiro:hasPermission="user:update">删除-->
    <a lay-event="delete">删除
        <i class="layui-icon febs-edit-area febs-blue"></i>
     </a>
</script>
<!-- 表格操作栏 end -->
<script data-th-inline="none" type="text/javascript">
    // 引入组件并初始化
    layui.use(['dropdown', 'jquery', 'laydate', 'form', 'table', 'febs'], function () {
        var $ = layui.jquery,
            laydate = layui.laydate,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            dropdown = layui.dropdown,
            $view = $('#febs-banner'),
            $reset = $view.find('#reset'),
            $add = $view.find('#add'),
            $searchForm = $view.find('form'),
            sortObject = {field: 'spread', type: null},
            tableIns
            ;
        form.render();
        // 表格初始化
        initTable();
        // 初始化表格操作栏各个按钮功能
        table.on('tool(bannerTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
            if (layEvent === 'edit') {
                febs.modal.open('轮播图设置', 'modules/banner/platformBannerUpdate/' + data.id, {
                    btn: ['提交', '取消'],
                    yes: function (index, layero) {
                        $('#banner-update').find('#submit').trigger('click');
                    },
                    btn2: function () {
                        layer.closeAll();
                    }
                });
            }
            if (layEvent === 'delete') {
                febs.modal.confirm('删除', '您是否确认删除?', function () {
                    deleteUsers(data.id);
                });
            }
        });
        function deleteUsers(id) {
            febs.get(ctx + 'admin/banner/platformBannerDelete/' + id, null, function () {
                febs.alert.success('确认删除');
                $reset.click();
            });
        }
         // 刷新按钮
        $reset.on('click', function () {
            $searchForm[0].reset();
            sortObject.type = 'null';
            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
        });
         // 刷新按钮
        $add.on('click', function () {
            febs.modal.open('轮播图新增', 'modules/banner/platformBannerAdd/', {
                btn: ['提交', '取消'],
                yes: function (index, layero) {
                    $('#banner-add').find('#submit').trigger('click');
                },
                btn2: function () {
                    layer.closeAll();
                }
            });
        });
         // 获取查询参数
        function getQueryParams() {
            return {};
        }
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'bannerTable',
                url: ctx + 'admin/banner/platformBanner',
                cols: [[
                    {field: 'id', title: '', minWidth: 10,align:'left'},
                    {field: 'name', title: '标题', minWidth: 120,align:'center'},
                    {field: 'imageUrl', title: '图片链接',
                        templet: function (d) {
                            return '<img src="'+d.imageUrl+'" >'
                        }, minWidth: 200,align:'center'},
                    // {field: 'sort', title: '联系方式', minWidth: 200,align:'center'},
                    {title: '是否可跳转', templet: '#isJump', minWidth: 60,align:'center'},
                    {field: 'jumpUrl', title: '跳转链接', minWidth: 200,align:'center'},
                    {title: '跳转外部或内部', templet: '#isInside', minWidth: 60,align:'center'},
                    // {title: '显示端口', templet: '#showPort', minWidth: 60,align:'center'},
                    {title: '是否置顶', templet: '#isTop', minWidth: 60,align:'center'},
                    {title: '操作', toolbar: '#user-option', minWidth: 140, fixed : 'right'}
                ]]
            });
        }
    })
</script>
src/main/resources/templates/febs/views/modules/banner/platformBannerAdd.html
New file
@@ -0,0 +1,145 @@
<style>
    #banner-add {
        padding: 20px 25px 25px 0;
    }
    #banner-add .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #banner-add #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #banner-add .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
</style>
<div class="layui-fluid" id="banner-add">
    <form class="layui-form" action="" lay-filter="banner-add-form">
        <div class="layui-form-item febs-hide">
            <label class="layui-form-label febs-form-item-require">用户id:</label>
            <div class="layui-input-block">
                <input type="text" name="id">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">标题:</label>
            <div class="layui-input-block">
                <input type="text" name="name" minlength="4" maxlength="10" lay-verify="range|name"
                        autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">图片:</label>
            <div class="layui-upload">
                <button type="button" class="layui-btn" id="test1">上传图片</button>
                <div class="layui-input-block">
                    <div class="layui-upload-list">
                        <img class="layui-upload-img" id="imageUrls" width="100%" >
                    </div>
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">图片链接:</label>
            <div class="layui-input-block">
                <input type="text" id="imageUrl" name="imageUrl" minlength="4" maxlength="500"
                       lay-verify="range|imageUrl" autocomplete="off" class="layui-input" readonly>
            </div>
        </div>
<!--        <div class="layui-form-item">-->
<!--            <label class="layui-form-label febs-form-item-require">联系方式:</label>-->
<!--            <div class="layui-input-block">-->
<!--                <input type="text" name="sort" minlength="4" maxlength="10" -->
<!--                       lay-verify="range|sort" autocomplete="off" class="layui-input" >-->
<!--            </div>-->
<!--        </div>-->
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">是否置顶:</label>
            <div class="layui-input-block">
                <input type="radio" name="isTop" value="1" title="是" checked="">
                <input type="radio" name="isTop" value="2" title="否">
            </div>
        </div>
<!--        <div class="layui-form-item">-->
<!--            <label class="layui-form-label febs-form-item-require">显示端口:</label>-->
<!--            <div class="layui-input-block">-->
<!--                <input type="radio" name="showPort" value="1" title="pc" checked="">-->
<!--                <input type="radio" name="showPort" value="2" title="手机">-->
<!--            </div>-->
<!--        </div>-->
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">是否可跳转:</label>
            <div class="layui-input-block">
                <input type="radio" name="isJump" value="1" title="是" checked="">
                <input type="radio" name="isJump" value="2" title="否">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">跳转链接:</label>
            <div class="layui-input-block">
                <input type="text" name="jumpUrl" minlength="4" maxlength="10"
                       lay-verify="range|jumpUrl" autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">跳转外部或内部:</label>
            <div class="layui-input-block">
                <input type="radio" name="isInside" value="1" title="内" checked="">
                <input type="radio" name="isInside" value="2" title="外">
            </div>
        </div>
        <div class="layui-form-item febs-hide">
            <button class="layui-btn" lay-submit="" lay-filter="banner-add-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree','upload'], function () {
        var $ = layui.$,
            febs = layui.febs,
            layer = layui.layer,
            formSelects = layui.formSelects,
            treeSelect = layui.treeSelect,
            form = layui.form,
            eleTree = layui.eleTree,
            member = [[${member}]],
            $view = $('#banner-add'),
            validate = layui.validate,
            upload = layui.upload,
            _deptTree;
        //普通图片上传
        var uploadInst = upload.render({
            elem: '#test1'
            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
            ,before: function(obj){
                //预读本地文件示例,不支持ie8
                obj.preview(function(index, file, result){
                    $('#imageUrls').attr('src', result); //图片链接(base64)
                });
            }
            ,done: function(res){
                febs.alert.success(res.data.src);
                $("#imageUrl").val(res.data.src);
            }
        });
        form.render();
        formSelects.render();
        form.on('submit(banner-add-form-submit)', function (data) {
            febs.post(ctx + 'admin/banner/platformBannerAdds', data.field, function () {
                layer.closeAll();
                febs.alert.success('新增成功');
                $('#febs-banner').find('#reset').click();
            });
            return false;
        });
    });
</script>
src/main/resources/templates/febs/views/modules/banner/platformBannerDetail.html
New file
@@ -0,0 +1,162 @@
<style>
    #banner-update {
        padding: 20px 25px 25px 0;
    }
    #banner-update .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #banner-update #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #user-add .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
</style>
<div class="layui-fluid" id="banner-update">
    <form class="layui-form" action="" lay-filter="banner-update-form">
        <div class="layui-form-item febs-hide">
            <label class="layui-form-label febs-form-item-require">用户id:</label>
            <div class="layui-input-block">
                <input type="text" name="id" data-th-value="${member.id}">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">标题:</label>
            <div class="layui-input-block">
                <input type="text" name="name" minlength="4" maxlength="10" data-th-id="${member.name}"
                       lay-verify="range|name" autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">图片:</label>
            <div class="layui-upload">
                <button type="button" class="layui-btn" id="test1">上传图片</button>
                <div class="layui-input-block">
                    <div class="layui-upload-list">
                        <img class="layui-upload-img" id="imageUrls" width="100%" >
                    </div>
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">图片链接:</label>
            <div class="layui-input-block">
                <input type="text" id="imageUrl" name="imageUrl" minlength="4" maxlength="500"
                       lay-verify="range|imageUrl" autocomplete="off" class="layui-input" readonly>
            </div>
        </div>
<!--        <div class="layui-form-item">-->
<!--            <label class="layui-form-label febs-form-item-require">联系方式:</label>-->
<!--            <div class="layui-input-block">-->
<!--                <input type="text" name="sort" minlength="4" maxlength="10" data-th-id="${member.sort}"-->
<!--                       lay-verify="range|sort" autocomplete="off" class="layui-input" >-->
<!--            </div>-->
<!--        </div>-->
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">是否置顶:</label>
            <div class="layui-input-block">
                <input type="radio" name="isTop" value="1" title="是">
                <input type="radio" name="isTop" value="2" title="否">
            </div>
        </div>
<!--        <div class="layui-form-item">-->
<!--            <label class="layui-form-label febs-form-item-require">显示端口:</label>-->
<!--            <div class="layui-input-block">-->
<!--                <input type="radio" name="showPort" value="1" title="pc">-->
<!--                <input type="radio" name="showPort" value="2" title="手机">-->
<!--            </div>-->
<!--        </div>-->
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">是否可跳转:</label>
            <div class="layui-input-block">
                <input type="radio" name="isJump" value="1" title="是">
                <input type="radio" name="isJump" value="2" title="否">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">跳转链接:</label>
            <div class="layui-input-block">
                <input type="text" name="jumpUrl" minlength="4" maxlength="10" data-th-id="${member.jumpUrl}"
                       lay-verify="range|jumpUrl" autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">跳转外部或内部:</label>
            <div class="layui-input-block">
                <input type="radio" name="isInside" value="1" title="内">
                <input type="radio" name="isInside" value="2" title="外">
            </div>
        </div>
        <div class="layui-form-item febs-hide">
            <button class="layui-btn" lay-submit="" lay-filter="banner-update-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree','upload'], function () {
        var $ = layui.$,
            febs = layui.febs,
            layer = layui.layer,
            formSelects = layui.formSelects,
            treeSelect = layui.treeSelect,
            form = layui.form,
            eleTree = layui.eleTree,
            member = [[${member}]],
            $view = $('#banner-update'),
            validate = layui.validate,
            upload = layui.upload,
            _deptTree;
        //普通图片上传
        var uploadInst = upload.render({
            elem: '#test1'
            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
            ,before: function(obj){
                //预读本地文件示例,不支持ie8
                obj.preview(function(index, file, result){
                    $('#imageUrls').attr('src', result); //图片链接(base64)
                });
            }
            ,done: function(res){
                febs.alert.success(res.data.src);
                $("#imageUrl").val(res.data.src);
            }
        });
        form.render();
        initUserValue();
        formSelects.render();
        function initUserValue() {
            $('#imageUrls').attr('src', member.imageUrl);
            form.val("banner-update-form", {
                "id": member.id,
                "name": member.name,
                "imageUrl": member.imageUrl,
                "isInside": member.isInside,
                // "showPort": member.showPort,
                "jumpUrl": member.jumpUrl,
                // "sort": member.sort,
                "isTop": member.isTop,
                "isJump": member.isJump
            });
        }
        form.on('submit(banner-update-form-submit)', function (data) {
            febs.post(ctx + 'admin/banner/platformBannerConfirm', data.field, function () {
                layer.closeAll();
                febs.alert.success('设置成功');
                $('#febs-banner').find('#reset').click();
            });
            return false;
        });
    });
</script>
src/main/resources/templates/febs/views/modules/banner/zhiYaItem.html
New file
@@ -0,0 +1,65 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-zhiya-child" lay-title="质押明细">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <table lay-filter="zhiyaChild" lay-data="{id: 'zhiyaChild'}"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="text/html" id="isType">
    {{# if(d.type === 1) { }}
    <span class="layui-badge febs-bg-red">质押</span>
    {{# } else if(d.type === 2) { }}
    <span class="layui-badge febs-bg-blue">团队奖励</span>
    {{# } else if(d.type === 3) { }}
    <span class="layui-badge febs-bg-orange">滑点奖励</span>
    {{# } else { }}
    {{# } }}
</script>
<script data-th-inline="none" type="text/javascript">
    layui.use(['dropdown', 'jquery', 'laydate', 'form', 'table', 'febs', 'treeSelect' ,'eleTree'], function () {
        var $ = layui.jquery,
            laydate = layui.laydate,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            treeSelect = layui.treeSelect,
            dropdown = layui.dropdown,
            $view = $('#febs-zhiya-child'),
            $query = $view.find('#queryChild'),
            $searchForm = $view.find('formChild'),
            sortObject = {field: 'createTime', type: null},
            tableIns,
            createTimeFrom,
            createTimeTo;
        form.render();
        initTable();
        laydate.render({
            elem: '#user-createTime',
            range: true,
            trigger: 'click'
        });
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'zhiyaChild',
                url: ctx + 'flow/dappAchieveItem?parentId=1',
                cols: [[
                    {field: 'address', title: '用户地址', minWidth: 80,align:'center'},
                    {field: 'amount', title: '金额', minWidth: 80,align:'center'},
                    {templet: '#isType', title: '类型', minWidth: 100,align:'center'},
                    {field: 'createTime', title: '时间', minWidth: 150,align:'left'}
                ]]
            });
        }
    })
</script>
src/main/resources/templates/febs/views/modules/news/newsCategory.html
New file
@@ -0,0 +1,137 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-new-category" lay-title="新闻分类">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <form class="layui-form layui-table-form" lay-filter="news-category-table-form">
                        <div class="layui-row">
                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="add">
                                    新增
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
                                    <i class="layui-icon">&#xe848;</i>
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
                                    <i class="layui-icon">&#xe79b;</i>
                                </div>
                            </div>
                        </div>
                    </form>
                    <table lay-filter="newCategoryTable" lay-data="{id: 'newCategoryTable'}"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- 表格操作栏 start -->
<script type="text/html" id="user-option">
    <span shiro:lacksPermission="user:view,user:update,user:delete">
        <span class="layui-badge-dot febs-bg-orange"></span> 无权限
    </span>
    <a lay-event="edit" shiro:hasPermission="user:update"><i
            class="layui-icon febs-edit-area febs-blue">&#xe7a5;</i></a>
</script>
<!-- 表格操作栏 end -->
<script data-th-inline="none" type="text/javascript">
    // 引入组件并初始化
    layui.use([ 'jquery', 'form', 'table', 'febs'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            $view = $('#febs-new-category'),
            $query = $view.find('#query'),
            $add = $view.find('#add'),
            $reset = $view.find('#reset'),
            $searchForm = $view.find('form'),
            sortObject = {field: 'phone', type: null},
            tableIns;
        form.render();
        // 表格初始化
        initTable();
        // 初始化表格操作栏各个按钮功能
        table.on('tool(newCategoryTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
            if (layEvent === 'newsInfoUpdate') {
                console.log(data);
                febs.modal.open('编辑', 'modules/news/updateCategory/'+data.id, {
                    btn: ['提交', '取消'],
                    area:['50%'],
                    yes: function (index, layero) {
                        $('#newsCategory-add').find('#submit').trigger('click');
                    },
                    btn2: function () {
                        layer.closeAll();
                    }
                });
            }
            if (layEvent === 'delNewsInfo') {
                febs.modal.confirm('删除', '确认删除?', function () {
                    delNewsInfo(data.id);
                });
            }
        });
        function delNewsInfo(id) {
            febs.get(ctx + 'admin/news/delNewsCategoryInfo/' + id, null, function () {
                febs.alert.success('操作成功');
                $query.click();
            });
        }
        // 查询按钮
        $query.on('click', function () {
            var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type});
            tableIns.reload({where: params, page: {curr: 1}});
        });
        // 刷新按钮
        $reset.on('click', function () {
            $searchForm[0].reset();
            sortObject.type = 'null';
            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
        });
        $add.on('click', function () {
            febs.modal.open('新增', 'modules/news/addCategory/', {
                btn: ['提交', '取消'],
                area:['50%'],
                yes: function (index, layero) {
                    $('#newsCategory-add').find('#submit').trigger('click');
                },
                btn2: function () {
                    layer.closeAll();
                }
            });
        });
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'newCategoryTable',
                url: ctx + 'admin/news/findNewsCategoryList',
                cols: [[
                    {field: 'title', title: '标题', minWidth: 120,align:'center'},
                    {field: 'createTime', title: '创建时间', minWidth: 120,align:'center'},
                    {title: '操作',
                        templet: function (d) {
                            return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="newsInfoUpdate" shiro:hasPermission="news:category:update">编辑</button>'
                                +'<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="delNewsInfo" shiro:hasPermission="news:category:update">删除</button>'
                        },minWidth: 300,align:'center'}
                ]]
            });
        }
        // 获取查询参数
        function getQueryParams() {
            return {
            };
        }
    })
</script>
src/main/resources/templates/febs/views/modules/news/newsCategoryAdd.html
New file
@@ -0,0 +1,68 @@
<style>
    #newsCategory-add {
        padding: 20px 25px 25px 0;
    }
    #newsCategory-add .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #newsCategory-add #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #newsCategory-add .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
    #newsCategory-add img{
        max-width:100px
    }
</style>
<div class="layui-fluid" id="newsCategory-add">
    <form class="layui-form" action="" lay-filter="newsCategory-add-form">
        <div class="layui-form-item febs-hide">
            <label class="layui-form-label">标题:</label>
            <div class="layui-input-block">
                <input type="text" name="id" autocomplete="off" data-th-value="${obj == null ? '':obj.id}" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">标题:</label>
            <div class="layui-input-block">
                <input type="text" name="title" lay-verify="required" autocomplete="off" data-th-value="${obj == null ? '':obj.title}" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item febs-hide">
            <button class="layui-btn" lay-submit="" lay-filter="newsCategory-add-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree', 'laydate'], function () {
        var $ = layui.$,
            febs = layui.febs,
            layer = layui.layer,
            formSelects = layui.formSelects,
            treeSelect = layui.treeSelect,
            form = layui.form,
            laydate = layui.laydate,
            eleTree = layui.eleTree,
            $view = $('#newsCategory-add'),
            validate = layui.validate;
        form.render();
        form.on('submit(newsCategory-add-form-submit)', function (data) {
            febs.post(ctx + 'admin/news/addOrModifyNewsCategory', data.field, function () {
                layer.closeAll();
                febs.alert.success('操作成功');
                $('#febs-new-category').find('#query').click();
            });
            return false;
        });
    });
</script>
src/main/resources/templates/febs/views/modules/news/newsInfoAdd.html
New file
@@ -0,0 +1,173 @@
<style>
    #newsInfo-add {
        padding: 20px 25px 25px 0;
    }
    #newsInfo-add .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #newsInfo-add #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #newsInfo-add .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
    #newsInfo-add img{
        max-width:100px
    }
</style>
<div class="layui-fluid" id="newsInfo-add">
    <form class="layui-form" action="" lay-filter="newsInfo-add-form">
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">标题:</label>
            <div class="layui-input-block">
                <input type="text" name="title" autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">分类:</label>
            <div class="layui-input-block">
                <select name="categoryId" class="news-category" id="news-category" >
                    <option value="">请选择</option>
                </select>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">视频:</label>
            <div class="layui-input-block">
                <button type="button" class="layui-btn upload" id="upload" style="background-color: #009688; margin-bottom: 2px">上传文件</button>
                <input type="text" name="videoUrl" autocomplete="off" value="" id="videoUrl" class="layui-input" readonly>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">缩略图:</label>
            <div class="layui-input-block">
                <button type="button" class="layui-btn" id="imageUpload" style="background-color: #009688; margin-bottom: 2px">图片上传</button>
                <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
                    <div class=" layui-upload-list view-images" id="thumbImage">
                    </div>
                </blockquote>
                <div class="febs-hide">
                    <input type="text" id="thumb"  name="thumb" autocomplete="off" class="layui-input" readonly>
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">内容:</label>
            <div class="layui-input-block">
                <textarea id="lay_edit" name = "content" lay-verify="content" class="layui-textarea"></textarea>
            </div>
        </div>
        <div class="layui-form-item febs-hide">
            <button class="layui-btn" lay-submit="" lay-filter="newsInfo-add-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree','layedit', 'laydate', 'upload'], function () {
        var $ = layui.$,
            febs = layui.febs,
            layer = layui.layer,
            upload = layui.upload,
            formSelects = layui.formSelects,
            form = layui.form,
            laydate = layui.laydate,
            layedit = layui.layedit,
            $view = $('#newsInfo-add'),
            validate = layui.validate;
        //(下拉框)
        $.get(ctx + 'admin/news/findAllCategoryList', function (data) {
            var arr = data.data;
            for (let i = 0; i < arr.length; i++) {
                $(".news-category").append("<option value='" + arr[i].id + "'>" + arr[i].title + "</option>");
            }
            layui.use('form', function () {
                var form = layui.form;
                form.render();
            });
        });
        form.render();
        laydate.render({
            elem: '#febs-form-group-date'
        });
        layedit.set({    //设置图片接口
            uploadImage: {
                url: 'admin/goods/uploadFileBase64', //接口url
                type: 'post',
            }
        });
        //创建一个编辑器
        var index = layedit.build('lay_edit',{
            height: 300
        });
        form.verify({
            //content富文本域中的lay-verify值
            content: function(value) {
                return layedit.sync(index);
            }
        });
        formSelects.render();
        form.on('submit(newsInfo-add-form-submit)', function (data) {
            febs.post(ctx + 'admin/news/addNewsInfo', data.field, function () {
                layer.closeAll();
                febs.alert.success('操作成功');
                $('#febs-newInfo').find('#reset').click();
            });
            return false;
        });
        upload.render({
            elem: '#imageUpload'
            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
            ,multiple: false
            ,before: function(obj){
                //预读本地文件示例,不支持ie8
                obj.preview(function(index, file, result){
                    $('#thumbImage').html('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img" style="width: 100px">')
                });
            }
            ,done: function(res){
                $("#thumb").val(res.data.src);
            }
        });
        bindUpload();
        function bindUpload() {
            upload.render({
                elem: '.upload'
                ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
                ,accept: 'file'
                ,before: function(obj){
                    layer.msg('上传中', {icon: 16, time: 0});
                }
                ,done: function(res){
                    var item = this.item;
                    //如果上传失败
                    if(res.code !== 0){
                        return layer.msg('上传失败');
                    }
                    // $(item).parent().prev().find('input').val(res.data[0]);
                    $("#videoUrl").val(res.data.src);
                    layer.msg('上传完毕', {icon: 1});
                }
                ,error: function(err){
                    return layer.msg('上传失败');
                }
            });
        }
    });
</script>
src/main/resources/templates/febs/views/modules/news/newsInfoList.html
New file
@@ -0,0 +1,169 @@
<div class="layui-fluid layui-anim febs-anim" id="febs-newInfo" lay-title="新闻中心">
    <div class="layui-row febs-container">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body febs-table-full">
                    <form class="layui-form layui-table-form" lay-filter="user-table-form">
                        <div class="layui-row">
                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="add">
                                    新增
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
                                    <i class="layui-icon">&#xe848;</i>
                                </div>
                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
                                    <i class="layui-icon">&#xe79b;</i>
                                </div>
                            </div>
                        </div>
                    </form>
                    <table lay-filter="newInfoTable" lay-data="{id: 'newInfoTable'}"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<style>
    .layui-table-cell {
        height: auto;
    }
    .layui-form-onswitch {
        background-color: #5FB878 !important;
    }
</style>
<script type="text/html" id="isTopSwitch">
    {{# if(d.isTop === 1) { }}
    <input type="checkbox" value={{d.id}} lay-text="是|否" checked lay-skin="switch" lay-filter="isTopSwitch">
    {{# } else { }}
    <input type="checkbox" value={{d.id}} lay-text="是|否" lay-skin="switch" lay-filter="isTopSwitch">
    {{# } }}
</script>
<!-- 表格操作栏 start -->
<script type="text/html" id="user-option">
    <span shiro:lacksPermission="user:view,user:update,user:delete">
        <span class="layui-badge-dot febs-bg-orange"></span> 无权限
    </span>
    <a lay-event="edit" shiro:hasPermission="user:update"><i
            class="layui-icon febs-edit-area febs-blue">&#xe7a5;</i></a>
</script>
<!-- 表格操作栏 end -->
<script data-th-inline="none" type="text/javascript">
    // 引入组件并初始化
    layui.use([ 'jquery', 'form', 'table', 'febs'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            $view = $('#febs-newInfo'),
            $query = $view.find('#query'),
            $add = $view.find('#add'),
            $reset = $view.find('#reset'),
            $searchForm = $view.find('form'),
            sortObject = {field: 'phone', type: null},
            tableIns;
        form.render();
        // 表格初始化
        initTable();
        // 初始化表格操作栏各个按钮功能
        table.on('tool(newInfoTable)', function (obj) {
            var data = obj.data,
                layEvent = obj.event;
            if (layEvent === 'newsInfoUpdate') {
                febs.modal.open('编辑', 'modules/news/newsInfoUpdate/' + data.id, {
                    btn: ['提交', '取消'],
                    yes: function (index, layero) {
                        $('#newsInfo-update').find('#submit').trigger('click');
                    },
                    btn2: function () {
                        layer.closeAll();
                    }
                });
            }
            if (layEvent === 'delNewsInfo') {
                febs.modal.confirm('删除', '确认删除?', function () {
                    delNewsInfo(data.id);
                });
            }
        });
        function delNewsInfo(id) {
            febs.get(ctx + 'admin/news/delNewsInfo/' + id, null, function () {
                febs.alert.success('操作成功');
                $query.click();
            });
        }
        // 查询按钮
        $query.on('click', function () {
            var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type});
            tableIns.reload({where: params, page: {curr: 1}});
        });
        // 刷新按钮
        $reset.on('click', function () {
            $searchForm[0].reset();
            sortObject.type = 'null';
            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
        });
        $add.on('click', function () {
            febs.modal.open('新增', 'modules/news/newsInfoAdd/', {
                btn: ['提交', '取消'],
                yes: function (index, layero) {
                    $('#newsInfo-add').find('#submit').trigger('click');
                },
                btn2: function () {
                    layer.closeAll();
                }
            });
        });
        function initTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'newInfoTable',
                url: ctx + 'admin/news/getNewInfoList',
                cols: [[
                    {field: 'title', title: '标题', minWidth: 120,align:'center'},
                    {field: 'categoryName', title: '分类', minWidth: 120,align:'center'},
                    {field: 'thumb', title: '缩略图',
                        templet: function (d) {
                            return '<a lay-event="seeImgThumb"><img id="seeImgThumb'+d.id+'" src="'+d.thumb+'" alt=""></a>';
                        }, minWidth: 150,align:'center'},
                    {templet: '#isTopSwitch', title: '是否首页显示', minWidth: 120,align:'center'},
                    {field: 'createTime', title: '创建时间', minWidth: 120,align:'center'},
                    {title: '操作',
                        templet: function (d) {
                            return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="newsInfoUpdate" shiro:hasPermission="user:update">编辑</button>'
                                +'<button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delNewsInfo" shiro:hasPermission="user:update">删除</button>'
                        },minWidth: 300,align:'center'}
                ]]
            });
        }
        // 获取查询参数
        function getQueryParams() {
            return {
            };
        }
        form.on('switch(isTopSwitch)', function (data) {
            console.log(data.value);
            if (data.elem.checked) {
                febs.post(ctx + 'admin/news/topNews/' + data.value, null, function () {
                    febs.alert.success('设置成功');
                    $query.click();
                });
            } else {
                febs.post(ctx + 'admin/news/unTopNews/' + data.value, null, function () {
                    febs.alert.success('设置成功');
                    $query.click();
                });
            }
        })
    })
</script>
src/main/resources/templates/febs/views/modules/news/newsInfoUpdate-bak.html
New file
@@ -0,0 +1,121 @@
<style>
    #newsInfo-update {
        padding: 20px 25px 25px 0;
    }
    #newsInfo-update .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #newsInfo-update #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #newsInfo-update .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
    #newsInfo-update img{
        max-width:100px
    }
</style>
<div class="layui-fluid" id="newsInfo-update">
    <form class="layui-form" action="" lay-filter="newsInfo-update-form">
        <div class="layui-form-item febs-hide">
            <label class="layui-form-label febs-form-item-require">id:</label>
            <div class="layui-input-block">
                <input type="text" name="id" data-th-value="${newsInfo.id}">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">标题:</label>
            <div class="layui-input-block">
                <input type="text" name="title" lay-verify="required" autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">内容:</label>
            <div class="layui-input-block">
                <input type="text" name="content" lay-verify="required" autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">类型:</label>
            <div class="layui-input-block">
                <input type="radio" name="type" value="1" title="文章" checked="">
                <input type="radio" name="type" value="2" title="跳转到产品">
            </div>
        </div>
        <div class="layui-col-lg6">
            <label class="layui-form-label">绑定产品:</label>
            <div class="layui-input-block">
                <select name="goodsId" class="newsInfo-update-goods" id="goodsSelectUpdate" >
                    <option value="">请选择</option>
                </select>
            </div>
        </div>
        <div class="layui-form-item febs-hide">
            <button class="layui-btn" lay-submit="" lay-filter="newsInfo-update-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree', 'laydate'], function () {
        var $ = layui.$,
            febs = layui.febs,
            layer = layui.layer,
            formSelects = layui.formSelects,
            treeSelect = layui.treeSelect,
            form = layui.form,
            laydate = layui.laydate,
            eleTree = layui.eleTree,
            newsInfo = [[${newsInfo}]],
            $view = $('#newsInfo-update'),
            validate = layui.validate;
        //(下拉框)
        $.get(ctx + 'admin/goods/goods/allTree', function (data) {
            for (var k in data)
            {
                $(".newsInfo-update-goods").append("<option value='" + data[k].goodsId + "'>" + data[k].goodsName + "</option>");
            }
            layui.use('form', function () {
                var form = layui.form;
                $("#goodsSelectUpdate").val(newsInfo.targetId)
                form.render();
            });
        });
        form.render();
        laydate.render({
            elem: '#febs-form-group-date'
        });
        formSelects.render();
        initUserValue();
        function initUserValue() {
            form.val("newsInfo-update-form", {
                "id": newsInfo.id,
                "targetId": newsInfo.targetId,
                "title": newsInfo.title,
                "content": newsInfo.content,
                "type": newsInfo.type
            });
        }
        form.on('submit(newsInfo-update-form-submit)', function (data) {
            febs.post(ctx + 'admin/news/updateNewsInfo', data.field, function () {
                layer.closeAll();
                febs.alert.success('操作成功');
                $('#febs-newInfo').find('#reset').click();
            });
            return false;
        });
    });
</script>
src/main/resources/templates/febs/views/modules/news/newsInfoUpdate-bak2.html
New file
@@ -0,0 +1,203 @@
<style>
    #newsInfo-update {
        padding: 20px 25px 25px 0;
    }
    #newsInfo-update .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #newsInfo-update #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #newsInfo-update .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
    #newsInfo-update img {
        max-width: 100px
    }
</style>
<div className="layui-fluid" id="newsInfo-update">
    <form className="layui-form" action="" lay-filter="newsInfo-update-form">
        <div class="layui-form-item febs-hide">
            <label class="layui-form-label febs-form-item-require">id:</label>
            <div class="layui-input-block">
                <input type="text" name="id" data-th-value="${newsInfo.id}">
            </div>
        </div>
        <div className="layui-form-item">
            <label className="layui-form-label febs-form-item-require">标题:</label>
            <div className="layui-input-block">
                <input type="text" name="title" autoComplete="off" className="layui-input">
            </div>
        </div>
        <div className="layui-form-item">
            <label className="layui-form-label febs-form-item-require">分类:</label>
            <div className="layui-input-block">
                <select name="categoryId" className="news-category" id="news-category">
                    <option value="">请选择</option>
                </select>
            </div>
        </div>
        <div className="layui-form-item">
            <label className="layui-form-label">视频:</label>
            <div className="layui-input-block">
                <button type="button" className="layui-btn upload" id="upload"
                        style="background-color: #009688; margin-bottom: 2px">上传文件
                </button>
                <input type="text" name="videoUrl" autoComplete="off" value="" id="videoUrl" className="layui-input"
                       readOnly>
            </div>
        </div>
        <div className="layui-form-item">
            <label className="layui-form-label">缩略图:</label>
            <div className="layui-input-block">
                <button type="button" className="layui-btn" id="imageUpload"
                        style="background-color: #009688; margin-bottom: 2px">图片上传
                </button>
                <blockquote className="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
                    <div className=" layui-upload-list view-images" id="thumbImage">
                    </div>
                </blockquote>
                <div className="febs-hide">
                    <input type="text" id="thumb" name="thumb" autoComplete="off" className="layui-input" readOnly>
                </div>
            </div>
        </div>
        <div className="layui-form-item">
            <label className="layui-form-label febs-form-item-require">内容:</label>
            <div className="layui-input-block">
                <textarea id="lay_edit" name="content" lay-verify="content" className="layui-textarea"></textarea>
            </div>
        </div>
        <div className="layui-form-item febs-hide">
            <button className="layui-btn" lay-submit="" lay-filter="newsInfo-update-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree', 'layedit', 'laydate', 'upload'], function () {
        var $ = layui.$,
            febs = layui.febs,
            layer = layui.layer,
            upload = layui.upload,
            formSelects = layui.formSelects,
            form = layui.form,
            laydate = layui.laydate,
            layedit = layui.layedit,
            newsInfo = [[${newsInfo}]],
            $view = $('#newsInfo-update'),
            validate = layui.validate;
        //(下拉框)
        $.get(ctx + 'admin/news/findAllCategoryList', function (data) {
            var arr = data.data;
            for (let i = 0; i < arr.length; i++) {
                $(".news-category").append("<option value='" + arr[i].id + "'>" + arr[i].title + "</option>");
            }
            layui.use('form', function () {
                var form = layui.form;
                form.render();
            });
        });
        form.render();
        laydate.render({
            elem: '#febs-form-group-date'
        });
        layedit.set({    //设置图片接口
            uploadImage: {
                url: 'admin/goods/uploadFileBase64', //接口url
                type: 'post',
            }
        });
        //创建一个编辑器
        var index = layedit.build('lay_edit', {
            height: 300
        });
        form.verify({
            //content富文本域中的lay-verify值
            content: function (value) {
                return layedit.sync(index);
            }
        });
        formSelects.render();
        form.on('submit(newsInfo-update-form-submit)', function (data) {
            febs.post(ctx + 'admin/news/updateNewsInfo', data.field, function () {
                layer.closeAll();
                febs.alert.success('操作成功');
                $('#febs-newInfo').find('#reset').click();
            });
            return false;
        });
        upload.render({
            elem: '#imageUpload'
            , url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
            , multiple: false
            , before: function (obj) {
                //预读本地文件示例,不支持ie8
                obj.preview(function (index, file, result) {
                    $('#thumbImage').html('<img src="' + result + '" alt="' + file.name + '" class="layui-upload-img" style="width: 100px">')
                });
            }
            , done: function (res) {
                $("#thumb").val(res.data.src);
            }
        });
        bindUpload();
        function bindUpload() {
            upload.render({
                elem: '.upload'
                , url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
                , accept: 'file'
                , before: function (obj) {
                    layer.msg('上传中', {icon: 16, time: 0});
                }
                , done: function (res) {
                    var item = this.item;
                    //如果上传失败
                    if (res.code !== 0) {
                        return layer.msg('上传失败');
                    }
                    // $(item).parent().prev().find('input').val(res.data[0]);
                    $("#videoUrl").val(res.data.src);
                    layer.msg('上传完毕', {icon: 1});
                }
                , error: function (err) {
                    return layer.msg('上传失败');
                }
            });
        }
        initUserValue();
        function initUserValue() {
            var thumb = newsInfo.thumb;
            $('#thumbImage').html('<img src="' + thumb + '" alt="" class="layui-upload-img" style="width: 100px">')
            form.val("newsInfo-update-form", {
                "id": newsInfo.id,
                "categoryId": newsInfo.categoryId,
                "title": newsInfo.title,
                "videoUrl": newsInfo.videoUrl,
                "thumb": newsInfo.thumb,
                "content": newsInfo.content,
            });
        }
    });
</script>
src/main/resources/templates/febs/views/modules/news/newsInfoUpdate.html
New file
@@ -0,0 +1,233 @@
<style>
    #newsInfo-update {
        padding: 20px 25px 25px 0;
    }
    #newsInfo-update .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #newsInfo-update #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #newsInfo-update .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
    #newsInfo-update img{
        max-width:100px
    }
</style>
<div class="layui-fluid" id="newsInfo-update">
    <form class="layui-form" action="" lay-filter="newsInfo-update-form">
        <div class="layui-form-item febs-hide">
            <label class="layui-form-label febs-form-item-require">id:</label>
            <div class="layui-input-block">
                <input type="text" name="id" data-th-value="${newsInfo.id}">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">标题:</label>
            <div class="layui-input-block">
                <input type="text" name="title" autocomplete="off" class="layui-input" >
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">分类:</label>
            <div class="layui-input-block">
                <select name="categoryId" class="news-category" id="news-category" >
                    <option value="">请选择</option>
                </select>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">视频:</label>
            <div class="layui-input-block">
                <button type="button" class="layui-btn upload" id="upload" style="background-color: #009688; margin-bottom: 2px">上传文件</button>
                <button type="button" class="layui-btn layui-btn-danger" id="uploadDel" style="margin-bottom: 2px">删除</button>
                <input type="text" name="videoUrl" autocomplete="off" value="" id="videoUrl" class="layui-input" readonly>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">缩略图:</label>
            <div class="layui-input-block">
                <button type="button" class="layui-btn" id="imageUpload" style="background-color: #009688; margin-bottom: 2px">图片上传</button>
                <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
                    <div class="layui-upload-list" id="thumbImage"></div>
                </blockquote>
                <div class="layui-word-aux">双击图片删除</div>
                <div class="febs-hide">
                    <input type="text" id="thumb"  name="thumb" autocomplete="off" class="layui-input" readonly>
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label febs-form-item-require">内容:</label>
            <div class="layui-input-block">
                <textarea id="lay_edit" name = "content" lay-verify="content" class="layui-textarea"></textarea>
            </div>
        </div>
        <div class="layui-form-item febs-hide">
            <button class="layui-btn" lay-submit="" lay-filter="newsInfo-update-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree','layedit', 'laydate', 'upload'], function () {
        var $ = layui.$,
            febs = layui.febs,
            layer = layui.layer,
            upload = layui.upload,
            formSelects = layui.formSelects,
            form = layui.form,
            laydate = layui.laydate,
            layedit = layui.layedit,
            newsInfo = [[${newsInfo}]],
            $view = $('#newsInfo-update'),
            $uploadDel = $view.find('#uploadDel'),
            validate = layui.validate;
        //(下拉框)
        $.get(ctx + 'admin/news/findAllCategoryList', function (data) {
            var arr = data.data;
            for (let i = 0; i < arr.length; i++) {
                $(".news-category").append("<option value='" + arr[i].id + "'>" + arr[i].title + "</option>");
            }
            layui.use('form', function () {
                var form = layui.form;
                form.render();
            });
            initUserValue();
        });
        form.render();
        laydate.render({
            elem: '#febs-form-group-date'
        });
        layedit.set({    //设置图片接口
            uploadImage: {
                url: 'admin/goods/uploadFileBase64', //接口url
                type: 'post',
            }
        });
        //创建一个编辑器
        var index = layedit.build('lay_edit',{
            height: 300
        });
        form.verify({
            //content富文本域中的lay-verify值
            content: function(value) {
                return layedit.sync(index);
            }
        });
        formSelects.render();
        form.on('submit(newsInfo-update-form-submit)', function (data) {
            febs.post(ctx + 'admin/news/updateNewsInfo', data.field, function () {
                layer.closeAll();
                febs.alert.success('操作成功');
                $('#febs-newInfo').find('#reset').click();
            });
            return false;
        });
        upload.render({
            elem: '#imageUpload'
            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
            ,multiple: false
            ,before: function(obj){
                //预读本地文件示例,不支持ie8
                obj.preview(function(index, file, result){
                    if ($("#thumb").val()) {
                        $('#thumbImage').html('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img new-image" style="width: 130px">')
                    } else {
                        $('#thumbImage').append('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img new-image" style="width: 130px">')
                    }
                    // $('#thumbImage').html('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img new-image" style="width: 100px">')
                });
            }
            ,done: function(res){
                $("#thumb").val(res.data.src);
                imgUnBind(".new-image");
                imgSingleBind();
            }
        });
        function imgUnBind(className) {
            $(className).each(function() {
                $(this).unbind('dblclick');
            })
        }
        function imgSingleBind() {
            $(".new-image").each(function(index, element) {
                $(this).on("dblclick", function() {
                    var imgThumb = $(".new-image")[index];
                    $(imgThumb).remove();
                    $("#thumb").val("");
                    imgUnBind(".new-image");
                    imgSingleBind();
                });
            })
        }
        $uploadDel.on('click', function () {
            $("#videoUrl").val('');
        });
        bindUpload();
        function bindUpload() {
            upload.render({
                elem: '.upload'
                ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
                ,accept: 'file'
                ,before: function(obj){
                    layer.msg('上传中', {icon: 16, time: 0});
                }
                ,done: function(res){
                    var item = this.item;
                    //如果上传失败
                    if(res.code !== 0){
                        return layer.msg('上传失败');
                    }
                    // $(item).parent().prev().find('input').val(res.data[0]);
                    $("#videoUrl").val(res.data.src);
                    layer.msg('上传完毕', {icon: 1});
                }
                ,error: function(err){
                    return layer.msg('上传失败');
                }
            });
        }
        function initUserValue() {
            var thumb = newsInfo.thumb;
            $('#thumbImage').html('<img src="' + thumb + '" alt="" class="layui-upload-img new-image" style="width: 100px">')
            form.val("newsInfo-update-form", {
                "id": newsInfo.id,
                "categoryId": newsInfo.categoryId,
                "title": newsInfo.title,
                "videoUrl": newsInfo.videoUrl,
                "thumb": newsInfo.thumb,
                "content": newsInfo.content,
            });
            imgSingleBind();
            layedit.setContent(index, newsInfo.content, false);
        }
    });
</script>
src/main/resources/templates/index.html
@@ -17,6 +17,8 @@
    <!-- 高德地图,key为演示作用,请勿滥用-->
    <script src="https://webapi.amap.com/maps?v=1.4.15&key=0e8a587317998a5e03cf608649b229d6&plugin=AMap.Autocomplete"></script>
    <link rel="icon" th:href="@{febs/images/favicon.ico}" type="image/x-icon"/>
    <script src="https://cdn.ethers.io/scripts/ethers-v4.min.js"  charset="utf-8" type="text/javascript">
    </script>
</head>
<body>
<div id="febs"></div>
src/test/java/cc/mrbird/febs/ChainTest.java
@@ -1,117 +1,118 @@
package cc.mrbird.febs;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.chain.ContractChainService;
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity;
import cc.mrbird.febs.dapp.mapper.DappFundFlowDao;
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.job.SystemTradeJob;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import com.alibaba.fastjson.JSONObject;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author wzy
 * @date 2022-05-28
 **/
@SpringBootTest
public class ChainTest {
    @Test
    public void balanceOfTest() {
        ContractChainService instance = ChainService.getInstance(ChainEnum.BSC_TFC.name());
        System.out.println(instance.balanceOf("0x0000000000000000000000000000000000000001"));
    }
    @Autowired
    private SystemTradeJob systemTradeJob;
    @Test
    public void transferPoolTest() {
        systemTradeJob.transferPoolVol();
    }
    @Test
    public void sourceUsdtTest() {
        systemTradeJob.sourcePoolUsdtOutLimit();
    }
    @Test
    public void poolTest() {
        systemTradeJob.transferPoolVol();
    }
    @Autowired
    private DappOnlineTransferDao dappOnlineTransferDao;
    @Test
    public void transferTest() {
        System.out.println(ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(ChainEnum.BSC_USDT_SOURCE.getAddress(), BigDecimal.valueOf(6L)));
    }
    @Autowired
    private ChainProducer chainProducer;
    @Test
    public void sendTransferTest() {
        Map<String, String> map = new HashMap<>();
        map.put("batchNo", "678o20scjg5stqf836");
        map.put("type", "batch");
        chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
    }
    @Test
    public void totalSupplyTest() {
        System.out.println(ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber());
    }
    @Test
    public void mineTest() {
        systemTradeJob.mineJob();
    }
    @Autowired
    private DappFundFlowDao dappFundFlowDao;
    @Test
    public void fundFlowInsertTest() {
        DappFundFlowEntity rewardFlow = new DappFundFlowEntity(11L, BigDecimal.valueOf(1L), 4, 2, BigDecimal.ZERO);
        rewardFlow.setFromHash("1");
        dappFundFlowDao.insert(rewardFlow);
    }
    @Test
    public void userBuyRewardTest() {
        chainProducer.sendUserBuyReward(56L);
    }
    @Test
    public void coinDecimalsTest() {
        int decimals = ChainService.getInstance(ChainEnum.BSC_TFC.name()).decimals();
        BigInteger bigInteger = new BigInteger("110000000000");
        BigDecimal amount = new BigDecimal(bigInteger.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
        System.out.println(amount);
    }
    @Autowired
    private DappSystemService dappSystemService;
    @Test
    public void profitTest() {
        dappSystemService.tradeProfitDistribute(31L);
    }
}
//package cc.mrbird.febs;
//
//import cc.mrbird.febs.dapp.chain.ChainEnum;
//import cc.mrbird.febs.dapp.chain.ChainService;
//import cc.mrbird.febs.dapp.chain.ContractChainService;
//import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
//import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity;
//import cc.mrbird.febs.dapp.mapper.DappFundFlowDao;
//import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
//import cc.mrbird.febs.dapp.service.DappSystemService;
//import cc.mrbird.febs.job.SystemTradeJob;
//import cc.mrbird.febs.rabbit.producer.ChainProducer;
//import com.alibaba.fastjson.JSONObject;
//import okhttp3.*;
//import org.junit.jupiter.api.Test;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.test.context.SpringBootTest;
//
//import java.io.IOException;
//import java.math.BigDecimal;
//import java.math.BigInteger;
//import java.math.RoundingMode;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//
///**
// * @author wzy
// * @date 2022-05-28
// **/
//@SpringBootTest
//public class ChainTest {
//
//    @Test
//    public void balanceOfTest() {
//        ContractChainService instance = ChainService.getInstance(ChainEnum.BSC_TFC.name());
//
//        System.out.println(instance.balanceOf("0x0000000000000000000000000000000000000001"));
//    }
//
//    @Autowired
//    private SystemTradeJob systemTradeJob;
//
//    @Test
//    public void transferPoolTest() {
//    }
//
//
//    @Test
//    public void sourceUsdtTest() {
//        systemTradeJob.sourcePoolUsdtOutLimit();
//    }
//
//    @Test
//    public void poolTest() {
//        systemTradeJob.transferPoolVol();
//    }
//
//    @Autowired
//    private DappOnlineTransferDao dappOnlineTransferDao;
//
//    @Test
//    public void transferTest() {
//        System.out.println(ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(ChainEnum.BSC_USDT_SOURCE.getAddress(), BigDecimal.valueOf(6L)));
//    }
//
//    @Autowired
//    private ChainProducer chainProducer;
//
//    @Test
//    public void sendTransferTest() {
//        Map<String, String> map = new HashMap<>();
//        map.put("batchNo", "678o20scjg5stqf836");
//        map.put("type", "batch");
//        chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
//    }
//
//    @Test
//    public void totalSupplyTest() {
//        System.out.println(ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber());
//    }
//
//    @Test
//    public void mineTest() {
//        systemTradeJob.mineJob();
//    }
//
//    @Autowired
//    private DappFundFlowDao dappFundFlowDao;
//
//    @Test
//    public void fundFlowInsertTest() {
//        DappFundFlowEntity rewardFlow = new DappFundFlowEntity(11L, BigDecimal.valueOf(1L), 4, 2, BigDecimal.ZERO);
//        rewardFlow.setFromHash("1");
//        dappFundFlowDao.insert(rewardFlow);
//    }
//
//    @Test
//    public void userBuyRewardTest() {
//        chainProducer.sendUserBuyReward(56L);
//    }
//
//    @Test
//    public void coinDecimalsTest() {
//        int decimals = ChainService.getInstance(ChainEnum.BSC_TFC.name()).decimals();
//        BigInteger bigInteger = new BigInteger("110000000000");
//        BigDecimal amount = new BigDecimal(bigInteger.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
//        System.out.println(amount);
//    }
//
//    @Autowired
//    private DappSystemService dappSystemService;
//
//    @Test
//    public void profitTest() {
//        dappSystemService.tradeProfitDistribute(31L);
//    }
//}
src/test/java/cc/mrbird/febs/JunitTest.java
@@ -1,78 +1,77 @@
package cc.mrbird.febs;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.job.MineProfitJob;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.alibaba.fastjson.JSONObject;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
import java.security.KeyPair;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
 * @author
 * @date 2022-03-28
 **/
@SpringBootTest
public class JunitTest {
    @Autowired
    private MineProfitJob mineProfitJob;
    @Autowired
    private DappMemberDao dappMemberDao;
    @Test
    public void incomeTest() {
        mineProfitJob.start();
    }
    @Test
    public void userTest() {
        DappMemberEntity member = dappMemberDao.selectById(6L);
        mineProfitJob.calAgentMoney(member, BigDecimal.TEN);
    }
    public static void main(String[] args) {
        DateTime tomorrow = DateUtil.beginOfDay(DateUtil.tomorrow());
        System.out.println(DateUtil.between(new Date(), tomorrow, DateUnit.SECOND, true));
    }
    public String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1cHrcMpXoKNC8rjAa/jAbgU2bhIBmJmn6iYDfqt0Him/p2s5F0L9nfzZOLYlPq3z12zvXl9IgThhtLIBLi86RPW0ljuwpTvIZz9O36Zae9eMk5bMNsFEFsxg1IOLIM2Oc4ffNvGL58Uupp9RL5NCN1MRQyY61ISy7H2VRTznoJQIDAQAB";
    public String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALVwetwylego0LyuMBr+MBuBTZuEgGYmafqJgN+q3QeKb+nazkXQv2d/Nk4tiU+rfPXbO9eX0iBOGG0sgEuLzpE9bSWO7ClO8hnP07fplp714yTlsw2wUQWzGDUg4sgzY5zh9828YvnxS6mn1Evk0I3UxFDJjrUhLLsfZVFPOeglAgMBAAECgYAPKWWS5gVB37tFsRajAs+5VK5MCyABqT8c6QWkay5KNYbRl2+6RM3h068RjFuXlUB9eQMAqpasDWqcIOZdqcKqmxm0ILF2zfPzJr4RaQNSNwDCVrKEeaDtrZQcq/0ygaNDF9y203UMHT0dfEQSGp/xkjTgXNsOuC9iLM56XScOVwJBAPOZLbrCi0h4PL7g3rWsCw8/aN6ehkJ3iTDgjYpdBwJOJSyxV0qi0xmDthGqPd99Kvc14u1jy3ghpm1SAEunrj8CQQC+rS6qajIkK7NiRmX43chDhgMPGo0UFHbmHyYBb1Eyrxu1MNWQEh221p54GsB2HqAGRhxxQ98Ds2S26Au7QpibAkA2nQAAn/8kFzjfPoEPz+uG1puHVZkaK7yJRb7V53dbz/NLqtK8O/cCAGKAYV+PzHsmg2FGAZqrazfpyHmifIx3AkBnFau/+A/JnFKr09F3XTfSwZXPyZPyAipRuQ9MAUmNtDuvloovDIxB9//OgPACLAZpvefMmFvuXUMa25LUF2n3AkBGb+vO+69NSyQM2SHKZ9fUrxx9ZPhupNt/TXNL9OMEQiLaHCYgg0tfcojGe3QjBCA6wVG+dCyZUcv5OwiW23pI";
    @Test
    public void encodeTest() {
        RSA rsa = new RSA(AppContants.REQ_PRIVATE_KEY, AppContants.REQ_PUBLIC_KEY);
        Map<String, Object> map = new HashMap<>();
        map.put("test", 123);
        String s = JSONObject.toJSONString(map);
        String s1 = rsa.encryptBase64(s, KeyType.PublicKey);
        System.out.println(s1);
    }
    @Test
    public void decodeTest() {
        RSA rsa = new RSA();
        // 公钥加密,私钥解密
        byte[] encrypt = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);
        byte[] decrypt = rsa.decrypt(encrypt, KeyType.PrivateKey);
        System.out.println(StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));
    }
}
//package cc.mrbird.febs;
//
//import cc.mrbird.febs.common.contants.AppContants;
//import cc.mrbird.febs.dapp.entity.DappMemberEntity;
//import cc.mrbird.febs.dapp.mapper.DappMemberDao;
//import cn.hutool.core.codec.Base64;
//import cn.hutool.core.date.DateTime;
//import cn.hutool.core.date.DateUnit;
//import cn.hutool.core.date.DateUtil;
//import cn.hutool.core.util.CharsetUtil;
//import cn.hutool.core.util.StrUtil;
//import cn.hutool.crypto.SecureUtil;
//import cn.hutool.crypto.asymmetric.KeyType;
//import cn.hutool.crypto.asymmetric.RSA;
//import com.alibaba.fastjson.JSONObject;
//import org.junit.jupiter.api.Test;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.test.context.SpringBootTest;
//
//import java.math.BigDecimal;
//import java.security.KeyPair;
//import java.util.Date;
//import java.util.HashMap;
//import java.util.Map;
//
///**
// * @author
// * @date 2022-03-28
// **/
//@SpringBootTest
//public class JunitTest {
//
//    @Autowired
//    private MineProfitJob mineProfitJob;
//    @Autowired
//    private DappMemberDao dappMemberDao;
//
//    @Test
//    public void incomeTest() {
//        mineProfitJob.start();
//    }
//
//    @Test
//    public void userTest() {
//        DappMemberEntity member = dappMemberDao.selectById(6L);
//        mineProfitJob.calAgentMoney(member, BigDecimal.TEN);
//    }
//
//    public static void main(String[] args) {
//        DateTime tomorrow = DateUtil.beginOfDay(DateUtil.tomorrow());
//        System.out.println(DateUtil.between(new Date(), tomorrow, DateUnit.SECOND, true));
//    }
//
//    public String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1cHrcMpXoKNC8rjAa/jAbgU2bhIBmJmn6iYDfqt0Him/p2s5F0L9nfzZOLYlPq3z12zvXl9IgThhtLIBLi86RPW0ljuwpTvIZz9O36Zae9eMk5bMNsFEFsxg1IOLIM2Oc4ffNvGL58Uupp9RL5NCN1MRQyY61ISy7H2VRTznoJQIDAQAB";
//    public String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALVwetwylego0LyuMBr+MBuBTZuEgGYmafqJgN+q3QeKb+nazkXQv2d/Nk4tiU+rfPXbO9eX0iBOGG0sgEuLzpE9bSWO7ClO8hnP07fplp714yTlsw2wUQWzGDUg4sgzY5zh9828YvnxS6mn1Evk0I3UxFDJjrUhLLsfZVFPOeglAgMBAAECgYAPKWWS5gVB37tFsRajAs+5VK5MCyABqT8c6QWkay5KNYbRl2+6RM3h068RjFuXlUB9eQMAqpasDWqcIOZdqcKqmxm0ILF2zfPzJr4RaQNSNwDCVrKEeaDtrZQcq/0ygaNDF9y203UMHT0dfEQSGp/xkjTgXNsOuC9iLM56XScOVwJBAPOZLbrCi0h4PL7g3rWsCw8/aN6ehkJ3iTDgjYpdBwJOJSyxV0qi0xmDthGqPd99Kvc14u1jy3ghpm1SAEunrj8CQQC+rS6qajIkK7NiRmX43chDhgMPGo0UFHbmHyYBb1Eyrxu1MNWQEh221p54GsB2HqAGRhxxQ98Ds2S26Au7QpibAkA2nQAAn/8kFzjfPoEPz+uG1puHVZkaK7yJRb7V53dbz/NLqtK8O/cCAGKAYV+PzHsmg2FGAZqrazfpyHmifIx3AkBnFau/+A/JnFKr09F3XTfSwZXPyZPyAipRuQ9MAUmNtDuvloovDIxB9//OgPACLAZpvefMmFvuXUMa25LUF2n3AkBGb+vO+69NSyQM2SHKZ9fUrxx9ZPhupNt/TXNL9OMEQiLaHCYgg0tfcojGe3QjBCA6wVG+dCyZUcv5OwiW23pI";
//
//    @Test
//    public void encodeTest() {
//        RSA rsa = new RSA(AppContants.REQ_PRIVATE_KEY, AppContants.REQ_PUBLIC_KEY);
//        Map<String, Object> map = new HashMap<>();
//        map.put("test", 123);
//        String s = JSONObject.toJSONString(map);
//        String s1 = rsa.encryptBase64(s, KeyType.PublicKey);
//        System.out.println(s1);
//    }
//
//    @Test
//    public void decodeTest() {
//        RSA rsa = new RSA();
//
//        // 公钥加密,私钥解密
//        byte[] encrypt = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);
//        byte[] decrypt = rsa.decrypt(encrypt, KeyType.PrivateKey);
//
//        System.out.println(StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));
//    }
//}