@fe-free/ai 4.1.5 → 4.1.7

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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # @fe-free/ai
2
2
 
3
+ ## 4.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: ai
8
+ - @fe-free/core@4.1.7
9
+ - @fe-free/icons@4.1.7
10
+ - @fe-free/tool@4.1.7
11
+
12
+ ## 4.1.6
13
+
14
+ ### Patch Changes
15
+
16
+ - feat: ai
17
+ - @fe-free/core@4.1.6
18
+ - @fe-free/icons@4.1.6
19
+ - @fe-free/tool@4.1.6
20
+
3
21
  ## 4.1.5
4
22
 
5
23
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fe-free/ai",
3
- "version": "4.1.5",
3
+ "version": "4.1.7",
4
4
  "description": "",
5
5
  "main": "./src/index.ts",
6
6
  "author": "",
@@ -12,9 +12,11 @@
12
12
  "dependencies": {
13
13
  "ahooks": "^3.7.8",
14
14
  "classnames": "^2.5.1",
15
- "@fe-free/core": "4.1.5"
15
+ "lodash-es": "^4.17.21",
16
+ "@fe-free/core": "4.1.7"
16
17
  },
17
18
  "peerDependencies": {
19
+ "@ant-design/x-sdk": "^2.1.3",
18
20
  "antd": "^5.27.1",
19
21
  "dayjs": "~1.11.10",
20
22
  "i18next": "^25.7.2",
@@ -22,8 +24,8 @@
22
24
  "i18next-icu": "^2.4.1",
23
25
  "react": "^19.2.0",
24
26
  "react-i18next": "^16.4.0",
25
- "@fe-free/icons": "4.1.5",
26
- "@fe-free/tool": "4.1.5"
27
+ "@fe-free/tool": "4.1.7",
28
+ "@fe-free/icons": "4.1.7"
27
29
  },
