mirror of
https://github.com/getrebuild/rebuild.git
synced 2025-02-25 06:45:20 +08:00
Chart support for thousands
This commit is contained in:
parent
723a6f2396
commit
901c1ce275
8 changed files with 78 additions and 59 deletions
2
pom.xml
2
pom.xml
|
@ -127,7 +127,7 @@
|
|||
<dependency>
|
||||
<groupId>com.github.devezhao</groupId>
|
||||
<artifactId>persist4j</artifactId>
|
||||
<version>3c386162b5</version>
|
||||
<version>1307de500f</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
|
|
@ -43,7 +43,7 @@ import java.util.Set;
|
|||
* @since 12/14/2018
|
||||
*/
|
||||
public abstract class ChartData extends SetUser<ChartData> implements ChartSpec {
|
||||
|
||||
|
||||
protected JSONObject config;
|
||||
|
||||
private boolean fromPreview = false;
|
||||
|
@ -265,21 +265,35 @@ public abstract class ChartData extends SetUser<ChartData> implements ChartSpec
|
|||
/**
|
||||
* 格式化数值
|
||||
*
|
||||
* @param axis
|
||||
* @param numerical
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
protected String wrapAxisValue(Numerical axis, Object value) {
|
||||
protected String wrapAxisValue(Numerical numerical, Object value) {
|
||||
return wrapAxisValue(numerical, value, Boolean.FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numerical
|
||||
* @param value
|
||||
* @param thousands 是否千分位
|
||||
* @return
|
||||
*/
|
||||
protected String wrapAxisValue(Numerical numerical, Object value, boolean thousands) {
|
||||
if (value == null) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
|
||||
String format = "###";
|
||||
if (axis.getScale() > 0) {
|
||||
if (numerical.getScale() > 0) {
|
||||
format = "##0.";
|
||||
format = StringUtils.rightPad(format, format.length() + axis.getScale(), "0");
|
||||
format = StringUtils.rightPad(format, format.length() + numerical.getScale(), "0");
|
||||
}
|
||||
|
||||
|
||||
if (thousands) {
|
||||
format = "#," + format;
|
||||
}
|
||||
|
||||
if (ID.isId(value)) {
|
||||
value = 1;
|
||||
}
|
||||
|
@ -289,16 +303,16 @@ public abstract class ChartData extends SetUser<ChartData> implements ChartSpec
|
|||
/**
|
||||
* 获取纬度标签
|
||||
*
|
||||
* @param axis
|
||||
* @param dimension
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
protected String wrapAxisValue(Dimension axis, Object value) {
|
||||
protected String wrapAxisValue(Dimension dimension, Object value) {
|
||||
if (value == null) {
|
||||
return "无";
|
||||
}
|
||||
|
||||
EasyMeta axisField = EasyMeta.valueOf(axis.getField());
|
||||
EasyMeta axisField = EasyMeta.valueOf(dimension.getField());
|
||||
DisplayType axisType = axisField.getDisplayType();
|
||||
|
||||
String label;
|
||||
|
@ -310,25 +324,6 @@ public abstract class ChartData extends SetUser<ChartData> implements ChartSpec
|
|||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化汇总数值
|
||||
*
|
||||
* @param sumOfAxis
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
protected String wrapSumValue(Axis sumOfAxis, Object value) {
|
||||
if (value == null) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
if (sumOfAxis instanceof Numerical) {
|
||||
return wrapAxisValue((Numerical) sumOfAxis, value);
|
||||
} else {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建数据
|
||||
|
|
|
@ -41,7 +41,7 @@ public class Dimension extends Axis {
|
|||
case Y:
|
||||
return String.format("DATE_FORMAT(%s,'%s')", super.getSqlName(), "%Y");
|
||||
case Q:
|
||||
return MessageFormat.format("CONCAT(YEAR({0}),''Q'',QUARTER({0}))", super.getSqlName());
|
||||
return MessageFormat.format("CONCAT(YEAR({0}),'' Q'',QUARTER({0}))", super.getSqlName());
|
||||
case M:
|
||||
return String.format("DATE_FORMAT(%s,'%s')", super.getSqlName(), "%Y-%m");
|
||||
case H:
|
||||
|
|
|
@ -34,7 +34,7 @@ public class IndexChart extends ChartData {
|
|||
|
||||
JSONObject index = JSONUtils.toJSONObject(
|
||||
new String[] { "data", "label" },
|
||||
new Object[] { wrapAxisValue(axis, dataRaw[0]), axis.getLabel() });
|
||||
new Object[] { wrapAxisValue(axis, dataRaw[0], true), axis.getLabel() });
|
||||
|
||||
return JSONUtils.toJSONObject("index", index);
|
||||
}
|
||||
|
|
|
@ -70,13 +70,18 @@ public class TableBuilder {
|
|||
|
||||
for (int i = 0; i < row.length; i++) {
|
||||
Axis axis = axes.get(i);
|
||||
TD td = null;
|
||||
TD td;
|
||||
if (axis == LN_REF) {
|
||||
td = new TD(row[i] + "", "th");
|
||||
} else {
|
||||
String text = isLast == 0
|
||||
? chart.wrapSumValue(axis, row[i])
|
||||
: chart.wrapAxisValue(axis, row[i]);
|
||||
String text;
|
||||
if (isLast == 0) {
|
||||
text = chart.wrapSumValue(axis, row[i]);
|
||||
} else if (axis instanceof Numerical) {
|
||||
text = chart.wrapAxisValue((Numerical) axis, row[i], true);
|
||||
} else {
|
||||
text = chart.wrapAxisValue(axis, row[i]);
|
||||
}
|
||||
td = new TD(text);
|
||||
}
|
||||
tds.addChild(td);
|
||||
|
@ -103,9 +108,8 @@ public class TableBuilder {
|
|||
}
|
||||
|
||||
String tClazz = (chart.isShowLineNumber() ? "line-number " : "") + (chart.isShowSums() ? "sums" : "");
|
||||
String table = String.format("<table class=\"table table-bordered %s\">%s%s</table>",
|
||||
return String.format("<table class=\"table table-bordered %s\">%s%s</table>",
|
||||
tClazz, thead.toString(), tbody.toString());
|
||||
return table;
|
||||
}
|
||||
|
||||
// --
|
||||
|
@ -113,17 +117,22 @@ public class TableBuilder {
|
|||
|
||||
// <tbody> or <thead>
|
||||
private static class TBODY {
|
||||
|
||||
private String tag = "tbody";
|
||||
private List<TR> children = new ArrayList<>();
|
||||
|
||||
private TBODY() {
|
||||
}
|
||||
|
||||
private TBODY(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
private TBODY addChild(TR c) {
|
||||
children.add(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -136,11 +145,14 @@ public class TableBuilder {
|
|||
|
||||
// <tr>
|
||||
private static class TR {
|
||||
|
||||
private List<TD> children = new ArrayList<>();
|
||||
|
||||
private TR addChild(TD c) {
|
||||
children.add(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -153,16 +165,19 @@ public class TableBuilder {
|
|||
|
||||
// <td> or <th>
|
||||
private static class TD {
|
||||
private String tag = null;
|
||||
|
||||
private String tag;
|
||||
private String content;
|
||||
private int rowspan = 1;
|
||||
private TD(String content) {
|
||||
this(content, null);
|
||||
}
|
||||
|
||||
private TD(String content, String tag) {
|
||||
this.content = StringUtils.defaultIfBlank(content, "");
|
||||
this.tag = StringUtils.defaultIfBlank(tag, "td");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (rowspan == 0) {
|
||||
|
|
|
@ -85,10 +85,7 @@ public class TableChart extends ChartData {
|
|||
}
|
||||
|
||||
String tableHtml = new TableBuilder(this, dataRaw).toHTML();
|
||||
|
||||
return JSONUtils.toJSONObject(
|
||||
new String[] { "html" },
|
||||
new Object[] { tableHtml });
|
||||
return JSONUtils.toJSONObject("html", tableHtml);
|
||||
}
|
||||
|
||||
protected boolean isShowLineNumber() {
|
||||
|
@ -99,6 +96,18 @@ public class TableChart extends ChartData {
|
|||
return showSums;
|
||||
}
|
||||
|
||||
protected String wrapSumValue(Axis sumAxis, Object value) {
|
||||
if (value == null) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
if (sumAxis instanceof Numerical) {
|
||||
return wrapAxisValue((Numerical) sumAxis, value, true);
|
||||
} else {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String buildSql(Dimension[] dims, Numerical[] nums) {
|
||||
List<String> dimSqlItems = new ArrayList<>();
|
||||
for (Dimension dim : dims) {
|
||||
|
|
|
@ -202,10 +202,9 @@ const add_axis = ((target, axis) => {
|
|||
isNumAxis: isNumAxis,
|
||||
label: $dropdown.attr('data-label'),
|
||||
scale: $dropdown.attr('data-scale'),
|
||||
thousands: $dropdown.attr('data-thousands') === 'true'
|
||||
}
|
||||
state.callback = (s) => {
|
||||
$dropdown.attr({ 'data-label': s.label, 'data-scale': s.scale, 'data-thousands': s.thousands })
|
||||
$dropdown.attr({ 'data-label': s.label, 'data-scale': s.scale })
|
||||
render_preview()
|
||||
}
|
||||
console.log(JSON.stringify(state))
|
||||
|
@ -362,12 +361,6 @@ class DlgAxisProps extends RbFormHandler {
|
|||
<option value="5">5</option>
|
||||
<option value="6">6</option>
|
||||
</select>
|
||||
<div>
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline mt-3 mb-0">
|
||||
<input className="custom-control-input" type="checkbox" checked={this.state.thousands || false} data-id="thousands" onChange={this.handleChange} />
|
||||
<span className="custom-control-label">显示千分位</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ const ECHART_TOOLTIP_FORMATTER = function (i) {
|
|||
if (!Array.isArray(i)) i = [i] // Object > Array
|
||||
const tooltip = [`<b>${i[0].name}</b>`]
|
||||
i.forEach((item) => {
|
||||
tooltip.push(`${item.marker} ${item.seriesName} : ${item.value}`)
|
||||
tooltip.push(`${item.marker} ${item.seriesName} : ${formatThousands(item.value)}`)
|
||||
})
|
||||
return tooltip.join('<br>')
|
||||
}
|
||||
|
@ -208,6 +208,13 @@ const shortNumber = function (num) {
|
|||
else return num
|
||||
}
|
||||
|
||||
const formatThousands = function (num) {
|
||||
if (~~num < 1000) return num
|
||||
const nums = (num + '').split('.')
|
||||
nums[0] = nums[0].replace(/\d{1,3}(?=(\d{3})+$)/g, '$&,')
|
||||
return nums.join('.')
|
||||
}
|
||||
|
||||
const cloneOption = function (opt) {
|
||||
opt = JSON.stringify(opt)
|
||||
return JSON.parse(opt)
|
||||
|
@ -389,8 +396,8 @@ class ChartFunnel extends BaseChart {
|
|||
}
|
||||
opt.tooltip.trigger = 'item'
|
||||
opt.tooltip.formatter = function (i) {
|
||||
if (data.xLabel) return `<b>${i.name}</b> <br/> ${i.marker} ${data.xLabel} : ${i.value}`
|
||||
else return `<b>${i.name}</b> <br/> ${i.marker} ${i.value}`
|
||||
if (data.xLabel) return `<b>${i.name}</b> <br/> ${i.marker} ${data.xLabel} : ${formatThousands(i.value)}`
|
||||
else return `<b>${i.name}</b> <br/> ${i.marker} ${formatThousands(i.value)}`
|
||||
}
|
||||
|
||||
const c = echarts.init(document.getElementById(elid), 'light', ECHART_RENDER_OPT)
|
||||
|
@ -443,7 +450,7 @@ class ChartTreemap extends BaseChart {
|
|||
opt.tooltip.trigger = 'item'
|
||||
opt.tooltip.formatter = function (i) {
|
||||
const p = i.value > 0 ? (i.value * 100 / data.xAmount).toFixed(2) : 0
|
||||
return `<b>${i.name.split('--------').join('<br/>')}</b> <br/> ${i.marker} ${data.xLabel} : ${i.value} (${p}%)`
|
||||
return `<b>${i.name.split('--------').join('<br/>')}</b> <br/> ${i.marker} ${data.xLabel} : ${formatThousands(i.value)} (${p}%)`
|
||||
}
|
||||
opt.label = {
|
||||
formatter: function (i) {
|
||||
|
@ -709,9 +716,9 @@ class ChartRadar extends BaseChart {
|
|||
opt.tooltip.formatter = function (a) {
|
||||
const tooltip = [`<b>${a.name}</b>`]
|
||||
a.value.forEach((item, idx) => {
|
||||
tooltip.push(`${data.indicator[idx].name} : ${item}`)
|
||||
tooltip.push(`${data.indicator[idx].name} : ${formatThousands(item)}`)
|
||||
})
|
||||
return tooltip.join('<br>')
|
||||
return tooltip.join('<br/>')
|
||||
}
|
||||
|
||||
const c = echarts.init(document.getElementById(elid), 'light', ECHART_RENDER_OPT)
|
||||
|
@ -778,8 +785,8 @@ class ChartScatter extends BaseChart {
|
|||
if (a.value.length === 3) {
|
||||
tooltip.push(`<b>${a.value[2]}</b>`)
|
||||
}
|
||||
tooltip.push(`${data.dataLabel[1]} : ${a.value[1]}`)
|
||||
tooltip.push(`${data.dataLabel[0]} : ${a.value[0]}`)
|
||||
tooltip.push(`${data.dataLabel[1]} : ${formatThousands(a.value[1])}`)
|
||||
tooltip.push(`${data.dataLabel[0]} : ${formatThousands(a.value[0])}`)
|
||||
return tooltip.join('<br>')
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue