st-comp 0.0.247 → 0.0.249

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.
Files changed (170) hide show
  1. package/components.d.ts +1 -0
  2. package/es/ChartLayout.js +4 -4
  3. package/es/CustomFunction.cjs +2 -2
  4. package/es/CustomFunction.js +72 -70
  5. package/es/FactorWarning.cjs +1 -1
  6. package/es/FactorWarning.js +36 -35
  7. package/es/Kline.cjs +1 -1
  8. package/es/Kline.js +20 -19
  9. package/es/KlineBasic.cjs +1 -1
  10. package/es/KlineBasic.js +30 -28
  11. package/es/KlineConfig.cjs +1 -1
  12. package/es/KlineConfig.js +50 -49
  13. package/es/KlineNew.cjs +1 -1
  14. package/es/KlineNew.js +19 -18
  15. package/es/KlinePlus.cjs +4 -4
  16. package/es/KlinePlus.js +590 -575
  17. package/es/MonacoEditor.cjs +1 -1
  18. package/es/MonacoEditor.js +28 -26
  19. package/es/Pagination.cjs +1 -1
  20. package/es/Pagination.js +77 -76
  21. package/es/PasswordPrompt.cjs +1 -1
  22. package/es/PasswordPrompt.js +3 -3
  23. package/es/Table.cjs +1 -1
  24. package/es/Table.js +38 -37
  25. package/es/User.cjs +1 -1
  26. package/es/User.js +143 -141
  27. package/es/VarSelectDialog.cjs +2 -2
  28. package/es/VarSelectDialog.js +29 -27
  29. package/es/VarietyAiHelper.cjs +4 -0
  30. package/es/VarietyAiHelper.js +270 -0
  31. package/es/VarietyAutoComplete.cjs +1 -1
  32. package/es/VarietyAutoComplete.js +13 -12
  33. package/es/VarietySearch.cjs +10 -10
  34. package/es/VarietySearch.js +70 -68
  35. package/es/{VarietySelect-2fd501da.cjs → VarietySelect-5c845562.cjs} +1 -1
  36. package/es/{VarietySelect-5a9dd50b.js → VarietySelect-9f267958.js} +4 -4
  37. package/es/VarietyTextCopy.cjs +1 -1
  38. package/es/VarietyTextCopy.js +24 -22
  39. package/es/VirtualTable.cjs +1 -1
  40. package/es/VirtualTable.js +70 -70
  41. package/es/{_initCloneObject-3823a101.cjs → _initCloneObject-2b82e9f7.cjs} +1 -1
  42. package/es/{_initCloneObject-c34c65bc.js → _initCloneObject-69c8ae23.js} +3 -3
  43. package/es/aiTools.js +36 -0
  44. package/es/{base-a5af3db3.js → base-29f73b05.js} +2 -2
  45. package/es/{castArray-7741a212.js → castArray-609a313e.js} +1 -1
  46. package/es/{config-provider-2182708a.cjs → config-provider-2ae47cc8.cjs} +1 -1
  47. package/es/{config-provider-06a63185.js → config-provider-7860903c.js} +4 -4
  48. package/es/{debounce-8d53f4dd.js → debounce-a09ce9a3.js} +1 -1
  49. package/es/{dropdown-302f71e7.js → dropdown-497442b7.js} +20 -19
  50. package/es/dropdown-eba9eaf5.cjs +1 -0
  51. package/es/{el-autocomplete-ed75a659.js → el-autocomplete-27c60cc8.js} +18 -17
  52. package/es/el-autocomplete-b59eb529.cjs +1 -0
  53. package/es/{el-button-68baab7b.cjs → el-button-974ff9e9.cjs} +1 -1
  54. package/es/{el-button-d09ff85f.js → el-button-e2c63c08.js} +4 -4
  55. package/es/el-checkbox-08185353.cjs +1 -0
  56. package/es/{el-checkbox-64648e02.js → el-checkbox-71ebd862.js} +4 -4
  57. package/es/el-dialog-1b185570.cjs +1 -0
  58. package/es/{el-dialog-6a80e3d8.js → el-dialog-eedcfd3e.js} +6 -6
  59. package/es/{el-divider-4e059794.js → el-divider-523e5874.js} +1 -1
  60. package/es/{el-empty-33cb66f1.js → el-empty-f5a1607a.js} +3 -3
  61. package/es/{el-form-item-4eca95be.js → el-form-item-bdcfd297.js} +8 -8
  62. package/es/{el-form-item-4076e55f.cjs → el-form-item-c997b4fa.cjs} +1 -1
  63. package/es/{el-input-cae60510.js → el-input-d47281da.js} +68 -68
  64. package/es/el-input-fa18ef84.cjs +1 -0
  65. package/es/el-input-number-3d94fa58.cjs +1 -0
  66. package/es/{el-input-number-c2499410.js → el-input-number-c8018cb1.js} +15 -15
  67. package/es/{el-loading-c738468d.js → el-loading-0cd81d05.js} +2 -2
  68. package/es/{el-loading-05826e64.cjs → el-loading-969a79ca.cjs} +1 -1
  69. package/es/el-menu-item-26071fd6.cjs +1 -0
  70. package/es/{el-menu-item-f904f685.js → el-menu-item-dac65bb3.js} +18 -17
  71. package/es/el-message-0ea8fbf8.cjs +1 -0
  72. package/es/el-message-4ed993c7.js +1 -0
  73. package/es/el-message-box-31e0aa98.cjs +1 -0
  74. package/es/{el-message-box-05d8cf39.js → el-message-box-fea4fca8.js} +11 -11
  75. package/es/{el-overlay-cc9bc792.js → el-overlay-1ee0338d.js} +19 -19
  76. package/es/el-overlay-ea65cb05.cjs +1 -0
  77. package/es/{el-popconfirm-a6f66a0e.js → el-popconfirm-089b8bec.js} +21 -20
  78. package/es/el-popconfirm-9e232436.cjs +1 -0
  79. package/es/el-popper-2d3914e4.cjs +1 -0
  80. package/es/el-popper-c9b3d3cf.js +1662 -0
  81. package/es/el-segmented-140ac042.cjs +1 -0
  82. package/es/{el-segmented-51b1c797.js → el-segmented-9d3a9e11.js} +4 -4
  83. package/es/el-select-a11f33e8.cjs +1 -0
  84. package/es/{el-select-1b149fab.js → el-select-e51e11c1.js} +44 -43
  85. package/es/{el-table-column-3e30ebae.js → el-table-column-05d292a8.js} +25 -24
  86. package/es/el-table-column-98570a4d.cjs +14 -0
  87. package/es/{el-tag-0a25efdf.js → el-tag-17cd04a1.js} +13 -13
  88. package/es/el-tag-6d8e653e.cjs +1 -0
  89. package/es/{el-text-73d899ff.js → el-text-2710fff3.js} +2 -2
  90. package/es/{el-text-1470de46.cjs → el-text-a18106cb.cjs} +1 -1
  91. package/es/{index-42e59bf5.js → index-0ee486ad.js} +3 -3
  92. package/es/index-0f79095c.js +440 -0
  93. package/es/{index-6806997d.js → index-1d9b50de.js} +3 -3
  94. package/es/index-28e03bad.cjs +1 -0
  95. package/es/{index-269b22da.cjs → index-299ee017.cjs} +1 -1
  96. package/es/{index-cebc7160.cjs → index-33f80550.cjs} +1 -1
  97. package/es/{index-4f48940d.cjs → index-37b8d3c6.cjs} +1 -1
  98. package/es/{index-2375023e.cjs → index-5befc414.cjs} +4 -4
  99. package/es/{index-696b6a94.cjs → index-6b99def3.cjs} +1 -1
  100. package/es/index-6ca95c8a.cjs +1 -0
  101. package/es/index-7dce9f59.cjs +1 -0
  102. package/es/{index-960806da.js → index-8391a3df.js} +3 -3
  103. package/es/{index-ac98a4d8.js → index-8f9d0d17.js} +16 -15
  104. package/es/{index-94e43e0d.js → index-95e5d454.js} +3 -3
  105. package/es/{index-4194c942.js → index-b0117ba2.js} +2 -2
  106. package/es/{index-6e967429.js → index-bcd895a0.js} +3 -3
  107. package/es/{index-87b4bf61.js → index-c2b9bbfd.js} +95 -65
  108. package/es/{index-54d289d1.js → index-c71e37dc.js} +11 -11
  109. package/es/{index-d77a7336.js → index-de24705f.js} +1 -1
  110. package/es/index-e8eeea22.cjs +1 -0
  111. package/es/{index-ee977f79.cjs → index-eb99b188.cjs} +1 -1
  112. package/es/{el-message-0df23ae7.js → index-f30561d3.js} +17 -17
  113. package/es/{python-c67c8901.cjs → python-27ece6fa.cjs} +2 -2
  114. package/es/{python-a914569a.js → python-656db04f.js} +30 -28
  115. package/es/{raf-80ef0c0a.js → raf-744cf95a.js} +1 -1
  116. package/es/{scroll-679bd6bf.js → scroll-6799bafc.js} +1 -1
  117. package/es/style.css +1 -1
  118. package/es/{use-form-common-props-47e50c10.js → use-form-common-props-cb0ca65c.js} +41 -41
  119. package/es/{use-form-common-props-344056f9.cjs → use-form-common-props-d3ed62c6.cjs} +1 -1
  120. package/es/{use-global-config-cf78ebac.cjs → use-global-config-c80f33a4.cjs} +1 -1
  121. package/es/{use-global-config-f52caea0.js → use-global-config-cdaeca54.js} +4 -4
  122. package/es/{validator-3cad04b2.cjs → validator-07160325.cjs} +1 -1
  123. package/es/{validator-94c04152.js → validator-4ab9774f.js} +1 -1
  124. package/es/{vnode-5ddb7ed1.js → vnode-a83e6de8.js} +1 -1
  125. package/es/{zh-cn-aabfaa94.cjs → zh-cn-6a0f844c.cjs} +1 -1
  126. package/es/{zh-cn-4921961d.js → zh-cn-8a6390a4.js} +2 -2
  127. package/lib/aiTools.js +36 -0
  128. package/lib/bundle.js +1 -1
  129. package/lib/bundle.umd.cjs +188 -185
  130. package/lib/{index-750ede1b.js → index-6ac0579e.js} +20224 -19939
  131. package/lib/{python-e34a2958.js → python-0432340a.js} +1 -1
  132. package/lib/style.css +1 -1
  133. package/package.json +1 -1
  134. package/packages/KlinePlus/index.vue +88 -62
  135. package/packages/VarietyAiHelper/index.ts +8 -0
  136. package/packages/VarietyAiHelper/index.vue +430 -0
  137. package/packages/index.ts +2 -0
  138. package/public/aiTools.js +36 -0
  139. package/src/App.vue +21 -0
  140. package/src/pages/KlineNew/components/KlineAction/mockApi/index.js +1 -1
  141. package/src/pages/KlineNew/components/KlineBasic/utils.js +1 -1
  142. package/src/pages/KlineNew/components/KlineSlide/utils.js +1 -1
  143. package/src/pages/KlinePlus/KlineDialog/MultiCycle.vue +312 -0
  144. package/src/pages/KlinePlus/KlineDialog/api.js +108 -0
  145. package/src/pages/KlinePlus/KlineDialog/index.vue +582 -0
  146. package/src/pages/KlinePlus/KlineDialog/indicator.js +109 -0
  147. package/src/pages/KlinePlus/KlineDialog/tools.js +86 -0
  148. package/src/pages/KlinePlus/index.vue +23 -209
  149. package/src/pages/VarietyAiHelper/index.vue +20 -0
  150. package/src/pages/VarietySearch/index.vue +75 -51
  151. package/src/router/routes.ts +5 -0
  152. package/es/dropdown-89b74bc9.cjs +0 -1
  153. package/es/el-autocomplete-b9a3054a.cjs +0 -1
  154. package/es/el-checkbox-b982e2ef.cjs +0 -1
  155. package/es/el-dialog-ad7309e9.cjs +0 -1
  156. package/es/el-input-172c49f8.cjs +0 -1
  157. package/es/el-input-number-c2e71528.cjs +0 -1
  158. package/es/el-menu-item-7f986598.cjs +0 -1
  159. package/es/el-message-a86c0efa.cjs +0 -1
  160. package/es/el-message-box-40ff2af5.cjs +0 -1
  161. package/es/el-overlay-d7a6e4a9.cjs +0 -1
  162. package/es/el-popconfirm-737a015b.cjs +0 -1
  163. package/es/el-popper-7ba87e05.cjs +0 -1
  164. package/es/el-popper-a38874f4.js +0 -2094
  165. package/es/el-segmented-3fd66a0e.cjs +0 -1
  166. package/es/el-select-12f6deb7.cjs +0 -1
  167. package/es/el-table-column-516a0ed9.cjs +0 -14
  168. package/es/el-tag-789f05d3.cjs +0 -1
  169. package/es/index-8de94a49.cjs +0 -1
  170. package/es/index-c04f444f.cjs +0 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "st-comp",
