feat(plugin,freelance,itops,web): P5-P6 dashboard widgets 平台扩展 + 仪表盘声明
P5 平台扩展: - manifest.rs: Dashboard 变体新增 widgets 字段 - manifest.rs: 定义 PluginWidget/StatCard/ActionQuery 类型 - 前端: 扩展 DashboardWidget 类型支持 stat_cards/action_list/funnel/card_list - 前端: 新增 4 个 widget 渲染器 (StatCardsWidget/ActionListWidget/FunnelStageWidget/CardListWidget) - 前端: PluginDashboardPage widget 数据加载支持新类型 P6 仪表盘 widgets: - freelance: 工作台仪表盘 4 个 widgets (财务概览/紧急待办/商机漏斗/活跃项目) - itops: 新增运维概览仪表盘 2 个 widgets (运维概览/紧急待办)
This commit is contained in:
@@ -2,7 +2,7 @@ import { useEffect, useState, useMemo, useCallback } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Row, Col, Empty, Select, theme } from 'antd';
|
||||
import { DashboardOutlined } from '@ant-design/icons';
|
||||
import { countPluginData, aggregatePluginData } from '../api/pluginData';
|
||||
import { countPluginData, aggregatePluginData, listPluginData } from '../api/pluginData';
|
||||
import {
|
||||
getPluginSchema,
|
||||
type PluginEntitySchema,
|
||||
@@ -134,10 +134,65 @@ export function PluginDashboardPage() {
|
||||
const results = await Promise.all(
|
||||
widgets.map(async (widget) => {
|
||||
try {
|
||||
// 旧类型
|
||||
if (widget.type === 'stat_card') {
|
||||
const count = await countPluginData(pluginId!, widget.entity);
|
||||
return { widget, data: [], count };
|
||||
}
|
||||
// stat_cards — 多个统计卡片
|
||||
if (widget.type === 'stat_cards' && widget.cards) {
|
||||
const cardResults = await Promise.all(
|
||||
widget.cards.map(async (card) => {
|
||||
try {
|
||||
const count = await countPluginData(pluginId!, card.entity, {
|
||||
filter: card.filter ? JSON.parse(card.filter) : undefined,
|
||||
});
|
||||
return { card, value: count };
|
||||
} catch {
|
||||
return { card, value: 0 };
|
||||
}
|
||||
}),
|
||||
);
|
||||
return { widget, data: [], statCards: cardResults };
|
||||
}
|
||||
// action_list — 待办列表
|
||||
if (widget.type === 'action_list' && widget.queries) {
|
||||
const actionResults = await Promise.all(
|
||||
widget.queries.map(async (query) => {
|
||||
try {
|
||||
const filterObj = query.filter ? JSON.parse(query.filter) : undefined;
|
||||
const sortParts = query.sort?.split(' ') ?? [];
|
||||
const result = await listPluginData(pluginId!, query.entity, 1, widget.max_items ?? 10, {
|
||||
filter: filterObj,
|
||||
sort_by: sortParts[0] || undefined,
|
||||
sort_order: (sortParts[1] as 'asc' | 'desc') || undefined,
|
||||
});
|
||||
return { query, records: result.data };
|
||||
} catch {
|
||||
return { query, records: [] };
|
||||
}
|
||||
}),
|
||||
);
|
||||
return { widget, data: [], actionItems: actionResults };
|
||||
}
|
||||
// funnel — 阶段漏斗
|
||||
if (widget.type === 'funnel' && widget.lane_field) {
|
||||
const data = await aggregatePluginData(
|
||||
pluginId!,
|
||||
widget.entity,
|
||||
widget.lane_field,
|
||||
);
|
||||
return { widget, data };
|
||||
}
|
||||
// card_list — 卡片列表
|
||||
if (widget.type === 'card_list') {
|
||||
const filterObj = widget.filter ? JSON.parse(widget.filter) : undefined;
|
||||
const result = await listPluginData(pluginId!, widget.entity, 1, widget.max_items ?? 10, {
|
||||
filter: filterObj,
|
||||
});
|
||||
return { widget, data: [], records: result.data };
|
||||
}
|
||||
// 旧类型图表
|
||||
if (widget.dimension_field) {
|
||||
const data = await aggregatePluginData(
|
||||
pluginId!,
|
||||
@@ -146,7 +201,7 @@ export function PluginDashboardPage() {
|
||||
);
|
||||
return { widget, data };
|
||||
}
|
||||
// 没有 dimension_field 时仅返回计数
|
||||
// fallback — 仅返回计数
|
||||
const count = await countPluginData(pluginId!, widget.entity);
|
||||
return { widget, data: [], count };
|
||||
} catch {
|
||||
@@ -313,6 +368,10 @@ export function PluginDashboardPage() {
|
||||
{widgetData.map((wd) => {
|
||||
const colSpan = wd.widget.type === 'stat_card' ? 6
|
||||
: wd.widget.type === 'pie_chart' || wd.widget.type === 'funnel_chart' ? 12
|
||||
: wd.widget.type === 'stat_cards' ? 24
|
||||
: wd.widget.type === 'action_list' ? 12
|
||||
: wd.widget.type === 'funnel' ? 12
|
||||
: wd.widget.type === 'card_list' ? 12
|
||||
: 12;
|
||||
return (
|
||||
<Col key={`${wd.widget.type}-${wd.widget.entity}-${wd.widget.title}`} xs={24} sm={colSpan}>
|
||||
|
||||
Reference in New Issue
Block a user