st-comp 0.0.277 → 0.0.279

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 (319) hide show
  1. package/README.md +19 -19
  2. package/es/ChartLayout.cjs +1 -1
  3. package/es/ChartLayout.js +1 -1
  4. package/es/ConfigProvider.cjs +1 -1
  5. package/es/ConfigProvider.js +3 -3
  6. package/es/Contextmenu.cjs +1 -1
  7. package/es/Contextmenu.js +7 -7
  8. package/es/CustomFunction.cjs +2 -2
  9. package/es/CustomFunction.js +514 -308
  10. package/es/FactorWarning.cjs +1 -1
  11. package/es/FactorWarning.js +37 -37
  12. package/es/HeatMap.cjs +1 -1
  13. package/es/HeatMap.js +7 -7
  14. package/es/Kline.cjs +1 -1
  15. package/es/Kline.js +18 -18
  16. package/es/KlineBasic.cjs +1 -1
  17. package/es/KlineBasic.js +93 -93
  18. package/es/KlineConfig.cjs +1 -1
  19. package/es/KlineConfig.js +17 -17
  20. package/es/KlineNew.cjs +1 -1
  21. package/es/KlineNew.js +14 -14
  22. package/es/KlinePlus.cjs +4 -4
  23. package/es/KlinePlus.js +760 -656
  24. package/es/LinearLegend.cjs +1 -1
  25. package/es/LinearLegend.js +1 -1
  26. package/es/Map.cjs +1 -1
  27. package/es/Map.js +1 -1
  28. package/es/MonacoEditor.cjs +1 -1
  29. package/es/MonacoEditor.js +18 -18
  30. package/es/Pagination.cjs +1 -1
  31. package/es/Pagination.js +76 -76
  32. package/es/PasswordPrompt.cjs +1 -1
  33. package/es/PasswordPrompt.js +2 -2
  34. package/es/Pie.cjs +2 -2
  35. package/es/Pie.js +14 -14
  36. package/es/Table.cjs +1 -1
  37. package/es/Table.js +22 -22
  38. package/es/TreeMap.cjs +1 -1
  39. package/es/TreeMap.js +4 -4
  40. package/es/User.cjs +1 -1
  41. package/es/User.js +73 -73
  42. package/es/VarSelectDialog.cjs +2 -2
  43. package/es/VarSelectDialog.js +21 -21
  44. package/es/VarietyAiHelper.cjs +4 -4
  45. package/es/VarietyAiHelper.js +139 -138
  46. package/es/VarietyAutoComplete.cjs +1 -1
  47. package/es/VarietyAutoComplete.js +16 -16
  48. package/es/VarietySearch.cjs +4 -4
  49. package/es/VarietySearch.js +861 -857
  50. package/es/{VarietySelect-6a166293.js → VarietySelect-41daac7b.js} +10 -10
  51. package/es/{VarietySelect-610903f0.cjs → VarietySelect-d58eee29.cjs} +1 -1
  52. package/es/VarietyTextCopy.cjs +2 -2
  53. package/es/VarietyTextCopy.js +25 -25
  54. package/es/VirtualTable.cjs +1 -1
  55. package/es/VirtualTable.js +6 -6
  56. package/es/{_initCloneObject-152b4f4e.js → _initCloneObject-5e73c9c8.js} +2 -2
  57. package/es/{_initCloneObject-76e116d0.cjs → _initCloneObject-a5832933.cjs} +1 -1
  58. package/es/aiTools-229609fb.cjs +2 -0
  59. package/es/aiTools-ce2f9281.js +115 -0
  60. package/es/aiTools.js +179 -176
  61. package/es/{config-provider-4c784baf.cjs → config-provider-06ea6b42.cjs} +1 -1
  62. package/es/{config-provider-7a3aca55.js → config-provider-88b637a8.js} +3 -3
  63. package/es/{dropdown-987c47fb.cjs → dropdown-4ce4c3e2.cjs} +1 -1
  64. package/es/{dropdown-01e09205.js → dropdown-72fbc15d.js} +2 -2
  65. package/es/{el-autocomplete-342ae823.js → el-autocomplete-6cafcdf1.js} +5 -5
  66. package/es/{el-autocomplete-16f66b34.cjs → el-autocomplete-e0857c5b.cjs} +1 -1
  67. package/es/{el-button-13dc915f.cjs → el-button-613e0bb2.cjs} +1 -1
  68. package/es/{el-button-314171a0.js → el-button-94d3de38.js} +3 -3
  69. package/es/{el-checkbox-5899681f.js → el-checkbox-6d4cb393.js} +3 -3
  70. package/es/{el-checkbox-bdf64663.cjs → el-checkbox-e90762df.cjs} +1 -1
  71. package/es/{el-dialog-0ef95df6.cjs → el-dialog-02942e22.cjs} +1 -1
  72. package/es/{el-dialog-86a3eec2.js → el-dialog-5e30161f.js} +4 -4
  73. package/es/{el-form-item-77ef6784.cjs → el-form-item-44f060d8.cjs} +1 -1
  74. package/es/{el-form-item-cda4d93c.js → el-form-item-9e8969ea.js} +5 -5
  75. package/es/{el-input-fa1445ad.js → el-input-342b2def.js} +13 -13
  76. package/es/{el-input-89222943.cjs → el-input-9a9a7f7f.cjs} +1 -1
  77. package/es/{el-input-number-d3338e5e.cjs → el-input-number-65c847d6.cjs} +1 -1
  78. package/es/{el-input-number-8f6dbf74.js → el-input-number-c22b803a.js} +35 -35
  79. package/es/{el-loading-84dde1a8.cjs → el-loading-8179b497.cjs} +1 -1
  80. package/es/{el-loading-9b671203.js → el-loading-bcc51e3d.js} +1 -1
  81. package/es/{el-menu-item-535fef90.js → el-menu-item-339baf6d.js} +21 -21
  82. package/es/{el-menu-item-4531fd0e.cjs → el-menu-item-83186444.cjs} +1 -1
  83. package/es/{el-message-box-621ed2f1.js → el-message-box-035b699c.js} +9 -9
  84. package/es/{el-message-box-f5717070.cjs → el-message-box-c62d3217.cjs} +1 -1
  85. package/es/{el-overlay-23de4324.js → el-overlay-3e17604b.js} +3 -3
  86. package/es/{el-overlay-151708cb.cjs → el-overlay-8f1da9e8.cjs} +1 -1
  87. package/es/{el-popconfirm-b8aa490e.cjs → el-popconfirm-4e32ec1b.cjs} +1 -1
  88. package/es/{el-popconfirm-bcff0aa5.js → el-popconfirm-f8a86e2c.js} +4 -4
  89. package/es/{el-popper-43ec37f4.cjs → el-popper-a4f3ae4d.cjs} +1 -1
  90. package/es/{el-popper-03988662.js → el-popper-fbd0dcea.js} +1 -1
  91. package/es/{el-segmented-db3a86be.js → el-segmented-56bd58a8.js} +2 -2
  92. package/es/{el-segmented-79a1367c.cjs → el-segmented-833ac177.cjs} +1 -1
  93. package/es/{el-select-4bd0010d.js → el-select-44fa547d.js} +8 -8
  94. package/es/{el-select-ec04e7ce.cjs → el-select-70806166.cjs} +1 -1
  95. package/es/{el-table-column-35e47229.cjs → el-table-column-3e2cdfca.cjs} +1 -1
  96. package/es/{el-table-column-7af2bec7.js → el-table-column-b74a857d.js} +9 -9
  97. package/es/{el-tag-bef9e83d.js → el-tag-66c83156.js} +2 -2
  98. package/es/{el-tag-5d5608e0.cjs → el-tag-9c2f329f.cjs} +1 -1
  99. package/es/{el-text-f998902c.js → el-text-034bd3f4.js} +1 -1
  100. package/es/{el-text-abf10fdf.cjs → el-text-6b2374bb.cjs} +1 -1
  101. package/es/index-00f6ca75.cjs +1 -0
  102. package/es/{index-a00e0534.cjs → index-185792a7.cjs} +1 -1
  103. package/es/{index-d1b554ac.js → index-1e2a38ab.js} +2 -2
  104. package/es/{index-0986e373.cjs → index-3153c1db.cjs} +1 -1
  105. package/es/{index-936e7dec.js → index-44a382a5.js} +2 -2
  106. package/es/{index-ce21e2ce.js → index-5216d5f5.js} +5 -5
  107. package/es/{index-7ed0999e.js → index-53cc4e43.js} +720 -716
  108. package/es/{index-cfcd60ca.cjs → index-5c0dd943.cjs} +1 -1
  109. package/es/{index-cfd00899.cjs → index-870b6c9d.cjs} +1 -1
  110. package/es/{index-a83ec4b7.js → index-8c2d7e05.js} +1 -1
  111. package/es/{index-8901a38c.cjs → index-94131fd7.cjs} +30 -30
  112. package/es/{index-db846633.cjs → index-9d16cea8.cjs} +1 -1
  113. package/es/{index-f3f6ee27.js → index-a33b2fb8.js} +178 -178
  114. package/es/{index-2d7ac156.cjs → index-a9246d17.cjs} +17 -17
  115. package/es/{index-60c69dd1.cjs → index-ac8dc53d.cjs} +1 -1
  116. package/es/{index-102edf6c.js → index-c5f2d372.js} +2 -2
  117. package/es/{index-6290ae0f.js → index-c6584658.js} +2 -2
  118. package/es/{index-5c44d71a.js → index-eb96e074.js} +149 -119
  119. package/es/{index-5ed42e9c.js → index-f034b910.js} +2 -2
  120. package/es/{index-c58e90e9.cjs → index-f58b2920.cjs} +1 -1
  121. package/es/{python-6cc6ec1b.js → python-8a1664e6.js} +18 -18
  122. package/es/{python-71f59893.cjs → python-a3db9620.cjs} +1 -1
  123. package/es/style.css +1 -1
  124. package/es/{use-form-common-props-02be4928.cjs → use-form-common-props-ac666630.cjs} +1 -1
  125. package/es/{use-form-common-props-76a09d89.js → use-form-common-props-ed72e914.js} +11 -11
  126. package/es/{use-global-config-31b3ec57.cjs → use-global-config-23472471.cjs} +1 -1
  127. package/es/{use-global-config-0f43458b.js → use-global-config-ee406d58.js} +2 -2
  128. package/es/{validator-ea292506.cjs → validator-366dbf39.cjs} +1 -1
  129. package/es/{validator-0e037618.js → validator-c60a8956.js} +1 -1
  130. package/es/{zh-cn-1227eb8a.js → zh-cn-b59a0910.js} +1 -1
  131. package/es/{zh-cn-0edc7234.cjs → zh-cn-c21d12d8.cjs} +1 -1
  132. package/lib/aiTools.js +179 -176
  133. package/lib/bundle.js +1 -1
  134. package/lib/bundle.umd.cjs +230 -230
  135. package/lib/{index-2a269748.js → index-62fa175a.js} +30149 -29800
  136. package/lib/{python-41da18e5.js → python-4a48fa39.js} +1 -1
  137. package/lib/style.css +1 -1
  138. package/package.json +53 -44
  139. package/auto-imports.d.ts +0 -13
  140. package/components.d.ts +0 -59
  141. package/es/aiTools-a3b095f6.js +0 -113
  142. package/es/aiTools-f36136a4.cjs +0 -2
  143. package/es/index-476c4459.cjs +0 -1
  144. package/index.html +0 -13
  145. package/packages/ChartLayout/index.ts +0 -8
  146. package/packages/ChartLayout/index.vue +0 -63
  147. package/packages/ConfigProvider/index.ts +0 -8
  148. package/packages/ConfigProvider/index.vue +0 -66
  149. package/packages/Contextmenu/index.ts +0 -8
  150. package/packages/Contextmenu/index.vue +0 -134
  151. package/packages/CustomFunction/components/ManageDialog.vue +0 -706
  152. package/packages/CustomFunction/index.ts +0 -8
  153. package/packages/CustomFunction/index.vue +0 -200
  154. package/packages/FactorWarning/index.ts +0 -8
  155. package/packages/FactorWarning/index.vue +0 -754
  156. package/packages/FactorWarning/tools.js +0 -10
  157. package/packages/HeatMap/index.ts +0 -8
  158. package/packages/HeatMap/index.vue +0 -141
  159. package/packages/Kline/components/Contextmenu/index.vue +0 -110
  160. package/packages/Kline/components/Tips/index.vue +0 -40
  161. package/packages/Kline/componentsNew/KlineSlide/index.vue +0 -155
  162. package/packages/Kline/componentsNew/KlineSub/index.vue +0 -297
  163. package/packages/Kline/componentsNew/KlineTips/index.vue +0 -66
  164. package/packages/Kline/componentsNew/KlineUtils/index.vue +0 -84
  165. package/packages/Kline/componentsNew/Tips/index.vue +0 -33
  166. package/packages/Kline/formatKlineData.ts +0 -109
  167. package/packages/Kline/images/buy.svg +0 -1
  168. package/packages/Kline/images/pen.png +0 -0
  169. package/packages/Kline/images/sell.svg +0 -1
  170. package/packages/Kline/images/t.svg +0 -1
  171. package/packages/Kline/index.ts +0 -16
  172. package/packages/Kline/index.vue +0 -891
  173. package/packages/Kline/option.ts +0 -539
  174. package/packages/Kline/type.d.ts +0 -219
  175. package/packages/Kline/utils.ts +0 -682
  176. package/packages/KlineBasic/api.js +0 -58
  177. package/packages/KlineBasic/components/AverageTips/index.vue +0 -33
  178. package/packages/KlineBasic/components/Contextmenu/index.vue +0 -105
  179. package/packages/KlineBasic/components/KlineSub/index.vue +0 -332
  180. package/packages/KlineBasic/components/KlineTips/index.vue +0 -99
  181. package/packages/KlineBasic/components/Tips/index.vue +0 -56
  182. package/packages/KlineBasic/index.ts +0 -8
  183. package/packages/KlineBasic/index.vue +0 -839
  184. package/packages/KlineBasic/utils.js +0 -258
  185. package/packages/KlineConfig/config.js +0 -46
  186. package/packages/KlineConfig/index.ts +0 -8
  187. package/packages/KlineConfig/index.vue +0 -356
  188. package/packages/KlineNew/components/KlineSlide/index.vue +0 -156
  189. package/packages/KlineNew/components/KlineSub/index.vue +0 -335
  190. package/packages/KlineNew/components/KlineTips/index.vue +0 -96
  191. package/packages/KlineNew/components/KlineUtils/index.vue +0 -341
  192. package/packages/KlineNew/components/Tips/index.vue +0 -33
  193. package/packages/KlineNew/index.ts +0 -14
  194. package/packages/KlinePlus/components/SliderChart.vue +0 -208
  195. package/packages/KlinePlus/components/Tips.vue +0 -36
  196. package/packages/KlinePlus/images/buy.svg +0 -1
  197. package/packages/KlinePlus/images/sell.svg +0 -1
  198. package/packages/KlinePlus/images/t.svg +0 -1
  199. package/packages/KlinePlus/index.ts +0 -8
  200. package/packages/KlinePlus/index.vue +0 -1067
  201. package/packages/KlinePlus/utils.js +0 -771
  202. package/packages/LinearLegend/index.ts +0 -8
  203. package/packages/LinearLegend/index.vue +0 -112
  204. package/packages/Map/China.json +0 -1
  205. package/packages/Map/index.ts +0 -8
  206. package/packages/Map/index.vue +0 -147
  207. package/packages/MonacoEditor/index.ts +0 -8
  208. package/packages/MonacoEditor/index.vue +0 -1141
  209. package/packages/MonacoEditor/tools.js +0 -18
  210. package/packages/Pagination/index.ts +0 -8
  211. package/packages/Pagination/index.vue +0 -87
  212. package/packages/PasswordPrompt/index.ts +0 -8
  213. package/packages/PasswordPrompt/index.vue +0 -267
  214. package/packages/Pie/index.ts +0 -8
  215. package/packages/Pie/index.vue +0 -148
  216. package/packages/Table/components/Button/index.vue +0 -61
  217. package/packages/Table/components/Formatter/index.vue +0 -26
  218. package/packages/Table/index.d.ts +0 -0
  219. package/packages/Table/index.ts +0 -8
  220. package/packages/Table/index.vue +0 -133
  221. package/packages/TreeMap/index.ts +0 -8
  222. package/packages/TreeMap/index.vue +0 -186
  223. package/packages/User/components/EditInfoDialog/Mobile.vue +0 -214
  224. package/packages/User/components/EditInfoDialog/index.vue +0 -161
  225. package/packages/User/components/EditPasswordDialog.vue +0 -168
  226. package/packages/User/components/SetPasswordDialog.vue +0 -160
  227. package/packages/User/index.ts +0 -8
  228. package/packages/User/index.vue +0 -117
  229. package/packages/VarSelectDialog/Mock.js +0 -495
  230. package/packages/VarSelectDialog/VarietySelect.vue +0 -78
  231. package/packages/VarSelectDialog/index.ts +0 -8
  232. package/packages/VarSelectDialog/index.vue +0 -323
  233. package/packages/VarietyAiHelper/images/like.png +0 -0
  234. package/packages/VarietyAiHelper/images/like_no.png +0 -0
  235. package/packages/VarietyAiHelper/index.ts +0 -8
  236. package/packages/VarietyAiHelper/index.vue +0 -910
  237. package/packages/VarietyAutoComplete/index.ts +0 -8
  238. package/packages/VarietyAutoComplete/index.vue +0 -89
  239. package/packages/VarietySearch/components/AddTag/index.vue +0 -268
  240. package/packages/VarietySearch/components/CommonIndicator/IndicatorTags.vue +0 -52
  241. package/packages/VarietySearch/components/CommonIndicator/index.vue +0 -697
  242. package/packages/VarietySearch/components/CommonIndicator/tools.js +0 -260
  243. package/packages/VarietySearch/components/CompositeOrder/index.vue +0 -260
  244. package/packages/VarietySearch/components/FactorScreen/FactorDescription.vue +0 -70
  245. package/packages/VarietySearch/components/FactorScreen/index.vue +0 -1158
  246. package/packages/VarietySearch/components/FactorScreen/tools.js +0 -34
  247. package/packages/VarietySearch/config.js +0 -539
  248. package/packages/VarietySearch/index.ts +0 -8
  249. package/packages/VarietySearch/index.vue +0 -688
  250. package/packages/VarietyTextCopy/index.ts +0 -8
  251. package/packages/VarietyTextCopy/index.vue +0 -136
  252. package/packages/VirtualTable/index.ts +0 -8
  253. package/packages/VirtualTable/index.vue +0 -241
  254. package/packages/index.ts +0 -59
  255. package/public/aiTools.js +0 -176
  256. package/public/talib.wasm +0 -0
  257. package/public/vite.svg +0 -1
  258. package/src/App.vue +0 -140
  259. package/src/assets/vue.svg +0 -1
  260. package/src/components/Dialog/index.vue +0 -16
  261. package/src/components/Kline/index.vue +0 -21
  262. package/src/components/Table/index.vue +0 -27
  263. package/src/main.ts +0 -17
  264. package/src/pages/ChartLayout/index.vue +0 -22
  265. package/src/pages/ConfigProvider/index.vue +0 -9
  266. package/src/pages/Contextmenu/index.vue +0 -46
  267. package/src/pages/CustomFunction/index.vue +0 -13
  268. package/src/pages/FactorWarning/index.vue +0 -203
  269. package/src/pages/HeatMap/index.vue +0 -128
  270. package/src/pages/Kline/index.vue +0 -12
  271. package/src/pages/KlineBasic/api.js +0 -48
  272. package/src/pages/KlineBasic/index.vue +0 -366
  273. package/src/pages/KlineBasic/indicator.js +0 -114
  274. package/src/pages/KlineConfig/index.vue +0 -20
  275. package/src/pages/KlineNew/components/KlineAction/components/ContextMenu/index.vue +0 -91
  276. package/src/pages/KlineNew/components/KlineAction/components/YearChart/index.vue +0 -532
  277. package/src/pages/KlineNew/components/KlineAction/images/pen.png +0 -0
  278. package/src/pages/KlineNew/components/KlineAction/index.vue +0 -716
  279. package/src/pages/KlineNew/components/KlineAction/mockApi/index.js +0 -13
  280. package/src/pages/KlineNew/components/KlineAction/utils.js +0 -571
  281. package/src/pages/KlineNew/components/KlineBasic/index.vue +0 -336
  282. package/src/pages/KlineNew/components/KlineBasic/utils.js +0 -46
  283. package/src/pages/KlineNew/components/KlineNew/index.vue +0 -316
  284. package/src/pages/KlineNew/components/KlineNew/utils.js +0 -31
  285. package/src/pages/KlineNew/components/KlineSlide/index.vue +0 -448
  286. package/src/pages/KlineNew/components/KlineSlide/utils.js +0 -78
  287. package/src/pages/KlineNew/components/KlineSlideNew/index.vue +0 -430
  288. package/src/pages/KlineNew/components/KlineSlideNew/utils.js +0 -78
  289. package/src/pages/KlineNew/index.vue +0 -92
  290. package/src/pages/KlinePlus/KlineDialog/MultiCycle.vue +0 -312
  291. package/src/pages/KlinePlus/KlineDialog/api.js +0 -108
  292. package/src/pages/KlinePlus/KlineDialog/index.vue +0 -582
  293. package/src/pages/KlinePlus/KlineDialog/indicator.js +0 -109
  294. package/src/pages/KlinePlus/KlineDialog/tools.js +0 -86
  295. package/src/pages/KlinePlus/index.vue +0 -30
  296. package/src/pages/KlinePlus/tradeLogMock.js +0 -1927
  297. package/src/pages/LinearLegend/index.vue +0 -92
  298. package/src/pages/Map/index.vue +0 -62
  299. package/src/pages/MonacoEditor/index.vue +0 -63
  300. package/src/pages/Pagination/index.vue +0 -24
  301. package/src/pages/PasswordPrompt/index.vue +0 -12
  302. package/src/pages/Pie/index.vue +0 -36
  303. package/src/pages/Table/index.vue +0 -117
  304. package/src/pages/TreeMap/index.vue +0 -542
  305. package/src/pages/User/index.vue +0 -24
  306. package/src/pages/VarSelectDialog/index.vue +0 -16
  307. package/src/pages/VarietyAiHelper/index.vue +0 -20
  308. package/src/pages/VarietyAutoComplete/index.vue +0 -19
  309. package/src/pages/VarietySearch/api.js +0 -70
  310. package/src/pages/VarietySearch/index.vue +0 -467
  311. package/src/pages/VarietyTextCopy/index.vue +0 -24
  312. package/src/pages/VirtualTable/demo.json +0 -6377
  313. package/src/pages/VirtualTable/index.vue +0 -79
  314. package/src/router/index.ts +0 -9
  315. package/src/router/routes.ts +0 -132
  316. package/src/style.css +0 -79
  317. package/src/vite-env.d.ts +0 -9
  318. package/tsconfig.json +0 -30
  319. package/tsconfig.node.json +0 -10
