plain-design 1.0.0-beta.162 → 1.0.0-beta.163

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": "plain-design",
3
- "version": "1.0.0-beta.162",
3
+ "version": "1.0.0-beta.163",
4
4
  "description": "",
5
5
  "main": "dist/plain-design.min.js",
6
6
  "module": "dist/plain-design.commonjs.min.js",
@@ -10,6 +10,7 @@ import {uuid} from "@peryl/utils/uuid";
10
10
  import {PlainObject} from "@peryl/utils/event";
11
11
  import {defer} from "@peryl/utils/defer";
12
12
  import {toArray} from "@peryl/utils/toArray";
13
+ import {iEffects} from "@peryl/utils/createEffects";
13
14
 
14
15
  export const $ai = (() => {
15
16
 
@@ -100,9 +101,13 @@ export const $ai = (() => {
100
101
  onThinking,
101
102
  onThinkEnd,
102
103
  onThinkStart,
104
+ abortEffects,
103
105
  }: iAiChatStreamParameter
104
106
  ) => {
105
107
  const aiConfig = _aiConfig ?? getConfig();
108
+
109
+ const controller = new AbortController();
110
+ !!abortEffects && abortEffects.push(() => {controller.abort('abort stream.');});
106
111
  // 发送请求
107
112
  const response = await fetch(aiConfig.url, {
108
113
  method: 'POST',
@@ -115,7 +120,8 @@ export const $ai = (() => {
115
120
  "messages": messages,
116
121
  // "messages": [{ role: 'user', content: '你好' }],
117
122
  stream: true // 请求流式响应
118
- })
123
+ }),
124
+ signal: controller.signal,
119
125
  });
120
126
 
121
127
  if (!response.ok || !response.body) {throw response;}
@@ -357,4 +363,5 @@ export interface iAiChatStreamParameter {
357
363
  onThinking?: (thinkText: string) => void,
358
364
  onThinkStart?: () => void,
359
365
  onThinkEnd?: () => void,
366
+ abortEffects?: iEffects,
360
367
  }
@@ -1,4 +1,4 @@
1
- import {designComponent, getComponentCls, iKeyboardEvent, PropType, reactive, useClasses, useRefs} from "@peryl/react-compose";
1
+ import {designComponent, getComponentCls, iKeyboardEvent, PropType, reactive, useClasses, useModel, useRefs} from "@peryl/react-compose";
2
2
  import Input from "../Input";
3
3
  import {EditProps, useEdit} from "../../uses/useEdit";
4
4
  import {StyleProps, useStyle} from "../../uses/useStyle";
@@ -13,6 +13,7 @@ import Scroll from "../Scroll";
13
13
  import {delay} from "@peryl/utils/delay";
14
14
  import {toArray} from "@peryl/utils/toArray";
15
15
  import {lastItem} from "@peryl/utils/lastItem";
16
+ import {createEffects} from "@peryl/utils/createEffects";
16
17
 
17
18
  export const AiChatBox = designComponent({
18
19
  props: {
@@ -26,6 +27,8 @@ export const AiChatBox = designComponent({
26
27
  histories: { type: Array as PropType<iChatBoxHistory[]> },
27
28
  /*系统提示词*/
28
29
  systemContent: { type: String },
30
+ /*用户输入的内容*/
31
+ modelValue: { type: String },
29
32
  /*手动处理大模型返回的message*/
30
33
  handleMessage: { type: Function as PropType<iChatBoxHandleMessage> },
31
34
  handleReceive: { type: Function as PropType<(data: { fullText?: string, chunkText?: string }) => void> },
@@ -33,9 +36,16 @@ export const AiChatBox = designComponent({
33
36
  handleChatStream: { type: Function as PropType<(parameter: iAiChatStreamParameter & { userContent: string }) => Promise<any>> },
34
37
  inputMinHeight: { type: String, default: '80px' },
35
38
  inputMaxHeight: { type: String, default: '225px' },
39
+ enableMemory: { type: Boolean },
40
+ memoryLimit: { type: Number, default: 15 },
36
41
  },
37
42
  slots: ['prepend'],
38
- setup({ props, slots }) {
43
+ emits: {
44
+ onUpdateModelValue: (val?: string) => true,
45
+ },
46
+ setup({ props, slots, event: { emit } }) {
47
+
48
+ const model = useModel(() => props.modelValue, emit.onUpdateModelValue);
39
49
 
40
50
  const { refs, onRef } = useRefs({ scroll: Scroll });
41
51
 
@@ -53,11 +63,12 @@ export const AiChatBox = designComponent({
53
63
  ]);
54
64
 
55
65
  const state = reactive({
56
- userContent: '',
57
66
  histories: props.histories || [] as iChatBoxHistory[],
58
67
  loading: false
59
68
  });
60
69
 
70
+ const { effects: abortEffects } = createEffects();
71
+
61
72
  const methods = {
62
73
  scrollEnd: async () => {
63
74
  if (!!refs.scroll) {
@@ -73,11 +84,16 @@ export const AiChatBox = designComponent({
73
84
  },
74
85
  send: async (userContent: string) => {
75
86
  await delay(23);
76
- state.userContent = '';
77
- await methods.addHistory({ role: 'user', content: userContent, id: uuid() });
87
+ model.value = '';
88
+ const newUserHistory: iChatBoxHistory = { role: 'user', content: userContent, id: uuid() };
89
+ await methods.addHistory(newUserHistory);
78
90
 
79
91
  /*const { message, chatData } = await $ai.chatSystem(userContent, props.systemContent, aiConfig);*/
80
- const messages: iAiHistory[] = [{ role: 'user', content: userContent }];
92
+ let messages: iAiHistory[] = props.enableMemory ? state.histories : (() => {
93
+ const { role, content } = newUserHistory;
94
+ return [{ role, content }];
95
+ })();
96
+ messages = messages.slice(props.memoryLimit * -1);
81
97
  await props.beforeSendUserContent?.({ userContent, messages });
82
98
  if (!!props.systemContent?.trim().length) {messages.unshift({ role: 'system', content: props.systemContent });}
83
99
  let chatBoxHistory: iChatBoxHistory | undefined = undefined;
@@ -87,6 +103,7 @@ export const AiChatBox = designComponent({
87
103
  aiConfig,
88
104
  messages,
89
105
  userContent,
106
+ abortEffects,
90
107
  onReceiving: ({ fullText, chunkText }) => {
91
108
  // console.log('receiving', fullText);
92
109
  props.handleReceive?.({ fullText, chunkText });
@@ -133,9 +150,18 @@ export const AiChatBox = designComponent({
133
150
 
134
151
  const handler = {
135
152
  onClickSend: async () => {
153
+ if (state.loading) {
154
+ console.log('abort');
155
+ abortEffects.clear();
156
+ return;
157
+ }
158
+
159
+ console.log('send');
160
+ abortEffects.clear();
161
+ abortEffects.push(() => state.loading = false);
136
162
  state.loading = true;
137
163
  try {
138
- const userContent = state.userContent;
164
+ const userContent = model.value;
139
165
  if (!userContent?.trim().length) {
140
166
  $message.error(i18n.$it('ai.require').d('提问的内容不能为空'));
141
167
  return;
@@ -187,13 +213,13 @@ export const AiChatBox = designComponent({
187
213
  <Input
188
214
  readonly={state.loading}
189
215
  textarea
190
- v-model={state.userContent}
216
+ v-model={model.value}
191
217
  placeholder={props.placeholder || i18n.$it('ai.placeholder').d('请输入要发送给ai的内容如:你是谁')}
192
218
  minHeight={props.inputMinHeight}
193
219
  maxHeight={props.inputMaxHeight}
194
220
  onEnter={handler.onEnterTextarea}
195
221
  />
196
- <Button shape="round" mode="fill" icon="pi-send" className="ai-chat-box-send-button" onClick={handler.onClickSend} loading={state.loading}/>
222
+ <Button shape="round" mode="fill" icon={state.loading ? 'ie-stop' : 'ie-send'} className="ai-chat-box-send-button" onClick={handler.onClickSend}/>
197
223
  </div>
198
224
  </div>
199
225
  )
@@ -103,5 +103,15 @@ export const IconExternal: Record<string, () => RenderNode> = {
103
103
  <path
104
104
  d="M15.5355 2.80744C17.0976 1.24534 19.6303 1.24534 21.1924 2.80744C22.7545 4.36953 22.7545 6.90219 21.1924 8.46429L18.3638 11.2929L18.7175 11.6466C19.108 12.0371 19.108 12.6703 18.7175 13.0608C18.327 13.4513 17.6938 13.4513 17.3033 13.0608L16.9498 12.7073L10.7351 18.922C10.1767 19.4804 9.46547 19.861 8.6911 20.0159L6.93694 20.3667C6.54976 20.4442 6.19416 20.6345 5.91496 20.9137L4.92894 21.8997C4.53841 22.2902 3.90525 22.2902 3.51472 21.8997L2.10051 20.4855C1.70999 20.095 1.70999 19.4618 2.10051 19.0713L3.08653 18.0852C3.36574 17.806 3.55605 17.4504 3.63348 17.0633L3.98431 15.3091C4.13919 14.5347 4.51981 13.8235 5.07821 13.2651L11.2929 7.05045L10.9393 6.69686C10.5488 6.30634 10.5488 5.67317 10.9393 5.28265C11.3299 4.89212 11.963 4.89212 12.3535 5.28265L12.7069 5.63604L15.5355 2.80744ZM12.7071 8.46466L6.49242 14.6794C6.21322 14.9586 6.02291 15.3142 5.94548 15.7013L5.59464 17.4555C5.43977 18.2299 5.05915 18.9411 4.50075 19.4995C5.05915 18.9411 5.77035 18.5604 6.54471 18.4056L8.29887 18.0547C8.68605 17.9773 9.04165 17.787 9.32085 17.5078L15.5355 11.2931L12.7071 8.46466Z"></path>
105
105
  </svg>
106
+ ),
107
+ 'ie-send': () => (
108
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
109
+ <path d="M1.94607 9.31543C1.42353 9.14125 1.4194 8.86022 1.95682 8.68108L21.043 2.31901C21.5715 2.14285 21.8746 2.43866 21.7265 2.95694L16.2733 22.0432C16.1223 22.5716 15.8177 22.59 15.5944 22.0876L11.9999 14L17.9999 6.00005L9.99992 12L1.94607 9.31543Z"></path>
110
+ </svg>
111
+ ),
112
+ 'ie-stop': () => (
113
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
114
+ <path d="M6 5H18C18.5523 5 19 5.44772 19 6V18C19 18.5523 18.5523 19 18 19H6C5.44772 19 5 18.5523 5 18V6C5 5.44772 5.44772 5 6 5Z"></path>
115
+ </svg>
106
116
  )
107
117
  };