@fe-free/core 2.1.3 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +2 -2
- package/src/markdown/chart.tsx +72 -19
- package/src/markdown/markdown.stories.tsx +25 -0
- package/src/table/index.tsx +0 -2
- package/src/value_type_map/index.tsx +8 -1
- package/src/value_type_map/json_modal.tsx +56 -0
- package/src/value_type_map/value_type_map.stories.tsx +6 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fe-free/core",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"author": "",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"remark-gfm": "^4.0.1",
|
|
40
40
|
"vanilla-jsoneditor": "^0.23.1",
|
|
41
41
|
"zustand": "^4.5.4",
|
|
42
|
-
"@fe-free/tool": "2.1.
|
|
42
|
+
"@fe-free/tool": "2.1.5"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"@ant-design/pro-components": "^2.8.7",
|
package/src/markdown/chart.tsx
CHANGED
|
@@ -7,8 +7,8 @@ interface ChartData {
|
|
|
7
7
|
rows: (string | number)[][];
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
interface
|
|
11
|
-
chart_type: '
|
|
10
|
+
interface ChartConfigBase {
|
|
11
|
+
chart_type: 'bar' | 'pie' | 'table' | 'scatter';
|
|
12
12
|
x_field?: string;
|
|
13
13
|
y_field?: string;
|
|
14
14
|
angle_field?: string;
|
|
@@ -16,6 +16,18 @@ interface ChartConfig {
|
|
|
16
16
|
title: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
interface LineChartConfig {
|
|
20
|
+
chart_type: 'line';
|
|
21
|
+
x_field?: string;
|
|
22
|
+
y_field: string | string[];
|
|
23
|
+
angle_field?: string;
|
|
24
|
+
color_field?: string;
|
|
25
|
+
title: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
interface ChartConfig extends ChartConfigBase, ChartConfigLine {}
|
|
30
|
+
|
|
19
31
|
// 错误处理组件
|
|
20
32
|
function ChartError(props: { children?: React.ReactNode }) {
|
|
21
33
|
const { children } = props;
|
|
@@ -29,7 +41,8 @@ function ChartError(props: { children?: React.ReactNode }) {
|
|
|
29
41
|
class ErrorBoundary extends React.Component {
|
|
30
42
|
state = { hasError: false };
|
|
31
43
|
|
|
32
|
-
static getDerivedStateFromError() {
|
|
44
|
+
static getDerivedStateFromError(error) {
|
|
45
|
+
console.error('ErrorBoundary:', error);
|
|
33
46
|
return { hasError: true };
|
|
34
47
|
}
|
|
35
48
|
|
|
@@ -102,7 +115,7 @@ function PieChart(props: { data: ChartData; chart: ChartConfig }) {
|
|
|
102
115
|
}
|
|
103
116
|
|
|
104
117
|
// 折线图组件
|
|
105
|
-
function LineChart(props: { data: ChartData; chart:
|
|
118
|
+
function LineChart(props: { data: ChartData; chart: LineChartConfig }) {
|
|
106
119
|
const { data, chart } = props;
|
|
107
120
|
const { columns, rows } = data;
|
|
108
121
|
const { x_field, y_field } = chart;
|
|
@@ -112,25 +125,64 @@ function LineChart(props: { data: ChartData; chart: ChartConfig }) {
|
|
|
112
125
|
}
|
|
113
126
|
|
|
114
127
|
const xIndex = columns.indexOf(x_field);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (xIndex === -1 || yIndex === -1) {
|
|
128
|
+
if (xIndex === -1) {
|
|
118
129
|
return <ChartError />;
|
|
119
130
|
}
|
|
120
131
|
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
132
|
+
// 处理 y_field 为数组的情况
|
|
133
|
+
if (Array.isArray(y_field)) {
|
|
134
|
+
// 验证所有 y_field 是否存在于 columns 中
|
|
135
|
+
const yIndices = y_field.map((field) => columns.indexOf(field));
|
|
136
|
+
if (yIndices.some((index) => index === -1)) {
|
|
137
|
+
return <ChartError />;
|
|
138
|
+
}
|
|
126
139
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
// 转换数据格式为 Ant Design Charts 需要的格式(长数据格式)
|
|
141
|
+
const chartData: any[] = [];
|
|
142
|
+
rows.forEach((row) => {
|
|
143
|
+
y_field.forEach((field, index) => {
|
|
144
|
+
const value = row[yIndices[index]];
|
|
145
|
+
if (value !== null && value !== undefined) {
|
|
146
|
+
chartData.push({
|
|
147
|
+
[x_field]: row[xIndex],
|
|
148
|
+
type: field,
|
|
149
|
+
value: Number(value),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const config = {
|
|
156
|
+
data: chartData,
|
|
157
|
+
xField: x_field,
|
|
158
|
+
yField: 'value',
|
|
159
|
+
seriesField: 'type',
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
console.log('config', config);
|
|
163
|
+
|
|
164
|
+
return <Line {...config} />;
|
|
165
|
+
} else {
|
|
166
|
+
// 处理单个 y_field 的情况(保持向后兼容)
|
|
167
|
+
const yIndex = columns.indexOf(y_field);
|
|
168
|
+
if (yIndex === -1) {
|
|
169
|
+
return <ChartError />;
|
|
170
|
+
}
|
|
132
171
|
|
|
133
|
-
|
|
172
|
+
// 转换数据格式为 Ant Design Charts 需要的格式
|
|
173
|
+
const chartData = rows.map((row) => ({
|
|
174
|
+
[x_field]: row[xIndex],
|
|
175
|
+
[y_field]: Number(row[yIndex]),
|
|
176
|
+
}));
|
|
177
|
+
|
|
178
|
+
const config = {
|
|
179
|
+
data: chartData,
|
|
180
|
+
xField: x_field,
|
|
181
|
+
yField: y_field,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
return <Line {...config} />;
|
|
185
|
+
}
|
|
134
186
|
}
|
|
135
187
|
|
|
136
188
|
// 柱状图组件
|
|
@@ -253,7 +305,8 @@ function ChartBlock(props: any) {
|
|
|
253
305
|
|
|
254
306
|
// 大模型会返回一些奇怪字符,需要去掉
|
|
255
307
|
// 不间断空格
|
|
256
|
-
|
|
308
|
+
// eslint-disable-next-line no-irregular-whitespace
|
|
309
|
+
const content = children?.replace(/ /g, '');
|
|
257
310
|
|
|
258
311
|
return (
|
|
259
312
|
<ErrorBoundary>
|
|
@@ -166,6 +166,30 @@ export const Chart: Story = {
|
|
|
166
166
|
}
|
|
167
167
|
\`\`\`
|
|
168
168
|
|
|
169
|
+
多条折线
|
|
170
|
+
|
|
171
|
+
\`\`\`chart
|
|
172
|
+
{
|
|
173
|
+
"data": {
|
|
174
|
+
"columns": ["quarter", "L'Oreal", "P&G", "Proya"],
|
|
175
|
+
"rows": [
|
|
176
|
+
["FY23-Q4/23-Q2", 8, 7, null],
|
|
177
|
+
["FY24-Q1/23-Q3", 7, 6, null],
|
|
178
|
+
["FY24-Q2/23-Q4", 4, 3, null],
|
|
179
|
+
["FY24-Q3/24-Q1", 3, null, null],
|
|
180
|
+
["FY24-Q4/24-Q2", null, null, null],
|
|
181
|
+
["FY25-Q1/24-Q34",null,null,null]
|
|
182
|
+
]
|
|
183
|
+
},
|
|
184
|
+
"chart": {
|
|
185
|
+
"chart_type": "line",
|
|
186
|
+
"x_field": "quarter",
|
|
187
|
+
"y_field": ["L'Oreal", "P&G","Proya"],
|
|
188
|
+
"title": "欧莱雅、宝洁及珀莱雅增长率变化趋势"
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
\`\`\`
|
|
192
|
+
|
|
169
193
|
## 柱状图示例
|
|
170
194
|
|
|
171
195
|
\`\`\`chart
|
|
@@ -189,6 +213,7 @@ export const Chart: Story = {
|
|
|
189
213
|
}
|
|
190
214
|
\`\`\`
|
|
191
215
|
|
|
216
|
+
|
|
192
217
|
## 饼图示例
|
|
193
218
|
|
|
194
219
|
\`\`\`chart
|
package/src/table/index.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ProRenderFieldPropsType } from '@ant-design/pro-components';
|
|
2
2
|
import { dateRender } from './date';
|
|
3
3
|
import { jsonRender } from './json';
|
|
4
|
+
import { jsonModalRender } from './json_modal';
|
|
4
5
|
|
|
5
6
|
enum CustomValueTypeEnum {
|
|
6
7
|
/** 渲染时间 + 搜索日期范围 */
|
|
@@ -9,6 +10,8 @@ enum CustomValueTypeEnum {
|
|
|
9
10
|
CustomDateAndDateRange = 'CustomDateAndDateRange',
|
|
10
11
|
/** JSON */
|
|
11
12
|
CustomJSON = 'CustomJSON',
|
|
13
|
+
/** JSON Modal */
|
|
14
|
+
CustomJSONModal = 'CustomJSONModal',
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
const customValueTypeMap: Record<string, ProRenderFieldPropsType> = {
|
|
@@ -24,6 +27,10 @@ const customValueTypeMap: Record<string, ProRenderFieldPropsType> = {
|
|
|
24
27
|
render: jsonRender.render,
|
|
25
28
|
renderFormItem: jsonRender.renderFormItem,
|
|
26
29
|
},
|
|
30
|
+
[CustomValueTypeEnum.CustomJSONModal]: {
|
|
31
|
+
render: jsonModalRender.render,
|
|
32
|
+
renderFormItem: jsonModalRender.renderFormItem,
|
|
33
|
+
},
|
|
27
34
|
};
|
|
28
35
|
|
|
29
|
-
export {
|
|
36
|
+
export { CustomValueTypeEnum, customValueTypeMap };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ProFormItemProps } from '@ant-design/pro-components';
|
|
2
|
+
import { Modal } from 'antd';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import type { EditorJSONProps } from '../editor_json';
|
|
5
|
+
import { EditorJSON } from '../editor_json';
|
|
6
|
+
|
|
7
|
+
interface JSONModalProps extends EditorJSONProps {
|
|
8
|
+
/** 默认 查看 */
|
|
9
|
+
title?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function Render(text, props: ProFormItemProps<JSONModalProps>) {
|
|
13
|
+
const { title = '查看' } = props.fieldProps || {};
|
|
14
|
+
|
|
15
|
+
const [show, setShow] = useState(false);
|
|
16
|
+
|
|
17
|
+
let jsonText = text;
|
|
18
|
+
|
|
19
|
+
if (!text) {
|
|
20
|
+
return <div>-</div>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
jsonText = JSON.stringify(JSON.parse(text), null, 2);
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error(e, text);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<>
|
|
31
|
+
<a onClick={() => setShow(true)}>{title}</a>
|
|
32
|
+
<Modal
|
|
33
|
+
title={title}
|
|
34
|
+
open={show}
|
|
35
|
+
onCancel={() => setShow(false)}
|
|
36
|
+
onOk={() => setShow(false)}
|
|
37
|
+
cancelButtonProps={{
|
|
38
|
+
style: {
|
|
39
|
+
display: 'none',
|
|
40
|
+
},
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
<div className="h-[500px]">
|
|
44
|
+
<EditorJSON value={jsonText} readonly />
|
|
45
|
+
</div>
|
|
46
|
+
</Modal>
|
|
47
|
+
</>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const jsonModalRender = {
|
|
52
|
+
render: Render,
|
|
53
|
+
renderFormItem: () => <></>,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export { jsonModalRender };
|