@alicloud/appflow-chat 0.0.4-beta.2 → 0.0.4-beta.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alicloud/appflow-chat",
3
- "version": "0.0.4-beta.2",
3
+ "version": "0.0.4-beta.4",
4
4
  "description": "Appflow-Chat AI聊天机器人组件库,提供聊天服务和UI组件",
5
5
  "type": "module",
6
6
  "main": "./dist/appflow-chat.cjs.js",
@@ -1,40 +1,72 @@
1
- import React, { useCallback, useMemo, useEffect, useState } from 'react';
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
2
  import { DatePicker, version } from 'antd';
3
3
  import { TimeFieldProps, TimeSubType } from './types';
4
4
  import styled from 'styled-components';
5
5
 
6
- // ==================== Styled Components ====================
7
-
8
- // 时间选择器容器
9
6
  const TimeFieldContainer = styled.div`
10
7
  width: 100%;
11
-
12
8
  .ant-picker {
13
9
  width: 100%;
14
10
  }
15
11
  `;
16
12
 
17
- // ==================== 版本检测 ====================
18
-
19
- /**
20
- * 检测 antd 版本是否为 5.x 或更高
21
- * antd 5.x 使用 dayjs,antd 4.x 使用 moment
22
- */
23
13
  const getAntdMajorVersion = (): number => {
24
14
  try {
25
15
  return parseInt(version.split('.')[0], 10);
26
16
  } catch {
27
- return 5; // 默认假设为 5.x
17
+ return 5;
28
18
  }
29
19
  };
30
20
 
31
21
  const isAntd5OrAbove = getAntdMajorVersion() >= 5;
32
22
 
33
- // ==================== 工具函数 ====================
23
+ // 兼容 ESM 和 CJS 环境的时间库加载
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ let timeLib: any = null;
26
+
27
+ // 同步尝试加载时间库(CJS 环境下可用)
28
+ const loadTimeLibSync = (): any => {
29
+ if (timeLib) return timeLib;
30
+
31
+ if (isAntd5OrAbove) {
32
+ try {
33
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
34
+ timeLib = require('dayjs');
35
+ } catch {
36
+ // require 在 ESM 环境中可能失败,后续通过异步 import 兜底
37
+ }
38
+ } else {
39
+ try {
40
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
41
+ timeLib = require('moment');
42
+ } catch {
43
+ // require 在 ESM 环境中可能失败,后续通过异步 import 兜底
44
+ }
45
+ }
46
+ return timeLib;
47
+ };
48
+
49
+ // 异步加载时间库(ESM 环境下的兜底方案)
50
+ const loadTimeLibAsync = async (): Promise<any> => {
51
+ if (timeLib) return timeLib;
52
+
53
+ try {
54
+ if (isAntd5OrAbove) {
55
+ const dayjs = await import('dayjs');
56
+ timeLib = dayjs.default || dayjs;
57
+ } else {
58
+ const moment = await import('moment');
59
+ timeLib = moment.default || moment;
60
+ }
61
+ } catch {
62
+ console.warn('Failed to load time library (both sync and async)');
63
+ }
64
+ return timeLib;
65
+ };
66
+
67
+ // 先尝试同步加载
68
+ loadTimeLibSync();
34
69
 
