diff --git a/src/main/java/com/rebuild/core/service/dashboard/charts/ChartsFactory.java b/src/main/java/com/rebuild/core/service/dashboard/charts/ChartsFactory.java index b203f18872..b794a7317e 100644 --- a/src/main/java/com/rebuild/core/service/dashboard/charts/ChartsFactory.java +++ b/src/main/java/com/rebuild/core/service/dashboard/charts/ChartsFactory.java @@ -7,6 +7,7 @@ package com.rebuild.core.service.dashboard.charts; +import cn.devezhao.commons.ReflectUtils; import cn.devezhao.persist4j.Entity; import cn.devezhao.persist4j.engine.ID; import com.alibaba.fastjson.JSONObject; @@ -93,7 +94,8 @@ public static ChartData create(JSONObject config, ID user) throws ChartsExceptio } else { for (BuiltinChart ch : getBuiltinCharts()) { if (ch.getChartType().equalsIgnoreCase(type)) { - return (ChartData) ((ChartData) ch).setUser(user); + ChartData c = (ChartData) ReflectUtils.newObject(ch.getClass().getName()); + return (ChartData) c.setUser(user); } } } diff --git a/src/main/java/com/rebuild/core/service/dashboard/charts/builtin/DataList.java b/src/main/java/com/rebuild/core/service/dashboard/charts/builtin/DataList.java index 1f7779eef1..0fe9a8a18b 100644 --- a/src/main/java/com/rebuild/core/service/dashboard/charts/builtin/DataList.java +++ b/src/main/java/com/rebuild/core/service/dashboard/charts/builtin/DataList.java @@ -32,9 +32,7 @@ * * @author devezhao * @since 2023/1/6 - * @deprecated v3.6 */ -@Deprecated public class DataList extends ChartData implements BuiltinChart { // 虚拟ID @@ -57,11 +55,11 @@ public String getChartTitle() { @Override public JSON build() { Map params = getExtraParams(); - final JSONObject extconfig = (JSONObject) params.get("extconfig"); - if (extconfig == null) return JSONUtils.toJSONObject("error", "UNSET"); + final JSONObject extConfig = (JSONObject) params.get("extconfig"); + if (extConfig == null) return JSONUtils.toJSONObject("error", "UNSET"); - final Entity entity = MetadataHelper.getEntity(extconfig.getString("entity")); - final JSONArray fields = extconfig.getJSONArray("fields"); + final Entity entity = MetadataHelper.getEntity(extConfig.getString("entity")); + final JSONArray fields = extConfig.getJSONArray("fields"); if (fields == null || fields.isEmpty()) return JSONUtils.toJSONObject("error", "UNSET"); List fieldsRich = new ArrayList<>(); @@ -74,16 +72,21 @@ public JSON build() { EasyField lastFieldEasy = EasyMetaFactory.valueOf(lastField); JSONObject rich = JSONUtils.toJSONObject( - new String[] { "field", "type", "label" }, - new Object[] { fieldName, lastFieldEasy.getDisplayType(), EasyMetaFactory.getLabel(entity, fieldName) }); + new String[]{"field", "type", "label"}, + new Object[]{fieldName, lastFieldEasy.getDisplayType(), EasyMetaFactory.getLabel(entity, fieldName)}); fieldsRich.add(rich); } - extconfig.put("pageNo", 1); - extconfig.put("reload", false); - extconfig.put("statsField", false); + int pageSize = extConfig.getIntValue("pageSize"); + if (pageSize <= 0) pageSize = 40; + if (pageSize >= 2000) pageSize = 2000; - DataListBuilder builder = new DataListBuilderImpl(extconfig, getUser()); + extConfig.put("pageNo", 1); + extConfig.put("pageSize", pageSize); + extConfig.put("reload", false); + extConfig.put("statsField", false); + + DataListBuilder builder = new DataListBuilderImpl(extConfig, getUser()); JSONObject data = (JSONObject) builder.getJSONResult(); data.put("fields", fieldsRich); return data; diff --git a/src/main/java/com/rebuild/web/dashboard/DashboardController.java b/src/main/java/com/rebuild/web/dashboard/DashboardController.java index 3436a05d12..2e9e6a9fc1 100644 --- a/src/main/java/com/rebuild/web/dashboard/DashboardController.java +++ b/src/main/java/com/rebuild/web/dashboard/DashboardController.java @@ -152,11 +152,9 @@ public JSONArray chartList(HttpServletRequest request) { // 附加内置图表 if (!("ENTITY".equalsIgnoreCase(type) || "MYSELF".equalsIgnoreCase(type))) { for (BuiltinChart b : ChartsFactory.getBuiltinCharts()) { - if (b.getChartId().equals(DataList.MYID)) continue; - charts.add(JSONUtils.toJSONObject( - new String[] { "id", "title", "type", "entityLabel" }, - new Object[] { b.getChartId(), b.getChartTitle(), b.getChartType(), Language.L("内置") })); + new String[]{"id", "title", "type", "entityLabel"}, + new Object[]{b.getChartId(), b.getChartTitle(), b.getChartType(), Language.L("内置")})); } } diff --git a/src/main/resources/web/assets/js/charts/chart-settings.js b/src/main/resources/web/assets/js/charts/chart-settings.js new file mode 100644 index 0000000000..1444abb919 --- /dev/null +++ b/src/main/resources/web/assets/js/charts/chart-settings.js @@ -0,0 +1,274 @@ +/*! +Copyright (c) REBUILD and/or its owners. All rights reserved. + +rebuild is dual-licensed under commercial and open source licenses (GPLv3). +See LICENSE and COMMERCIAL in the project root for license information. +*/ + +const COLUMN_UNSORT = window.COLUMN_UNSORT || ['SIGN', 'N2NREFERENCE', 'MULTISELECT', 'FILE', 'IMAGE', 'AVATAR', 'TAG'] + +// ~~ 数据列表配置 +// eslint-disable-next-line no-unused-vars +class DataListSettings extends RbModalHandler { + render() { + const state = this.state || {} + const filterLen = state.filterData ? (state.filterData.items || []).length : 0 + + return ( + (this._dlg = c)}> +
+
+ +
+ +
+
+
+ +
+
(this._$showfields = c)}> +
    +
    +
    + +
    +
    +
    + + +
    + +
    + (this._$pageSize = c)} /> +
    +
    +
    + +
    + (this._$chartTitle = c)} /> +
    +
    + {rb.isAdminUser && ( +
    + +
    + +
    +
    + )} + +
    +
    (this._$btn = c)}> + + + {$L('取消')} + +
    +
    +
    +
    + ) + } + + componentDidMount() { + let $showfields = $(this._$showfields).perfectScrollbar() + $showfields = $showfields + .find('ol') + .sortable({ + placeholder: 'dd-placeholder', + handle: '.dd3-handle', + axis: 'y', + }) + .disableSelection() + + const that = this + const props = this.props + + let $afields2 + function _loadFields() { + if (!that._entity) { + $(that._$afields).select2({ + placeholder: $L('无可用字段'), + }) + return + } + + $.get(`/app/${that._entity}/list-fields`, (res) => { + // clear last + if ($afields2) { + $(that._$afields).select2('destroy') + $showfields.empty() + that.setState({ filterData: null }) + } + + that._afields = (res.data || {}).fieldList || [] + that.setState({ afields: that._afields }, () => { + $afields2 = $(that._$afields) + .select2({ + placeholder: $L('添加显示字段'), + allowClear: false, + }) + .val('') + .on('change', (e) => { + let name = e.target.value + $showfields.find('li').each(function () { + if ($(this).data('key') === name) { + name = null + } + }) + + const x = name ? that._afields.find((x) => x.field === name) : null + if (!x) return + + const $item = $( + `
  1. ${x.label}
  2. ` + ).appendTo($showfields) + + // eslint-disable-next-line no-undef + if (!COLUMN_UNSORT.includes(x.type)) { + $(``) + .appendTo($item.find('.dd3-action')) + .on('click', () => { + const hasActive = $item.hasClass('active') + $showfields.find('.dd-item').removeClass('active') + $item.addClass('active') + if (hasActive) $item.find('.sort').toggleClass('desc') + }) + + // init + if (props.entity === that._entity && props.sort) { + const s = props.sort.split(':') + if (s[0] === name) { + $item.addClass('active') + if (s[1] === 'desc') $item.find('.sort').toggleClass('desc') + } + } + } + + $(``) + .appendTo($item.find('.dd3-action')) + .on('click', () => $item.remove()) + }) + + // init + if (props.entity === that._entity && props.fields) { + props.fields.forEach((name) => { + $afields2.val(name).trigger('change') + }) + $afields2.val('').trigger('change') + } + }) + }) + } + + $.get('/commons/metadata/entities?detail=yes', (res) => { + this.setState({ entities: res.data || [] }, () => { + const $s = $(this._$entity).select2({ + allowClear: false, + }) + + if (props.entity && props.entity !== 'User') $s.val(props.entity || null) + $s.on('change', (e) => { + this._entity = e.target.value + _loadFields() + }).trigger('change') + }) + }) + + // init + $(this._$pageSize).val(props.pageSize || null) + $(this._$chartTitle).val(props.title || null) + if (props.filter) this.setState({ filterData: props.filter }) + if ((props.option || {}).shareChart) $(this._$shareChart).attr('checked', true) + } + + _showFilter() { + renderRbcomp( + { + this.setState({ filterData: s }) + }} + /> + ) + } + + handleConfirm() { + const fields = [] + let sort = null + $(this._$showfields) + .find('li') + .each(function () { + const $this = $(this) + fields.push($this.data('key')) + + if ($this.hasClass('active')) { + sort = $this.data('key') + `:${$this.find('.desc')[0] ? 'desc' : 'asc'}` + } + }) + + const post = { + type: 'DataList', + entity: $(this._$entity).val(), + title: $(this._$chartTitle).val() || $L('数据列表'), + option: { + shareChart: $val(this._$shareChart) && rb.isAdminUser, + }, + fields: fields, + pageSize: $(this._$pageSize).val(), + filter: this.state.filterData || null, + sort: sort, + } + + if (!post.entity) return RbHighbar.create($L('请选择图表数据来源')) + if (post.fields.length === 0) return RbHighbar.create($L('请添加显示字段')) + if (post.pageSize && post.pageSize > 500) post.pageSize = 500 + + const $btn = $(this._$btn).find('.btn').button('loading') + $.post(`/dashboard/builtin-chart-save?id=${this.props.chart}`, JSON.stringify(post), (res) => { + $btn.button('reset') + if (res.error_code === 0) { + typeof this.props.onConfirm === 'function' && this.props.onConfirm(post) + this.hide() + } else { + RbHighbar.error(res.error_msg) + } + }) + } +} diff --git a/src/main/resources/web/assets/js/charts/charts.js b/src/main/resources/web/assets/js/charts/charts.js index 8fb96ed35a..4145b41593 100644 --- a/src/main/resources/web/assets/js/charts/charts.js +++ b/src/main/resources/web/assets/js/charts/charts.js @@ -1380,7 +1380,23 @@ class DataList extends BaseChart { const $op = $(this._$box).find('.chart-oper') $op.find('.J_chart-edit').on('click', (e) => { $stopEvent(e, true) - RbHighbar.create('[DEPRECATED] 该功能将在下一版本禁用') + + const config2 = this.state.config + renderRbcomp( + // eslint-disable-next-line react/jsx-no-undef + { + if (typeof window.save_dashboard === 'function') { + config2.extconfig = s + this.setState({ config: config2 }, () => this.loadChartData()) + } else { + console.log('No `save_dashboard` found :', s) + } + }} + /> + ) }) } } @@ -1404,9 +1420,7 @@ class DataList extends BaseChart { return } - const extconfig = this.state.config.extconfig - // extconfig && this.setState({ title: extconfig.title || $L('数据列表') }) - + const extconfig2 = this.state.config.extconfig const listFields = data.fields const listData = data.data const lastIndex = listFields.length @@ -1418,8 +1432,8 @@ class DataList extends BaseChart { (this._$head = c)}> {listFields.map((item) => { let sortClazz = null - if (extconfig && extconfig.sort) { - const s = extconfig.sort.split(':') + if (extconfig2 && extconfig2.sort) { + const s = extconfig2.sort.split(':') if (s[0] === item.field && s[1] === 'asc') sortClazz = 'sort-asc' if (s[0] === item.field && s[1] === 'desc') sortClazz = 'sort-desc' } diff --git a/src/main/resources/web/dashboard/home.html b/src/main/resources/web/dashboard/home.html index 5bd29c81ed..f805d76a79 100644 --- a/src/main/resources/web/dashboard/home.html +++ b/src/main/resources/web/dashboard/home.html @@ -75,6 +75,7 @@

    [[${bundle.L +