能量发送失败记录列表功能

pull/520/head
dorion 2024-07-07 23:54:28 +08:00
parent 265cf6207f
commit 3ae5fa0dc6
12 changed files with 1288 additions and 7 deletions

View File

@ -0,0 +1,134 @@
package com.ruoyi.web.controller.trx2Energy;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.TrxExchangeFail;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ITrxExchangeFailService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* Controller
*
* @author dorion
* @date 2024-07-07
*/
@Controller
@RequestMapping("/trx2Energy/fail")
public class TrxExchangeFailController extends BaseController
{
private String prefix = "trx2Energy/fail";
@Autowired
private ITrxExchangeFailService trxExchangeFailService;
@RequiresPermissions("trx2Energy:fail:view")
@GetMapping()
public String fail()
{
return prefix + "/fail";
}
/**
*
*/
@RequiresPermissions("trx2Energy:fail:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(TrxExchangeFail trxExchangeFail)
{
startPage();
List<TrxExchangeFail> list = trxExchangeFailService.selectTrxExchangeFailList(trxExchangeFail);
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("trx2Energy:fail:export")
@Log(title = "发送失败记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(TrxExchangeFail trxExchangeFail)
{
List<TrxExchangeFail> list = trxExchangeFailService.selectTrxExchangeFailList(trxExchangeFail);
ExcelUtil<TrxExchangeFail> util = new ExcelUtil<TrxExchangeFail>(TrxExchangeFail.class);
return util.exportExcel(list, "发送失败记录数据");
}
/**
*
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
*
*/
@RequiresPermissions("trx2Energy:fail:add")
@Log(title = "发送失败记录", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(TrxExchangeFail trxExchangeFail)
{
return toAjax(trxExchangeFailService.insertTrxExchangeFail(trxExchangeFail));
}
/**
*
*/
@RequiresPermissions("trx2Energy:fail:edit")
@GetMapping("/edit/{idTrxExchangeFail}")
public String edit(@PathVariable("idTrxExchangeFail") Long idTrxExchangeFail, ModelMap mmap)
{
TrxExchangeFail trxExchangeFail = trxExchangeFailService.selectTrxExchangeFailByIdTrxExchangeFail(idTrxExchangeFail);
mmap.put("trxExchangeFail", trxExchangeFail);
return prefix + "/edit";
}
/**
*
*/
@RequiresPermissions("trx2Energy:fail:edit")
@Log(title = "发送失败记录", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(TrxExchangeFail trxExchangeFail)
{
return toAjax(trxExchangeFailService.updateTrxExchangeFail(trxExchangeFail));
}
/**
*
*/
@RequiresPermissions("trx2Energy:fail:remove")
@Log(title = "发送失败记录", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(trxExchangeFailService.deleteTrxExchangeFailByIdTrxExchangeFails(ids));
}
@RequiresPermissions("trx2Energy:fail:edit")
@Log(title = "批量补偿", businessType = BusinessType.ACTIVE_DATA)
@PostMapping( "/completeTask")
@ResponseBody
public AjaxResult completeTask(String ids) throws Exception {
return toAjax(trxExchangeFailService.complete(ids));
}
}

View File

@ -0,0 +1,123 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('新增发送失败记录')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-fail-add">
<div class="form-group">
<label class="col-sm-3 control-label">转出账户:</label>
<div class="col-sm-8">
<input name="fromAddress" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转入账户:</label>
<div class="col-sm-8">
<input name="toAddress" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">实际出账账户:</label>
<div class="col-sm-8">
<input name="accountAddress" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">单价:</label>
<div class="col-sm-8">
<input name="price" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">订单hash</label>
<div class="col-sm-8">
<input name="trxTxId" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">笔数:</label>
<div class="col-sm-8">
<select name="tranferCount" class="form-control m-b" th:with="type=${@dict.getType('sys_transfer_number')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">业务类型:</label>
<div class="col-sm-8">
<select name="energyBusiType" class="form-control m-b" th:with="type=${@dict.getType('sys_energy_busi_type')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转入金额:</label>
<div class="col-sm-8">
<input name="trxAmount" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转入单位:</label>
<div class="col-sm-8">
<select name="trxAmountUnit" class="form-control m-b" th:with="type=${@dict.getType('sys_monitor_type')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">兑换支出能量:</label>
<div class="col-sm-8">
<input name="delegateAmountTrx" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">资源类型:</label>
<div class="col-sm-8">
<select name="resourceCode" class="form-control m-b" th:with="type=${@dict.getType('sys_trx_exchange')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">锁定周期:</label>
<div class="col-sm-8">
<select name="lockPeriod" class="form-control m-b" th:with="type=${@dict.getType('sys_lock_period')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">补偿状态:</label>
<div class="col-sm-8">
<select name="delegateStatus" class="form-control m-b" th:with="type=${@dict.getType('sys_delegate_status')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">笔数计算规则:</label>
<div class="col-sm-8">
<select name="calcRule" class="form-control m-b" th:with="type=${@dict.getType('sys_transaction_count_calc_rule')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "trx2Energy/fail"
$("#form-fail-add").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-fail-add').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('修改发送失败记录')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-fail-edit" th:object="${trxExchangeFail}">
<input name="idTrxExchangeFail" th:field="*{idTrxExchangeFail}" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">转出账户:</label>
<div class="col-sm-8">
<input name="fromAddress" th:field="*{fromAddress}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转入账户:</label>
<div class="col-sm-8">
<input name="toAddress" th:field="*{toAddress}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">实际出账账户:</label>
<div class="col-sm-8">
<input name="accountAddress" th:field="*{accountAddress}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">单价:</label>
<div class="col-sm-8">
<input name="price" th:field="*{price}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">订单hash</label>
<div class="col-sm-8">
<input name="trxTxId" th:field="*{trxTxId}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">笔数:</label>
<div class="col-sm-8">
<select name="tranferCount" class="form-control m-b" th:with="type=${@dict.getType('sys_transfer_number')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{tranferCount}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">业务类型:</label>
<div class="col-sm-8">
<select name="energyBusiType" class="form-control m-b" th:with="type=${@dict.getType('sys_energy_busi_type')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{energyBusiType}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转入金额:</label>
<div class="col-sm-8">
<input name="trxAmount" th:field="*{trxAmount}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转入单位:</label>
<div class="col-sm-8">
<select name="trxAmountUnit" class="form-control m-b" th:with="type=${@dict.getType('sys_monitor_type')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{trxAmountUnit}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">兑换支出能量:</label>
<div class="col-sm-8">
<input name="delegateAmountTrx" th:field="*{delegateAmountTrx}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">资源类型:</label>
<div class="col-sm-8">
<select name="resourceCode" class="form-control m-b" th:with="type=${@dict.getType('sys_trx_exchange')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{resourceCode}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">锁定周期:</label>
<div class="col-sm-8">
<select name="lockPeriod" class="form-control m-b" th:with="type=${@dict.getType('sys_lock_period')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{lockPeriod}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">补偿状态:</label>
<div class="col-sm-8">
<select name="delegateStatus" class="form-control m-b" th:with="type=${@dict.getType('sys_delegate_status')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{delegateStatus}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">笔数计算规则:</label>
<div class="col-sm-8">
<select name="calcRule" class="form-control m-b" th:with="type=${@dict.getType('sys_transaction_count_calc_rule')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{calcRule}"></option>
</select>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "trx2Energy/fail";
$("#form-fail-edit").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-fail-edit').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('发送失败记录列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>转出账户:</label>
<input type="text" name="fromAddress"/>
</li>
<li>
<label>订单hash</label>
<input type="text" name="trxTxId"/>
</li>
<li>
<label>补偿状态:</label>
<select name="delegateStatus" th:with="type=${@dict.getType('sys_delegate_status')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li class="select-time">
<label>创建时间:</label>
<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginCreateTime]"/>
<span>-</span>
<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endCreateTime]"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<!--<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="trx2Energy:fail:add">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="trx2Energy:fail:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="trx2Energy:fail:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="trx2Energy:fail:export">
<i class="fa fa-download"></i> 导出
</a>-->
<a class="btn btn-danger multiple disabled" onclick="$.table.completeTask()" shiro:hasPermission="trx2Energy:fail:edit">
<i class="fa fa-edit"></i> 批量补偿
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('trx2Energy:fail:edit')}]];
var removeFlag = [[${@permission.hasPermi('trx2Energy:fail:remove')}]];
var tranferCountDatas = [[${@dict.getType('sys_transfer_number')}]];
var energyBusiTypeDatas = [[${@dict.getType('sys_energy_busi_type')}]];
var trxAmountUnitDatas = [[${@dict.getType('sys_monitor_type')}]];
var resourceCodeDatas = [[${@dict.getType('sys_trx_exchange')}]];
var lockPeriodDatas = [[${@dict.getType('sys_lock_period')}]];
var delegateStatusDatas = [[${@dict.getType('sys_delegate_status')}]];
var calcRuleDatas = [[${@dict.getType('sys_transaction_count_calc_rule')}]];
var prefix = ctx + "trx2Energy/fail";
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
completeTaskUrl: prefix + "/completeTask",
modalName: "发送失败记录",
columns: [{
checkbox: true
},
{
field: 'idTrxExchangeFail',
title: '主键id',
visible: false
},
{
field: 'fromAddress',
title: '转出账户'
},
{
field: 'toAddress',
title: '转入账户'
},
{
field: 'accountAddress',
title: '实际出账账户'
},
{
field: 'price',
title: '单价'
},
{
field: 'trxTxId',
title: '订单hash'
},
{
field: 'tranferCount',
title: '笔数',
formatter: function(value, row, index) {
return $.table.selectDictLabel(tranferCountDatas, value);
}
},
{
field: 'energyBusiType',
title: '业务类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(energyBusiTypeDatas, value);
}
},
{
field: 'trxAmount',
title: '转入金额',
formatter: function (value, row, index) {
if (value == null) {
return value;
}
return value + ' ' + row['trxAmountUnit'];
}
},
{
field: 'trxAmountUnit',
title: '转入单位',
formatter: function(value, row, index) {
return $.table.selectDictLabel(trxAmountUnitDatas, value);
},
visible: false
},
{
field: 'resourceCode',
title: '资源类型',
formatter: function(value, row, index) {
return $.table.selectDictLabel(resourceCodeDatas, value);
}
},
{
field: 'lockPeriod',
title: '锁定周期',
formatter: function(value, row, index) {
return $.table.selectDictLabel(lockPeriodDatas, value);
}
},
{
field: 'delegateStatus',
title: '补偿状态',
formatter: function(value, row, index) {
return $.table.selectDictLabel(delegateStatusDatas, value);
}
},
{
field: 'calcRule',
title: '笔数计算规则',
formatter: function(value, row, index) {
return $.table.selectDictLabel(calcRuleDatas, value);
}
}/*,
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.idTrxExchangeFail + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.idTrxExchangeFail + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}*/]
};
$.table.init(options);
});
</script>
</body>
</html>

