@363045841yyt/klinechart 0.7.1 → 0.7.3-alpha.0

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 (236) hide show
  1. package/README.md +10 -6
  2. package/dist/components/DrawingStyleToolbar.vue.d.ts +28 -0
  3. package/dist/components/DrawingStyleToolbar.vue.d.ts.map +1 -0
  4. package/dist/{src/components → components}/IndicatorParams.vue.d.ts +3 -3
  5. package/dist/components/IndicatorParams.vue.d.ts.map +1 -0
  6. package/dist/{src/components → components}/IndicatorSelector.vue.d.ts +4 -4
  7. package/dist/components/IndicatorSelector.vue.d.ts.map +1 -0
  8. package/dist/components/KLineChart.vue.d.ts +63 -0
  9. package/dist/components/KLineChart.vue.d.ts.map +1 -0
  10. package/dist/components/KLineTooltip.vue.d.ts +30 -0
  11. package/dist/components/KLineTooltip.vue.d.ts.map +1 -0
  12. package/dist/{src/components → components}/LeftToolbar.vue.d.ts +3 -2
  13. package/dist/components/LeftToolbar.vue.d.ts.map +1 -0
  14. package/dist/components/MarkerTooltip.vue.d.ts +26 -0
  15. package/dist/components/MarkerTooltip.vue.d.ts.map +1 -0
  16. package/dist/components/index.d.ts +8 -0
  17. package/dist/components/index.d.ts.map +1 -0
  18. package/dist/{src/composables → composables}/useFullscreenTeleportTarget.d.ts +1 -0
  19. package/dist/composables/useFullscreenTeleportTarget.d.ts.map +1 -0
  20. package/dist/{src/debug → debug}/canvasProfiler.d.ts +1 -0
  21. package/dist/debug/canvasProfiler.d.ts.map +1 -0
  22. package/dist/index.cjs +2 -49
  23. package/dist/index.d.cts +124 -0
  24. package/dist/index.d.ts +124 -2
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +1390 -23809
  27. package/dist/klinechart.css +1 -1
  28. package/dist/version.d.ts +3 -0
  29. package/dist/version.d.ts.map +1 -0
  30. package/package.json +75 -112
  31. package/src/__tests__/_mockController.ts +192 -0
  32. package/src/__tests__/contract.test.ts +132 -0
  33. package/src/components/DrawingStyleToolbar.vue +199 -0
  34. package/src/components/IndicatorParams.vue +570 -0
  35. package/src/components/IndicatorSelector.vue +1042 -0
  36. package/src/components/KLineChart.vue +1570 -0
  37. package/src/components/KLineTooltip.vue +200 -0
  38. package/src/components/LeftToolbar.vue +844 -0
  39. package/src/components/MarkerTooltip.vue +155 -0
  40. package/src/components/index.ts +7 -0
  41. package/src/composables/useFullscreenTeleportTarget.ts +18 -0
  42. package/src/debug/canvasProfiler.ts +296 -0
  43. package/src/index.ts +402 -0
  44. package/src/version.ts +3 -0
  45. package/LICENSE +0 -21
  46. package/dist/favicon.ico +0 -0
  47. package/dist/mock-stock-data.json +0 -1
  48. package/dist/schema-CzmPW09E.cjs +0 -1
  49. package/dist/schema-DBMGp6Af.js +0 -437
  50. package/dist/src/App.vue.d.ts +0 -4
  51. package/dist/src/api/data/baostock.d.ts +0 -90
  52. package/dist/src/api/data/baostock.integration.test.d.ts +0 -1
  53. package/dist/src/api/data/index.d.ts +0 -26
  54. package/dist/src/api/data/kLine.d.ts +0 -11
  55. package/dist/src/api/data/types.d.ts +0 -33
  56. package/dist/src/api/data/unified.d.ts +0 -37
  57. package/dist/src/components/DrawingStyleToolbar.vue.d.ts +0 -12
  58. package/dist/src/components/KLineChart.vue.d.ts +0 -100
  59. package/dist/src/components/KLineTooltip.vue.d.ts +0 -17
  60. package/dist/src/components/MarkerTooltip.vue.d.ts +0 -13
  61. package/dist/src/components/index.d.ts +0 -2
  62. package/dist/src/config/chartSettings.d.ts +0 -69
  63. package/dist/src/core/chart-store.d.ts +0 -74
  64. package/dist/src/core/chart.d.ts +0 -617
  65. package/dist/src/core/controller/interaction.d.ts +0 -167
  66. package/dist/src/core/controller/markerInteraction.d.ts +0 -28
  67. package/dist/src/core/controller/pinchTracker.d.ts +0 -18
  68. package/dist/src/core/controller/tooltipPosition.d.ts +0 -21
  69. package/dist/src/core/draw/pixelAlign.d.ts +0 -114
  70. package/dist/src/core/drawing/index.d.ts +0 -47
  71. package/dist/src/core/drawing/interaction.d.ts +0 -75
  72. package/dist/src/core/drawing/plugin.d.ts +0 -27
  73. package/dist/src/core/indicators/atrState.d.ts +0 -16
  74. package/dist/src/core/indicators/bollState.d.ts +0 -34
  75. package/dist/src/core/indicators/calculators.d.ts +0 -465
  76. package/dist/src/core/indicators/cciState.d.ts +0 -15
  77. package/dist/src/core/indicators/chaikinVolState.d.ts +0 -18
  78. package/dist/src/core/indicators/cmfState.d.ts +0 -16
  79. package/dist/src/core/indicators/demaState.d.ts +0 -16
  80. package/dist/src/core/indicators/donchianState.d.ts +0 -23
  81. package/dist/src/core/indicators/eneState.d.ts +0 -30
  82. package/dist/src/core/indicators/expmaState.d.ts +0 -30
  83. package/dist/src/core/indicators/fastkState.d.ts +0 -15
  84. package/dist/src/core/indicators/fibState.d.ts +0 -26
  85. package/dist/src/core/indicators/hmaState.d.ts +0 -16
  86. package/dist/src/core/indicators/hvState.d.ts +0 -18
  87. package/dist/src/core/indicators/ichimokuState.d.ts +0 -44
  88. package/dist/src/core/indicators/indicator.worker.d.ts +0 -5
  89. package/dist/src/core/indicators/indicatorDefinitionRegistry.d.ts +0 -30
  90. package/dist/src/core/indicators/indicatorMetadata.d.ts +0 -81
  91. package/dist/src/core/indicators/indicatorRegistry.d.ts +0 -57
  92. package/dist/src/core/indicators/indicatorRuntime.d.ts +0 -126
  93. package/dist/src/core/indicators/kamaState.d.ts +0 -20
  94. package/dist/src/core/indicators/keltnerState.d.ts +0 -27
  95. package/dist/src/core/indicators/kstState.d.ts +0 -21
  96. package/dist/src/core/indicators/maState.d.ts +0 -26
  97. package/dist/src/core/indicators/macdState.d.ts +0 -58
  98. package/dist/src/core/indicators/mfiState.d.ts +0 -16
  99. package/dist/src/core/indicators/momState.d.ts +0 -15
  100. package/dist/src/core/indicators/obvState.d.ts +0 -14
  101. package/dist/src/core/indicators/parkinsonState.d.ts +0 -18
  102. package/dist/src/core/indicators/pivotState.d.ts +0 -29
  103. package/dist/src/core/indicators/pvtState.d.ts +0 -14
  104. package/dist/src/core/indicators/rocState.d.ts +0 -16
  105. package/dist/src/core/indicators/rsiState.d.ts +0 -43
  106. package/dist/src/core/indicators/sarState.d.ts +0 -26
  107. package/dist/src/core/indicators/scheduler.d.ts +0 -262
  108. package/dist/src/core/indicators/soa.d.ts +0 -115
  109. package/dist/src/core/indicators/stateComposer.d.ts +0 -146
  110. package/dist/src/core/indicators/stochState.d.ts +0 -18
  111. package/dist/src/core/indicators/structureState.d.ts +0 -43
  112. package/dist/src/core/indicators/supertrendState.d.ts +0 -22
  113. package/dist/src/core/indicators/temaState.d.ts +0 -16
  114. package/dist/src/core/indicators/trixState.d.ts +0 -20
  115. package/dist/src/core/indicators/vmaState.d.ts +0 -16
  116. package/dist/src/core/indicators/volumeProfileState.d.ts +0 -34
  117. package/dist/src/core/indicators/vwapState.d.ts +0 -16
  118. package/dist/src/core/indicators/wmaState.d.ts +0 -16
  119. package/dist/src/core/indicators/wmsrState.d.ts +0 -15
  120. package/dist/src/core/indicators/workerProtocol.d.ts +0 -496
  121. package/dist/src/core/indicators/zonesState.d.ts +0 -26
  122. package/dist/src/core/layout/pane.d.ts +0 -103
  123. package/dist/src/core/marker/registry.d.ts +0 -174
  124. package/dist/src/core/paneRenderer.d.ts +0 -45
  125. package/dist/src/core/renderers/Indicator/atr.d.ts +0 -17
  126. package/dist/src/core/renderers/Indicator/boll.d.ts +0 -2
  127. package/dist/src/core/renderers/Indicator/cci.d.ts +0 -22
  128. package/dist/src/core/renderers/Indicator/chaikinVol.d.ts +0 -4
  129. package/dist/src/core/renderers/Indicator/cmf.d.ts +0 -4
  130. package/dist/src/core/renderers/Indicator/dema.d.ts +0 -5
  131. package/dist/src/core/renderers/Indicator/donchian.d.ts +0 -5
  132. package/dist/src/core/renderers/Indicator/ene.d.ts +0 -2
  133. package/dist/src/core/renderers/Indicator/expma.d.ts +0 -2
  134. package/dist/src/core/renderers/Indicator/fastk.d.ts +0 -22
  135. package/dist/src/core/renderers/Indicator/fib.d.ts +0 -4
  136. package/dist/src/core/renderers/Indicator/hma.d.ts +0 -5
  137. package/dist/src/core/renderers/Indicator/hv.d.ts +0 -4
  138. package/dist/src/core/renderers/Indicator/ichimoku.d.ts +0 -5
  139. package/dist/src/core/renderers/Indicator/index.d.ts +0 -59
  140. package/dist/src/core/renderers/Indicator/indicatorData.d.ts +0 -13
  141. package/dist/src/core/renderers/Indicator/kama.d.ts +0 -5
  142. package/dist/src/core/renderers/Indicator/keltner.d.ts +0 -5
  143. package/dist/src/core/renderers/Indicator/kst.d.ts +0 -22
  144. package/dist/src/core/renderers/Indicator/ma.d.ts +0 -3
  145. package/dist/src/core/renderers/Indicator/macd.d.ts +0 -50
  146. package/dist/src/core/renderers/Indicator/macdLegend.d.ts +0 -12
  147. package/dist/src/core/renderers/Indicator/mainIndicatorLegend.d.ts +0 -10
  148. package/dist/src/core/renderers/Indicator/mfi.d.ts +0 -4
  149. package/dist/src/core/renderers/Indicator/mom.d.ts +0 -22
  150. package/dist/src/core/renderers/Indicator/obv.d.ts +0 -4
  151. package/dist/src/core/renderers/Indicator/parkinson.d.ts +0 -4
  152. package/dist/src/core/renderers/Indicator/pivot.d.ts +0 -4
  153. package/dist/src/core/renderers/Indicator/pvt.d.ts +0 -4
  154. package/dist/src/core/renderers/Indicator/roc.d.ts +0 -5
  155. package/dist/src/core/renderers/Indicator/rsi.d.ts +0 -33
  156. package/dist/src/core/renderers/Indicator/sar.d.ts +0 -5
  157. package/dist/src/core/renderers/Indicator/scale/atr_scale.d.ts +0 -11
  158. package/dist/src/core/renderers/Indicator/scale/cci_scale.d.ts +0 -11
  159. package/dist/src/core/renderers/Indicator/scale/fastk_scale.d.ts +0 -11
  160. package/dist/src/core/renderers/Indicator/scale/indicator_scale.d.ts +0 -38
  161. package/dist/src/core/renderers/Indicator/scale/kst_scale.d.ts +0 -11
  162. package/dist/src/core/renderers/Indicator/scale/macd_scale.d.ts +0 -14
  163. package/dist/src/core/renderers/Indicator/scale/mom_scale.d.ts +0 -11
  164. package/dist/src/core/renderers/Indicator/scale/rsi_scale.d.ts +0 -11
  165. package/dist/src/core/renderers/Indicator/scale/stoch_scale.d.ts +0 -11
  166. package/dist/src/core/renderers/Indicator/scale/volume_scale.d.ts +0 -14
  167. package/dist/src/core/renderers/Indicator/scale/wmsr_scale.d.ts +0 -11
  168. package/dist/src/core/renderers/Indicator/stoch.d.ts +0 -22
  169. package/dist/src/core/renderers/Indicator/structure.d.ts +0 -4
  170. package/dist/src/core/renderers/Indicator/subPaneConfig.d.ts +0 -9
  171. package/dist/src/core/renderers/Indicator/supertrend.d.ts +0 -5
  172. package/dist/src/core/renderers/Indicator/tema.d.ts +0 -5
  173. package/dist/src/core/renderers/Indicator/trix.d.ts +0 -5
  174. package/dist/src/core/renderers/Indicator/vma.d.ts +0 -4
  175. package/dist/src/core/renderers/Indicator/volumeProfile.d.ts +0 -4
  176. package/dist/src/core/renderers/Indicator/vwap.d.ts +0 -4
  177. package/dist/src/core/renderers/Indicator/wma.d.ts +0 -5
  178. package/dist/src/core/renderers/Indicator/wmsr.d.ts +0 -22
  179. package/dist/src/core/renderers/Indicator/zones.d.ts +0 -4
  180. package/dist/src/core/renderers/candle.d.ts +0 -21
  181. package/dist/src/core/renderers/crosshair.d.ts +0 -17
  182. package/dist/src/core/renderers/customMarkers.d.ts +0 -6
  183. package/dist/src/core/renderers/extremaMarkers.d.ts +0 -5
  184. package/dist/src/core/renderers/gridLines.d.ts +0 -7
  185. package/dist/src/core/renderers/lastPrice.d.ts +0 -9
  186. package/dist/src/core/renderers/paneTitle.d.ts +0 -40
  187. package/dist/src/core/renderers/subVolume.d.ts +0 -13
  188. package/dist/src/core/renderers/timeAxis.d.ts +0 -14
  189. package/dist/src/core/renderers/webgl/candleSurface.d.ts +0 -80
  190. package/dist/src/core/renderers/webgl/sharedWebGLSurface.d.ts +0 -33
  191. package/dist/src/core/renderers/yAxis.d.ts +0 -14
  192. package/dist/src/core/scale/logFormula.d.ts +0 -66
  193. package/dist/src/core/scale/price.d.ts +0 -11
  194. package/dist/src/core/scale/priceScale.d.ts +0 -87
  195. package/dist/src/core/subPaneManager.d.ts +0 -22
  196. package/dist/src/core/theme/colors.d.ts +0 -222
  197. package/dist/src/core/theme/fonts.d.ts +0 -12
  198. package/dist/src/core/utils/klineConfig.d.ts +0 -28
  199. package/dist/src/core/utils/tickCount.d.ts +0 -8
  200. package/dist/src/core/utils/tickPosition.d.ts +0 -24
  201. package/dist/src/core/utils/zoom.d.ts +0 -30
  202. package/dist/src/core/viewport/viewport.d.ts +0 -31
  203. package/dist/src/index.d.ts +0 -8
  204. package/dist/src/main.d.ts +0 -0
  205. package/dist/src/plugin/ConfigManager.d.ts +0 -31
  206. package/dist/src/plugin/EventBus.d.ts +0 -34
  207. package/dist/src/plugin/HookSystem.d.ts +0 -28
  208. package/dist/src/plugin/PluginHost.d.ts +0 -57
  209. package/dist/src/plugin/PluginRegistry.d.ts +0 -40
  210. package/dist/src/plugin/StateStore.d.ts +0 -37
  211. package/dist/src/plugin/index.d.ts +0 -11
  212. package/dist/src/plugin/rendererPluginManager.d.ts +0 -77
  213. package/dist/src/plugin/stateKeys.d.ts +0 -6
  214. package/dist/src/plugin/types.d.ts +0 -445
  215. package/dist/src/semantic/controller.d.ts +0 -35
  216. package/dist/src/semantic/drawShape.d.ts +0 -14
  217. package/dist/src/semantic/index.d.ts +0 -8
  218. package/dist/src/semantic/types.d.ts +0 -298
  219. package/dist/src/semantic/validator.d.ts +0 -43
  220. package/dist/src/test-setup.d.ts +0 -6
  221. package/dist/src/types/kLine.d.ts +0 -3
  222. package/dist/src/types/price.d.ts +0 -31
  223. package/dist/src/types/volumePrice.d.ts +0 -26
  224. package/dist/src/utils/cache.d.ts +0 -33
  225. package/dist/src/utils/dateFormat.d.ts +0 -83
  226. package/dist/src/utils/http.d.ts +0 -14
  227. package/dist/src/utils/kLineDraw/MA.d.ts +0 -7
  228. package/dist/src/utils/kLineDraw/axis.d.ts +0 -150
  229. package/dist/src/utils/kLineDraw/grid.d.ts +0 -30
  230. package/dist/src/utils/kLineDraw/kLine.d.ts +0 -15
  231. package/dist/src/utils/kline/format.d.ts +0 -11
  232. package/dist/src/utils/kline/viewport.d.ts +0 -10
  233. package/dist/src/utils/logger.d.ts +0 -5
  234. package/dist/src/utils/mock/genRandomPriceData.d.ts +0 -3
  235. package/dist/src/utils/priceToY.d.ts +0 -7
  236. package/dist/src/utils/volumePrice.d.ts +0 -54
