plain-design 1.0.0-beta.160 → 1.0.0-beta.161

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.160",
3
+ "version": "1.0.0-beta.161",
4
4
  "description": "",
5
5
  "main": "dist/plain-design.min.js",
6
6
  "module": "dist/plain-design.commonjs.min.js",
@@ -136,7 +136,11 @@ export const $ai = (() => {
136
136
  done = readerDone;
137
137
  if (done) {
138
138
  console.log('Chat stream done...');
139
- onFinish?.(fullText);
139
+ let message = fullText;
140
+ if (message.slice(0, 7) === '```json' && message.slice(-3) === '```') {
141
+ message = message.slice(7, -3).trim();
142
+ }
143
+ onFinish?.(message);
140
144
  }
141
145
  if (!value?.length) {
142
146
  continue;
@@ -1,4 +1,4 @@
1
- import {designComponent, getComponentCls, PropType, reactive, useClasses, useRefs} from "@peryl/react-compose";
1
+ import {designComponent, getComponentCls, iKeyboardEvent, PropType, reactive, useClasses, 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";
@@ -27,7 +27,7 @@ export const AiChatBox = designComponent({
27
27
  /*系统提示词*/
28
28
  systemContent: { type: String },
29
29
  /*手动处理大模型返回的message*/
30
- handleMessage: { type: Function as PropType<(param: { message: string, userContent: string, chatData?: iAiChatResponse, addHistory: (history: iChatBoxHistory) => void }) => void | iChatBoxHistory | iChatBoxHistory[] | Promise<void | iChatBoxHistory | iChatBoxHistory[]>> },
30
+ handleMessage: { type: Function as PropType<iChatBoxHandleMessage> },
31
31
  handleReceive: { type: Function as PropType<(data: { fullText?: string, chunkText?: string }) => void> },
32
32
  beforeSendUserContent: { type: Function as PropType<(data: { userContent: string, messages: iAiHistory[] }) => Promise<void>> },
33
33
  handleChatStream: { type: Function as PropType<(parameter: iAiChatStreamParameter & { userContent: string }) => Promise<any>> },
@@ -67,7 +67,9 @@ export const AiChatBox = designComponent({
67
67
  },
68
68
  addHistory: async (...history: iChatBoxHistory[]) => {
69
69
  state.histories.push(...history);
70
+ history = state.histories.slice(history.length * -1);
70
71
  await methods.scrollEnd();
72
+ return history;
71
73
  },
72
74
  send: async (userContent: string) => {
73
75
  await delay(23);
@@ -79,7 +81,7 @@ export const AiChatBox = designComponent({
79
81
  await props.beforeSendUserContent?.({ userContent, messages });
80
82
  if (!!props.systemContent?.trim().length) {messages.unshift({ role: 'system', content: props.systemContent });}
81
83
  let chatBoxHistory: iChatBoxHistory | undefined = undefined;
82
- let message: string | undefined = undefined;
84
+ let message = '';
83
85
 
84
86
  const aiChatStreamParameter: iAiChatStreamParameter & { userContent: string } = {
85
87
  aiConfig,
@@ -107,7 +109,7 @@ export const AiChatBox = designComponent({
107
109
  await $ai.chatStream(aiChatStreamParameter);
108
110
  }
109
111
 
110
- if (!message) {
112
+ if (!message.length) {
111
113
  throw new Error('message is empty!');
112
114
  }
113
115
 
@@ -116,7 +118,9 @@ export const AiChatBox = designComponent({
116
118
  message,
117
119
  userContent,
118
120
  // chatData,
119
- addHistory: methods.addHistory
121
+ addHistory: methods.addHistory,
122
+ histories: state.histories,
123
+ scrollEnd: methods.scrollEnd,
120
124
  });
121
125
 
122
126
  if (newHistory != null) {
@@ -141,6 +145,10 @@ export const AiChatBox = designComponent({
141
145
  state.loading = false;
142
146
  }
143
147
  },
148
+ onEnterTextarea: (e: KeyboardEvent) => {
149
+ if (e.shiftKey) {return;}
150
+ handler.onClickSend();
151
+ },
144
152
  };
145
153
 
146
154
  return {
@@ -183,7 +191,7 @@ export const AiChatBox = designComponent({
183
191
  placeholder={props.placeholder || i18n.$it('ai.placeholder').d('请输入要发送给ai的内容如:你是谁')}
184
192
  minHeight={props.inputMinHeight}
185
193
  maxHeight={props.inputMaxHeight}
186
- onEnter={handler.onClickSend}
194
+ onEnter={handler.onEnterTextarea}
187
195
  />
188
196
  <Button shape="round" mode="fill" icon="pi-send" className="ai-chat-box-send-button" onClick={handler.onClickSend} loading={state.loading}/>
189
197
  </div>
@@ -199,3 +207,14 @@ export interface iChatBoxHistory extends iAiHistory {
199
207
  }
200
208
 
201
209
  export default AiChatBox;
210
+
211
+ export interface iChatBoxHandleMessage {
212
+ (param: {
213
+ message: string,
214
+ userContent: string,
215
+ chatData?: iAiChatResponse,
216
+ addHistory: (...history: iChatBoxHistory[]) => void,
217
+ histories: iChatBoxHistory[],
218
+ scrollEnd: () => Promise<void>,
219
+ }): void | iChatBoxHistory | iChatBoxHistory[] | Promise<void | iChatBoxHistory | iChatBoxHistory[]>;
220
+ }
@@ -5,7 +5,7 @@ import Button from "../../Button";
5
5
  import {iAutoTableAiConfig, iTableAiOperate, iTableAiOperateConfig, iTableAiOperatePlcMeta, iTableAiOperateSearch, iTableAiOperateSort} from "../utils/AutoTable.utils";
6
6
  import $configuration from "../../$configuration";
7
7
  import $dialog from "../../$dialog";
8
- import AiChatBox, {iChatBoxHistory} from "../../AiChatBox";
8
+ import AiChatBox, {iChatBoxHandleMessage, iChatBoxHistory} from "../../AiChatBox";
9
9
  import {createSimpleDate} from "../../createSimpleDate";
10
10
  import {iTableOptionSeniorFilterMeta} from "../setting/useTableOption.setting.senior.filter";
11
11
  import {iFilterFormSingleData} from "../../FilterFormSingle";
@@ -20,6 +20,7 @@ import {uuid} from "@peryl/utils/uuid";
20
20
  import {eAddressTypeEnum} from "../../$address/address.utils";
21
21
  import Alert from "../../Alert";
22
22
  import {$ai, iAiConfiguration} from "../../$ai";
23
+ import {lastItem} from "@peryl/utils/lastItem";
23
24
 
24
25
  declare module '../utils/TableOption.space' {
25
26
  namespace TableOptionSpace {
@@ -77,71 +78,14 @@ export const useTableOptionAi = AutoModule.createRegistration((option) => {
77
78
  const availableFields = await methods.getAvailableFields();
78
79
  console.log({ availableFields });
79
80
 
80
- /**
81
- * 对话提示词
82
- * @author 韦胜健
83
- * @date 2025/4/6 23:31
84
- */
85
81
  const systemContent = `
86
-
87
- 当前时间是:${createSimpleDate()["YYYY-MM-DD HH:mm:ss"]}
88
- 你是一名专业的自然语言分析师,你需要将用户对一个表格的需求描述转化为结构化的json数据;
89
-
90
- 这个json数据的结构如下 {type:"",data:""},type表示用户对表格的操作类型,data为分析出来的数据,type有四种类型:
91
- 第1个是"search",表明用户需求是搜索,也就是对数据进行筛选;
92
- 第2个是"sort",表明用户需求是排序;
93
- 第3个是"config",表明用户需求是配置表格;
94
- 第4个是"error",表明用户的需求不支持,此时data属性值为不支持的原因;
95
-
96
- 你只能返回给我这个json数据,用户只能对表格进行搜索,排序,配置表格,其他的需求一律拒绝;也就是返回 {type:"error",data:""},记住data要给出拒绝的原因;
97
- 如果用户同时存在两种及以上需求,比如同时要搜索以及排序,那么你返回的json数据应该是一个数组,比如 [{type:"search",data:""},{type:"sort",data:""}];
98
-
99
- 我会以JSON数组的方式给你表格中支持操作的字段,这个数组中每一个元素的结构为字段类型结构,结构如下所示:{title, field, filterType, width, order, fixed, hide, align},以下为结构中的每个属性说明:
100
- title:字段的标题;
101
- field:字段的唯一标识;
102
- filterType:字段的筛选类型;
103
- width:字段的宽度;
104
- order:字段的顺序;
105
- fixed:字段的冻结方式,如果是左冻结/左固定,那么值为left;如果是右冻结/右固定,那么值为right;
106
- hide:字段是否隐藏,为布尔值;
107
- align:字段的对齐方式,左对齐的话是left,居中对齐的话是center,右对齐的话是right;
108
-
109
- 表格中目前支持的字段:${JSON.stringify(availableFields)}
110
-
111
- 如果用户要配置的字段不存在,则拒绝并且给出拒绝原因;
112
-
113
- 如果用户操作为搜索或者说筛选,那么返回的结构数据中的data应该是一个对象,结构为{filters:[],filterExpression:""},
114
- 结构中的filters为数组,数组中的每个元素结构如下所示:{id,field,filterHandler,value},以下对元素结构中每个属性做解释:
115
- id: 唯一标识,需要你生成,按照 FF_1, FF_2, FF_3 的递增规则生成;
116
- field: 要搜索的字段的唯一标识;
117
- filterHandler: 搜索方式;
118
- 如果用户要求字段等于某个值,此时filterHandler为"eq";
119
- 如果用户要求字段约等于某个值,此时filterHandler为"like";
120
- 如果用户要求字段匹配多个值,当字段的filterType既不是text也不是number,那么返回的filterHandler为"in";否则filterHandler为"in_like";
121
- 如果用户要求字段不包含或者排除某些值,那么此时如果字段的filterType为(text或者number)的话filterHandler为"not_in_like",否则filterHandler为"not_in";;
122
- 如果用户要求字段值为空,则filterHandler为"is_null";
123
- 如果用户要求字段值不为空,则filterHandler为"is_not_null";
124
- 如果用户要求字段处于某个范围,比如大于或者小于某个日期,比如大于或者小于某个数字,那么此时filterHandler为"range";
125
- value: 搜索的值;
126
- 如果用户对这个字段的搜索只有一个值,那么value应该是一个字符串;
127
- 如果用户对这个字段的搜索包含多个值或者用了包含,不包含,排除之类的字眼,此时value应该是json数组;
128
- 如果用户对这个字段的要求是一个范围,比如大于某个值小于某个值等等,那么value应该是一个对象{start,end},start为开始时间或者最小值,end为结束时间或者最大值;
129
- 当字段要求是一个范围时,
130
- 如果这个字段的filterType为date,那么value为日期字符串,格式为YYYY-MM-DD;
131
- 如果这个字段的filterType为datetime,那么value为日期时间字符串,格式为YYYY-MM-DD HH:mm:ss;如果用户仅给出了日期没有给出时间,那么给一个默认的时间;如果是开始日期时间,这个时间的默认值为00:00:00;如果是结束日期时间,这个时间的默认值为23:59:59
132
-
133
- data数据中的filterExpression为表达式,如果用户的搜索条件都是"并且"关系,那么filterHandler为空字符串;如果用户的搜索条件存在"或"关系,那么需要生成这个表达式字符串,表达式中用筛选条件的id来代替表达式;
134
- 比如用户要求搜索性别为男并且状态为在职的员工,你会给我返回两条数据[{id:'FF_1',field:'gender',filterHandler:'=',value:'男'},{id:'FF_2',field:'status',filterHandler:'=',value:'在职'}],此时filterExpression为空字符串;
135
- 如果用户要求是搜索性别为男或者状态在职的员工,你除了要给我返回这两条数据之外,返回的filterExpression应该为"FF_1 or FF_2";filterExpression表达式中的筛选条件如果是并且关系用and代替,如果是或者关系用or代替,如果用户需求带有小括号,那么需要保留小括号;
136
-
137
- 如果用户操作为排序,那么返回的结构数据中的data应该是一个数组,数组中每个元素结果如下所示:{field,desc,title},以下对元素结构中每个属性做解释:
138
- field:要搜索的字段的唯一标识;
139
- desc:如果降序或者从大到小,那么值为true;如果升序或者从小到大模大,那么值为false;
140
- title: 字段的标题;
141
-
142
- 如果用户操作为配置列表字段,那么返回数据的data为数组,每一个元素为字段类型结构;比如有一个字段,其标题为"商品名称",其字段标识为"prodName",如果用户要隐藏这个字段,那么返回的字段类型结构为 {field:"prodName", hide:true}
143
-
144
- `;
82
+ 你是一名专业的自然语言分析师,需要你分析用户的内容返回结构化的数据返回给我;
83
+ 你返回的数据结构是这样的:{"search":"","sort":"","config":""}
84
+ 用户的内容中涉及到数据筛选查询相关的语句,你需要将这段语句放在结果的search属性中;
85
+ 用户的内容中涉及到排序相关的语句,你需要将这段语句放在结果的sort属性中;
86
+ 用户的内容中涉及到字段配置相关(比如字段排序、设置宽度、隐藏、字段固定冻结等等)的语句,你需要将这段语句放在结果的config属性中;
87
+ 如果用户的内容不涉及到查询/筛选、排序以及字段配置,你需要返回 {"error":""},将错误信息放在这个error属性中;
88
+ `.trim();
145
89
 
146
90
  // console.log(systemContent);
147
91
  $dialog({
@@ -171,9 +115,80 @@ export const useTableOptionAi = AutoModule.createRegistration((option) => {
171
115
  )
172
116
  });
173
117
 
174
- const handleMessage = async ({ message }: { message: string }): Promise<iChatBoxHistory | iChatBoxHistory[] | void> => {
118
+ // (计数大于500或者数字小于10)并且选项值为会员折扣
119
+ // ✓ 查询省份为上海市,按照创建时间降序,然后将更新时间左固定放在文本前面
120
+ // ✓ 查询选项值包含秒杀折扣以及会员折扣的数据
121
+ // ✓ 查询选项值包含秒杀折扣的数据
122
+ // ✓ 查询文本为yeezy或者hello的数据
123
+ const handleMessage: iChatBoxHandleMessage = async ({ message, histories, scrollEnd }) => {
175
124
  try {
176
- const operateItems: iTableAiOperate[] = toArray(JSON.parse(message));
125
+
126
+ const messageData: any = Object.entries(JSON.parse(message));
127
+ if (!!messageData.error) {return [{ id: uuid(), role: 'assistant', content: messageData.error }];}
128
+
129
+ const operateItems: iTableAiOperate[] = [];
130
+
131
+ await Promise.all(Object.entries(JSON.parse(message)).map(async ([key, val]: [string, any]) => {
132
+ if (!val?.trim().length) {
133
+ return;
134
+ }
135
+ if (key === 'search') {
136
+ histories.push({ id: uuid(), role: 'assistant', content: '' });
137
+ const history = lastItem(histories)!;
138
+ await $ai.chatStream({
139
+ messages: [
140
+ { role: 'system', content: getSearchPrompt(availableFields) },
141
+ { role: 'user', content: val }
142
+ ],
143
+ onReceiving: async ({ fullText }) => {
144
+ history.content = fullText;
145
+ await scrollEnd();
146
+ },
147
+ onFinish: (fullText) => {
148
+ history.content = fullText;
149
+ console.log('search', history.content);
150
+ operateItems.push({ type: "search", data: JSON.parse(fullText) });
151
+ },
152
+ });
153
+ } else if (key === 'sort') {
154
+ histories.push({ id: uuid(), role: 'assistant', content: '' });
155
+ const history = lastItem(histories)!;
156
+ await $ai.chatStream({
157
+ messages: [
158
+ { role: 'system', content: getSortPrompt(availableFields) },
159
+ { role: 'user', content: val }
160
+ ],
161
+ onReceiving: async ({ fullText }) => {
162
+ history.content = fullText;
163
+ await scrollEnd();
164
+ },
165
+ onFinish: (fullText) => {
166
+ history.content = fullText;
167
+ console.log('sort', history.content);
168
+ operateItems.push({ type: "sort", data: JSON.parse(fullText) });
169
+ },
170
+ });
171
+ } else if (key === 'config') {
172
+ histories.push({ id: uuid(), role: 'assistant', content: '' });
173
+ const history = lastItem(histories)!;
174
+ await $ai.chatStream({
175
+ messages: [
176
+ { role: 'system', content: getConfigPrompt(availableFields) },
177
+ { role: 'user', content: val }
178
+ ],
179
+ onReceiving: async ({ fullText }) => {
180
+ history.content = fullText;
181
+ await scrollEnd();
182
+ },
183
+ onFinish: (fullText) => {
184
+ history.content = fullText;
185
+ console.log('config', history.content);
186
+ operateItems.push({ type: "config", data: JSON.parse(fullText) });
187
+ },
188
+ });
189
+ }
190
+ }));
191
+
177
192
  if (operateItems.length == 1 && operateItems[0].type === 'error') {
178
193
  return;
179
194
  }
@@ -242,6 +257,13 @@ export const useTableOptionAi = AutoModule.createRegistration((option) => {
242
257
 
243
258
  usingFilterOption = { ...usingFilterOption };
244
259
  usingFilterOption.filterHandler = f.filterHandler;
260
+ if (usingFilterOption.filterType === 'select') {
261
+ if (usingFilterOption.filterHandler === 'in_like') {
262
+ usingFilterOption.filterHandler = 'in';
263
+ } else if (usingFilterOption.filterHandler === 'not_in_like') {
264
+ usingFilterOption.filterHandler = 'not_in';
265
+ }
266
+ }
245
267
 
246
268
  /**
247
269
  * 由于大模型返回对字段的筛选值都是显示值,某些情况下需要对这个显示值转化为实际值,才能用来进行搜索,以下做列举
@@ -305,6 +327,8 @@ export const useTableOptionAi = AutoModule.createRegistration((option) => {
305
327
  filterQueryParam,
306
328
  };
307
329
 
330
+ console.log({ id: f.id, fsd, usingFilterOption });
331
+
308
332
  return {
309
333
  id: f.id,
310
334
  data: fsd,
@@ -483,3 +507,137 @@ export const useTableOptionAi = AutoModule.createRegistration((option) => {
483
507
 
484
508
  return ret;
485
509
  });
510
+
511
+ /**
512
+ * 字段描述提示词
513
+ * @author 韦胜健
514
+ * @date 2025/5/30 23:05
515
+ */
516
+ const getFieldsPrompt = (availableFields: iTableAiOperatePlcMeta[]) => `
517
+
518
+ 当前时间是:${createSimpleDate()["YYYY-MM-DD HH:mm:ss"]}
519
+ 我会以JSON数组的方式给你表格中支持操作的字段,这个数组中每一个元素的结构为字段类型结构,结构如下所示:{title, field, filterType, width, order, fixed, hide, align},以下为结构中的每个属性说明:
520
+
521
+ - title:字段的标题;
522
+ - field:字段的唯一标识;
523
+ - filterType:字段的筛选类型;
524
+ - width:字段的宽度;
525
+ - order:字段的顺序;
526
+ - fixed:字段的冻结方式,如果是左冻结/左固定,那么值为left;如果是右冻结/右固定,那么值为right,如果是不固定/不冻结则值为center
527
+ - hide:字段是否隐藏,为布尔值;
528
+ - align:字段的对齐方式,左对齐的话是left,居中对齐的话是center,右对齐的话是right;
529
+
530
+ # 表格字段数据
531
+
532
+ ${JSON.stringify(availableFields)}
533
+ `.trim();
534
+
535
+ /**
536
+ * 搜索提示词
537
+ * @author 韦胜健
538
+ * @date 2025/5/30 23:05
539
+ */
540
+ const getSearchPrompt = (availableFields: iTableAiOperatePlcMeta[]) => `
541
+ # 角色
542
+
543
+ 你是一名专业自然语言分析专家,需要你将用户的内容转化为结构化的数据筛选参数
544
+
545
+ ${getFieldsPrompt(availableFields)}
546
+
547
+ # 返回的数据类型
548
+
549
+ - 你要返回的数据结构类型为:{"filters":[],"filterExpression":""},
550
+ - 返回数据中的filters为数组,数组中的每个元素结构如下所示:{id,field,filterHandler,value},以下对元素结构中每个属性做解释:
551
+ - id: 唯一标识,需要你生成,按照 FF_1, FF_2, FF_3 的递增规则生成;
552
+ - field: 要搜索的字段的唯一标识;
553
+ - filterHandler: 搜索方式;
554
+ - 如果用户要求字段等于某个值,此时filterHandler为"eq";
555
+ - 如果用户要求字段约等于某个值,此时filterHandler为"like";
556
+ - 如果用户要求字段匹配多个值,当字段的filterType既不是text也不是number,那么返回的filterHandler为"in";否则filterHandler为"in_like";
557
+ - 如果用户要求字段不包含或者排除某些值,那么此时如果字段的filterType为(text或者number)的话filterHandler为"not_in_like",否则filterHandler为"not_in";;
558
+ - 如果用户要求字段值为空,则filterHandler为"is_null";
559
+ - 如果用户要求字段值不为空,则filterHandler为"is_not_null";
560
+ - 如果用户要求字段处于某个范围,比如大于或者小于某个日期,比如大于或者小于某个数字,那么此时filterHandler为"range";
561
+ - value: 搜索的值;
562
+ - 如果用户对这个字段的搜索只有一个值,那么value应该是一个字符串;
563
+ - 如果用户对这个字段的搜索包含多个值或者用了包含,不包含,排除之类的字眼,此时value应该是json数组;
564
+ - 如果用户对这个字段的要求是一个范围,比如大于某个值小于某个值等等,那么value应该是一个对象{start,end},start为开始时间或者最小值,end为结束时间或者最大值;
565
+ - 当字段要求是一个范围时,
566
+ - 如果这个字段的filterType为date,那么value为日期字符串,格式为YYYY-MM-DD;
567
+ - 如果这个字段的filterType为datetime,那么value为日期时间字符串,格式为YYYY-MM-DD HH:mm:ss;如果用户仅给出了日期没有给出时间,那么给一个默认的时间;如果是开始日期时间,这个时间的默认值为00:00:00;如果是结束日期时间,这个时间的默认值为23:59:59
568
+ - 返回数据中的data数据中的filterExpression为表达式,如果用户的搜索条件都是"并且"关系,那么filterHandler为空字符串;如果用户的搜索条件存在"或"关系,那么需要生成这个表达式字符串,表达式中用筛选条件的id来代替表达式;
569
+
570
+ # 样例说明
571
+
572
+ ## 样例一
573
+
574
+ 比如用户的描述为“查询(创建时间大于2025-05-30或者更新时间小于2025-05-31)并且订单状态为待支付”,那么你分析得到的结构化查询参数为:
575
+
576
+ {
577
+ "filterExpression":"(FF_1 or FF_2) and FF_3",
578
+ "filters":[
579
+ {"id":"FF_1","field":"createdAt","filterHandler":"range",value:{start:"2025-05-30", end:""}},
580
+ {"id":"FF_2","field":"updatedAt","filterHandler":"range",value:{start:"", end:"2025-05-31"}},
581
+ {"id":"FF_1","field":"orderStatus","filterHandler":"eq",value:"unpaid"},
582
+ ]
583
+ }
584
+
585
+ ## 样例二
586
+
587
+ 比如用户的描述为“查询用户名为zhangsan或者lisi”,由于用户名字段的filterType为text,此时复合text字段匹配多个值的情况,那么分析得到的结构化查询参数为:
588
+
589
+ {
590
+ "filters":[
591
+ {"id":"FF_1","field":"username","filterHandler":"in_like","value":["zhangsan","lisi"]},
592
+ ]
593
+ }
594
+
595
+ # 注意事项
596
+
597
+ - 你一定检查用户要求中的小括号,并且在在filterExpression中保留这个小括号,如果用户提供的是中文小括号,请转化为英文小括号
598
+ - 出现错误的情况下,请返回数据 {error:""},将错误信息放在error属性中;
599
+ - 如果用户要配置的字段不存在,则拒绝并且给出拒绝原因放在错误信息中;
600
+
601
+ `;
602
+
603
+ /**
604
+ * 排序提示词
605
+ * @author 韦胜健
606
+ * @date 2025/5/30 23:05
607
+ */
608
+ const getSortPrompt = (availableFields: iTableAiOperatePlcMeta[]) => `
609
+ # 角色
610
+
611
+ 你是一名专业自然语言分析专家,需要你将用户的内容转化为结构化的数据排序参数
612
+
613
+ ${getFieldsPrompt(availableFields)}
614
+
615
+ # 返回的数据类型
616
+
617
+ 你返回的数据data应该是一个数组,数组中每个元素结果如下所示:{field,desc,title},以下对元素结构中每个属性做解释:
618
+
619
+ - field:要搜索的字段的唯一标识;
620
+ - desc:如果降序或者从大到小,那么值为true;如果升序或者从小到大模大,那么值为false;
621
+ - title: 字段的标题;
622
+
623
+ # 样例
624
+
625
+ 比如用户要求先按照创建时间降序,再按照更新时间升序,你需要返回的数据为[{"field":"createdAt","desc":true,"title":"创建时间"},{"field":"updatedAt","desc":false,"title":"更新时间"}]
626
+ `.trim();
627
+
628
+ /**
629
+ * 字段配置提示词
630
+ * @author 韦胜健
631
+ * @date 2025/5/30 23:05
632
+ */
633
+ const getConfigPrompt = (availableFields: iTableAiOperatePlcMeta[]) => `
634
+ # 角色
635
+
636
+ 你是一名专业自然语言分析专家,需要你将用户的内容转化为结构化的字段配置参数
637
+
638
+ ${getFieldsPrompt(availableFields)}
639
+
640
+ # 返回的数据类型
641
+
642
+ 你返回的数据data为数组,每一个元素为字段类型结构;比如有一个字段,其标题为"商品名称",其字段标识为"prodName",如果用户要隐藏这个字段,那么返回的字段类型结构为 {field:"prodName", hide:true}
643
+ `.trim();
@@ -136,7 +136,7 @@ export {Corner} from './components/Corner';
136
136
  export {useContextmenuOptions} from './components/useContextmenuOptions';
137
137
  export type {iContextmenuOption} from './components/useContextmenuOptions';
138
138
  export {AiChatBox} from './components/AiChatBox';
139
- export type {iChatBoxHistory} from './components/AiChatBox';
139
+ export type {iChatBoxHandleMessage, iChatBoxHistory} from './components/AiChatBox';
140
140
  export {$ai} from './components/$ai';
141
141
  export type {iAiChoice, iAiChatResponse, iAiConfiguration, iAiHistory} from './components/$ai';
142
142
  export {IconPicker} from './components/IconPicker';