View File

@ -0,0 +1,225 @@
package com.ruoyi.common.core.domain.entity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* trx_exchange_fail
*
* @author dorion
* @date 2024-07-07
*/
public class TrxExchangeFail extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键id */
private Long idTrxExchangeFail;
/** 转出账户 */
@Excel(name = "转出账户")
private String fromAddress;
/** 转入账户 */
@Excel(name = "转入账户")
private String toAddress;
/** 实际出账账户 */
@Excel(name = "实际出账账户")
private String accountAddress;
/** 单价 */
@Excel(name = "单价")
private Long price;
/** 订单hash */
@Excel(name = "订单hash")
private String trxTxId;
/** 笔数 */
@Excel(name = "笔数")
private Long tranferCount;
/** 业务类型 */
@Excel(name = "业务类型")
private String energyBusiType;
/** 转入金额 */
@Excel(name = "转入金额")
private Long trxAmount;
/** 转入单位 */
@Excel(name = "转入单位")
private String trxAmountUnit;
/** 资源类型 */
@Excel(name = "资源类型")
private String resourceCode;
/** 锁定周期 */
@Excel(name = "锁定周期")
private Long lockPeriod;
/** 补偿状态 */
@Excel(name = "补偿状态")
private String delegateStatus;
/** 笔数计算规则 */
@Excel(name = "笔数计算规则")
private String calcRule;
public void setIdTrxExchangeFail(Long idTrxExchangeFail)
{
this.idTrxExchangeFail = idTrxExchangeFail;
}
public Long getIdTrxExchangeFail()
{
return idTrxExchangeFail;
}
public void setFromAddress(String fromAddress)
{
this.fromAddress = fromAddress;
}
public String getFromAddress()
{
return fromAddress;
}
public void setToAddress(String toAddress)
{
this.toAddress = toAddress;
}
public String getToAddress()
{
return toAddress;
}
public void setAccountAddress(String accountAddress)
{
this.accountAddress = accountAddress;
}
public String getAccountAddress()
{
return accountAddress;
}
public void setPrice(Long price)
{
this.price = price;
}
public Long getPrice()
{
return price;
}
public void setTrxTxId(String trxTxId)
{
this.trxTxId = trxTxId;
}
public String getTrxTxId()
{
return trxTxId;
}
public void setTranferCount(Long tranferCount)
{
this.tranferCount = tranferCount;
}
public Long getTranferCount()
{
return tranferCount;
}
public void setEnergyBusiType(String energyBusiType)
{
this.energyBusiType = energyBusiType;
}
public String getEnergyBusiType()
{
return energyBusiType;
}
public void setTrxAmount(Long trxAmount)
{
this.trxAmount = trxAmount;
}
public Long getTrxAmount()
{
return trxAmount;
}
public void setTrxAmountUnit(String trxAmountUnit)
{
this.trxAmountUnit = trxAmountUnit;
}
public String getTrxAmountUnit()
{
return trxAmountUnit;
}
public void setResourceCode(String resourceCode)
{
this.resourceCode = resourceCode;
}
public String getResourceCode()
{
return resourceCode;
}
public void setLockPeriod(Long lockPeriod)
{
this.lockPeriod = lockPeriod;
}
public Long getLockPeriod()
{
return lockPeriod;
}
public void setDelegateStatus(String delegateStatus)
{
this.delegateStatus = delegateStatus;
}
public String getDelegateStatus()
{
return delegateStatus;
}
public void setCalcRule(String calcRule)
{
this.calcRule = calcRule;
}
public String getCalcRule()
{
return calcRule;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("idTrxExchangeFail", getIdTrxExchangeFail())
.append("fromAddress", getFromAddress())
.append("toAddress", getToAddress())
.append("accountAddress", getAccountAddress())
.append("price", getPrice())
.append("trxTxId", getTrxTxId())
.append("tranferCount", getTranferCount())
.append("energyBusiType", getEnergyBusiType())
.append("trxAmount", getTrxAmount())
.append("trxAmountUnit", getTrxAmountUnit())
.append("resourceCode", getResourceCode())
.append("lockPeriod", getLockPeriod())
.append("delegateStatus", getDelegateStatus())
.append("calcRule", getCalcRule())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@ -4,8 +4,8 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/**
*
@ -77,8 +77,10 @@ public class DictUtils
if (StringUtils.isNotNull(cacheObj))
{
List<SysDictData> sysDictDataList = StringUtils.cast(cacheObj);
Collections.shuffle(sysDictDataList);
return sysDictDataList.get(0).getDictValue();
Random random = new Random();
int i = random.nextInt(sysDictDataList.size());
// Collections.shuffle(sysDictDataList);
return sysDictDataList.get(i).getDictValue();
}
return null;

View File

@ -7,6 +7,7 @@ import cn.hutool.json.JSONUtil;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.ErrorLog;
import com.ruoyi.common.core.domain.entity.TenantInfo;
import com.ruoyi.common.core.domain.entity.TrxExchangeFail;
import com.ruoyi.common.core.domain.entity.TrxExchangeInfo;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.ForwardCounter;
@ -22,6 +23,7 @@ import com.ruoyi.system.dto.Data;
import com.ruoyi.system.dto.TronGridResponse;
import com.ruoyi.system.dto.Value;
import com.ruoyi.system.mapper.TenantInfoMapper;
import com.ruoyi.system.mapper.TrxExchangeFailMapper;
import com.ruoyi.system.mapper.TrxExchangeInfoMapper;
import com.ruoyi.system.service.IErrorLogService;
import com.ruoyi.system.service.ISysConfigService;
@ -75,6 +77,8 @@ public class TRX2EneryTransferHandler {
@Autowired
private IErrorLogService errorLogService;
@Autowired
private TrxExchangeFailMapper trxExchangeFailMapper;
public void doMonitorTrxTransferByMonitorAddressInfo(MonitorAddressAccount monitorAddressAccount) {
@ -146,9 +150,10 @@ public class TRX2EneryTransferHandler {
.errorMsg(exceptionString.length() > 2000 ? exceptionString.substring(0, 2000) : exceptionString)
.fcu("system")
.lcu("system").build();
errorLogService.insertErrorLog(errorLog);
// throw new RuntimeException("doDelegateResource业务处理异常", e);
} finally {
if (lock.isLocked()) {
if (lock.isHeldByCurrentThread()) {
@ -366,7 +371,30 @@ public class TRX2EneryTransferHandler {
/* lock_period: 锁定周期以区块时间3s为单位表示锁定多少个区块的时间当lock为true时该字段有效。如果代理锁定期为1天则lock_period为28800*/
delegateResourceTxid = getDelegateResourceTxid(apiWrapper, accountAddress, balance, ownerAddress, resourceCode);
try {
delegateResourceTxid = getDelegateResourceTxid(apiWrapper, accountAddress, balance, ownerAddress, resourceCode);
} catch (Exception e) {
Object cacheidTrxExchangeFail = redisTemplate.opsForValue().get("transfer_trx_fail_" + txID);
if (cacheidTrxExchangeFail == null){
TrxExchangeFail trxExchangeFail = new TrxExchangeFail();
trxExchangeFail.setFromAddress(ownerAddress);
trxExchangeFail.setToAddress(toAddress);
trxExchangeFail.setAccountAddress(accountAddress);
trxExchangeFail.setPrice(price);
trxExchangeFail.setTrxTxId(txID);
trxExchangeFail.setTranferCount(transferCount);
trxExchangeFail.setEnergyBusiType(sysEnergyBusiType);
trxExchangeFail.setTrxAmount(amount);
trxExchangeFail.setTrxAmountUnit(trxAmountUnit);
trxExchangeFail.setResourceCode(resourceCode);
trxExchangeFail.setLockPeriod(lockPeriod);
trxExchangeFail.setDelegateStatus("2");
trxExchangeFail.setCalcRule(calcRule);
trxExchangeFailMapper.insertTrxExchangeFail(trxExchangeFail);
redisTemplate.opsForValue().set("transfer_trx_fail_" + txID, trxExchangeFail.getIdTrxExchangeFail(), 1, TimeUnit.HOURS);
}
throw new RuntimeException(e);
}
}
String fromAddress = AddressUtil.hexToBase58(ownerAddress);
@ -393,6 +421,16 @@ public class TRX2EneryTransferHandler {
.build();
trxExchangeInfoMapper.insertTrxExchangeInfo(trxExchangeInfo);
Object cacheidTrxExchangeFail = redisTemplate.opsForValue().get("transfer_trx_fail_" + txID);
if (cacheidTrxExchangeFail != null){
TrxExchangeFail trxExchangeFail = new TrxExchangeFail();
trxExchangeFail.setIdTrxExchangeFail(Long.valueOf(cacheidTrxExchangeFail.toString()));
trxExchangeFail.setDelegateStatus("1");
trxExchangeFailMapper.updateTrxExchangeFail(trxExchangeFail);
redisTemplate.delete("transfer_trx_fail_" + txID);
}
String sysenTrxTransferNotice = configService.selectConfigByKey("sys.energy.transaction.notice");
String sysTgGroupChatId = configService.selectConfigByKey("sys.tg.group.chat.id");
if (longPollingBot != null && StringUtils.isNotEmpty(sysenTrxTransferNotice) && StringUtils.isNotEmpty(sysTgGroupChatId)) {
@ -443,11 +481,13 @@ public class TRX2EneryTransferHandler {
}
private String getDelegateResourceTxid(ApiWrapper apiWrapper, String accountAddress, long balance, String ownerAddress, String resourceCode) throws IllegalException {
Response.TransactionExtention transactionExtention = apiWrapper.delegateResourceV2(accountAddress, balance * 1000000, Common.ResourceCode.valueOf(resourceCode).getNumber(), ownerAddress, false, 0);
Chain.Transaction transaction = apiWrapper.signTransaction(transactionExtention);
String delegateResourceTxid = apiWrapper.broadcastTransaction(transaction);
return delegateResourceTxid;
}

View File

@ -246,6 +246,7 @@ public class UndelegateEnergyHandler {
tenantInfo.setLcu("system");
tenantInfo.setLcd(new Date());
tenantInfoMapper.updateTenantInfo(tenantInfo);
}
@ -261,7 +262,6 @@ public class UndelegateEnergyHandler {
.fcu("system")
.lcu("system").build();
errorLogService.insertErrorLog(errorLog);
// throw new RuntimeException("回收能量业务处理异常", e);
} finally {
if (lock.isLocked()) {
if (lock.isHeldByCurrentThread()) {

View File

@ -0,0 +1,67 @@
package com.ruoyi.system.mapper;
import com.ruoyi.common.core.domain.entity.TrxExchangeFail;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Mapper
*
* @author dorion
* @date 2024-07-07
*/
public interface TrxExchangeFailMapper
{
/**
*
*
* @param idTrxExchangeFail
* @return
*/
public TrxExchangeFail selectTrxExchangeFailByIdTrxExchangeFail(Long idTrxExchangeFail);
/**
*
*
* @param trxExchangeFail
* @return
*/
public List<TrxExchangeFail> selectTrxExchangeFailList(TrxExchangeFail trxExchangeFail);
/**
*
*
* @param trxExchangeFail
* @return
*/
public int insertTrxExchangeFail(TrxExchangeFail trxExchangeFail);
/**
*
*
* @param trxExchangeFail
* @return
*/
public int updateTrxExchangeFail(TrxExchangeFail trxExchangeFail);
/**
*
*
* @param idTrxExchangeFail
* @return
*/
public int deleteTrxExchangeFailByIdTrxExchangeFail(Long idTrxExchangeFail);
/**
*
*
* @param idTrxExchangeFails
* @return
*/
public int deleteTrxExchangeFailByIdTrxExchangeFails(String[] idTrxExchangeFails);
public List<TrxExchangeFail> selectTrxExchangeFailListByIdList(@Param("idsList") List<String> idsList);
}

View File

@ -0,0 +1,65 @@
package com.ruoyi.system.service;
import com.ruoyi.common.core.domain.entity.TrxExchangeFail;
import java.util.List;
/**
* Service
*
* @author dorion
* @date 2024-07-07
*/
public interface ITrxExchangeFailService
{
/**
*
*
* @param idTrxExchangeFail
* @return
*/
public TrxExchangeFail selectTrxExchangeFailByIdTrxExchangeFail(Long idTrxExchangeFail);
/**
*
*
* @param trxExchangeFail
* @return
*/
public List<TrxExchangeFail> selectTrxExchangeFailList(TrxExchangeFail trxExchangeFail);
/**
*
*
* @param trxExchangeFail
* @return
*/
public int insertTrxExchangeFail(TrxExchangeFail trxExchangeFail);
/**
*
*
* @param trxExchangeFail
* @return
*/
public int updateTrxExchangeFail(TrxExchangeFail trxExchangeFail);
/**
*
*
* @param idTrxExchangeFails
* @return
*/
public int deleteTrxExchangeFailByIdTrxExchangeFails(String idTrxExchangeFails);
/**
*
*
* @param idTrxExchangeFail
* @return
*/
public int deleteTrxExchangeFailByIdTrxExchangeFail(Long idTrxExchangeFail);
int complete(String ids) throws Exception;
}

View File

@ -0,0 +1,179 @@
package com.ruoyi.system.service.impl;
import com.ruoyi.common.core.domain.entity.TrxExchangeFail;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.*;
import com.ruoyi.system.handler.TRX2EneryTransferHandler;
import com.ruoyi.system.mapper.TrxExchangeFailMapper;
import com.ruoyi.system.service.IAccountAddressInfoService;
import com.ruoyi.system.service.ITrxExchangeFailService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.tron.trident.core.ApiWrapper;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Service
*
* @author dorion
* @date 2024-07-07
*/
@Service
public class TrxExchangeFailServiceImpl implements ITrxExchangeFailService
{
private static final Logger log = LoggerFactory.getLogger(TrxExchangeFailServiceImpl.class);
@Autowired
private TrxExchangeFailMapper trxExchangeFailMapper;
@Autowired
private TRX2EneryTransferHandler trx2EneryTransferHandler;
@Autowired
private IAccountAddressInfoService accountAddressInfoService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RedissonClient redissonClient;
/**
*
*
* @param idTrxExchangeFail
* @return
*/
@Override
public TrxExchangeFail selectTrxExchangeFailByIdTrxExchangeFail(Long idTrxExchangeFail)
{
return trxExchangeFailMapper.selectTrxExchangeFailByIdTrxExchangeFail(idTrxExchangeFail);
}
/**
*
*
* @param trxExchangeFail
* @return
*/
@Override
public List<TrxExchangeFail> selectTrxExchangeFailList(TrxExchangeFail trxExchangeFail)
{
return trxExchangeFailMapper.selectTrxExchangeFailList(trxExchangeFail);
}
/**
*
*
* @param trxExchangeFail
* @return
*/
@Override
public int insertTrxExchangeFail(TrxExchangeFail trxExchangeFail)
{
trxExchangeFail.setCreateTime(DateUtils.getNowDate());
return trxExchangeFailMapper.insertTrxExchangeFail(trxExchangeFail);
}
/**
*
*
* @param trxExchangeFail
* @return
*/
@Override
public int updateTrxExchangeFail(TrxExchangeFail trxExchangeFail)
{
trxExchangeFail.setUpdateTime(DateUtils.getNowDate());
return trxExchangeFailMapper.updateTrxExchangeFail(trxExchangeFail);
}
/**
*
*
* @param idTrxExchangeFails
* @return
*/
@Override
public int deleteTrxExchangeFailByIdTrxExchangeFails(String idTrxExchangeFails)
{
return trxExchangeFailMapper.deleteTrxExchangeFailByIdTrxExchangeFails(Convert.toStrArray(idTrxExchangeFails));
}
/**
*
*
* @param idTrxExchangeFail
* @return
*/
@Override
public int deleteTrxExchangeFailByIdTrxExchangeFail(Long idTrxExchangeFail)
{
return trxExchangeFailMapper.deleteTrxExchangeFailByIdTrxExchangeFail(idTrxExchangeFail);
}
@Override
public int complete(String ids) throws Exception {
List<String> idsList = Arrays.asList(ids.split(","));
List<TrxExchangeFail> trxExchangeFails = trxExchangeFailMapper.selectTrxExchangeFailListByIdList(idsList);
String apiKey = DictUtils.getRandomDictValue("sys_tron_api_key");
for (TrxExchangeFail trxExchangeFail : trxExchangeFails) {
String decryptPrivateKey = accountAddressInfoService.getDecryptPrivateKey(trxExchangeFail.getAccountAddress());
ApiWrapper apiWrapper = ApiWrapper.ofMainnet( decryptPrivateKey,apiKey);
String txID = trxExchangeFail.getTrxTxId();
Boolean hasKey = redisTemplate.hasKey("transfer_trx_" + txID);
if (hasKey) {
continue;
}
RLock lock = redissonClient.getLock("lock_" + txID);
try {
boolean res = lock.tryLock(3, 50, TimeUnit.SECONDS);
if (!res) {
//有其他程序正在处理则不需要再处理
continue;
}
trx2EneryTransferHandler.calcBalanceAndDelegate(txID,
apiWrapper,
trxExchangeFail.getAccountAddress(),
trxExchangeFail.getTranferCount(),
trxExchangeFail.getFromAddress(),
trxExchangeFail.getLockPeriod(),
trxExchangeFail.getToAddress(),
trxExchangeFail.getPrice(),
trxExchangeFail.getEnergyBusiType(),
trxExchangeFail.getTrxAmount(),
trxExchangeFail.getTrxAmountUnit(),
ShiroUtils.getLoginName(),
trxExchangeFail.getResourceCode(), trxExchangeFail.getCalcRule());
}catch (Exception e){
log.error("doDelegateResource业务处理异常{},txid:{},exception:", trxExchangeFail.getFromAddress(), txID, e);
throw new RuntimeException("补偿失败");
}finally {
if (lock.isLocked()) {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
return idsList.size();
}
}

View File

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.TrxExchangeFailMapper">
<resultMap type="TrxExchangeFail" id="TrxExchangeFailResult">
<result property="idTrxExchangeFail" column="id_trx_exchange_fail" />
<result property="fromAddress" column="from_address" />
<result property="toAddress" column="to_address" />
<result property="accountAddress" column="account_address" />
<result property="price" column="price" />
<result property="trxTxId" column="trx_tx_id" />
<result property="tranferCount" column="tranfer_count" />
<result property="energyBusiType" column="energy_busi_type" />
<result property="trxAmount" column="trx_amount" />
<result property="trxAmountUnit" column="trx_amount_unit" />
<result property="resourceCode" column="resource_code" />
<result property="lockPeriod" column="lock_period" />
<result property="delegateStatus" column="delegate_status" />
<result property="calcRule" column="calc_rule" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectTrxExchangeFailVo">
select id_trx_exchange_fail, from_address, to_address, account_address, price, trx_tx_id, tranfer_count, energy_busi_type, trx_amount, trx_amount_unit, resource_code, lock_period, delegate_status, calc_rule, create_by, create_time, update_by, update_time from trx_exchange_fail
</sql>
<select id="selectTrxExchangeFailList" parameterType="TrxExchangeFail" resultMap="TrxExchangeFailResult">
<include refid="selectTrxExchangeFailVo"/>
<where>
<if test="fromAddress != null and fromAddress != ''"> and from_address = #{fromAddress}</if>
<if test="trxTxId != null and trxTxId != ''"> and trx_tx_id = #{trxTxId}</if>
<if test="delegateStatus != null and delegateStatus != ''"> and delegate_status = #{delegateStatus}</if>
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
</where>
</select>
<select id="selectTrxExchangeFailByIdTrxExchangeFail" parameterType="Long" resultMap="TrxExchangeFailResult">
<include refid="selectTrxExchangeFailVo"/>
where id_trx_exchange_fail = #{idTrxExchangeFail}
</select>
<insert id="insertTrxExchangeFail" parameterType="TrxExchangeFail" useGeneratedKeys="true" keyProperty="idTrxExchangeFail">
insert into trx_exchange_fail
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="fromAddress != null">from_address,</if>
<if test="toAddress != null">to_address,</if>
<if test="accountAddress != null">account_address,</if>
<if test="price != null">price,</if>
<if test="trxTxId != null">trx_tx_id,</if>
<if test="tranferCount != null">tranfer_count,</if>
<if test="energyBusiType != null">energy_busi_type,</if>
<if test="trxAmount != null">trx_amount,</if>
<if test="trxAmountUnit != null">trx_amount_unit,</if>
<if test="resourceCode != null">resource_code,</if>
<if test="lockPeriod != null">lock_period,</if>
<if test="delegateStatus != null">delegate_status,</if>
<if test="calcRule != null">calc_rule,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="fromAddress != null">#{fromAddress},</if>
<if test="toAddress != null">#{toAddress},</if>
<if test="accountAddress != null">#{accountAddress},</if>
<if test="price != null">#{price},</if>
<if test="trxTxId != null">#{trxTxId},</if>
<if test="tranferCount != null">#{tranferCount},</if>
<if test="energyBusiType != null">#{energyBusiType},</if>
<if test="trxAmount != null">#{trxAmount},</if>
<if test="trxAmountUnit != null">#{trxAmountUnit},</if>
<if test="resourceCode != null">#{resourceCode},</if>
<if test="lockPeriod != null">#{lockPeriod},</if>
<if test="delegateStatus != null">#{delegateStatus},</if>
<if test="calcRule != null">#{calcRule},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateTrxExchangeFail" parameterType="TrxExchangeFail">
update trx_exchange_fail
<trim prefix="SET" suffixOverrides=",">
<if test="fromAddress != null">from_address = #{fromAddress},</if>
<if test="toAddress != null">to_address = #{toAddress},</if>
<if test="accountAddress != null">account_address = #{accountAddress},</if>
<if test="price != null">price = #{price},</if>
<if test="trxTxId != null">trx_tx_id = #{trxTxId},</if>
<if test="tranferCount != null">tranfer_count = #{tranferCount},</if>
<if test="energyBusiType != null">energy_busi_type = #{energyBusiType},</if>
<if test="trxAmount != null">trx_amount = #{trxAmount},</if>
<if test="trxAmountUnit != null">trx_amount_unit = #{trxAmountUnit},</if>
<if test="resourceCode != null">resource_code = #{resourceCode},</if>
<if test="lockPeriod != null">lock_period = #{lockPeriod},</if>
<if test="delegateStatus != null">delegate_status = #{delegateStatus},</if>
<if test="calcRule != null">calc_rule = #{calcRule},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where id_trx_exchange_fail = #{idTrxExchangeFail}
</update>
<delete id="deleteTrxExchangeFailByIdTrxExchangeFail" parameterType="Long">
delete from trx_exchange_fail where id_trx_exchange_fail = #{idTrxExchangeFail}
</delete>
<delete id="deleteTrxExchangeFailByIdTrxExchangeFails" parameterType="String">
delete from trx_exchange_fail where id_trx_exchange_fail in
<foreach item="idTrxExchangeFail" collection="array" open="(" separator="," close=")">
#{idTrxExchangeFail}
</foreach>
</delete>
<select id="selectTrxExchangeFailListByIdList" resultMap="TrxExchangeFailResult">
<include refid="selectTrxExchangeFailVo"/>
WHERE id_trx_exchange_fail IN
<foreach item="id" collection="idsList" open="(" separator="," close=")">
#{id}
</foreach>
</select>
</mapper>