@@ -0,0 +1,570 @@
1
+ <template>
2
+ <Teleport :to="teleportTarget">
3
+ <Transition name="overlay">
4
+ <div v-if="visible" class="params-overlay" @click="$emit('close')">
5
+ <Transition name="modal">
6
+ <div class="indicator-params" @click.stop>
7
+ <!-- 头部 -->
8
+ <div class="params-header">
9
+ <div class="header-left">
10
+ <span class="params-title">{{ indicatorName }}</span>
11
+ <span class="params-subtitle">参数设置</span>
12
+ </div>
13
+ <div class="header-right">
14
+ <button
15
+ class="toggle-desc-btn"
16
+ :class="{ active: showDescription }"
17
+ @click="showDescription = !showDescription"
18
+ title="显示/隐藏说明"
19
+ >
20
+ <svg viewBox="0 0 1024 1024">
21
+ <path d="M512 97.52381c228.912762 0 414.47619 185.563429 414.47619 414.47619s-185.563429 414.47619-414.47619 414.47619S97.52381 740.912762 97.52381 512 283.087238 97.52381 512 97.52381z m0 73.142857C323.486476 170.666667 170.666667 323.486476 170.666667 512s152.81981 341.333333 341.333333 341.333333 341.333333-152.81981 341.333333-341.333333S700.513524 170.666667 512 170.666667z m36.571429 268.190476v292.571428h-73.142858V438.857143h73.142858z m0-121.904762v73.142857h-73.142858v-73.142857h73.142858z" fill="currentColor" />
22
+ </svg>
23
+ </button>
24
+ <button class="params-close" @click="$emit('close')">
25
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
26
+ <path d="M18 6L6 18M6 6l12 12" />
27
+ </svg>
28
+ </button>
29
+ </div>
30
+ </div>
31
+
32
+ <!-- 指标描述 -->
33
+ <Transition name="slide">
34
+ <div v-if="showDescription && indicatorDescription" class="indicator-description">
35
+ <p>{{ indicatorDescription }}</p>
36
+ </div>
37
+ </Transition>
38
+
39
+ <!-- 体部 -->
40
+ <div class="params-body">
41
+ <div
42
+ v-for="param in params"
43
+ :key="param.key"
44
+ class="param-item"
45
+ :class="{ 'has-desc': showDescription && param.description }"
46
+ >
47
+ <div class="param-header">
48
+ <label class="param-label">
49
+ <span class="param-label-text">{{ param.label }}</span>
50
+ <span
51
+ v-if="param.min !== undefined || param.max !== undefined"
52
+ class="param-range"
53
+ >
54
+ {{ param.min ?? '-∞' }} ~ {{ param.max ?? '+∞' }}
55
+ </span>
56
+ </label>
57
+ <div class="input-wrapper">
58
+ <button
59
+ class="stepper-btn"
60
+ :disabled="param.min !== undefined && (localValues[param.key] ?? 0) <= param.min"
61
+ @click="step(param, -1)"
62
+ >
63
+
64
+ </button>
65
+ <input
66
+ v-if="param.type === 'number'"
67
+ type="number"
68
+ class="param-input"
69
+ :value="localValues[param.key]"
70
+ :min="param.min"
71
+ :max="param.max"
72
+ :step="param.step || 1"
73
+ @input="onInput(param.key, $event)"
74
+ />
75
+ <button
76
+ class="stepper-btn"
77
+ :disabled="param.max !== undefined && (localValues[param.key] ?? 0) >= param.max"
78
+ @click="step(param, 1)"
79
+ >
80
+ +
81
+ </button>
82
+ </div>
83
+ </div>
84
+ <Transition name="slide">
85
+ <div v-if="showDescription && param.description" class="param-description">
86
+ {{ param.description }}
87
+ </div>
88
+ </Transition>
89
+ </div>
90
+ </div>
91
+
92
+ <!-- 底部 -->
93
+ <div class="params-footer">
94
+ <button class="params-btn reset" @click="onReset">
95
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
96
+ <path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" />
97
+ <path d="M3 3v5h5" />
98
+ </svg>
99
+ 重置
100
+ </button>
101
+ <div class="footer-right">
102
+ <button class="params-btn cancel" @click="$emit('close')">取消</button>
103
+ <button class="params-btn confirm" @click="onConfirm">
104
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
105
+ <path d="M20 6L9 17l-5-5" />
106
+ </svg>
107
+ 确定
108
+ </button>
109
+ </div>
110
+ </div>
111
+ </div>
112
+ </Transition>
113
+ </div>
114
+ </Transition>
115
+ </Teleport>
116
+ </template>
117
+
118
+ <script setup lang="ts">
119
+ import { ref, watch, computed } from 'vue'
120
+
121
+ export interface ParamConfig {
122
+ key: string
123
+ label: string
124
+ type: 'number'
125
+ min?: number
126
+ max?: number
127
+ step?: number
128
+ default?: number
129
+ description?: string
130
+ }
131
+
132
+ const props = defineProps<{
133
+ visible: boolean
134
+ indicatorId: string
135
+ indicatorName: string
136
+ indicatorDescription?: string
137
+ params: ParamConfig[]
138
+ values: Record<string, number>
139
+ }>()
140
+
141
+ const emit = defineEmits<{
142
+ close: []
143
+ confirm: [values: Record<string, number>]
144
+ }>()
145
+
146
+ const localValues = ref<Record<string, number>>({ ...props.values })
147
+ const showDescription = ref(true)
148
+
149
+ const teleportTarget = computed(() => 'body')
150
+
151
+ watch(
152
+ () => props.values,
153
+ (newValues) => {
154
+ localValues.value = { ...newValues }
155
+ },
156
+ { deep: true, immediate: true }
157
+ )
158
+
159
+ watch(
160
+ () => props.visible,
161
+ (visible) => {
162
+ if (visible) localValues.value = { ...props.values }
163
+ }
164
+ )
165
+
166
+ function onInput(key: string, event: Event) {
167
+ const target = event.target as HTMLInputElement
168
+ const value = parseFloat(target.value)
169
+ if (!isNaN(value)) localValues.value[key] = value
170
+ }
171
+
172
+ function step(param: ParamConfig, direction: 1 | -1) {
173
+ const s = param.step || 1
174
+ let next = (localValues.value[param.key] || 0) + direction * s
175
+ if (param.min !== undefined) next = Math.max(param.min, next)
176
+ if (param.max !== undefined) next = Math.min(param.max, next)
177
+ localValues.value[param.key] = parseFloat(next.toFixed(10))
178
+ }
179
+
180
+ function onReset() {
181
+ const defaults: Record<string, number> = {}
182
+ props.params.forEach((p) => {
183
+ defaults[p.key] = p.default ?? props.values[p.key] ?? 0
184
+ })
185
+ localValues.value = defaults
186
+ }
187
+
188
+ function onConfirm() {
189
+ emit('confirm', { ...localValues.value })
190
+ }
191
+ </script>
192
+
193
+ <style scoped>
194
+ /* ── 遮罩 ── */
195
+ .params-overlay {
196
+ position: fixed;
197
+ inset: 0;
198
+ background: rgba(0, 0, 0, 0.3);
199
+ backdrop-filter: blur(4px);
200
+ display: flex;
201
+ align-items: center;
202
+ justify-content: center;
203
+ z-index: 1000;
204
+ }
205
+
206
+ /* ── 弹窗 ── */
207
+ .indicator-params {
208
+ background: #ffffff;
209
+ border: 1px solid #e0e0e0;
210
+ border-radius: 12px;
211
+ box-shadow: 0 8px 40px rgba(0, 0, 0, 0.15);
212
+ min-width: 340px;
213
+ max-width: 420px;
214
+ width: 90vw;
215
+ overflow: hidden;
216
+ }
217
+
218
+ /* ── 头部 ── */
219
+ .params-header {
220
+ display: flex;
221
+ justify-content: space-between;
222
+ align-items: center;
223
+ padding: 16px 20px;
224
+ background: #f8f8f8;
225
+ border-bottom: 1px solid #e8e8e8;
226
+ }
227
+
228
+ .header-left {
229
+ display: flex;
230
+ align-items: baseline;
231
+ gap: 8px;
232
+ }
233
+
234
+ .header-right {
235
+ display: flex;
236
+ align-items: center;
237
+ gap: 8px;
238
+ }
239
+
240
+ .params-title {
241
+ font-size: 14px;
242
+ font-weight: 600;
243
+ color: #1a1a1a;
244
+ letter-spacing: 0.2px;
245
+ }
246
+
247
+ .params-subtitle {
248
+ font-size: 11px;
249
+ color: #999;
250
+ }
251
+
252
+ .toggle-desc-btn {
253
+ background: #fff;
254
+ border: 1px solid #e0e0e0;
255
+ border-radius: 6px;
256
+ width: 28px;
257
+ height: 28px;
258
+ display: flex;
259
+ align-items: center;
260
+ justify-content: center;
261
+ cursor: pointer;
262
+ color: #888;
263
+ transition: all 0.2s;
264
+ padding: 0;
265
+ }
266
+
267
+ .toggle-desc-btn:hover {
268
+ background: #f0f0f0;
269
+ color: #555;
270
+ border-color: #ccc;
271
+ }
272
+
273
+ .toggle-desc-btn.active {
274
+ background: #1a1a1a;
275
+ border-color: #1a1a1a;
276
+ color: #fff;
277
+ }
278
+
279
+ .toggle-desc-btn svg {
280
+ width: 14px;
281
+ height: 14px;
282
+ }
283
+
284
+ .params-close {
285
+ background: #fff;
286
+ border: 1px solid #e0e0e0;
287
+ border-radius: 6px;
288
+ width: 28px;
289
+ height: 28px;
290
+ display: flex;
291
+ align-items: center;
292
+ justify-content: center;
293
+ cursor: pointer;
294
+ color: #888;
295
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
296
+ padding: 0;
297
+ }
298
+
299
+ .params-close:hover {
300
+ background: #f0f0f0;
301
+ color: #333;
302
+ border-color: #ccc;
303
+ }
304
+
305
+ .params-close svg {
306
+ width: 14px;
307
+ height: 14px;
308
+ }
309
+
310
+ /* ── 指标描述 ── */
311
+ .indicator-description {
312
+ padding: 12px 20px;
313
+ background: #f0f7ff;
314
+ border-bottom: 1px solid #d6e8f5;
315
+ }
316
+
317
+ .indicator-description p {
318
+ margin: 0;
319
+ font-size: 12px;
320
+ line-height: 1.6;
321
+ color: #2c5282;
322
+ }
323
+
324
+ /* ── 体部 ── */
325
+ .params-body {
326
+ padding: 16px 20px;
327
+ display: flex;
328
+ flex-direction: column;
329
+ gap: 10px;
330
+ }
331
+
332
+ .param-item {
333
+ padding: 10px 14px;
334
+ border-radius: 8px;
335
+ background: #f8f8f8;
336
+ border: 1px solid #e8e8e8;
337
+ transition: border-color 0.2s;
338
+ }
339
+
340
+ .param-item:has(.param-input:focus) {
341
+ border-color: #bbb;
342
+ }
343
+
344
+ .param-item.has-desc {
345
+ padding: 10px 14px 8px;
346
+ }
347
+
348
+ .param-header {
349
+ display: flex;
350
+ align-items: center;
351
+ justify-content: space-between;
352
+ gap: 16px;
353
+ }
354
+
355
+ .param-label {
356
+ display: flex;
357
+ flex-direction: column;
358
+ gap: 3px;
359
+ }
360
+
361
+ .param-label-text {
362
+ font-size: 13px;
363
+ font-weight: 500;
364
+ color: #333;
365
+ }
366
+
367
+ .param-range {
368
+ font-size: 11px;
369
+ color: #999;
370
+ }
371
+
372
+ /* ── 参数描述 ── */
373
+ .param-description {
374
+ margin-top: 8px;
375
+ padding-top: 8px;
376
+ border-top: 1px dashed #e0e0e0;
377
+ font-size: 11px;
378
+ line-height: 1.5;
379
+ color: #666;
380
+ }
381
+
382
+ /* ── 步进输入框 ── */
383
+ .input-wrapper {
384
+ display: flex;
385
+ align-items: stretch;
386
+ height: 32px;
387
+ border: 1px solid #d0d0d0;
388
+ border-radius: 7px;
389
+ overflow: hidden;
390
+ background: #fff;
391
+ transition: border-color 0.2s;
392
+ }
393
+
394
+ .input-wrapper:focus-within {
395
+ border-color: #999;
396
+ }
397
+
398
+ .stepper-btn {
399
+ width: 28px;
400
+ background: #f0f0f0;
401
+ border: none;
402
+ cursor: pointer;
403
+ font-size: 15px;
404
+ font-weight: 400;
405
+ color: #666;
406
+ display: flex;
407
+ align-items: center;
408
+ justify-content: center;
409
+ transition: background 0.15s, color 0.15s;
410
+ flex-shrink: 0;
411
+ line-height: 1;
412
+ }
413
+
414
+ .stepper-btn:hover:not(:disabled) {
415
+ background: #e0e0e0;
416
+ color: #333;
417
+ }
418
+
419
+ .stepper-btn:disabled {
420
+ color: #ccc;
421
+ cursor: not-allowed;
422
+ }
423
+
424
+ .param-input {
425
+ width: 60px;
426
+ border: none;
427
+ border-left: 1px solid #e8e8e8;
428
+ border-right: 1px solid #e8e8e8;
429
+ font-size: 13px;
430
+ font-weight: 600;
431
+ text-align: center;
432
+ color: #1a1a1a;
433
+ background: transparent;
434
+ -moz-appearance: textfield;
435
+ appearance: textfield;
436
+ }
437
+
438
+ .param-input::-webkit-inner-spin-button,
439
+ .param-input::-webkit-outer-spin-button {
440
+ -webkit-appearance: none;
441
+ }
442
+
443
+ .param-input:focus {
444
+ outline: none;
445
+ }
446
+
447
+ /* ── 底部 ── */
448
+ .params-footer {
449
+ display: flex;
450
+ align-items: center;
451
+ justify-content: space-between;
452
+ padding: 12px 20px;
453
+ background: #f8f8f8;
454
+ border-top: 1px solid #e8e8e8;
455
+ }
456
+
457
+ .footer-right {
458
+ display: flex;
459
+ gap: 8px;
460
+ }
461
+
462
+ .params-btn {
463
+ display: flex;
464
+ align-items: center;
465
+ gap: 5px;
466
+ padding: 6px 14px;
467
+ border-radius: 7px;
468
+ font-size: 13px;
469
+ font-weight: 500;
470
+ cursor: pointer;
471
+ border: 1px solid transparent;
472
+ transition: all 0.15s;
473
+ line-height: 1.4;
474
+ }
475
+
476
+ .params-btn svg {
477
+ width: 12px;
478
+ height: 12px;
479
+ flex-shrink: 0;
480
+ }
481
+
482
+ /* 重置 */
483
+ .params-btn.reset {
484
+ background: transparent;
485
+ border-color: #d0d0d0;
486
+ color: #666;
487
+ }
488
+
489
+ .params-btn.reset:hover {
490
+ border-color: #c0392b;
491
+ color: #e74c3c;
492
+ background: rgba(231, 76, 60, 0.08);
493
+ }
494
+
495
+ /* 取消 */
496
+ .params-btn.cancel {
497
+ background: transparent;
498
+ border-color: #d0d0d0;
499
+ color: #666;
500
+ }
501
+
502
+ .params-btn.cancel:hover {
503
+ background: #f0f0f0;
504
+ color: #333;
505
+ border-color: #bbb;
506
+ }
507
+
508
+ /* 确定 */
509
+ .params-btn.confirm {
510
+ background: #1a1a1a;
511
+ border-color: #1a1a1a;
512
+ color: #fff;
513
+ }
514
+
515
+ .params-btn.confirm:hover {
516
+ background: #333;
517
+ border-color: #333;
518
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
519
+ transform: translateY(-1px);
520
+ }
521
+
522
+ .params-btn.confirm:active {
523
+ transform: translateY(0);
524
+ box-shadow: none;
525
+ }
526
+
527
+ /* ── 动画 ── */
528
+ .overlay-enter-active,
529
+ .overlay-leave-active {
530
+ transition: opacity 0.2s ease;
531
+ }
532
+
533
+ .overlay-enter-from,
534
+ .overlay-leave-to {
535
+ opacity: 0;
536
+ }
537
+
538
+ .modal-enter-active {
539
+ transition: all 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
540
+ }
541
+
542
+ .modal-leave-active {
543
+ transition: all 0.16s ease-in;
544
+ }
545
+
546
+ .modal-enter-from {
547
+ opacity: 0;
548
+ transform: scale(0.88) translateY(-16px);
549
+ }
550
+
551
+ .modal-leave-to {
552
+ opacity: 0;
553
+ transform: scale(0.94) translateY(8px);
554
+ }
555
+
556
+ .slide-enter-active,
557
+ .slide-leave-active {
558
+ transition: all 0.2s ease;
559
+ overflow: hidden;
560
+ }
561
+
562
+ .slide-enter-from,
563
+ .slide-leave-to {
564
+ opacity: 0;
565
+ max-height: 0;
566
+ padding-top: 0;
567
+ padding-bottom: 0;
568
+ margin-top: 0;
569
+ }
570
+ </style>