@fe-free/core 5.0.0 → 6.0.2
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 +391 -5
- package/package.json +5 -3
- package/src/copy/index.tsx +10 -5
- package/src/crud/crud.stories.tsx +13 -1
- package/src/crud/crud.tsx +5 -2
- package/src/crud/helper.tsx +10 -5
- package/src/crud/style.scss +27 -0
- package/src/crud/table/index.tsx +7 -2
- package/src/crud/table/style.scss +10 -21
- package/src/crud/use_operate.tsx +1 -1
- package/src/crud_of_list/crud_of_list.stories.tsx +42 -0
- package/src/crud_of_list/index.tsx +2 -1
- package/src/crud_of_list/style.scss +27 -0
- package/src/crud_of_pure/crud_of_pure.stories.tsx +7 -1
- package/src/crud_of_pure/index.tsx +52 -2
- package/src/crud_of_pure/style.scss +4 -0
- package/src/editor/editor.stories.tsx +8 -0
- package/src/editor/index.tsx +7 -3
- package/src/form/form_list/form_list_modal_helper.tsx +1 -0
- package/src/index.ts +4 -1
- package/src/infinite_list/index.tsx +5 -2
- package/src/markdown/chart.tsx +3 -3
- package/src/markdown/code.tsx +19 -32
- package/src/markdown/custom_markdown.stories.tsx +485 -0
- package/src/markdown/hm_chart.tsx +1 -1
- package/src/markdown/index.tsx +93 -34
- package/src/markdown/knowledge_ref.tsx +5 -5
- package/src/markdown/markdown.stories.tsx +68 -410
- package/src/markdown/messages/message_think.tsx +69 -0
- package/src/markdown/messages/svgs/think.svg +3 -0
- package/src/markdown/think.tsx +55 -0
- package/src/page_layout/index.tsx +12 -0
- package/src/scroll/helper.tsx +23 -0
- package/src/scroll/index.tsx +70 -0
- package/src/style.scss +0 -30
- package/src/tailwind.css +54 -0
- package/src/theme.ts +1 -1
- package/src/upload/index.tsx +32 -30
- package/src/value_type_map/index.tsx +7 -0
- package/src/value_type_map/json_modal.tsx +17 -15
- package/src/value_type_map/markdown_modal.tsx +45 -0
- package/src/value_type_map/value_type_map.stories.tsx +8 -0
- package/src/markdown/deep_seek.tsx +0 -53
- package/src/markdown/style.scss +0 -46
- package/src/tailwind.config.ts +0 -14
|
@@ -12,9 +12,13 @@ interface PageLayoutProps {
|
|
|
12
12
|
/** beta equalParts */
|
|
13
13
|
equalParts?: boolean;
|
|
14
14
|
className?: string;
|
|
15
|
+
style?: React.CSSProperties;
|
|
15
16
|
startClassName?: string;
|
|
17
|
+
startStyle?: React.CSSProperties;
|
|
16
18
|
childrenClassName?: string;
|
|
19
|
+
childrenStyle?: React.CSSProperties;
|
|
17
20
|
endClassName?: string;
|
|
21
|
+
endStyle?: React.CSSProperties;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
function PageLayout({
|
|
@@ -24,9 +28,13 @@ function PageLayout({
|
|
|
24
28
|
end,
|
|
25
29
|
equalParts,
|
|
26
30
|
className,
|
|
31
|
+
style,
|
|
27
32
|
startClassName,
|
|
33
|
+
startStyle,
|
|
28
34
|
childrenClassName,
|
|
35
|
+
childrenStyle,
|
|
29
36
|
endClassName,
|
|
37
|
+
endStyle,
|
|
30
38
|
}: PageLayoutProps) {
|
|
31
39
|
return (
|
|
32
40
|
<div
|
|
@@ -38,6 +46,7 @@ function PageLayout({
|
|
|
38
46
|
},
|
|
39
47
|
className,
|
|
40
48
|
)}
|
|
49
|
+
style={style}
|
|
41
50
|
>
|
|
42
51
|
{start && (
|
|
43
52
|
<div
|
|
@@ -48,6 +57,7 @@ function PageLayout({
|
|
|
48
57
|
},
|
|
49
58
|
startClassName,
|
|
50
59
|
)}
|
|
60
|
+
style={startStyle}
|
|
51
61
|
>
|
|
52
62
|
{start}
|
|
53
63
|
</div>
|
|
@@ -60,6 +70,7 @@ function PageLayout({
|
|
|
60
70
|
},
|
|
61
71
|
childrenClassName,
|
|
62
72
|
)}
|
|
73
|
+
style={childrenStyle}
|
|
63
74
|
>
|
|
64
75
|
{children}
|
|
65
76
|
</div>
|
|
@@ -72,6 +83,7 @@ function PageLayout({
|
|
|
72
83
|
},
|
|
73
84
|
endClassName,
|
|
74
85
|
)}
|
|
86
|
+
style={endStyle}
|
|
75
87
|
>
|
|
76
88
|
{end}
|
|
77
89
|
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
function getScrollbarWidth() {
|
|
2
|
+
const target = document.body;
|
|
3
|
+
|
|
4
|
+
// 创建一个不可见的 div 元素
|
|
5
|
+
const outer = document.createElement('div');
|
|
6
|
+
outer.style.visibility = 'hidden';
|
|
7
|
+
outer.style.overflow = 'scroll'; // 强制显示滚动条
|
|
8
|
+
target.appendChild(outer);
|
|
9
|
+
|
|
10
|
+
// 创建一个内部 div,宽度为 100%
|
|
11
|
+
const inner = document.createElement('div');
|
|
12
|
+
outer.appendChild(inner);
|
|
13
|
+
|
|
14
|
+
// 滚动条宽度 = 外部容器的宽度 - 内部内容的宽度
|
|
15
|
+
const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
|
|
16
|
+
|
|
17
|
+
// 清理 DOM
|
|
18
|
+
target.removeChild(outer);
|
|
19
|
+
|
|
20
|
+
return scrollbarWidth;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { getScrollbarWidth };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { getScrollbarWidth } from './helper';
|
|
4
|
+
|
|
5
|
+
function useScrollFixed({
|
|
6
|
+
ref,
|
|
7
|
+
disabled,
|
|
8
|
+
}: {
|
|
9
|
+
ref: React.RefObject<HTMLElement | null>;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}) {
|
|
12
|
+
const [marginRight, setMarginRight] = useState(0);
|
|
13
|
+
|
|
14
|
+
const scrollbarWidth = useMemo(() => {
|
|
15
|
+
return getScrollbarWidth();
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (disabled) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const el = ref.current;
|
|
24
|
+
if (!el) return;
|
|
25
|
+
|
|
26
|
+
const updateMargin = () => {
|
|
27
|
+
const hasVerticalScrollbar = el.scrollHeight > el.clientHeight;
|
|
28
|
+
setMarginRight(hasVerticalScrollbar ? scrollbarWidth : 0);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
updateMargin();
|
|
32
|
+
|
|
33
|
+
const resizeObserver = new ResizeObserver(updateMargin);
|
|
34
|
+
resizeObserver.observe(el);
|
|
35
|
+
el.addEventListener('scroll', updateMargin);
|
|
36
|
+
|
|
37
|
+
return () => {
|
|
38
|
+
resizeObserver.disconnect();
|
|
39
|
+
el.removeEventListener('scroll', updateMargin);
|
|
40
|
+
};
|
|
41
|
+
}, [ref, scrollbarWidth, disabled]);
|
|
42
|
+
|
|
43
|
+
return { marginRight };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface ScrollFixedProps {
|
|
47
|
+
refScroll?: React.RefObject<HTMLDivElement | null>;
|
|
48
|
+
disabled?: boolean;
|
|
49
|
+
className?: string;
|
|
50
|
+
style?: React.CSSProperties;
|
|
51
|
+
children: React.ReactNode;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ScrollFixed({ refScroll, className, children, disabled, ...rest }: ScrollFixedProps) {
|
|
55
|
+
const innerRef = useRef<HTMLDivElement>(null);
|
|
56
|
+
const ref = refScroll || innerRef;
|
|
57
|
+
const { marginRight } = useScrollFixed({ ref, disabled });
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div
|
|
61
|
+
ref={ref}
|
|
62
|
+
{...rest}
|
|
63
|
+
className={classNames('h-full w-full overflow-y-auto overflow-x-hidden', className)}
|
|
64
|
+
>
|
|
65
|
+
<div style={{ marginRight: `-${marginRight || 0}px` }}>{children}</div>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { getScrollbarWidth, ScrollFixed, useScrollFixed };
|
package/src/style.scss
CHANGED
|
@@ -1,33 +1,3 @@
|
|
|
1
|
-
/** 和 antd 冲突,不开启 */
|
|
2
|
-
/* stylelint-disable-next-line at-rule-no-unknown */
|
|
3
|
-
// @tailwind base;
|
|
4
|
-
|
|
5
|
-
// base
|
|
6
|
-
* {
|
|
7
|
-
border: 0 solid;
|
|
8
|
-
box-sizing: border-box;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/* stylelint-disable-next-line at-rule-no-unknown */
|
|
12
|
-
@tailwind components;
|
|
13
|
-
|
|
14
|
-
/* stylelint-disable-next-line at-rule-no-unknown */
|
|
15
|
-
@tailwind utilities;
|
|
16
|
-
|
|
17
|
-
::-webkit-scrollbar {
|
|
18
|
-
width: 8px;
|
|
19
|
-
height: 8px;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
::-webkit-scrollbar-thumb {
|
|
23
|
-
background: #ccc;
|
|
24
|
-
border-radius: 2px;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
::-webkit-scrollbar-track {
|
|
28
|
-
background: transparent;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
1
|
.fec-app-hidden-form-item-label-colon {
|
|
32
2
|
// 隐藏 label 的冒号
|
|
33
3
|
.ant-form-item .ant-form-item-label > label::after {
|
package/src/tailwind.css
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
/* stylelint-disable-next-line */
|
|
4
|
+
@theme {
|
|
5
|
+
--color-primary: #0374e9;
|
|
6
|
+
--color-theme09: #0368d2;
|
|
7
|
+
--color-theme08: #0374e9;
|
|
8
|
+
--color-theme05: #a2cbf7;
|
|
9
|
+
--color-theme03: #e6f1fd;
|
|
10
|
+
--color-theme02: #f0f7fe;
|
|
11
|
+
--color-red09: #e64547;
|
|
12
|
+
--color-red08: #ff4d4f;
|
|
13
|
+
--color-red05: #ffb8b9;
|
|
14
|
+
--color-red03: #ffeded;
|
|
15
|
+
--color-green09: #01a468;
|
|
16
|
+
--color-green08: #01b673;
|
|
17
|
+
--color-green05: #9be5c8;
|
|
18
|
+
--color-green03: #ddf9ec;
|
|
19
|
+
--color-yellow09: #bf7a05;
|
|
20
|
+
--color-yellow08: #faad14;
|
|
21
|
+
--color-yellow05: #eecf9b;
|
|
22
|
+
--color-yellow03: #f6e7cd;
|
|
23
|
+
--text-color-01: #15191e;
|
|
24
|
+
--text-color-02: #444;
|
|
25
|
+
--text-color-03: #777;
|
|
26
|
+
--text-color-04: #bfbfbf;
|
|
27
|
+
--border-color-01: #e2e7f0;
|
|
28
|
+
--border-color-02: #d5dde9;
|
|
29
|
+
--border-color-03: #c0c7d2;
|
|
30
|
+
--background-color-01: #f1f3f5;
|
|
31
|
+
--background-color-02: #ececec;
|
|
32
|
+
--background-color-03: #d9d9d9;
|
|
33
|
+
--background-color-04: #c0c0c0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@layer base {
|
|
37
|
+
* {
|
|
38
|
+
-webkit-font-smoothing: antialiased;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
::-webkit-scrollbar {
|
|
42
|
+
width: 8px;
|
|
43
|
+
height: 8px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
::-webkit-scrollbar-thumb {
|
|
47
|
+
background: #ccc;
|
|
48
|
+
border-radius: 2px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
::-webkit-scrollbar-track {
|
|
52
|
+
background: transparent;
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/theme.ts
CHANGED
package/src/upload/index.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CloseOutlined, InboxOutlined, PlusOutlined, UploadOutlined } from '@fe-free/icons';
|
|
2
2
|
import type { UploadProps as AntdUploadProps, UploadFile } from 'antd';
|
|
3
3
|
import { Upload as AntdUpload, App, Avatar, Button } from 'antd';
|
|
4
4
|
import type { UploadChangeParam } from 'antd/es/upload';
|
|
@@ -272,37 +272,39 @@ interface AvatarImageUploadProps {
|
|
|
272
272
|
}
|
|
273
273
|
function AvatarImageUpload(props: AvatarImageUploadProps) {
|
|
274
274
|
const { value, onChange, action, customRequest, accept = 'image/*', headers } = props;
|
|
275
|
-
const { t } = useTranslation();
|
|
276
275
|
|
|
277
276
|
return (
|
|
278
|
-
<div
|
|
279
|
-
<
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
277
|
+
<div>
|
|
278
|
+
<AntdUpload
|
|
279
|
+
action={action}
|
|
280
|
+
customRequest={customRequest}
|
|
281
|
+
onChange={(info) => {
|
|
282
|
+
const url = info.file.response?.data?.url;
|
|
283
|
+
if (url) {
|
|
284
|
+
onChange?.(url);
|
|
285
|
+
}
|
|
286
|
+
}}
|
|
287
|
+
accept={accept}
|
|
288
|
+
headers={headers}
|
|
289
|
+
itemRender={() => null}
|
|
290
|
+
>
|
|
291
|
+
{value ? (
|
|
292
|
+
<div className="group relative h-20 w-20 cursor-pointer">
|
|
293
|
+
<Avatar size={80} src={value} shape="square" className="bg-01 shadow" />
|
|
294
|
+
<CloseOutlined
|
|
295
|
+
className="absolute right-1 top-1 cursor-pointer rounded-full bg-black/50 p-1 text-[10px] text-white opacity-0 transition-opacity group-hover:opacity-100"
|
|
296
|
+
onClick={(e) => {
|
|
297
|
+
e.stopPropagation();
|
|
298
|
+
onChange?.();
|
|
299
|
+
}}
|
|
300
|
+
/>
|
|
301
|
+
</div>
|
|
302
|
+
) : (
|
|
303
|
+
<div className="flex h-20 w-20 cursor-pointer items-center justify-center rounded bg-01 shadow transition-colors hover:bg-02">
|
|
304
|
+
<PlusOutlined className="text-xl text-02" />
|
|
305
|
+
</div>
|
|
306
|
+
)}
|
|
307
|
+
</AntdUpload>
|
|
306
308
|
</div>
|
|
307
309
|
);
|
|
308
310
|
}
|
|
@@ -2,6 +2,7 @@ import type { ProRenderFieldPropsType } from '@ant-design/pro-components';
|
|
|
2
2
|
import { dateRender } from './date';
|
|
3
3
|
import { jsonRender } from './json';
|
|
4
4
|
import { jsonModalRender } from './json_modal';
|
|
5
|
+
import { markdownModalRender } from './markdown_modal';
|
|
5
6
|
import { switchNumberRender, switchOptionsRender } from './switch';
|
|
6
7
|
|
|
7
8
|
enum CustomValueTypeEnum {
|
|
@@ -13,6 +14,8 @@ enum CustomValueTypeEnum {
|
|
|
13
14
|
CustomJSON = 'CustomJSON',
|
|
14
15
|
/** JSON Modal */
|
|
15
16
|
CustomJSONModal = 'CustomJSONModal',
|
|
17
|
+
/** Markdown Modal */
|
|
18
|
+
CustomMarkdownModal = 'CustomMarkdownModal',
|
|
16
19
|
/** 渲染开关 */
|
|
17
20
|
CustomSwitchNumber = 'CustomSwitchNumber',
|
|
18
21
|
CustomSwitchOptions = 'CustomSwitchOptions',
|
|
@@ -37,6 +40,10 @@ const customValueTypeMap: Record<string, ProRenderFieldPropsType> = {
|
|
|
37
40
|
render: jsonModalRender.render,
|
|
38
41
|
renderFormItem: jsonModalRender.renderFormItem,
|
|
39
42
|
},
|
|
43
|
+
[CustomValueTypeEnum.CustomMarkdownModal]: {
|
|
44
|
+
render: markdownModalRender.render,
|
|
45
|
+
renderFormItem: markdownModalRender.renderFormItem,
|
|
46
|
+
},
|
|
40
47
|
[CustomValueTypeEnum.CustomSwitchNumber]: {
|
|
41
48
|
render: switchNumberRender.render,
|
|
42
49
|
renderFormItem: switchNumberRender.renderFormItem,
|
|
@@ -31,21 +31,23 @@ function Render(text, props: ProFormItemProps<JSONModalProps>) {
|
|
|
31
31
|
return (
|
|
32
32
|
<>
|
|
33
33
|
<a onClick={() => setShow(true)}>{title}</a>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
34
|
+
{show && (
|
|
35
|
+
<Modal
|
|
36
|
+
title={title}
|
|
37
|
+
open
|
|
38
|
+
onCancel={() => setShow(false)}
|
|
39
|
+
onOk={() => setShow(false)}
|
|
40
|
+
cancelButtonProps={{
|
|
41
|
+
style: {
|
|
42
|
+
display: 'none',
|
|
43
|
+
},
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
<div>
|
|
47
|
+
<EditorJSON value={jsonText} readonly />
|
|
48
|
+
</div>
|
|
49
|
+
</Modal>
|
|
50
|
+
)}
|
|
49
51
|
</>
|
|
50
52
|
);
|
|
51
53
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Modal } from 'antd';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Markdown } from '../markdown';
|
|
4
|
+
|
|
5
|
+
function Render(text) {
|
|
6
|
+
const [show, setShow] = useState(false);
|
|
7
|
+
|
|
8
|
+
if (!text) {
|
|
9
|
+
return <div>-</div>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<div onClick={() => setShow(true)} className="flex cursor-pointer items-center">
|
|
15
|
+
<div className="flex-1 truncate">{text}</div>
|
|
16
|
+
<span className="min-w-0 text-primary">查看</span>
|
|
17
|
+
</div>
|
|
18
|
+
{show && (
|
|
19
|
+
<Modal
|
|
20
|
+
title="Markdown"
|
|
21
|
+
open
|
|
22
|
+
onCancel={() => setShow(false)}
|
|
23
|
+
onOk={() => setShow(false)}
|
|
24
|
+
cancelButtonProps={{
|
|
25
|
+
style: {
|
|
26
|
+
display: 'none',
|
|
27
|
+
},
|
|
28
|
+
}}
|
|
29
|
+
width={900}
|
|
30
|
+
>
|
|
31
|
+
<div>
|
|
32
|
+
<Markdown content={text} />
|
|
33
|
+
</div>
|
|
34
|
+
</Modal>
|
|
35
|
+
)}
|
|
36
|
+
</>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const markdownModalRender = {
|
|
41
|
+
render: Render,
|
|
42
|
+
renderFormItem: () => <></>,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export { markdownModalRender };
|
|
@@ -25,6 +25,7 @@ async function fakeRequest() {
|
|
|
25
25
|
dateNumber: +dayjs('2024-10-01'),
|
|
26
26
|
seconds: Math.abs(+dayjs('2024-10-01') / 1000),
|
|
27
27
|
jsonText: JSON.stringify({ name: 'hello world hello world hello world' }),
|
|
28
|
+
markdownText: `# Hello World\n\nThis is a markdown text.`,
|
|
28
29
|
switchNumber: Math.random() > 0.5 ? 1 : 0,
|
|
29
30
|
switchOptions: Math.random() > 0.5 ? 'ON' : 'OFF',
|
|
30
31
|
}));
|
|
@@ -84,6 +85,12 @@ const Table = () => {
|
|
|
84
85
|
ellipsis: true,
|
|
85
86
|
valueType: CustomValueTypeEnum.CustomJSONModal,
|
|
86
87
|
},
|
|
88
|
+
{
|
|
89
|
+
title: 'markdownModal',
|
|
90
|
+
dataIndex: 'markdownText',
|
|
91
|
+
ellipsis: true,
|
|
92
|
+
valueType: CustomValueTypeEnum.CustomMarkdownModal,
|
|
93
|
+
},
|
|
87
94
|
{
|
|
88
95
|
title: '开关 number',
|
|
89
96
|
dataIndex: 'switchNumber',
|
|
@@ -104,6 +111,7 @@ const Table = () => {
|
|
|
104
111
|
<CRUD
|
|
105
112
|
actions={[]}
|
|
106
113
|
tableProps={{
|
|
114
|
+
rowKey: 'id',
|
|
107
115
|
columns,
|
|
108
116
|
request: fakeRequest,
|
|
109
117
|
}}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { DownOutlined, UpOutlined } from '@fe-free/icons';
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
|
|
4
|
-
function DeepSeekBlock(props: { children: string }) {
|
|
5
|
-
const [show, setShow] = useState(true);
|
|
6
|
-
|
|
7
|
-
return (
|
|
8
|
-
<div className="markdown-body-block-deep-seek mb-3 flex flex-col gap-2 text-[12px] text-03">
|
|
9
|
-
<div
|
|
10
|
-
className="cursor-pointer"
|
|
11
|
-
onClick={() => {
|
|
12
|
-
setShow((v) => !v);
|
|
13
|
-
}}
|
|
14
|
-
>
|
|
15
|
-
深度思考 {show ? <UpOutlined /> : <DownOutlined />}
|
|
16
|
-
</div>
|
|
17
|
-
{show && (
|
|
18
|
-
<div className="relative pl-[15px]">
|
|
19
|
-
<div className="top=0 absolute left-0 h-full w-[2px] bg-[#00000014]" />
|
|
20
|
-
{props.children === '<br/>' ? undefined : props.children}
|
|
21
|
-
</div>
|
|
22
|
-
)}
|
|
23
|
-
</div>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function processWithDeepSeek(text: string) {
|
|
28
|
-
// 开始 <think> 才算开始
|
|
29
|
-
if (!text.startsWith('<think>')) {
|
|
30
|
-
return text;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const [left, right] = text.split('</think>');
|
|
34
|
-
|
|
35
|
-
let newText = text;
|
|
36
|
-
|
|
37
|
-
// 如果 think 部分是 <think>\n\n</think>,相当于没有,则直接返回 right
|
|
38
|
-
if (text.startsWith('<think>\n\n</think>')) {
|
|
39
|
-
newText = right;
|
|
40
|
-
}
|
|
41
|
-
// 否则做一些处理
|
|
42
|
-
else {
|
|
43
|
-
newText =
|
|
44
|
-
left
|
|
45
|
-
.replace('<think>\n', '<think>')
|
|
46
|
-
.replace('\n</think>', '</think>')
|
|
47
|
-
.replace(/\n/g, '<br/>') + (right || '');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return newText;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export { DeepSeekBlock, processWithDeepSeek };
|
package/src/markdown/style.scss
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
.markdown-body {
|
|
2
|
-
font-size: 14px;
|
|
3
|
-
|
|
4
|
-
pre {
|
|
5
|
-
padding: 0;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.markdown-body-block-code {
|
|
9
|
-
margin: 0.5rem 0;
|
|
10
|
-
|
|
11
|
-
& > div {
|
|
12
|
-
margin: 0 !important;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.markdown-body-block-chart {
|
|
17
|
-
background: white;
|
|
18
|
-
border-radius: 6px;
|
|
19
|
-
margin: 0.5rem;
|
|
20
|
-
|
|
21
|
-
.markdown-body-block-chart-title {
|
|
22
|
-
font-size: 16px;
|
|
23
|
-
font-weight: bold;
|
|
24
|
-
padding: 10px;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.markdown-body-block-knowledge-ref[data-id] {
|
|
29
|
-
height: 16px;
|
|
30
|
-
min-width: 16px;
|
|
31
|
-
cursor: pointer;
|
|
32
|
-
display: inline-flex;
|
|
33
|
-
align-items: center;
|
|
34
|
-
justify-content: center;
|
|
35
|
-
border-radius: 999px;
|
|
36
|
-
border: 1px solid #0374e9;
|
|
37
|
-
color: #0374e9;
|
|
38
|
-
font-size: 12px;
|
|
39
|
-
padding: 0 4px;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.markdown-body-block-knowledge-ref-source {
|
|
43
|
-
color: #0374e9;
|
|
44
|
-
cursor: pointer;
|
|
45
|
-
}
|
|
46
|
-
}
|
package/src/tailwind.config.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/** @type {import('tailwindcss').Config} */
|
|
2
|
-
import { themeVariables } from './theme';
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
theme: {
|
|
6
|
-
extend: {
|
|
7
|
-
colors: themeVariables.color,
|
|
8
|
-
textColor: themeVariables.textColor,
|
|
9
|
-
borderColor: themeVariables.borderColor,
|
|
10
|
-
backgroundColor: themeVariables.backgroundColor,
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
plugins: [],
|
|
14
|
-
};
|