35
- /**
36
- * 根据时间子类型获取日期格式
37
- */
38
70
  const getDateFormat = (subType?: TimeSubType): string => {
39
71
  switch (subType) {
40
72
  case 'year-month':
@@ -48,76 +80,40 @@ const getDateFormat = (subType?: TimeSubType): string => {
48
80
  }
49
81
  };
50
82
 
51
- /**
52
- * 根据时间子类型获取 picker 类型
53
- */
54
83
  const getPickerType = (subType?: TimeSubType): 'date' | 'month' | undefined => {
55
84
  switch (subType) {
56
85
  case 'year-month':
57
86
  return 'month';
58
- case 'year-month-day':
59
- case 'datetime':
60
87
  default:
61
88
  return 'date';
62
89
  }
63
90
  };
64
91
 
65
- // ==================== 时间库加载器 ====================
66
-
67
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
- type TimeLibrary = any;
69
-
70
- /**
71
- * 异步加载时间库
72
- * antd 5.x 使用 dayjs,antd 4.x 使用 moment
73
- */
74
- const loadTimeLibrary = async (): Promise<TimeLibrary | null> => {
75
- if (isAntd5OrAbove) {
76
- try {
77
- const dayjs = await import('dayjs');
78
- return dayjs.default || dayjs;
79
- } catch {
80
- console.warn('dayjs not found, TimeField may not work correctly with antd 5.x');
81
- return null;
82
- }
83
- } else {
84
- try {
85
- const moment = await import('moment');
86
- return moment.default || moment;
87
- } catch {
88
- console.warn('moment not found, TimeField may not work correctly with antd 4.x');
89
- return null;
90
- }
91
- }
92
- };
93
-
94
- /**
95
- * 时间字段组件
96
- * 根据 SubType 渲染不同的时间选择器
97
- * 优先从 AssociationPropertyMetadata.SubType 读取,兼容旧的 TimeSubType 字段
98
- *
99
- * 兼容性说明:
100
- * - antd 5.x: 使用 dayjs
101
- * - antd 4.x: 使用 moment
102
- */
103
92
  export const TimeField: React.FC<TimeFieldProps> = ({
104
93
  schema,
105
94
  value,
106
95
  onChange,
107
96
  disabled = false,
108
97
  }) => {
109
- // 时间库状态
110
- const [timeLib, setTimeLib] = useState<TimeLibrary | null>(null);
98
+ // 使用 state 管理时间库引用,确保异步加载完成后能触发重新渲染
99
+ const [lib, setLib] = useState<any>(() => timeLib);
111
100
 
112
- // 异步加载时间库
101
+ // 如果同步加载失败,通过异步 import 兜底加载
113
102
  useEffect(() => {
114
- loadTimeLibrary().then(lib => {
115
- setTimeLib(lib);
103
+ if (lib) return;
104
+
105
+ let cancelled = false;
106
+ loadTimeLibAsync().then((loaded) => {
107
+ if (!cancelled && loaded) {
108
+ setLib(loaded);
109
+ }
116
110
  });
117
- }, []);
118
111
 
119
- // 优先从 AssociationPropertyMetadata.SubType 读取,取数组第一个元素
120
- // 兼容旧的 TimeSubType 字段
112
+ return () => {
113
+ cancelled = true;
114
+ };
115
+ }, [lib]);
116
+
121
117
  const subType = useMemo((): TimeSubType | undefined => {
122
118
  const subTypeArray = schema.AssociationPropertyMetadata?.SubType;
123
119
  if (Array.isArray(subTypeArray) && subTypeArray.length > 0) {
@@ -132,27 +128,22 @@ export const TimeField: React.FC<TimeFieldProps> = ({
132
128
 
133
129
  // 将字符串值转换为时间对象
134
130
  const dateValue = useMemo(() => {
135
- if (!value || !timeLib) return null;
131
+ if (!value || !lib) return null;
136
132
 
137
133
  try {
138
- const parsed = timeLib(value, format);
139
- // 检查解析是否有效
134
+ const parsed = lib(value, format);
140
135
  if (parsed && typeof parsed.isValid === 'function' && !parsed.isValid()) {
141
- return null;
136
+ // 如果严格解析失败,尝试宽松解析
137
+ return lib(value);
142
138
  }
143
139
  return parsed;
144
140
  } catch {
145
141
  return null;
146
142
  }
147
- }, [value, format, timeLib]);
143
+ }, [value, format, lib]);
148
144
 
149
- // 处理值变化
150
- // antd DatePicker onChange 签名: (date: Moment | Dayjs | null, dateString: string) => void
151
145
  const handleChange = useCallback(
152
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
153
146
  (_date: any, dateString: string | string[]) => {
154
- // 直接使用 antd 提供的 dateString,这是已经格式化好的字符串
155
- // 这样可以避免手动调用 format 方法,更加可靠
156
147
  const stringValue = Array.isArray(dateString) ? dateString[0] : dateString;
157
148
  onChange?.(stringValue || null);
158
149
  },
@@ -169,10 +160,10 @@ export const TimeField: React.FC<TimeFieldProps> = ({
169
160
  showTime={showTime ? { format: 'HH:mm:ss' } : false}
170
161
  disabled={disabled}
171
162
  style={{ width: '100%' }}
172
- placeholder={`请选择`}
163
+ placeholder="请选择"
173
164
  />
174
165
  </TimeFieldContainer>
175
166
  );
176
167
  };
177
168
 
178
- export default TimeField;
169
+ export default TimeField;