28
30
  "scripts": {
29
31
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -0,0 +1,22 @@
1
+ import { FileViewList } from '@fe-free/ai';
2
+ import type { Meta, StoryObj } from '@storybook/react-vite';
3
+
4
+ const meta: Meta<typeof FileViewList> = {
5
+ title: '@fe-free/ai/FileViewList',
6
+ component: FileViewList,
7
+ tags: ['autodocs'],
8
+ };
9
+
10
+ type Story = StoryObj<typeof FileViewList>;
11
+
12
+ export const Default: Story = {
13
+ args: {
14
+ urls: [
15
+ 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',
16
+ 'https://minio-api-dev.pre-ai.pivotecho.cn/ai-agent/YWIW_%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20260108121456_230_1.png',
17
+ 'https://minio-api-dev.pre-ai.pivotecho.cn/ai-agent/3Uck_%E5%8D%8E%E4%BD%8FAI%E9%A2%84%E8%AE%A2%E7%AC%AC%E4%BA%8C%E8%BD%AEPOC%E8%A6%81%E6%B1%82%282%29.pdf',
18
+ ],
19
+ },
20
+ };
21
+
22
+ export default meta;
@@ -0,0 +1,41 @@
1
+ import { FileCard } from '@fe-free/core';
2
+ import { Image } from 'antd';
3
+ import './style.scss';
4
+
5
+ function isUrl(url: string) {
6
+ return url.startsWith('http') || url.startsWith('https');
7
+ }
8
+
9
+ function FileView({ url, isImage: propsIsImage }: { url: string; isImage?: boolean }) {
10
+ const isImage = propsIsImage ?? FileCard.isImage(url);
11
+
12
+ // 判断是 url 才 decodeURIComponent
13
+ const decodedUrl = isUrl(url) ? decodeURIComponent(url) : url;
14
+ const name = decodedUrl.split('/').pop() || decodedUrl;
15
+
16
+ return (
17
+ <div className="fea-file-view">
18
+ {isImage ? (
19
+ <Image width={60} height={60} src={url} />
20
+ ) : (
21
+ <div className="flex h-[60px] w-[250px] items-center rounded bg-01 px-1">
22
+ <div className="min-w-0">
23
+ <FileCard name={name} />
24
+ </div>
25
+ </div>
26
+ )}
27
+ </div>
28
+ );
29
+ }
30
+
31
+ function FileViewList({ urls }: { urls: string[] }) {
32
+ return (
33
+ <div className="flex flex-wrap gap-2">
34
+ {urls.map((url) => (
35
+ <FileView key={url} url={url} />
36
+ ))}
37
+ </div>
38
+ );
39
+ }
40
+
41
+ export { FileView, FileViewList };
@@ -0,0 +1,7 @@
1
+ .fea-file-view {
2
+ .ant-image {
3
+ .ant-image-img {
4
+ object-fit: cover;
5
+ }
6
+ }
7
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
+ export { FileView, FileViewList } from './files';
1
2
  export { MSender } from './m_sender';
2
3
  export type { MSenderProps, MSenderRef } from './m_sender';
3
4
  export { Sender } from './sender';
4
5
  export type { SenderProps, SenderRef } from './sender';
6
+ export { fetchStream } from './stream';
5
7
  export { Tip } from './tip';
6
8
  import './style.scss';
@@ -5,6 +5,7 @@ import { App, Button, Dropdown, Input, Modal, Upload } from 'antd';
5
5
  import type { RefObject } from 'react';
6
6
  import { useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
+ import { FileView } from '../files';
8
9
  import FilesIcon from '../svgs/files.svg?react';
9
10
  import type { SenderProps } from './types';
10
11
 
@@ -136,16 +137,9 @@ function UploadFileItem({ file, onDelete }: { file: UploadFile; onDelete: () =>
136
137
  return (
137
138
  <div className="group relative">
138
139
  {isImage ? (
139
- <img
140
- src={file.originFileObj && URL.createObjectURL(file.originFileObj)}
141
- className="h-[53px] w-[53px] rounded-lg border border-01 bg-01 object-cover"
142
- />
140
+ <FileView url={URL.createObjectURL(file.originFileObj!)} isImage={isImage} />
143
141
  ) : (
144
- <div className="flex h-[53px] w-[200px] items-center rounded bg-01 px-1">
145
- <div className="min-w-0">
146
- <FileCard name={file.name} size={file.size} />
147
- </div>
148
- </div>
142
+ <FileView url={file.name} />
149
143
  )}
150
144
  {!isDone && (
151
145
  <div className="absolute inset-0 flex items-center justify-center bg-01/80">
@@ -163,7 +157,7 @@ function UploadFileItem({ file, onDelete }: { file: UploadFile; onDelete: () =>
163
157
  function UrlFileItem({ url, onDelete }: { url: string; onDelete: () => void }) {
164
158
  return (
165
159
  <div className="group relative">
166
- <div className="flex h-[53px] w-[200px] items-center rounded bg-01 px-2">
160
+ <div className="flex h-[60px] w-[250px] items-center rounded bg-01 px-2">
167
161
  <div className="line-clamp-2">{url}</div>
168
162
  </div>
169
163
  <CloseOutlined
@@ -186,7 +180,7 @@ function Files(
186
180
 
187
181
  return (
188
182
  <>
189
- {fileList && fileList.length > 0 && (
183
+ {((fileList && fileList.length > 0) || (fileUrls && fileUrls.length > 0)) && (
190
184
  <div className="scrollbar-hide mb-2 flex gap-2 overflow-x-auto">
191
185
  {fileList.map((file) => (
192
186
  <UploadFileItem
@@ -0,0 +1,41 @@
1
+ import { XRequest } from '@ant-design/x-sdk';
2
+
3
+ async function fetchStream(
4
+ url: string,
5
+ {
6
+ params,
7
+ headers,
8
+ callbacks,
9
+ ...rest
10
+ }: {
11
+ params?: Record<string, any>;
12
+ headers?: Record<string, string>;
13
+ callbacks?: {
14
+ onUpdate?: ({ event, data }: { event: string; data: string }, headers: Headers) => void;
15
+ onError?: (error: Error, errorInfo?: any) => void;
16
+ };
17
+ },
18
+ ) {
19
+ await XRequest<any, { event: string; data: string }>(url, {
20
+ ...rest,
21
+ params: params,
22
+ headers: headers,
23
+ callbacks: {
24
+ onUpdate: (message, headers) => {
25
+ // 会存在 message 为 undefined 的情况
26
+ if (message) {
27
+ callbacks?.onUpdate?.(message, headers);
28
+ }
29
+ },
30
+ onSuccess: () => {
31
+ // nothing
32
+ },
33
+ onError: (error, errorInfo) => {
34
+ console.log('XRequest onError', error);
35
+ callbacks?.onError?.(error, errorInfo);
36
+ },
37
+ },
38
+ });
39
+ }
40
+
41
+ export { fetchStream };