3
3
  "public": true,
4
- "version": "0.0.247",
4
+ "version": "0.0.249",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -11,7 +11,6 @@ import SliderChart from "./components/SliderChart.vue";
11
11
  const { round, formatValue } = stMath;
12
12
  const { request } = inject("stConfig"); // 组件库全局配置
13
13
 
14
- const sliderChartRef = ref();
15
14
  const loading = ref(false);
16
15
  const isHover = ref(false);
17
16
  const props = defineProps({
@@ -53,8 +52,9 @@ let isloadAllHistory = false;
53
52
  let resizeRo = null;
54
53
  let subChartIns = null;
55
54
  let mainChartIns = null;
56
- const subChartRef = ref(null);
57
55
  const mainChartRef = ref(null);
56
+ const subChartRef = ref(null);
57
+ const sliderChartRef = ref(null);
58
58
 
59
59
  // K线数据
60
60
  const klineData = ref({
@@ -112,57 +112,73 @@ const subIndicatorTips = computed(() => {
112
112
 
113
113
  // 图表: 初始化
114
114
  const initChart = () => {
115
- if (mainChartIns) return;
115
+ // 检查DOM元素是否存在
116
+ if (!mainChartRef.value) {
117
+ console.warn("[K线] 主图DOM元素不存在,取消初始化");
118
+ return false;
119
+ }
120
+ if (mainChartIns) return true;
116
121
 
117
- // 主图
118
- mainChartIns = echarts.init(mainChartRef.value);
119
- mainChartIns.on(
120
- "highlight",
121
- debounce((params) => {
122
- if (params.dataIndex) {
123
- activeIndex.value = params.dataIndex;
124
- } else {
125
- activeIndex.value = params.batch?.[0].dataIndex ?? -1;
122
+ try {
123
+ // 主图
124
+ mainChartIns = echarts.init(mainChartRef.value);
125
+ mainChartIns.on(
126
+ "highlight",
127
+ debounce((params) => {
128
+ if (params.dataIndex) {
129
+ activeIndex.value = params.dataIndex;
130
+ } else {
131
+ activeIndex.value = params.batch?.[0].dataIndex ?? -1;
132
+ }
133
+ }, 10),
134
+ );
135
+ mainChartIns.on(
136
+ "datazoom",
137
+ debounce(async () => {
138
+ const { loadCheckCount } = loadKlineConfig;
139
+ const { startValue, endValue } = mainChartIns.getOption()?.dataZoom[0] ?? {};
140
+ // 当前开始索引 < 阈值边界, 触发加载更多数据
141
+ if (isLoadHistory === false && isloadAllHistory === false && startValue < loadCheckCount) await getMoreData("history");
142
+ // 当前结束索引 > 阈值边界, 触发加载更多数据
143
+ if (isLoadNew === false && isloadAllNew === false && endValue > klineData.value.time.length - loadCheckCount) await getMoreData("new");
144
+ getScreenTimeRange();
145
+ drawScreenMaxPrice();
146
+ }),
147
+ );
148
+ mainChartIns.on("globalout", () => {
149
+ if (mainChartIns) {
150
+ const option = mainChartIns.getOption();
151
+ activeIndex.value = option.dataZoom[0].endValue;
126
152
  }
127
- }, 10)
128
- );
129
- mainChartIns.on(
130
- "datazoom",
131
- debounce(async () => {
132
- const { loadCheckCount } = loadKlineConfig;
133
- const { startValue, endValue } = mainChartIns.getOption()?.dataZoom[0] ?? {};
134
- // 当前开始索引 < 阈值边界, 触发加载更多数据
135
- if (isLoadHistory === false && isloadAllHistory === false && startValue < loadCheckCount) await getMoreData("history");
136
- // 当前结束索引 > 阈值边界, 触发加载更多数据
137
- if (isLoadNew === false && isloadAllNew === false && endValue > klineData.value.time.length - loadCheckCount) await getMoreData("new");
138
- getScreenTimeRange();
139
- drawScreenMaxPrice();
140
- })
141
- );
142
- mainChartIns.on("globalout", () => {
143
- const option = mainChartIns.getOption();
144
- activeIndex.value = option.dataZoom[0].endValue;
145
- });
146
- mainChartIns.getZr().on("contextmenu", () => {
147
- contextmenuKlineTime.value = klineData.value?.time[activeIndex.value];
148
- });
149
- window.addEventListener("keydown", handleKeyDownEvent);
153
+ });
154
+ mainChartIns.getZr().on("contextmenu", () => {
155
+ contextmenuKlineTime.value = klineData.value?.time[activeIndex.value];
156
+ });
157
+ window.addEventListener("keydown", handleKeyDownEvent);
150
158
 
151
- // 副图
152
- if (props.userKlineConfig.enable_subChart) {
153
- subChartIns = echarts.init(subChartRef.value);
154
- echarts.connect([mainChartIns, subChartIns]);
155
- }
159
+ // 副图
160
+ if (props.userKlineConfig.enable_subChart && subChartRef.value) {
161
+ subChartIns = echarts.init(subChartRef.value);
162
+ echarts.connect([mainChartIns, subChartIns]);
163
+ }
156
164
 
157
- // DOM缩放
158
- resizeRo = addResizeListener(mainChartRef.value);
159
- resizeRo.listen(() => {
160
- requestAnimationFrame(() => {
161
- mainChartIns.resize();
162
- subChartIns?.resize();
163
- sliderChartRef.value?.resize();
164
- });
165
- });
165
+ // DOM缩放
166
+ if (mainChartRef.value) {
167
+ resizeRo = addResizeListener(mainChartRef.value);
168
+ resizeRo.listen(() => {
169
+ requestAnimationFrame(() => {
170
+ mainChartIns?.resize();
171
+ subChartIns?.resize();
172
+ sliderChartRef.value?.resize();
173
+ });
174
+ });
175
+ }
176
+
177
+ return true;
178
+ } catch (error) {
179
+ console.error("[st-klinePlus]: 初始化异常:", error);
180
+ return false;
181
+ }
166
182
  };
167
183
  // 图表: 获取数据 [首屏]
168
184
  const getMainData = async ({ startTime, endTime }) => {
@@ -312,7 +328,16 @@ const getScreenTimeRange = () => {
312
328
 
313
329
  // 图表: 绘制(主流程)
314
330
  const draw = (params = { startValue: 0, endValue: 0 }) => {
315
- initChart();
331
+ const isInitialized = initChart();
332
+ // 确保图表存在
333
+ if (!isInitialized || !mainChartIns) {
334
+ return console.warn("[st-klinePlus]: 图表未准备就绪, 跳过绘制");
335
+ }
336
+ // 检查数据是否存在
337
+ if (!klineData.value.time.length) {
338
+ return console.warn("[st-klinePlus]: 图表无数据, 跳过绘制");
339
+ }
340
+
316
341
  const { maxValueSpan } = loadKlineConfig;
317
342
  const { time, data, mainIndicator } = klineData.value;
318
343
 
@@ -570,7 +595,7 @@ const draw = (params = { startValue: 0, endValue: 0 }) => {
570
595
  },
571
596
  },
572
597
  },
573
- true
598
+ true,
574
599
  );
575
600
  if (props.userKlineConfig.enable_subChart) {
576
601
  subChartIns.setOption(getSubOptions(klineData.value, startValue, endValue), true);
@@ -712,7 +737,7 @@ const drawScreenMaxPrice = () => {
712
737
  {
713
738
  notMerge: false, // 合并模式
714
739
  replaceMerge: [], // 不替换任何配置
715
- }
740
+ },
716
741
  );
717
742
  };
718
743
 
@@ -727,6 +752,7 @@ const handleSliderChange = (params) => {
727
752
  };
728
753
  // 键盘控制 [↑↓←→缩放平移]
729
754
  const handleKeyDownEvent = ({ code, ctrlKey }) => {
755
+ if (!mainChartIns) return;
730
756
  if (!(ctrlKey || isHover.value)) return;
731
757
  const { xAxis, dataZoom } = mainChartIns.getOption();
732
758
  const { data: xAxisData } = xAxis?.[0] ?? { data: [] };
@@ -801,7 +827,7 @@ watch(
801
827
  const [startTime, endTime] = props.initTimeRange;
802
828
  getMainData({ startTime, endTime });
803
829
  },
804
- { deep: true }
830
+ { deep: true },
805
831
  );
806
832
  // 监控: [周期选项] => 重加载K线 (缩放不变+校验时间间隔)
807
833
  watch(
@@ -816,7 +842,7 @@ watch(
816
842
  });
817
843
  getMainData({ startTime, endTime });
818
844
  },
819
- { deep: true }
845
+ { deep: true },
820
846
  );
821
847
  // 监控: [主指标, 副指标, 指标配置, 复权选项, 常用选项] => 重加载K线 (缩放不变)
822
848
  watch(
@@ -826,7 +852,7 @@ watch(
826
852
  const [startTime, endTime] = [klineData.value.time[startValue], klineData.value.time[endValue]];
827
853
  getMainData({ startTime, endTime });
828
854
  },
829
- { deep: true }
855
+ { deep: true },
830
856
  );
831
857
  // 监控: [成交点类型, 成交数据, 净值数据, 收益计算类型, 成交收益率数据] => 重绘K线 (缩放不变)
832
858
  watch(
@@ -835,19 +861,19 @@ watch(
835
861
  const { startValue, endValue } = mainChartIns.getOption()?.dataZoom[0] ?? {};
836
862
  draw({ startValue, endValue });
837
863
  },
838
- { deep: true }
864
+ { deep: true },
839
865
  );
840
866
  onUnmounted(() => {
841
867
  // 解绑
842
- mainChartIns.off("highlight");
843
- mainChartIns.off("globalout");
844
- mainChartIns.off("datazoom");
845
- mainChartIns.getZr().off("contextmenu");
868
+ mainChartIns?.off("highlight");
869
+ mainChartIns?.off("globalout");
870
+ mainChartIns?.off("datazoom");
871
+ mainChartIns?.getZr()?.off("contextmenu");
846
872
  window.removeEventListener("keydown", handleKeyDownEvent);
847
873
  // 销毁
848
- mainChartIns.dispose();
874
+ mainChartIns?.dispose();
849
875
  subChartIns?.dispose();
850
- resizeRo.dispose();
876
+ resizeRo?.dispose();
851
877
  resizeRo = null;
852
878
  });
853
879
  defineExpose({
@@ -0,0 +1,8 @@
1
+ import { App } from "vue";
2
+ import StVarietyAiHelper from "./index.vue";
3
+
4
+ export default {
5
+ install(app: App) {
6
+ app.component("st-varietyAiHelper", StVarietyAiHelper);
7
+ },
8
+ }
@@ -0,0 +1,430 @@
1
+ <script setup>
2
+ import dayjs from "dayjs";
3
+ import { ElMessage } from "element-plus";
4
+ import { ref, nextTick, watch } from "vue";
5
+ import { sendToBaiLianAppNonStreaming } from "../../public/aiTools";
6
+ import { UserFilled, Service, Promotion } from "@element-plus/icons-vue";
7
+
8
+ const emit = defineEmits(["callBack"]);
9
+
10
+ const visible = ref(false);
11
+ const isSending = ref(false);
12
+ const isThinking = ref(false);
13
+
14
+ const messageListRef = ref(null);
15
+ const messages = ref([
16
+ {
17
+ role: "assistant",
18
+ time: dayjs().format("HH:mm"),
19
+ content: "你好呀!我是你的品种池AI助手,会根据您的自然语言去进行品种的条件查询\n\n示例: \n帮我查找A股,总市值1000亿,流通股本大于等于1000万",
20
+ },
21
+ ]);
22
+ const inputMessage = ref("");
23
+
24
+ // 发送消息
25
+ const sendMessage = async () => {
26
+ // 校验输入内容是否为空
27
+ const content = inputMessage.value.trim();
28
+ if (!content) return ElMessage.warning("请输入消息内容");
29
+ // 校验是否正在处理消息
30
+ if (isSending.value) return;
31
+
32
+ // 记录用户消息
33
+ messages.value.push({
34
+ role: "user",
35
+ time: dayjs().format("HH:mm"),
36
+ content: content,
37
+ });
38
+ inputMessage.value = "";
39
+ await scrollToBottom();
40
+
41
+ // 发送请求至百炼应用AI
42
+ isSending.value = true;
43
+ isThinking.value = true;
44
+ let apiRes = "{}";
45
+ try {
46
+ const appId = "9e54d112acfe4531bd1fc4fee8827fef";
47
+ const apiKey = "sk-d995eb26a4334bdeb2ccb4cbfaf51de8";
48
+ apiRes = await sendToBaiLianAppNonStreaming({ appId, apiKey, value: content });
49
+ messages.value.push({
50
+ role: "assistant",
51
+ time: dayjs().format("HH:mm"),
52
+ content: apiRes,
53
+ });
54
+ await scrollToBottom();
55
+ } catch (error) {
56
+ ElMessage.error(`AI响应异常: ${error}`);
57
+ console.error("AI响应异常:", error);
58
+ } finally {
59
+ isSending.value = false;
60
+ isThinking.value = false;
61
+ }
62
+ emit("callBack", JSON.parse(apiRes));
63
+ };
64
+ // 滚动到底部
65
+ const scrollToBottom = async () => {
66
+ await nextTick();
67
+ if (messageListRef.value) {
68
+ messageListRef.value.scrollTop = messageListRef.value.scrollHeight;
69
+ }
70
+ };
71
+ watch(
72
+ () => messages.value,
73
+ () => {
74
+ scrollToBottom();
75
+ },
76
+ { deep: true },
77
+ );
78
+ defineExpose({
79
+ open: (data) => {
80
+ visible.value = true;
81
+ // 自动滚动到底部
82
+ nextTick(() => {
83
+ scrollToBottom();
84
+ });
85
+ },
86
+ });
87
+ </script>
88
+
89
+ <template>
90
+ <el-dialog
91
+ class="ai-dialog"
92
+ v-model="visible"
93
+ title="✨ 品种池参数解析AI助手"
94
+ width="500px"
95
+ center
96
+ draggable
97
+ overflow
98
+ :modal="false"
99
+ :modal-penetrable="true"
100
+ >
101
+ <div class="chat-container">
102
+ <!-- 消息列表 -->
103
+ <div
104
+ ref="messageListRef"
105
+ class="message-list"
106
+ >
107
+ <div
108
+ v-for="(message, index) in messages"
109
+ :key="index"
110
+ class="message-item"
111
+ :class="message.role"
112
+ >
113
+ <div class="avatar">
114
+ <el-avatar
115
+ :size="32"
116
+ :icon="message.role === 'user' ? UserFilled : Service"
117
+ />
118
+ </div>
119
+ <div class="message-content">
120
+ <div class="message-text">{{ message.content }}</div>
121
+ <div class="message-time">{{ message.time }}</div>
122
+ </div>
123
+ </div>
124
+
125
+ <!-- AI 思考状态 -->
126
+ <div
127
+ v-if="isThinking"
128
+ class="message-item assistant"
129
+ >
130
+ <div class="avatar">
131
+ <el-avatar
132
+ :size="32"
133
+ :icon="Service"
134
+ />
135
+ </div>
136
+ <div class="message-content">
137
+ <div class="typing-indicator">
138
+ <span></span>
139
+ <span></span>
140
+ <span></span>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ <!-- 输入区域 -->
146
+ <div class="input-area">
147
+ <el-input
148
+ class="message-input"
149
+ v-model="inputMessage"
150
+ type="textarea"
151
+ :rows="4"
152
+ :autosize="{ minRows: 2, maxRows: 4 }"
153
+ placeholder="输入您想查询的品种条件..."
154
+ @keydown.ctrl.enter="sendMessage"
155
+ />
156
+ <div class="input-actions">
157
+ <div class="input-hint">
158
+ <span>Ctrl + Enter 发送</span>
159
+ </div>
160
+ <el-button
161
+ class="send-btn"
162
+ type="primary"
163
+ :icon="Promotion"
164
+ :loading="isSending"
165
+ @click="sendMessage"
166
+ round
167
+ >
168
+ 发送
169
+ </el-button>
170
+ </div>
171
+ </div>
172
+ </div>
173
+ </el-dialog>
174
+ </template>
175
+
176
+ <style lang="scss" scoped>
177
+ .ai-dialog {
178
+ :deep(.el-dialog) {
179
+ border-radius: 24px;
180
+ background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
181
+ box-shadow: 0 20px 35px -12px rgba(0, 0, 0, 0.15);
182
+ overflow: hidden;
183
+
184
+ .el-dialog__header {
185
+ padding: 20px 24px 12px;
186
+ margin: 0;
187
+ border-bottom: 1px solid rgba(102, 126, 234, 0.1);
188
+ background: rgba(255, 255, 255, 0.8);
189
+ backdrop-filter: blur(10px);
190
+
191
+ .el-dialog__title {
192
+ font-size: 18px;
193
+ font-weight: 600;
194
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
195
+ background-clip: text;
196
+ -webkit-background-clip: text;
197
+ -webkit-text-fill-color: transparent;
198
+ }
199
+ }
200
+
201
+ .el-dialog__body {
202
+ padding: 0;
203
+ }
204
+
205
+ .el-dialog__footer {
206
+ display: none;
207
+ }
208
+ }
209
+ }
210
+ .chat-container {
211
+ display: flex;
212
+ flex-direction: column;
213
+ height: 380px;
214
+ background: transparent;
215
+ }
216
+ .message-list {
217
+ flex: 1;
218
+ overflow-y: auto;
219
+ padding: 20px 24px;
220
+ scroll-behavior: smooth;
221
+
222
+ &::-webkit-scrollbar {
223
+ width: 6px;
224
+ }
225
+
226
+ &::-webkit-scrollbar-track {
227
+ background: rgba(0, 0, 0, 0.05);
228
+ border-radius: 3px;
229
+ }
230
+
231
+ &::-webkit-scrollbar-thumb {
232
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
233
+ border-radius: 3px;
234
+
235
+ &:hover {
236
+ background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
237
+ }
238
+ }
239
+ }
240
+ .message-item {
241
+ display: flex;
242
+ margin-bottom: 20px;
243
+ animation: fadeInUp 0.3s ease-out;
244
+
245
+ &.user {
246
+ flex-direction: row-reverse;
247
+
248
+ .avatar {
249
+ margin-left: 12px;
250
+ margin-right: 0;
251
+ }
252
+
253
+ .message-content {
254
+ align-items: flex-end;
255
+
256
+ .message-text {
257
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
258
+ color: white;
259
+ border-radius: 18px 18px 4px 18px;
260
+ }
261
+
262
+ .message-time {
263
+ text-align: right;
264
+ }
265
+ }
266
+ }
267
+
268
+ &.assistant {
269
+ .avatar {
270
+ margin-right: 12px;
271
+ }
272
+
273
+ .message-content {
274
+ align-items: flex-start;
275
+
276
+ .message-text {
277
+ background: white;
278
+ color: #2c3e50;
279
+ border-radius: 18px 18px 18px 4px;
280
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
281
+ border: 1px solid rgba(102, 126, 234, 0.1);
282
+ }
283
+ }
284
+ }
285
+
286
+ .avatar {
287
+ flex-shrink: 0;
288
+
289
+ :deep(.el-avatar) {
290
+ background: linear-gradient(135deg, #f0f2ff 0%, #e8ecff 100%);
291
+ color: #667eea;
292
+
293
+ svg {
294
+ width: 18px;
295
+ height: 18px;
296
+ }
297
+ }
298
+ }
299
+
300
+ .message-content {
301
+ display: flex;
302
+ flex-direction: column;
303
+ max-width: 70%;
304
+
305
+ .message-text {
306
+ padding: 10px 16px;
307
+ font-size: 14px;
308
+ line-height: 1.5;
309
+ word-wrap: break-word;
310
+ white-space: pre-wrap;
311
+ }
312
+
313
+ .message-time {
314
+ font-size: 11px;
315
+ color: #9ca3af;
316
+ margin-top: 6px;
317
+ padding: 0 4px;
318
+ }
319
+ }
320
+ }
321
+ .typing-indicator {
322
+ display: flex;
323
+ gap: 4px;
324
+ padding: 10px 16px;
325
+ background: white;
326
+ border-radius: 18px;
327
+ border: 1px solid rgba(102, 126, 234, 0.1);
328
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
329
+
330
+ span {
331
+ width: 6px;
332
+ height: 6px;
333
+ border-radius: 50%;
334
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
335
+ animation: typing 1.4s infinite ease-in-out;
336
+
337
+ &:nth-child(1) {
338
+ animation-delay: -0.32s;
339
+ }
340
+
341
+ &:nth-child(2) {
342
+ animation-delay: -0.16s;
343
+ }
344
+ }
345
+ }
346
+ .input-area {
347
+ padding: 16px 24px 24px;
348
+ border-top: 1px solid rgba(102, 126, 234, 0.1);
349
+ background: rgba(255, 255, 255, 0.9);
350
+ backdrop-filter: blur(10px);
351
+
352
+ .message-input {
353
+ :deep(.el-textarea__inner) {
354
+ border-radius: 16px;
355
+ border: 1px solid rgba(102, 126, 234, 0.2);
356
+ background: #ffffff;
357
+ font-size: 14px;
358
+ padding: 12px 16px;
359
+ transition: all 0.3s ease;
360
+
361
+ &:focus {
362
+ border-color: #667eea;
363
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
364
+ }
365
+
366
+ &::placeholder {
367
+ color: #cbd5e0;
368
+ }
369
+ }
370
+ }
371
+
372
+ .input-actions {
373
+ display: flex;
374
+ justify-content: space-between;
375
+ align-items: center;
376
+ margin-top: 12px;
377
+
378
+ .input-hint {
379
+ font-size: 12px;
380
+ color: #9ca3af;
381
+
382
+ span {
383
+ background: rgba(102, 126, 234, 0.1);
384
+ padding: 4px 8px;
385
+ border-radius: 12px;
386
+ font-size: 11px;
387
+ }
388
+ }
389
+
390
+ .send-btn {
391
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
392
+ border: none;
393
+ padding: 8px 20px;
394
+ font-weight: 500;
395
+ transition: all 0.3s ease;
396
+
397
+ &:hover {
398
+ transform: translateY(-2px);
399
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
400
+ }
401
+
402
+ &:active {
403
+ transform: translateY(0);
404
+ }
405
+ }
406
+ }
407
+ }
408
+ @keyframes fadeInUp {
409
+ from {
410
+ opacity: 0;
411
+ transform: translateY(10px);
412
+ }
413
+ to {
414
+ opacity: 1;
415
+ transform: translateY(0);
416
+ }
417
+ }
418
+ @keyframes typing {
419
+ 0%,
420
+ 60%,
421
+ 100% {
422
+ transform: translateY(0);
423
+ opacity: 0.4;
424
+ }
425
+ 30% {
426
+ transform: translateY(-8px);
427
+ opacity: 1;
428
+ }
429
+ }
430
+ </style>
package/packages/index.ts CHANGED
@@ -19,6 +19,7 @@ import StPie from "./Pie/index.ts"
19
19
  import StTable from "./Table/index.ts"
20
20
  import StTreeMap from "./TreeMap/index.ts"
21
21
  import StUser from "./User/index.ts"
22
+ import StVarietyAiHelper from "./VarietyAiHelper/index.ts"
22
23
  import StVarietyAutoComplete from "./VarietyAutoComplete/index.ts"
23
24
  import StVarietySearch from "./VarietySearch/index.ts"
24
25
  import StVarietyTextCopy from "./VarietyTextCopy/index.ts"
@@ -47,6 +48,7 @@ export default {
47
48
  StTable.install(app)
48
49
  StTreeMap.install(app)
49
50
  StUser.install(app)
51
+ StVarietyAiHelper.install(app)
50
52
  StVarietyAutoComplete.install(app)
51
53
  StVarietySearch.install(app)
52
54
  StVarietyTextCopy.install(app)