@@ -1,1141 +0,0 @@
1
- <script setup>
2
- import { debounce } from "st-func";
3
- import { InfoFilled } from "@element-plus/icons-vue";
4
- import { ref, onMounted, onUnmounted, nextTick, inject } from "vue";
5
- import { extractVariables } from "./tools";
6
- import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
7
- import "monaco-editor/esm/vs/basic-languages/python/python.contribution";
8
- import "monaco-editor/esm/vs/basic-languages/lua/lua.contribution";
9
- import VarietySelect from "../VarSelectDialog/VarietySelect.vue";
10
-
11
- const { request } = inject("stConfig"); // 组件库全局配置
12
-
13
- const emit = defineEmits(["change"]);
14
- const props = defineProps({
15
- // 编辑器相关参数
16
- defaultValue: {
17
- type: String,
18
- default: "",
19
- },
20
- language: {
21
- type: String,
22
- default: "python",
23
- },
24
- theme: {
25
- type: String,
26
- default: "vs-dark",
27
- },
28
- // 自定义函数建议列表开关
29
- suggestionEnable: {
30
- type: Boolean,
31
- default: false,
32
- },
33
- // 变量列表开关
34
- variableEnable: {
35
- type: Boolean,
36
- default: false,
37
- },
38
- // 变量列表类型
39
- useCase: {
40
- type: String,
41
- default: "1", // 1-选股, 2-回测
42
- },
43
- });
44
-
45
- let editorInstance = null;
46
- let lastCursorPosition = null;
47
- const editorContainer = ref(null);
48
-
49
- // 建议项相关参数
50
- const suggestions = ref([]);
51
- const suggestionIndex = ref(-1);
52
- const suggestionBoxRef = ref(null);
53
- const isShowingSuggestions = ref(false);
54
-
55
- // 变量列表相关参数
56
- const variables = ref([]);
57
- const variableIndex = ref(-1);
58
- const variableBoxRef = ref(null);
59
- const isShowingVariables = ref(false);
60
- const currentVarName = ref(null);
61
- const currentFormatList = ref([]);
62
- const currentKeyword = ref("");
63
-
64
- // 变量数据源
65
- const varList = ref([]);
66
-
67
- // 格式化配置项的下拉框数据源
68
- const handleOptionsStrToArray = (str) => {
69
- const trimmedStr = str.replace(/^\[|\]$/g, "");
70
- const items = trimmedStr.split("],[");
71
-
72
- return items.map((item) => {
73
- const cleanItem = item.replace(/\[|\]/g, "");
74
- const [label, value] = cleanItem.split(",");
75
-
76
- return {
77
- label: label.trim(),
78
- value: value.trim(),
79
- };
80
- });
81
- };
82
-
83
- // 获取变量列表数据
84
- const fetchVariables = async () => {
85
- if (!props.variableEnable) return;
86
- try {
87
- const { body } = await request.post("/common/conf/queryAllBackVariables", { useCase: props.useCase });
88
- varList.value = body ?? [];
89
- } catch (error) {
90
- console.error("获取变量列表失败:", error);
91
- }
92
- };
93
-
94
- // [变量列表] 数据筛选
95
- const getVariables = debounce(async (keyword = "") => {
96
- if (!props.variableEnable) return;
97
-
98
- currentKeyword.value = keyword;
99
-
100
- // 根据关键字筛选变量名
101
- const filtered = varList.value.filter(({ varName }) => varName.toLowerCase().includes(keyword.toLowerCase()));
102
-
103
- if (filtered.length > 0) {
104
- showVariables(filtered);
105
- } else {
106
- hideVariables();
107
- }
108
- }, 200);
109
-
110
- // [变量列表] 展示
111
- const showVariables = async (options) => {
112
- if (!props.variableEnable) return;
113
- variables.value = options;
114
- variableIndex.value = options.length > 0 ? 0 : -1;
115
- isShowingVariables.value = true;
116
-
117
- // 如果有选中项,更新其格式列表
118
- if (variableIndex.value !== -1) {
119
- updateCurrentFormatList();
120
- }
121
-
122
- updateVariableBoxPosition();
123
- };
124
-
125
- // [变量列表] 隐藏
126
- const hideVariables = () => {
127
- if (!props.variableEnable) return;
128
- variables.value = [];
129
- variableIndex.value = -1;
130
- isShowingVariables.value = false;
131
- currentVarName.value = null;
132
- currentFormatList.value = [];
133
- };
134
-
135
- // [变量列表] 更新当前选中变量的格式列表
136
- const updateCurrentFormatList = () => {
137
- if (variableIndex.value === -1 || !variables.value[variableIndex.value]) return;
138
-
139
- const selectedVar = variables.value[variableIndex.value];
140
- currentVarName.value = selectedVar.varName;
141
- currentFormatList.value = selectedVar.formatList ?? [];
142
- };
143
-
144
- // [变量列表] 更新DOM位置
145
- const updateVariableBoxPosition = () => {
146
- if (!props.variableEnable) return;
147
- nextTick(() => {
148
- if (!editorInstance || !variableBoxRef.value) return;
149
- const position = editorInstance.getPosition();
150
- const cursorCoords = editorInstance.getScrolledVisiblePosition(position);
151
-
152
- if (cursorCoords) {
153
- const editorDom = editorInstance.getDomNode();
154
- const editorRect = editorDom.getBoundingClientRect();
155
-
156
- // 计算相对于编辑器容器的位置(在光标右侧,但比建议列表低一些)
157
- const left = cursorCoords.left + editorRect.left + 40;
158
- const top = cursorCoords.top + editorRect.top + cursorCoords.height + 5;
159
-
160
- variableBoxRef.value.style.left = `${left}px`;
161
- variableBoxRef.value.style.top = `${top}px`;
162
- }
163
- });
164
- };
165
-
166
- // [变量列表] 插入变量内容
167
- const insertVariableContent = (configList) => {
168
- if (!editorInstance) return;
169
-
170
- // 1.校验是否填写完整 + 生成输出值
171
- const result = [];
172
- for (let index = 0; index < configList.length; index++) {
173
- const item = configList[index];
174
- switch (item.vtype) {
175
- case "text": {
176
- result.push(item.param);
177
- break;
178
- }
179
- default: {
180
- if (!item.modelValue) {
181
- ElMessage.error("请检查插入格式内是否填写完整");
182
- return;
183
- }
184
- let formatValue = item.modelValue;
185
- if (item.prefix) formatValue = `${item.prefix}${formatValue}`;
186
- if (item.suffix) formatValue = `${formatValue}${item.suffix}`;
187
- result.push(formatValue);
188
- break;
189
- }
190
- }
191
- }
192
-
193
- // 2.插入内容
194
- const content = result.join("_");
195
- const position = editorInstance.getPosition();
196
-
197
- const currentValue = editorInstance.getValue();
198
- const lines = currentValue.split("\n");
199
-
200
- // 如果光标位置有效
201
- if (position.lineNumber <= lines.length) {
202
- const lineIndex = position.lineNumber - 1;
203
- const line = lines[lineIndex];
204
- const columnIndex = position.column - 1;
205
-
206
- // 获取光标前后的字符
207
- const prevChar = columnIndex > 0 ? line[columnIndex - 1] : "";
208
- const nextChar = columnIndex < line.length ? line[columnIndex] : "";
209
-
210
- // 检测是否需要添加空格
211
- let contentToInsert = content;
212
-
213
- // 如果前面有内容且不是空格或行首,在前面添加空格
214
- if (prevChar && prevChar !== " " && !/[\s({[ ]/.test(prevChar)) {
215
- contentToInsert = " " + contentToInsert;
216
- }
217
-
218
- // 如果后面有内容且不是空格或行尾,在后面添加空格
219
- if (nextChar && nextChar !== " " && !/[\s)}\]]/.test(nextChar)) {
220
- contentToInsert = contentToInsert + " ";
221
- }
222
-
223
- // 获取当前光标前的单词范围(用于替换)
224
- const wordUntilPosition = editorInstance.getModel().getWordUntilPosition(position);
225
-
226
- // 如果当前有正在输入的变量名,替换整个单词
227
- const startPosition = {
228
- lineNumber: position.lineNumber,
229
- column: wordUntilPosition.startColumn,
230
- };
231
-
232
- const endPosition = {
233
- lineNumber: position.lineNumber,
234
- column: position.column,
235
- };
236
-
237
- // 执行编辑操作
238
- editorInstance.executeEdits("variable-insert", [
239
- {
240
- range: new monaco.Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column),
241
- text: contentToInsert,
242
- forceMoveMarkers: true,
243
- },
244
- ]);
245
-
246
- // 将光标移动到插入内容之后
247
- const newColumn = startPosition.column + contentToInsert.length;
248
- editorInstance.setPosition({
249
- lineNumber: position.lineNumber,
250
- column: newColumn,
251
- });
252
- editorInstance.focus();
253
- }
254
-
255
- // 插入后保持变量列表显示(不关闭)
256
- };
257
-
258
- // [建议列表] 数据获取
259
- const getSuggestions = debounce(async (keyword = "") => {
260
- if (!props.suggestionEnable) return;
261
- try {
262
- const { body } = await request.post("/common/qt/querySearchFunctions");
263
- const result = body.filter(({ funcName }) => funcName.toLowerCase().includes(keyword.toLowerCase()));
264
- if (result.length > 0) {
265
- showSuggestions(result);
266
- } else {
267
- hideSuggestions();
268
- }
269
- } catch (error) {
270
- console.error("获取自定义函数失败:", error);
271
- hideSuggestions();
272
- }
273
- }, 200);
274
-
275
- // [建议列表] 展示
276
- const showSuggestions = async (options) => {
277
- if (!props.suggestionEnable) return;
278
- suggestions.value = options;
279
- suggestionIndex.value = options.length > 0 ? 0 : -1;
280
- isShowingSuggestions.value = true;
281
- updateSuggestionBoxPosition();
282
- };
283
-
284
- // [建议列表] 隐藏
285
- const hideSuggestions = () => {
286
- if (!props.suggestionEnable) return;
287
- suggestions.value = [];
288
- suggestionIndex.value = -1;
289
- isShowingSuggestions.value = false;
290
- };
291
-
292
- // [建议列表] 更新DOM位置
293
- const updateSuggestionBoxPosition = () => {
294
- if (!props.suggestionEnable) return;
295
- nextTick(() => {
296
- if (!editorInstance || !suggestionBoxRef.value) return;
297
- const position = editorInstance.getPosition();
298
- const cursorCoords = editorInstance.getScrolledVisiblePosition(position);
299
-
300
- if (cursorCoords) {
301
- const editorDom = editorInstance.getDomNode();
302
- const editorRect = editorDom.getBoundingClientRect();
303
-
304
- const left = cursorCoords.left + editorRect.left + 40;
305
- const top = cursorCoords.top + editorRect.top + cursorCoords.height;
306
-
307
- suggestionBoxRef.value.style.left = `${left}px`;
308
- suggestionBoxRef.value.style.top = `${top}px`;
309
- }
310
- });
311
- };
312
-
313
- // [建议列表] 插入内容到编辑器
314
- const insertSelectedSuggestion = () => {
315
- if (!props.suggestionEnable) return;
316
- if (suggestionIndex.value === -1 || !suggestions.value[suggestionIndex.value]) return;
317
-
318
- const { funcName, funcExpression } = suggestions.value[suggestionIndex.value];
319
- let content = funcName;
320
- const varArray = extractVariables(funcExpression);
321
- if (varArray.length) {
322
- const str = varArray.reduce((result, item, index, arry) => {
323
- result += `${item}=`;
324
- if (index < arry.length - 1) result += ",";
325
- return result;
326
- }, "");
327
- content = `${content}(${str})`;
328
- }
329
-
330
- const currentPosition = editorInstance.getPosition();
331
-
332
- const model = editorInstance.getModel();
333
- const lineContent = model.getLineContent(currentPosition.lineNumber);
334
-
335
- const hashIndex = lineContent.lastIndexOf("#", currentPosition.column - 2);
336
- if (hashIndex === -1) {
337
- hideSuggestions();
338
- return;
339
- }
340
-
341
- const startPosition = {
342
- lineNumber: currentPosition.lineNumber,
343
- column: hashIndex + 1,
344
- };
345
-
346
- const endPosition = {
347
- lineNumber: currentPosition.lineNumber,
348
- column: currentPosition.column,
349
- };
350
-
351
- editorInstance.executeEdits("suggestion", [
352
- {
353
- range: new monaco.Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column),
354
- text: content,
355
- forceMoveMarkers: true,
356
- },
357
- ]);
358
-
359
- const newPosition = {
360
- lineNumber: currentPosition.lineNumber,
361
- column: hashIndex + 1 + content.length,
362
- };
363
-
364
- editorInstance.setPosition(newPosition);
365
- editorInstance.focus();
366
-
367
- hideSuggestions();
368
- };
369
-
370
- // [建议列表] 选项自动滚动
371
- const scrollToSelectedSuggestion = () => {
372
- if (!props.suggestionEnable) return;
373
- if (!suggestionBoxRef.value || suggestionIndex.value === -1) return;
374
-
375
- const suggestionList = suggestionBoxRef.value.querySelector(".suggestion-list");
376
- const selectedItem = suggestionBoxRef.value.querySelector(".suggestion-item.selected");
377
-
378
- if (suggestionList && selectedItem) {
379
- const listRect = suggestionList.getBoundingClientRect();
380
- const itemRect = selectedItem.getBoundingClientRect();
381
-
382
- if (itemRect.top < listRect.top) {
383
- suggestionList.scrollTop -= listRect.top - itemRect.top;
384
- } else if (itemRect.bottom > listRect.bottom) {
385
- suggestionList.scrollTop += itemRect.bottom - listRect.bottom;
386
- }
387
- }
388
- };
389
-
390
- // [变量列表] 选项自动滚动
391
- const scrollToSelectedVariable = () => {
392
- if (!props.variableEnable) return;
393
- if (!variableBoxRef.value || variableIndex.value === -1) return;
394
-
395
- const variableList = variableBoxRef.value.querySelector(".variable-list");
396
- const selectedItem = variableBoxRef.value.querySelector(".variable-item.selected");
397
-
398
- if (variableList && selectedItem) {
399
- const listRect = variableList.getBoundingClientRect();
400
- const itemRect = selectedItem.getBoundingClientRect();
401
-
402
- if (itemRect.top < listRect.top) {
403
- variableList.scrollTop -= listRect.top - itemRect.top;
404
- } else if (itemRect.bottom > listRect.bottom) {
405
- variableList.scrollTop += itemRect.bottom - listRect.bottom;
406
- }
407
- }
408
- };
409
-
410
- // 检查当前输入内容,决定显示建议列表还是变量列表
411
- const checkForCompletions = async () => {
412
- const position = editorInstance.getPosition();
413
- const model = editorInstance.getModel();
414
- const lineContent = model.getLineContent(position.lineNumber);
415
-
416
- const textBeforeCursor = lineContent.substring(0, position.column - 1);
417
- const lastHashIndex = textBeforeCursor.lastIndexOf("#");
418
-
419
- // 如果是#触发,显示建议列表
420
- if (lastHashIndex !== -1) {
421
- // 如果变量列表正在显示,先隐藏
422
- if (isShowingVariables.value) hideVariables();
423
-
424
- const keyword = textBeforeCursor.substring(lastHashIndex + 1);
425
- if (lastCursorPosition && (lastCursorPosition.lineNumber !== position.lineNumber || lastCursorPosition.column !== position.column)) {
426
- hideSuggestions();
427
- }
428
- lastCursorPosition = { ...position };
429
-
430
- if (props.suggestionEnable) {
431
- getSuggestions(keyword);
432
- }
433
- }
434
- // 否则检查变量列表
435
- else {
436
- // 如果建议列表正在显示,先隐藏
437
- if (isShowingSuggestions.value) hideSuggestions();
438
-
439
- // 获取光标前的单词作为关键字
440
- const wordUntilPosition = model.getWordUntilPosition(position);
441
- const keyword = wordUntilPosition.word;
442
-
443
- if (lastCursorPosition && (lastCursorPosition.lineNumber !== position.lineNumber || lastCursorPosition.column !== position.column)) {
444
- hideVariables();
445
- }
446
- lastCursorPosition = { ...position };
447
-
448
- if (props.variableEnable && keyword.length > 0) {
449
- getVariables(keyword);
450
- } else if (keyword.length === 0) {
451
- hideVariables();
452
- }
453
- }
454
- };
455
-
456
- // [代码编辑器] 键盘事件
457
- const handleKeyDown = (e) => {
458
- // 变量列表键盘导航
459
- if (isShowingVariables.value) {
460
- switch (e.code) {
461
- case "ArrowUp": {
462
- e.preventDefault();
463
- e.stopPropagation();
464
- variableIndex.value = variableIndex.value <= 0 ? variables.value.length - 1 : variableIndex.value - 1;
465
- updateCurrentFormatList();
466
- nextTick(() => scrollToSelectedVariable());
467
- break;
468
- }
469
- case "ArrowDown": {
470
- e.preventDefault();
471
- e.stopPropagation();
472
- variableIndex.value = variableIndex.value >= variables.value.length - 1 ? 0 : variableIndex.value + 1;
473
- updateCurrentFormatList();
474
- nextTick(() => scrollToSelectedVariable());
475
- break;
476
- }
477
- case "Escape": {
478
- e.preventDefault();
479
- e.stopPropagation();
480
- hideVariables();
481
- break;
482
- }
483
- default:
484
- break;
485
- }
486
- }
487
-
488
- // 建议列表键盘导航
489
- if (isShowingSuggestions.value) {
490
- switch (e.code) {
491
- case "ArrowUp": {
492
- e.preventDefault();
493
- e.stopPropagation();
494
- suggestionIndex.value = suggestionIndex.value <= 0 ? suggestions.value.length - 1 : suggestionIndex.value - 1;
495
- nextTick(() => scrollToSelectedSuggestion());
496
- break;
497
- }
498
- case "ArrowDown": {
499
- e.preventDefault();
500
- e.stopPropagation();
501
- suggestionIndex.value = suggestionIndex.value >= suggestions.value.length - 1 ? 0 : suggestionIndex.value + 1;
502
- nextTick(() => scrollToSelectedSuggestion());
503
- break;
504
- }
505
- case "Enter": {
506
- if (isShowingSuggestions.value) {
507
- e.preventDefault();
508
- e.stopPropagation();
509
- insertSelectedSuggestion();
510
- }
511
- break;
512
- }
513
- case "Escape": {
514
- e.preventDefault();
515
- e.stopPropagation();
516
- if (isShowingSuggestions.value) hideSuggestions();
517
- if (isShowingVariables.value) hideVariables();
518
- break;
519
- }
520
- default:
521
- break;
522
- }
523
- }
524
- };
525
-
526
- // [代码编辑器] 内容变化回调
527
- const handleContentChange = (event) => {
528
- if (!editorInstance) return;
529
- emit("change", editorInstance.getValue());
530
- checkForCompletions();
531
- };
532
-
533
- // [代码编辑器] 光标变化回调
534
- const handleCursorPositionChange = (event) => {
535
- if (isShowingSuggestions.value) {
536
- updateSuggestionBoxPosition();
537
- }
538
- if (isShowingVariables.value) {
539
- updateVariableBoxPosition();
540
- }
541
- };
542
-
543
- // [document] 全局监听的点击事件
544
- const handleClickOutside = (event) => {
545
- // 如果点击了建议列表外面的区域,就自动关闭
546
- if (suggestionBoxRef.value && !suggestionBoxRef.value.contains(event.target)) {
547
- hideSuggestions();
548
- }
549
- // 如果点击了变量列表外面的区域,就自动关闭
550
- if (variableBoxRef.value && !variableBoxRef.value.contains(event.target)) {
551
- hideVariables();
552
- }
553
- };
554
-
555
- onMounted(() => {
556
- editorInstance = monaco.editor.create(editorContainer.value, {
557
- value: props.defaultValue,
558
- language: props.language,
559
- theme: props.theme,
560
- });
561
-
562
- editorInstance.onKeyDown(handleKeyDown);
563
- editorInstance.onDidChangeModelContent(handleContentChange);
564
- editorInstance.onDidChangeCursorPosition(handleCursorPositionChange);
565
-
566
- document.addEventListener("click", handleClickOutside);
567
-
568
- // 获取变量列表数据
569
- fetchVariables();
570
- });
571
-
572
- onUnmounted(() => {
573
- editorInstance?.dispose();
574
- document.removeEventListener("click", handleClickOutside);
575
- });
576
-
577
- defineExpose({
578
- resize: () => {
579
- editorInstance.layout();
580
- },
581
- getInstance: () => {
582
- return editorInstance;
583
- },
584
- getValue: () => {
585
- return editorInstance.getValue();
586
- },
587
- setValue: (value) => {
588
- editorInstance.setValue(value);
589
- },
590
- setReadOnly: (readOnly = true) => {
591
- editorInstance.updateOptions({ readOnly });
592
- },
593
- focusToEnd: () => {
594
- if (!editorInstance) return;
595
-
596
- const model = editorInstance.getModel();
597
- if (!model) return;
598
-
599
- const lineCount = model.getLineCount();
600
- const lastLine = model.getLineContent(lineCount);
601
-
602
- const position = {
603
- lineNumber: lineCount,
604
- column: lastLine.length + 1,
605
- };
606
-
607
- editorInstance.setPosition(position);
608
- editorInstance.focus();
609
- editorInstance.revealPositionInCenter(position);
610
- },
611
- });
612
- </script>
613
-
614
- <template>
615
- <div class="editor-wrapper">
616
- <!-- 代码编辑器 -->
617
- <div
618
- ref="editorContainer"
619
- class="editor-container"
620
- />
621
-
622
- <!-- 建议列表 -->
623
- <Teleport
624
- to="body"
625
- v-if="isShowingSuggestions && suggestions.length > 0"
626
- >
627
- <div
628
- ref="suggestionBoxRef"
629
- class="suggestion-box"
630
- >
631
- <div class="suggestion-header">
632
- <span class="suggestion-title">相关自定义函数</span>
633
- <span class="suggestion-count">{{ suggestions.length }} 项</span>
634
- </div>
635
- <div class="suggestion-list">
636
- <div
637
- v-for="(item, index) in suggestions"
638
- :key="item.id"
639
- :class="['suggestion-item', { selected: index === suggestionIndex }]"
640
- @click="
641
- suggestionIndex = index;
642
- insertSelectedSuggestion();
643
- "
644
- >
645
- <span class="suggestion-text">{{ item.funcName }}</span>
646
- </div>
647
- </div>
648
- <div class="suggestion-footer">使用 ↑↓ 选择,Enter 确认,Esc 取消</div>
649
- </div>
650
- </Teleport>
651
-
652
- <!-- 变量列表 -->
653
- <Teleport
654
- to="body"
655
- v-if="isShowingVariables && variables.length > 0"
656
- >
657
- <div
658
- ref="variableBoxRef"
659
- class="variable-box"
660
- >
661
- <div class="variable-header">
662
- <span class="variable-title">变量列表</span>
663
- <span class="variable-count">{{ variables.length }} 项</span>
664
- <span
665
- class="variable-keyword"
666
- v-if="currentKeyword"
667
- >"{{ currentKeyword }}"</span
668
- >
669
- </div>
670
-
671
- <div class="variable-content">
672
- <!-- 左侧变量名列表 -->
673
- <div class="variable-list">
674
- <div
675
- v-for="(item, index) in variables"
676
- :key="item.varName"
677
- :class="['variable-item', { selected: index === variableIndex }]"
678
- @click="
679
- variableIndex = index;
680
- updateCurrentFormatList();
681
- "
682
- >
683
- <span class="variable-name">{{ item.varName }}</span>
684
- </div>
685
- </div>
686
-
687
- <!-- 右侧格式配置区域 -->
688
- <div
689
- class="format-section"
690
- v-if="currentFormatList.length"
691
- >
692
- <div
693
- class="format-item"
694
- v-for="(formatItem, formatIndex) in currentFormatList"
695
- :key="formatIndex"
696
- >
697
- <div class="format-header">
698
- <span>格式{{ formatIndex + 1 }}</span>
699
- <el-tooltip
700
- effect="dark"
701
- placement="top-start"
702
- >
703
- <template #content>
704
- <div style="max-width: 820px">
705
- <span style="white-space: pre-line">{{ formatItem.tip }}</span>
706
- </div>
707
- </template>
708
- <el-icon><InfoFilled /></el-icon>
709
- </el-tooltip>
710
- </div>
711
-
712
- <!-- 配置项 -->
713
- <div class="config-list">
714
- <template v-for="(config, configIndex) in formatItem.configList">
715
- <div class="config-item">
716
- <!-- 类型: 固定值 -->
717
- <template v-if="config.vtype === 'text'">
718
- <span>{{ config.param }}</span>
719
- </template>
720
- <template v-if="config.vtype === 'inputVariety'">
721
- <VarietySelect
722
- size="small"
723
- :placeholder="config.param"
724
- :selectClearEnable="false"
725
- :labelShowEnable="false"
726
- @select="({ name, code }) => (config.modelValue = code)"
727
- @change="(value) => (config.modelValue = value)"
728
- style="width: 100px"
729
- />
730
- </template>
731
- <template v-if="config.vtype === 'input'">
732
- <span v-if="config.prefix">{{ config.prefix }}</span>
733
- <el-input
734
- v-model="config.modelValue"
735
- :placeholder="config.param"
736
- size="small"
737
- />
738
- <span v-if="config.suffix">{{ config.suffix }}</span>
739
- </template>
740
- <template v-if="config.vtype === 'select'">
741
- <el-select
742
- v-model="config.modelValue"
743
- :placeholder="config.param"
744
- clearable
745
- size="small"
746
- >
747
- <el-option
748
- v-for="item in handleOptionsStrToArray(config.optionsStr)"
749
- :key="item.value"
750
- :label="item.label"
751
- :value="item.value"
752
- />
753
- </el-select>
754
- </template>
755
- </div>
756
- <span
757
- v-if="configIndex !== formatItem.configList.length - 1"
758
- class="separator"
759
- >_</span
760
- >
761
- </template>
762
- </div>
763
-
764
- <!-- 插入变量按钮 -->
765
- <el-button
766
- type="primary"
767
- size="small"
768
- class="insert-btn"
769
- @click="insertVariableContent(formatItem.configList)"
770
- >
771
- 插入变量
772
- </el-button>
773
- </div>
774
- </div>
775
- </div>
776
-
777
- <div class="variable-footer">使用 ↑↓ 选择变量,点击插入按钮确认,Esc 取消</div>
778
- </div>
779
- </Teleport>
780
- </div>
781
- </template>
782
-
783
- <style lang="scss">
784
- /* 变量列表下拉框和tooltip的全局样式 */
785
- .variable-select-popper,
786
- .variable-variety-popper,
787
- .variable-tooltip-popper {
788
- z-index: 100000 !important;
789
- }
790
-
791
- /* 确保所有 Element Plus 的弹层都有足够高的层级 */
792
- .el-popper {
793
- z-index: 100000 !important;
794
- }
795
-
796
- /* 如果是旧版本 Element Plus */
797
- .el-select__popper,
798
- .el-tooltip__popper {
799
- z-index: 100000 !important;
800
- }
801
- </style>
802
- <style scoped lang="scss">
803
- .editor-wrapper {
804
- position: relative;
805
- width: 100%;
806
- height: 100%;
807
- }
808
- .editor-container {
809
- width: 100%;
810
- height: 100%;
811
- }
812
-
813
- // 建议列表样式
814
- .suggestion-box {
815
- position: fixed;
816
- background: #1e1e1e;
817
- border: 1px solid #444;
818
- border-radius: 6px;
819
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6);
820
- z-index: 99999;
821
- min-width: 240px;
822
- max-height: 280px;
823
- overflow: hidden;
824
-
825
- &::before {
826
- content: "";
827
- position: absolute;
828
- top: -6px;
829
- left: 12px;
830
- width: 12px;
831
- height: 12px;
832
- background: #1e1e1e;
833
- border-left: 1px solid #444;
834
- border-top: 1px solid #444;
835
- transform: rotate(45deg);
836
- z-index: -1;
837
- }
838
-
839
- .suggestion-header {
840
- display: flex;
841
- justify-content: space-between;
842
- align-items: center;
843
- padding: 8px 12px;
844
- background: #2d2d30;
845
- border-bottom: 1px solid #444;
846
- font-size: 12px;
847
- color: #969696;
848
-
849
- .suggestion-title {
850
- font-weight: 600;
851
- }
852
-
853
- .suggestion-count {
854
- font-size: 11px;
855
- opacity: 0.8;
856
- }
857
- }
858
-
859
- .suggestion-list {
860
- max-height: 200px;
861
- overflow-y: auto;
862
- padding: 4px 0;
863
-
864
- &::-webkit-scrollbar {
865
- width: 6px;
866
- }
867
-
868
- &::-webkit-scrollbar-track {
869
- background: transparent;
870
- }
871
-
872
- &::-webkit-scrollbar-thumb {
873
- background: #424242;
874
- border-radius: 3px;
875
- }
876
-
877
- &::-webkit-scrollbar-thumb:hover {
878
- background: #4a4a4a;
879
- }
880
-
881
- .suggestion-item {
882
- display: flex;
883
- align-items: center;
884
- padding: 8px 12px;
885
- cursor: pointer;
886
- transition: all 0.2s ease;
887
- border-left: 3px solid transparent;
888
-
889
- &:hover {
890
- background: #2a2d2e;
891
- border-left-color: #007acc;
892
- }
893
-
894
- &.selected {
895
- background: #094771;
896
- border-left-color: #007acc;
897
-
898
- .suggestion-text {
899
- color: #ffffff;
900
- font-weight: 500;
901
- }
902
- }
903
-
904
- .suggestion-text {
905
- font-size: 13px;
906
- color: #d4d4d4;
907
- line-height: 1.4;
908
- }
909
- }
910
- }
911
-
912
- .suggestion-footer {
913
- padding: 6px 12px;
914
- background: #2d2d30;
915
- border-top: 1px solid #444;
916
- font-size: 11px;
917
- color: #969696;
918
- text-align: center;
919
- }
920
- }
921
- // 变量列表样式
922
- .variable-box {
923
- position: fixed;
924
- background: #1e1e1e;
925
- border: 1px solid #444;
926
- border-radius: 6px;
927
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6);
928
- z-index: 9999;
929
- min-width: 600px;
930
- max-width: 900px;
931
- overflow: hidden;
932
-
933
- &::before {
934
- content: "";
935
- position: absolute;
936
- top: -6px;
937
- left: 12px;
938
- width: 12px;
939
- height: 12px;
940
- background: #1e1e1e;
941
- border-left: 1px solid #444;
942
- border-top: 1px solid #444;
943
- transform: rotate(45deg);
944
- z-index: -1;
945
- }
946
-
947
- .variable-header {
948
- display: flex;
949
- justify-content: space-between;
950
- align-items: center;
951
- padding: 8px 12px;
952
- background: #2d2d30;
953
- border-bottom: 1px solid #444;
954
- font-size: 12px;
955
- color: #969696;
956
-
957
- .variable-title {
958
- font-weight: 600;
959
- }
960
-
961
- .variable-count {
962
- font-size: 11px;
963
- opacity: 0.8;
964
- }
965
-
966
- .variable-keyword {
967
- font-size: 11px;
968
- color: #007acc;
969
- background: #09477133;
970
- padding: 2px 6px;
971
- border-radius: 4px;
972
- }
973
- }
974
-
975
- .variable-content {
976
- display: flex;
977
- max-height: 300px;
978
- overflow: hidden;
979
-
980
- .variable-list {
981
- width: 160px;
982
- border-right: 1px solid #444;
983
- overflow-y: auto;
984
- padding: 4px 0;
985
-
986
- &::-webkit-scrollbar {
987
- width: 6px;
988
- }
989
-
990
- &::-webkit-scrollbar-track {
991
- background: transparent;
992
- }
993
-
994
- &::-webkit-scrollbar-thumb {
995
- background: #424242;
996
- border-radius: 3px;
997
- }
998
-
999
- .variable-item {
1000
- padding: 8px 12px;
1001
- cursor: pointer;
1002
- border-left: 3px solid transparent;
1003
- font-size: 12px;
1004
- color: #d4d4d4;
1005
-
1006
- &:hover {
1007
- background: #2a2d2e;
1008
- border-left-color: #007acc;
1009
- }
1010
-
1011
- &.selected {
1012
- background: #094771;
1013
- border-left-color: #007acc;
1014
- color: #ffffff;
1015
- font-weight: 500;
1016
- }
1017
- }
1018
- }
1019
-
1020
- .format-section {
1021
- flex: 1;
1022
- padding: 12px;
1023
- overflow-y: auto;
1024
- max-height: 300px;
1025
-
1026
- &::-webkit-scrollbar {
1027
- width: 6px;
1028
- }
1029
-
1030
- &::-webkit-scrollbar-track {
1031
- background: transparent;
1032
- }
1033
-
1034
- &::-webkit-scrollbar-thumb {
1035
- background: #424242;
1036
- border-radius: 3px;
1037
- }
1038
-
1039
- .format-item {
1040
- margin-bottom: 16px;
1041
- padding: 8px;
1042
- background: #2d2d30;
1043
- border-radius: 4px;
1044
-
1045
- &:last-child {
1046
- margin-bottom: 0;
1047
- }
1048
-
1049
- .format-header {
1050
- display: flex;
1051
- align-items: center;
1052
- gap: 6px;
1053
- margin-bottom: 8px;
1054
- font-size: 11px;
1055
- color: #969696;
1056
-
1057
- .el-icon {
1058
- cursor: help;
1059
- font-size: 14px;
1060
-
1061
- &:hover {
1062
- color: #007acc;
1063
- }
1064
- }
1065
- }
1066
-
1067
- .config-list {
1068
- display: flex;
1069
- align-items: center;
1070
- flex-wrap: wrap;
1071
- gap: 4px 8px;
1072
- margin-bottom: 8px;
1073
-
1074
- .config-item {
1075
- display: flex;
1076
- align-items: center;
1077
- gap: 2px;
1078
-
1079
- span {
1080
- font-size: 12px;
1081
- color: #d4d4d4;
1082
- }
1083
-
1084
- :deep(.el-input) {
1085
- width: 100px;
1086
-
1087
- .el-input__wrapper {
1088
- background: #3c3c3c;
1089
- box-shadow: none;
1090
- padding: 1px 8px;
1091
-
1092
- input {
1093
- color: #d4d4d4;
1094
- }
1095
- }
1096
- }
1097
-
1098
- :deep(.el-select) {
1099
- width: 100px;
1100
-
1101
- .el-select__wrapper {
1102
- background: #3c3c3c;
1103
- box-shadow: none;
1104
- min-height: 24px;
1105
- padding: 0 8px;
1106
-
1107
- .el-select__placeholder {
1108
- color: #969696;
1109
- }
1110
-
1111
- .el-select__selected-item {
1112
- color: #d4d4d4;
1113
- }
1114
- }
1115
- }
1116
- }
1117
-
1118
- .separator {
1119
- color: #969696;
1120
- font-size: 12px;
1121
- }
1122
- }
1123
-
1124
- .insert-btn {
1125
- width: 100%;
1126
- margin-top: 4px;
1127
- }
1128
- }
1129
- }
1130
- }
1131
-
1132
- .variable-footer {
1133
- padding: 6px 12px;
1134
- background: #2d2d30;
1135
- border-top: 1px solid #444;
1136
- font-size: 11px;
1137
- color: #969696;
1138
- text-align: center;
1139
- }
1140
- }
1141
- </style>