@baishuyun/chat-sdk 0.0.8 → 0.0.9
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/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +8 -0
- package/dist/chat-sdk.js +18430 -17466
- package/dist/chat-sdk.js.map +1 -1
- package/dist/chat-sdk.umd.cjs +177 -177
- package/dist/chat-sdk.umd.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/package.json +4 -4
- package/src/chat.tsx +7 -6
- package/src/components/biz-comp/chat-client.tsx +24 -5
- package/src/components/biz-comp/markdown-part.tsx +42 -18
- package/src/components/biz-comp/message-content.tsx +1 -1
- package/src/components/biz-comp/preview-message-wrapper.tsx +5 -1
- package/src/components/biz-comp/suggestions.tsx +3 -1
- package/src/components/bs-ui/bs-icons.tsx +95 -0
- package/src/components/bs-ui/card-field.tsx +23 -0
- package/src/components/bs-ui/chat-area-header.tsx +9 -0
- package/src/components/bs-ui/collapsible-txt-msg.tsx +13 -15
- package/src/components/bs-ui/fields-generating-indicator.tsx +2 -2
- package/src/components/bs-ui/fields-previewer.tsx +22 -3
- package/src/components/bs-ui/formula-tag.tsx +32 -0
- package/src/components/bs-ui/split-line.tsx +9 -0
- package/src/components/web-comp/fields-previewer-web-component.ts +1 -1
- package/src/hooks/use-chat-preference.ts +9 -0
- package/src/hooks/use-draggable.ts +154 -0
- package/src/hooks/use-msg-status-broadcast.ts +10 -0
- package/src/index.tsx +2 -4
- package/src/lib/utils.ts +22 -0
- package/src/plugins/form-filling-plugin/index.ts +1 -1
- package/src/plugins/mcp-form-builder-plugin/index.ts +5 -0
- package/src/plugins/report-query-plugin/components/avatar.tsx +12 -0
- package/src/plugins/report-query-plugin/components/query-entry-btn.tsx +17 -0
- package/src/plugins/report-query-plugin/components/query-msg-part.tsx +30 -0
- package/src/plugins/report-query-plugin/components/query-opening-lines.tsx +30 -0
- package/src/plugins/report-query-plugin/components/result-cards/DataTableCard.tsx +59 -0
- package/src/plugins/report-query-plugin/components/result-cards/DataTableFields.tsx +46 -0
- package/src/plugins/report-query-plugin/components/result-cards/FilterCondition.tsx +374 -0
- package/src/plugins/report-query-plugin/components/result-cards/FormulaField.tsx +24 -0
- package/src/plugins/report-query-plugin/const.ts +1 -0
- package/src/plugins/report-query-plugin/index.ts +96 -0
- package/src/plugins/report-query-plugin/types.ts +16 -0
- package/src/plugins/report-query-plugin/utils.tsx +389 -0
- package/src/sdk.impl.tsx +7 -0
- package/src/store/index.ts +2 -1
- package/src/stories/CardField.stories.tsx +87 -0
- package/src/stories/FormulaField.stories.tsx +145 -0
- package/src/stories/FormulaTag.stories.tsx +68 -0
- package/src/stories/SplitLine.stories.tsx +40 -0
- package/src/style.css +5 -2
- package/tailwind.config.js +19 -20
|
@@ -916,3 +916,98 @@ export const CheckerInBoxIcon = () => (
|
|
|
916
916
|
<path d="M9.5067 0.236399C9.33081 0.075254 9.09814 -0.00947067 8.85981 0.000842334C8.62149 0.0111553 8.39701 0.115663 8.2357 0.291399L3.4847 5.4714L1.6307 2.8764L1.5597 2.7884C1.40419 2.62083 1.19075 2.51872 0.962705 2.5028C0.734658 2.48687 0.509095 2.55832 0.331809 2.70264C0.154524 2.84697 0.0388021 3.05335 0.00813691 3.27988C-0.0225283 3.50642 0.0341613 3.73614 0.166697 3.9224L2.6667 7.4224L2.7427 7.5154C2.8275 7.60576 2.93004 7.67764 3.04391 7.72654C3.15778 7.77543 3.28052 7.80028 3.40444 7.79952C3.52836 7.79877 3.65079 7.77244 3.76406 7.72217C3.87733 7.6719 3.979 7.59879 4.0627 7.5074L9.5627 1.5074L9.6387 1.4124C9.76255 1.23353 9.81742 1.01586 9.79315 0.799654C9.76888 0.58345 9.66712 0.383356 9.5067 0.236399Z" />
|
|
917
917
|
</svg>
|
|
918
918
|
);
|
|
919
|
+
|
|
920
|
+
export const StatsIcon = ({ size }: { size?: number }) => (
|
|
921
|
+
<svg
|
|
922
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
923
|
+
width={size}
|
|
924
|
+
height={size}
|
|
925
|
+
viewBox="0 0 24 24"
|
|
926
|
+
fill="none"
|
|
927
|
+
>
|
|
928
|
+
<path
|
|
929
|
+
d="M20.2789 20.7891H3.72266C3.17188 20.7891 2.72656 20.3438 2.72656 19.793C2.72656 19.2422 3.17188 18.7969 3.72266 18.7969H20.2789C20.8297 18.7969 21.275 19.2422 21.275 19.793C21.275 20.3438 20.8297 20.7891 20.2789 20.7891Z"
|
|
930
|
+
fill="url(#paint0_linear_21740_6067)"
|
|
931
|
+
/>
|
|
932
|
+
<path
|
|
933
|
+
d="M5.52148 17.6605H4.16211C3.72148 17.6605 3.36523 17.3043 3.36523 16.8637V12.9473C3.36523 12.5066 3.72148 12.1504 4.16211 12.1504H5.52148C5.96211 12.1504 6.31836 12.5066 6.31836 12.9473V16.8637C6.31836 17.302 5.95977 17.6605 5.52148 17.6605Z"
|
|
934
|
+
fill="url(#paint1_linear_21740_6067)"
|
|
935
|
+
/>
|
|
936
|
+
<path
|
|
937
|
+
d="M10.2816 17.6602H8.94336C8.49805 17.6602 8.13477 17.2992 8.13477 16.8516V6.82969C8.13477 6.38437 8.4957 6.02109 8.94336 6.02109H10.2816C10.727 6.02109 11.0902 6.38203 11.0902 6.82969V16.8516C11.0902 17.2969 10.727 17.6602 10.2816 17.6602ZM15.0676 17.6602H13.7035C13.2652 17.6602 12.909 17.3039 12.909 16.8656V10.0031C12.909 9.56484 13.2652 9.20859 13.7035 9.20859H15.0676C15.5059 9.20859 15.8621 9.56484 15.8621 10.0031V16.8633C15.8621 17.3039 15.5059 17.6602 15.0676 17.6602ZM19.8371 17.6602H18.4824C18.0418 17.6602 17.6832 17.3016 17.6832 16.8609V4.01016C17.6832 3.56953 18.0418 3.21094 18.4824 3.21094H19.8371C20.2777 3.21094 20.6363 3.56953 20.6363 4.01016V16.8609C20.634 17.3016 20.2777 17.6602 19.8371 17.6602Z"
|
|
938
|
+
fill="url(#paint2_linear_21740_6067)"
|
|
939
|
+
/>
|
|
940
|
+
<defs>
|
|
941
|
+
<linearGradient
|
|
942
|
+
id="paint0_linear_21740_6067"
|
|
943
|
+
x1="12.0008"
|
|
944
|
+
y1="18.7969"
|
|
945
|
+
x2="12.0008"
|
|
946
|
+
y2="20.7891"
|
|
947
|
+
gradientUnits="userSpaceOnUse"
|
|
948
|
+
>
|
|
949
|
+
<stop stop-color="#0265FF" />
|
|
950
|
+
<stop offset="1" stop-color="#A6FFFF" />
|
|
951
|
+
</linearGradient>
|
|
952
|
+
<linearGradient
|
|
953
|
+
id="paint1_linear_21740_6067"
|
|
954
|
+
x1="4.8418"
|
|
955
|
+
y1="12.1504"
|
|
956
|
+
x2="4.8418"
|
|
957
|
+
y2="17.6605"
|
|
958
|
+
gradientUnits="userSpaceOnUse"
|
|
959
|
+
>
|
|
960
|
+
<stop stop-color="#0265FF" />
|
|
961
|
+
<stop offset="1" stop-color="#A6FFFF" />
|
|
962
|
+
</linearGradient>
|
|
963
|
+
<linearGradient
|
|
964
|
+
id="paint2_linear_21740_6067"
|
|
965
|
+
x1="14.3855"
|
|
966
|
+
y1="3.21094"
|
|
967
|
+
x2="14.3855"
|
|
968
|
+
y2="17.6602"
|
|
969
|
+
gradientUnits="userSpaceOnUse"
|
|
970
|
+
>
|
|
971
|
+
<stop stop-color="#0265FF" />
|
|
972
|
+
<stop offset="1" stop-color="#A6FFFF" />
|
|
973
|
+
</linearGradient>
|
|
974
|
+
</defs>
|
|
975
|
+
</svg>
|
|
976
|
+
);
|
|
977
|
+
|
|
978
|
+
export const DataTableIcon = () => (
|
|
979
|
+
<svg
|
|
980
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
981
|
+
width="16"
|
|
982
|
+
height="16"
|
|
983
|
+
viewBox="0 0 16 16"
|
|
984
|
+
fill="currentColor"
|
|
985
|
+
>
|
|
986
|
+
<path
|
|
987
|
+
fill-rule="evenodd"
|
|
988
|
+
clip-rule="evenodd"
|
|
989
|
+
d="M12.6671 1.00011C12.9743 0.99704 13.2792 1.05583 13.5636 1.17199C13.848 1.28815 14.1071 1.45962 14.3243 1.67687C14.5414 1.89404 14.7131 2.15236 14.8292 2.43664C14.9454 2.72105 15.0032 3.02593 15.0001 3.33312V12.6671C15.0032 12.9743 14.9453 13.2792 14.8292 13.5636C14.7131 13.8478 14.5414 14.1062 14.3243 14.3234C14.1071 14.5406 13.848 14.7131 13.5636 14.8292C13.2792 14.9453 12.9742 15.0032 12.6671 15.0001H3.33312C3.02597 15.0032 2.72101 14.9453 2.43664 14.8292C2.15225 14.7131 1.89409 14.5406 1.67687 14.3234C1.45971 14.1062 1.28811 13.8479 1.17199 13.5636C1.05583 13.2792 0.99704 12.9743 1.00011 12.6671V3.33312C0.997054 3.02593 1.05585 2.72105 1.17199 2.43664C1.28813 2.15232 1.45971 1.89405 1.67687 1.67687C1.89403 1.45972 2.15235 1.28814 2.43664 1.17199C2.72101 1.05586 3.02597 0.997071 3.33312 1.00011H12.6671ZM2.00011 10.5001V12.6153C2.00018 13.4001 2.60015 13.9999 3.38488 14.0001H5.00011V10.5001H2.00011ZM6.00011 10.5001V14.0001H10.0001V10.5001H6.00011ZM11.0001 10.5001V14.0001H12.6153C13.4003 14.0001 14.0001 13.4003 14.0001 12.6153V10.5001H11.0001ZM2.00011 9.50011H5.00011V6.50011H2.00011V9.50011ZM6.00011 9.50011H10.0001V6.50011H6.00011V9.50011ZM11.0001 9.50011H14.0001V6.50011H11.0001V9.50011ZM3.38488 2.00011C2.60022 2.00035 2.00029 2.6002 2.00011 3.38488V5.50011H14.0001V3.38488C13.9999 2.60005 13.4002 2.00012 12.6153 2.00011H3.38488Z"
|
|
990
|
+
/>
|
|
991
|
+
</svg>
|
|
992
|
+
);
|
|
993
|
+
|
|
994
|
+
export const DefaultFormIcon = () => (
|
|
995
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
996
|
+
<path
|
|
997
|
+
d="M9.15595 1.42188V4.08854C9.15595 4.56004 9.34325 5.01222 9.67664 5.34562C10.01 5.67902 10.4622 5.86632 10.9337 5.86632H13.6004V13.8663C13.6004 14.1021 13.5067 14.3282 13.34 14.4949C13.1733 14.6616 12.9472 14.7552 12.7115 14.7552H3.28928C3.05353 14.7552 2.82744 14.6616 2.66074 14.4949C2.49404 14.3282 2.40039 14.1021 2.40039 13.8663V2.31076C2.40039 2.07502 2.49404 1.84892 2.66074 1.68222C2.82744 1.51553 3.05353 1.42188 3.28928 1.42188H9.15595ZM5.5115 8.53299C5.39363 8.53299 5.28058 8.57981 5.19723 8.66316C5.11388 8.74651 5.06706 8.85956 5.06706 8.97743C5.06706 9.0953 5.11388 9.20835 5.19723 9.2917C5.28058 9.37505 5.39363 9.42187 5.5115 9.42187H10.4893C10.6072 9.42187 10.7202 9.37505 10.8035 9.2917C10.8869 9.20835 10.9337 9.0953 10.9337 8.97743C10.9337 8.85956 10.8869 8.74651 10.8035 8.66316C10.7202 8.57981 10.6072 8.53299 10.4893 8.53299H5.5115ZM5.5115 11.1997C5.39363 11.1997 5.28058 11.2465 5.19723 11.3298C5.11388 11.4132 5.06706 11.5262 5.06706 11.6441C5.06706 11.762 5.11388 11.875 5.19723 11.9584C5.28058 12.0417 5.39363 12.0885 5.5115 12.0885H10.4893C10.6072 12.0885 10.7202 12.0417 10.8035 11.9584C10.8869 11.875 10.9337 11.762 10.9337 11.6441C10.9337 11.5262 10.8869 11.4132 10.8035 11.3298C10.7202 11.2465 10.6072 11.1997 10.4893 11.1997H5.5115ZM10.0448 1.42188L13.6004 4.97743H10.9337C10.698 4.97743 10.4719 4.88378 10.3052 4.71708C10.1385 4.55038 10.0448 4.32429 10.0448 4.08854V1.42188Z"
|
|
998
|
+
fill="#0265FF"
|
|
999
|
+
/>
|
|
1000
|
+
</svg>
|
|
1001
|
+
);
|
|
1002
|
+
|
|
1003
|
+
export const FormulasIcon = () => (
|
|
1004
|
+
<svg
|
|
1005
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1006
|
+
width="16"
|
|
1007
|
+
height="16"
|
|
1008
|
+
viewBox="0 0 16 16"
|
|
1009
|
+
fill="currentColor"
|
|
1010
|
+
>
|
|
1011
|
+
<path d="M13.6028 7.93734C13.6699 7.99362 13.7252 8.06255 13.7656 8.14022C13.8061 8.21788 13.8308 8.30275 13.8385 8.38998C13.8461 8.47721 13.8365 8.56509 13.8101 8.64859C13.7838 8.7321 13.7413 8.80961 13.685 8.87668L11.8059 11.1158L13.0219 13.2218C13.0663 13.2976 13.0954 13.3815 13.1073 13.4686C13.1192 13.5557 13.1137 13.6444 13.0913 13.7294C13.0688 13.8144 13.0297 13.8941 12.9763 13.9639C12.9229 14.0337 12.8562 14.0923 12.7801 14.1363C12.704 14.1803 12.6199 14.2087 12.5327 14.2201C12.4455 14.2314 12.3569 14.2254 12.2721 14.2023C12.1872 14.1793 12.1078 14.1397 12.0383 14.0858C11.9688 14.032 11.9107 13.9649 11.8672 13.8885L10.8939 12.2029L9.39966 13.9836C9.34386 14.0521 9.275 14.1089 9.19706 14.1506C9.11913 14.1923 9.03368 14.2181 8.94569 14.2264C8.8577 14.2348 8.76893 14.2256 8.68453 14.1993C8.60013 14.1731 8.5218 14.1303 8.45409 14.0735C8.38638 14.0167 8.33064 13.947 8.29011 13.8684C8.24959 13.7899 8.22509 13.704 8.21804 13.6159C8.21099 13.5278 8.22153 13.4392 8.24905 13.3552C8.27656 13.2712 8.32051 13.1935 8.37832 13.1267L10.1843 10.974L8.97832 8.88468C8.93386 8.80883 8.90483 8.72494 8.89292 8.63783C8.88101 8.55072 8.88645 8.46211 8.90892 8.37711C8.9314 8.29211 8.97046 8.2124 9.02386 8.14256C9.07727 8.07272 9.14396 8.01413 9.2201 7.97017C9.29624 7.92621 9.38033 7.89774 9.46751 7.88641C9.5547 7.87508 9.64327 7.8811 9.72812 7.90414C9.81297 7.92717 9.89242 7.96676 9.96191 8.02063C10.0314 8.0745 10.0895 8.14158 10.133 8.21801L11.0965 9.8869L12.6634 8.01957C12.7197 7.95248 12.7886 7.89714 12.8663 7.8567C12.944 7.81626 13.0288 7.79151 13.1161 7.78388C13.2033 7.77624 13.2912 7.78587 13.3747 7.8122C13.4582 7.83853 13.5357 7.88106 13.6028 7.93734ZM9.55566 1.77734C9.72919 1.77718 9.89595 1.84468 10.0205 1.96552C10.1451 2.08635 10.2176 2.25099 10.2227 2.42445C10.2278 2.59791 10.165 2.76652 10.0478 2.89445C9.93053 3.02238 9.76801 3.09955 9.59477 3.10957L9.55566 3.11068H9.25477C8.77582 3.11068 8.31278 3.28256 7.94984 3.59506C7.58689 3.90757 7.34814 4.33994 7.27699 4.81357L7.26899 4.87246L7.24032 5.11068H8.66677C8.72513 5.11068 8.78293 5.12217 8.83685 5.14451C8.89077 5.16684 8.93977 5.19958 8.98104 5.24085C9.02231 5.28212 9.05504 5.33112 9.07738 5.38504C9.09972 5.43896 9.11121 5.49676 9.11121 5.55512V5.99957C9.11121 6.11744 9.06439 6.23049 8.98104 6.31384C8.89769 6.39719 8.78464 6.44401 8.66677 6.44401H7.08032L6.49943 11.2856C6.40386 12.0824 6.02403 12.818 5.4297 13.3572C4.83536 13.8965 4.06642 14.2032 3.2641 14.2211L3.18988 14.2218H2.88899C2.71545 14.222 2.54869 14.1545 2.42414 14.0336C2.29959 13.9128 2.22706 13.7481 2.22197 13.5747C2.21687 13.4012 2.27962 13.2326 2.39687 13.1047C2.51412 12.9768 2.67663 12.8996 2.84988 12.8896L2.88899 12.8885H3.18988C3.66882 12.8884 4.13186 12.7166 4.49481 12.4041C4.85775 12.0916 5.09651 11.6592 5.16766 11.1856L5.17566 11.1267L5.73721 6.44401H4.22232C4.10445 6.44401 3.9914 6.39719 3.90805 6.31384C3.8247 6.23049 3.77788 6.11744 3.77788 5.99957V5.55512C3.77788 5.49676 3.78937 5.43896 3.81171 5.38504C3.83404 5.33112 3.86678 5.28212 3.90805 5.24085C3.94932 5.19958 3.99832 5.16684 4.05224 5.14451C4.10616 5.12217 4.16396 5.11068 4.22232 5.11068H5.89721L5.94521 4.71357C6.04078 3.91675 6.42061 3.18117 7.01495 2.6419C7.60928 2.10264 8.37822 1.79589 9.18054 1.77801L9.25477 1.77734H9.55566Z" />
|
|
1012
|
+
</svg>
|
|
1013
|
+
);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface CardFieldProps {
|
|
5
|
+
label: string;
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const CardField = ({ label, children, className }: CardFieldProps) => {
|
|
11
|
+
return (
|
|
12
|
+
<div className={cn('flex gap-2 items-start w-full', className)}>
|
|
13
|
+
<div className="w-[100px] shrink-0 text-[#666] text-sm leading-normal truncate">{label}</div>
|
|
14
|
+
<div className="flex-1 min-w-0 text-sm leading-normal whitespace-pre-wrap break-words">
|
|
15
|
+
{children ?? <span className="text-[#666]">无</span>}
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const CardFieldsWrapper = ({ children }: { children: ReactNode }) => {
|
|
22
|
+
return <div className="flex flex-col gap-[10px] w-full">{children}</div>;
|
|
23
|
+
};
|
|
@@ -9,6 +9,9 @@ export interface ChatAreaHeaderProps {
|
|
|
9
9
|
onDockClick?: () => void;
|
|
10
10
|
onCloseClick?: () => void;
|
|
11
11
|
avatar?: React.ReactNode;
|
|
12
|
+
draggable?: boolean;
|
|
13
|
+
isDragging?: boolean;
|
|
14
|
+
onDragStart?: (e: React.MouseEvent) => void;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
export const ChatAreaHeader = ({
|
|
@@ -16,18 +19,24 @@ export const ChatAreaHeader = ({
|
|
|
16
19
|
width,
|
|
17
20
|
onDockClick,
|
|
18
21
|
onCloseClick,
|
|
22
|
+
draggable,
|
|
23
|
+
isDragging,
|
|
24
|
+
onDragStart,
|
|
19
25
|
}: ChatAreaHeaderProps) => {
|
|
20
26
|
return (
|
|
21
27
|
<div
|
|
22
28
|
className={cn('flex items-center justify-between', 'px-4', 'h-[52px] min-w-[200px]', {
|
|
23
29
|
'w-full': !width,
|
|
24
30
|
[`w-[${width}px]`]: width,
|
|
31
|
+
'cursor-grab': draggable && !isDragging,
|
|
32
|
+
'cursor-grabbing': isDragging,
|
|
25
33
|
})}
|
|
26
34
|
style={{
|
|
27
35
|
backgroundImage: ChatHeaderBgImgUrl,
|
|
28
36
|
backgroundSize: 'cover',
|
|
29
37
|
backgroundRepeat: 'no-repeat',
|
|
30
38
|
}}
|
|
39
|
+
onMouseDown={draggable ? onDragStart : undefined}
|
|
31
40
|
>
|
|
32
41
|
{avatar}
|
|
33
42
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ReactNode, useState } from
|
|
2
|
-
import { cn } from
|
|
3
|
-
import { transCls } from
|
|
4
|
-
import { AnalysisIcon, ChevronIcon } from
|
|
1
|
+
import { ReactNode, useState } from 'react';
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
import { transCls } from '@/const/ui';
|
|
4
|
+
import { AnalysisIcon, ChevronIcon } from './bs-icons';
|
|
5
5
|
|
|
6
6
|
export interface CollapsibleTxtMsgProps {
|
|
7
7
|
title: string;
|
|
@@ -11,7 +11,6 @@ export interface CollapsibleTxtMsgProps {
|
|
|
11
11
|
children?: ReactNode;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
export const CollapsibleTxtMsg = ({
|
|
16
15
|
title,
|
|
17
16
|
content,
|
|
@@ -23,9 +22,12 @@ export const CollapsibleTxtMsg = ({
|
|
|
23
22
|
|
|
24
23
|
return (
|
|
25
24
|
<div className="bg-[#fafafa] border border-[#e0e0e0] border-solid flex flex-col gap-2.5 p-2.5 rounded-[10px] w-full">
|
|
26
|
-
<div
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
<div
|
|
26
|
+
className="flex items-center justify-between w-full cursor-pointer"
|
|
27
|
+
onClick={() => {
|
|
28
|
+
setIsOpen(!isOpen);
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
29
31
|
<div className="flex gap-1.5 items-center">
|
|
30
32
|
<div className="w-4 h-4 shrink-0">{icon || <AnalysisIcon />}</div>
|
|
31
33
|
<p className="text-[#666] text-[14px] leading-normal">{title}</p>
|
|
@@ -33,18 +35,14 @@ export const CollapsibleTxtMsg = ({
|
|
|
33
35
|
<button
|
|
34
36
|
onClick={() => setIsOpen(!isOpen)}
|
|
35
37
|
className={cn(
|
|
36
|
-
|
|
38
|
+
'flex items-center justify-center w-5 h-5 rounded-[4px] cursor-pointer hover:bg-[#EFF0F6]',
|
|
37
39
|
transCls
|
|
38
40
|
)}
|
|
39
41
|
>
|
|
40
42
|
<ChevronIcon isOpen={isOpen} />
|
|
41
43
|
</button>
|
|
42
44
|
</div>
|
|
43
|
-
{isOpen &&
|
|
44
|
-
<div className="text-[#030303] text-[14px]">
|
|
45
|
-
{content || children}
|
|
46
|
-
</div>
|
|
47
|
-
)}
|
|
45
|
+
{isOpen && <div className="text-[#030303] text-[14px] word-wrap">{content || children}</div>}
|
|
48
46
|
</div>
|
|
49
47
|
);
|
|
50
|
-
};
|
|
48
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { BorderColorAnimation } from './border-color-animation';
|
|
2
2
|
import { MagicIcon } from './bs-icons';
|
|
3
3
|
|
|
4
|
-
export const FieldsGeneratingIndicator = () => {
|
|
4
|
+
export const FieldsGeneratingIndicator = ({ children }: { children?: React.ReactNode }) => {
|
|
5
5
|
return (
|
|
6
6
|
<BorderColorAnimation borderRadius={100} width={136} height={34} borderWidth={1}>
|
|
7
7
|
<div className="flex items-center gap-[6px] h-[31px] ml-[16px]">
|
|
8
8
|
<MagicIcon />
|
|
9
|
-
<span className="text-[14px] text-[#0265FF]"
|
|
9
|
+
<span className="text-[14px] text-[#0265FF]">{children || '字段生成中'}</span>
|
|
10
10
|
<div className="flex gap-[2px] flex-shrink-0 relative -left-[4px] top-[3px]">
|
|
11
11
|
<div
|
|
12
12
|
className="w-[2px] h-[2px] rounded-full bg-[#0265FF] flex-shrink-0"
|
|
@@ -15,6 +15,7 @@ export interface FieldsPreviewerProps extends PreviewerHeaderProps {
|
|
|
15
15
|
|
|
16
16
|
// generating fields
|
|
17
17
|
streaming?: boolean;
|
|
18
|
+
streamingText?: string;
|
|
18
19
|
|
|
19
20
|
empty?: boolean;
|
|
20
21
|
|
|
@@ -24,6 +25,8 @@ export interface FieldsPreviewerProps extends PreviewerHeaderProps {
|
|
|
24
25
|
|
|
25
26
|
containerStyle?: string;
|
|
26
27
|
|
|
28
|
+
fullContent?: boolean;
|
|
29
|
+
|
|
27
30
|
// children means the content inside the previewer, not the right side components
|
|
28
31
|
children?: React.ReactNode;
|
|
29
32
|
}
|
|
@@ -56,6 +59,7 @@ export const FieldsPreviewer = forwardRef<HTMLDivElement, FieldsPreviewerProps>(
|
|
|
56
59
|
rightSpaceRef,
|
|
57
60
|
rightElement,
|
|
58
61
|
streaming,
|
|
62
|
+
streamingText,
|
|
59
63
|
onBackClick,
|
|
60
64
|
dialogContainer,
|
|
61
65
|
variant = 'fields-previewer',
|
|
@@ -63,6 +67,7 @@ export const FieldsPreviewer = forwardRef<HTMLDivElement, FieldsPreviewerProps>(
|
|
|
63
67
|
onCancel,
|
|
64
68
|
style,
|
|
65
69
|
confirmContent,
|
|
70
|
+
fullContent,
|
|
66
71
|
confirmTitle,
|
|
67
72
|
containerStyle,
|
|
68
73
|
}: FieldsPreviewerProps) => {
|
|
@@ -87,6 +92,15 @@ export const FieldsPreviewer = forwardRef<HTMLDivElement, FieldsPreviewerProps>(
|
|
|
87
92
|
'rounded-[4px] bg-white': isData,
|
|
88
93
|
});
|
|
89
94
|
|
|
95
|
+
const fullContentStyle = fullContent
|
|
96
|
+
? {
|
|
97
|
+
width: '100%',
|
|
98
|
+
height: '100%',
|
|
99
|
+
padding: 0,
|
|
100
|
+
margin: 0,
|
|
101
|
+
}
|
|
102
|
+
: {};
|
|
103
|
+
|
|
90
104
|
const { shadowContainer } = useShadow({
|
|
91
105
|
id: 'dialog-container',
|
|
92
106
|
rootEl: dialogContainer,
|
|
@@ -116,18 +130,23 @@ export const FieldsPreviewer = forwardRef<HTMLDivElement, FieldsPreviewerProps>(
|
|
|
116
130
|
confirmTitle={confirmTitle}
|
|
117
131
|
confirmContent={confirmContent}
|
|
118
132
|
/>
|
|
119
|
-
<div className={contentCls}
|
|
133
|
+
<div className={contentCls} style={fullContentStyle}>
|
|
134
|
+
{empty && isFields ? <PlaceholderDashedBox /> : children}
|
|
135
|
+
</div>
|
|
120
136
|
{streaming && (
|
|
121
137
|
// abs center
|
|
122
138
|
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
|
|
123
|
-
<FieldsGeneratingIndicator
|
|
139
|
+
<FieldsGeneratingIndicator>{streamingText}</FieldsGeneratingIndicator>
|
|
124
140
|
</div>
|
|
125
141
|
)}
|
|
126
142
|
</>
|
|
127
143
|
);
|
|
128
144
|
|
|
129
145
|
const content = isFields ? (
|
|
130
|
-
<BorderColorAnimation
|
|
146
|
+
<BorderColorAnimation
|
|
147
|
+
width={pr ? `calc(100% - ${pr}px)` : '100%'}
|
|
148
|
+
style={{ overflow: 'hidden' }}
|
|
149
|
+
>
|
|
131
150
|
{contentJsx}
|
|
132
151
|
</BorderColorAnimation>
|
|
133
152
|
) : (
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import { type FormulaOp, FORMULA_OP_LABEL } from '@baishuyun/types';
|
|
3
|
+
|
|
4
|
+
/** 统计方式 → 背景色 */
|
|
5
|
+
const FORMULA_OP_COLOR: Record<FormulaOp, string> = {
|
|
6
|
+
sum: '#3767F1',
|
|
7
|
+
max: '#F06648',
|
|
8
|
+
min: '#4ACC8C',
|
|
9
|
+
average: '#4AC0EC',
|
|
10
|
+
count: '#9362CE',
|
|
11
|
+
countDistinct: '#F168B6',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export interface FormulaTagProps {
|
|
15
|
+
/** 统计方式 */
|
|
16
|
+
type: FormulaOp;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const FormulaTag = ({ type, className }: FormulaTagProps) => {
|
|
21
|
+
return (
|
|
22
|
+
<span
|
|
23
|
+
className={cn(
|
|
24
|
+
'inline-flex items-center justify-center rounded-[100px] px-[6px] text-[14px] leading-[20px] text-white',
|
|
25
|
+
className
|
|
26
|
+
)}
|
|
27
|
+
style={{ backgroundColor: FORMULA_OP_COLOR[type] }}
|
|
28
|
+
>
|
|
29
|
+
{FORMULA_OP_LABEL[type]}
|
|
30
|
+
</span>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
@@ -251,7 +251,7 @@ export class FieldsPreviewerWebComponent extends HTMLElement {
|
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
// Register the web component
|
|
254
|
-
|
|
254
|
+
function registerFieldsPreviewerWebComponent(tagName = 'previewer-container') {
|
|
255
255
|
if (!customElements.get(tagName)) {
|
|
256
256
|
customElements.define(tagName, FieldsPreviewerWebComponent);
|
|
257
257
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ChatPreference, IChatSDK } from '@baishuyun/types';
|
|
2
|
+
import { usePluginLifeCycleChainRunner } from './use-plugin-life-cycle-chain-runner';
|
|
3
|
+
|
|
4
|
+
export const useChatPreference = (client?: IChatSDK) => {
|
|
5
|
+
const { exec } = usePluginLifeCycleChainRunner('onBeforeChatRender');
|
|
6
|
+
const preference = exec(client) as ChatPreference;
|
|
7
|
+
|
|
8
|
+
return preference;
|
|
9
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface Position {
|
|
4
|
+
bottom: number;
|
|
5
|
+
right: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface UseDraggableOptions {
|
|
9
|
+
/** 是否启用拖拽 */
|
|
10
|
+
enabled?: boolean;
|
|
11
|
+
/** 初始位置 */
|
|
12
|
+
initialPosition?: Position;
|
|
13
|
+
/** 位置变化回调 */
|
|
14
|
+
onPositionChange?: (position: Position) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface UseDraggableReturn {
|
|
18
|
+
/** 当前位置 */
|
|
19
|
+
position: Position;
|
|
20
|
+
/** 是否正在拖拽 */
|
|
21
|
+
isDragging: boolean;
|
|
22
|
+
/** 拖拽开始处理函数,绑定到拖拽句柄的 onMouseDown */
|
|
23
|
+
handleDragStart: (e: React.MouseEvent) => void;
|
|
24
|
+
/** 重置位置到初始值 */
|
|
25
|
+
resetPosition: () => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const DEFAULT_POSITION: Position = { bottom: 10, right: 10 };
|
|
29
|
+
|
|
30
|
+
export function useDraggable(options: UseDraggableOptions = {}): UseDraggableReturn {
|
|
31
|
+
const { enabled = true, initialPosition = DEFAULT_POSITION, onPositionChange } = options;
|
|
32
|
+
|
|
33
|
+
// 稳定化 initialPosition,避免对象引用变化导致无限循环
|
|
34
|
+
const stableInitialPosition = useMemo(
|
|
35
|
+
() => initialPosition,
|
|
36
|
+
[initialPosition.bottom, initialPosition.right]
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const [position, setPosition] = useState<Position>(stableInitialPosition);
|
|
40
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
41
|
+
|
|
42
|
+
// 使用 ref 存储回调,避免依赖变化
|
|
43
|
+
const onPositionChangeRef = useRef(onPositionChange);
|
|
44
|
+
onPositionChangeRef.current = onPositionChange;
|
|
45
|
+
|
|
46
|
+
// 使用 ref 存储拖拽状态,避免闭包问题
|
|
47
|
+
const dragState = useRef({
|
|
48
|
+
isDragging: false,
|
|
49
|
+
startX: 0,
|
|
50
|
+
startY: 0,
|
|
51
|
+
startBottom: 0,
|
|
52
|
+
startRight: 0,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// 用于 requestAnimationFrame 节流
|
|
56
|
+
const rafId = useRef<number | null>(null);
|
|
57
|
+
|
|
58
|
+
// 重置位置 - 使用稳定的引用避免无限循环
|
|
59
|
+
const resetPosition = useCallback(() => {
|
|
60
|
+
setPosition(stableInitialPosition);
|
|
61
|
+
onPositionChangeRef.current?.(stableInitialPosition);
|
|
62
|
+
}, [stableInitialPosition]);
|
|
63
|
+
|
|
64
|
+
// 开始拖拽
|
|
65
|
+
const handleDragStart = useCallback(
|
|
66
|
+
(e: React.MouseEvent) => {
|
|
67
|
+
if (!enabled) return;
|
|
68
|
+
|
|
69
|
+
// 阻止默认行为和文本选择
|
|
70
|
+
e.preventDefault();
|
|
71
|
+
e.stopPropagation();
|
|
72
|
+
|
|
73
|
+
dragState.current = {
|
|
74
|
+
isDragging: true,
|
|
75
|
+
startX: e.clientX,
|
|
76
|
+
startY: e.clientY,
|
|
77
|
+
startBottom: position.bottom,
|
|
78
|
+
startRight: position.right,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
setIsDragging(true);
|
|
82
|
+
|
|
83
|
+
// 禁用文本选择
|
|
84
|
+
document.body.style.userSelect = 'none';
|
|
85
|
+
document.body.style.cursor = 'grabbing';
|
|
86
|
+
|
|
87
|
+
const handleMouseMove = (moveEvent: MouseEvent) => {
|
|
88
|
+
if (!dragState.current.isDragging) return;
|
|
89
|
+
|
|
90
|
+
// 使用 requestAnimationFrame 优化性能
|
|
91
|
+
if (rafId.current !== null) {
|
|
92
|
+
cancelAnimationFrame(rafId.current);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
rafId.current = requestAnimationFrame(() => {
|
|
96
|
+
const deltaX = moveEvent.clientX - dragState.current.startX;
|
|
97
|
+
const deltaY = moveEvent.clientY - dragState.current.startY;
|
|
98
|
+
|
|
99
|
+
const newPosition = {
|
|
100
|
+
// 向右移动时 deltaX > 0,right 应该减小
|
|
101
|
+
right: Math.max(10, dragState.current.startRight - deltaX),
|
|
102
|
+
// 向下移动时 deltaY > 0,bottom 应该减小
|
|
103
|
+
// bottom: Math.max(0, dragState.current.startBottom - deltaY),
|
|
104
|
+
bottom: Math.min(dragState.current.startBottom - deltaY, 10),
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
setPosition(newPosition);
|
|
108
|
+
onPositionChangeRef.current?.(newPosition);
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const handleMouseUp = () => {
|
|
113
|
+
dragState.current.isDragging = false;
|
|
114
|
+
setIsDragging(false);
|
|
115
|
+
|
|
116
|
+
// 恢复文本选择和光标
|
|
117
|
+
document.body.style.userSelect = '';
|
|
118
|
+
document.body.style.cursor = '';
|
|
119
|
+
|
|
120
|
+
// 清理 RAF
|
|
121
|
+
if (rafId.current !== null) {
|
|
122
|
+
cancelAnimationFrame(rafId.current);
|
|
123
|
+
rafId.current = null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
127
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
131
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
132
|
+
},
|
|
133
|
+
[enabled, position]
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// 清理 effect
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
return () => {
|
|
139
|
+
if (rafId.current !== null) {
|
|
140
|
+
cancelAnimationFrame(rafId.current);
|
|
141
|
+
}
|
|
142
|
+
// 确保清理样式
|
|
143
|
+
document.body.style.userSelect = '';
|
|
144
|
+
document.body.style.cursor = '';
|
|
145
|
+
};
|
|
146
|
+
}, []);
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
position,
|
|
150
|
+
isDragging,
|
|
151
|
+
handleDragStart,
|
|
152
|
+
resetPosition,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ChatStatus } from 'ai';
|
|
2
|
+
import { useEvtBus } from './use-evt-bus';
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
export const useMsgStatusBroadcast = (id: string, status: ChatStatus) => {
|
|
6
|
+
const evtBus = useEvtBus();
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
evtBus.emit<'chat-msg-status-change'>('chat-msg-status-change', { messageId: id, status });
|
|
9
|
+
}, [id, status]);
|
|
10
|
+
};
|
package/src/index.tsx
CHANGED
|
@@ -3,8 +3,6 @@ export { ChatSDK } from './sdk.impl';
|
|
|
3
3
|
export * from './plugins/mcp-form-builder-plugin';
|
|
4
4
|
export * from './plugins/general-model-form-builder-plugin';
|
|
5
5
|
export * from './plugins/form-filling-plugin';
|
|
6
|
+
export * from './plugins/report-query-plugin';
|
|
6
7
|
|
|
7
|
-
export {
|
|
8
|
-
FieldsPreviewerWebComponent,
|
|
9
|
-
registerFieldsPreviewerWebComponent,
|
|
10
|
-
} from './components/web-comp/fields-previewer-web-component';
|
|
8
|
+
export { FieldsPreviewerWebComponent } from './components/web-comp/fields-previewer-web-component';
|
package/src/lib/utils.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { clsx, type ClassValue } from 'clsx';
|
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import { UIDataTypes, UIMessagePart, UITools } from 'ai';
|
|
4
4
|
import { Field } from '@/plugins/form-builder-base-plugin/types';
|
|
5
|
+
import { IQueryResult } from '@baishuyun/types';
|
|
5
6
|
|
|
6
7
|
export function cn(...inputs: ClassValue[]) {
|
|
7
8
|
return twMerge(clsx(inputs));
|
|
@@ -39,6 +40,27 @@ export const IsFieldsJsonPart = (part: any): boolean => {
|
|
|
39
40
|
return payload?.type === 'mcp-fields-json';
|
|
40
41
|
};
|
|
41
42
|
|
|
43
|
+
export const IsQueryResultPart = (part: any): boolean => {
|
|
44
|
+
const payload = extractTextPartMeta(part);
|
|
45
|
+
return payload?.type === 'query-stream-parsed-info';
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const GetQueryResult = (part: any): IQueryResult | null => {
|
|
49
|
+
const payload = extractTextPartMeta(part);
|
|
50
|
+
if (payload?.type !== 'query-stream-parsed-info') {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const result = payload.result;
|
|
55
|
+
console.log('query result raw data:', result);
|
|
56
|
+
try {
|
|
57
|
+
return JSON.parse(result);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.error('invalid query result data');
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
42
64
|
export const IsErrorPart = (part: any): boolean => {
|
|
43
65
|
if (part?.type === 'error') {
|
|
44
66
|
return true;
|
|
@@ -137,7 +137,7 @@ export class FormFillingPlugin extends ChatAreaPlugin<FormFillingPluginCtx> {
|
|
|
137
137
|
};
|
|
138
138
|
|
|
139
139
|
public lifecycleHooks?: PluginHooks | undefined = {
|
|
140
|
-
onBeforeChatRender: (
|
|
140
|
+
onBeforeChatRender: () => {
|
|
141
141
|
return {
|
|
142
142
|
enableMessageMerge: true,
|
|
143
143
|
};
|
|
@@ -40,6 +40,11 @@ export class McpFormBuilderPlugin extends FormBuilderBasePlugin<McpFormBuilderPl
|
|
|
40
40
|
onBeforeMessagePartsRender(parts: Array<part>) {
|
|
41
41
|
return mergeConsecutiveTargets<part>(parts, IsFieldsJsonPart) as part[];
|
|
42
42
|
},
|
|
43
|
+
onBeforeChatRender: () => {
|
|
44
|
+
return {
|
|
45
|
+
appendLoadingIndicator: true,
|
|
46
|
+
};
|
|
47
|
+
},
|
|
43
48
|
};
|
|
44
49
|
|
|
45
50
|
public constructor(ctx: McpFormBuilderPluginCtx) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BotAvatarAndName } from '@/components/bs-ui/bot-avatar-name';
|
|
2
|
+
import { StatsIcon } from '@/components/bs-ui/bs-icons';
|
|
3
|
+
|
|
4
|
+
export const QueryAvatar = ({
|
|
5
|
+
variant = 'default',
|
|
6
|
+
}: {
|
|
7
|
+
variant?: 'default' | 'active';
|
|
8
|
+
size?: number;
|
|
9
|
+
}) => {
|
|
10
|
+
const size = variant === 'default' ? 20 : 24;
|
|
11
|
+
return <BotAvatarAndName name="AI问数" icon={<StatsIcon size={size} />} variant={variant} />;
|
|
12
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseButton } from '@/components/bs-ui/base-button';
|
|
2
|
+
import { MagicIcon } from '@/components/bs-ui/bs-icons';
|
|
3
|
+
import { EntryButtonProps } from '@baishuyun/types';
|
|
4
|
+
|
|
5
|
+
export const QueryEntryBtn = ({ style, onClick }: EntryButtonProps) => {
|
|
6
|
+
return (
|
|
7
|
+
<BaseButton
|
|
8
|
+
style={style}
|
|
9
|
+
onClick={() => {
|
|
10
|
+
onClick?.();
|
|
11
|
+
}}
|
|
12
|
+
icon={<MagicIcon />}
|
|
13
|
+
>
|
|
14
|
+
使用AI创建报表
|
|
15
|
+
</BaseButton>
|
|
16
|
+
);
|
|
17
|
+
};
|