st-comp 0.0.247 → 0.0.248

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 (86) hide show
  1. package/es/ChartLayout.js +4 -4
  2. package/es/CustomFunction.js +42 -42
  3. package/es/FactorWarning.js +33 -33
  4. package/es/Kline.js +17 -17
  5. package/es/KlineBasic.js +26 -26
  6. package/es/KlineConfig.js +61 -61
  7. package/es/KlineNew.js +16 -16
  8. package/es/KlinePlus.cjs +4 -4
  9. package/es/KlinePlus.js +589 -575
  10. package/es/LinearLegend.cjs +1 -1
  11. package/es/LinearLegend.js +1 -63
  12. package/es/MonacoEditor.js +24 -24
  13. package/es/Pagination.js +73 -73
  14. package/es/PasswordPrompt.js +3 -3
  15. package/es/Table.js +38 -38
  16. package/es/User.js +44 -44
  17. package/es/VarSelectDialog.js +25 -25
  18. package/es/VarietyAutoComplete.js +10 -10
  19. package/es/VarietySearch.js +38 -38
  20. package/es/{VarietySelect-5a9dd50b.js → VarietySelect-b9fe3000.js} +4 -4
  21. package/es/VarietyTextCopy.js +12 -12
  22. package/es/VirtualTable.js +14 -14
  23. package/es/{_initCloneObject-c34c65bc.js → _initCloneObject-382335b2.js} +7 -7
  24. package/es/{base-a5af3db3.js → base-ff0e366f.js} +40 -40
  25. package/es/{castArray-7741a212.js → castArray-15070be9.js} +1 -1
  26. package/es/{config-provider-06a63185.js → config-provider-2e85eee8.js} +6 -6
  27. package/es/{debounce-8d53f4dd.js → debounce-e9e47f9a.js} +1 -1
  28. package/es/{dropdown-302f71e7.js → dropdown-2b35a683.js} +13 -13
  29. package/es/{el-autocomplete-ed75a659.js → el-autocomplete-18be2c5a.js} +16 -16
  30. package/es/{el-button-d09ff85f.js → el-button-f08c0639.js} +39 -39
  31. package/es/{el-checkbox-64648e02.js → el-checkbox-058dba2d.js} +31 -31
  32. package/es/{el-dialog-6a80e3d8.js → el-dialog-d328e0d8.js} +15 -15
  33. package/es/{el-divider-4e059794.js → el-divider-4fe55ebe.js} +1 -1
  34. package/es/{el-empty-33cb66f1.js → el-empty-ceecb81c.js} +5 -5
  35. package/es/{el-form-item-4eca95be.js → el-form-item-cb328886.js} +36 -36
  36. package/es/{el-input-cae60510.js → el-input-0f6ead19.js} +50 -50
  37. package/es/{el-input-number-c2499410.js → el-input-number-66e68609.js} +36 -36
  38. package/es/{el-loading-c738468d.js → el-loading-412370c7.js} +5 -5
  39. package/es/{el-menu-item-f904f685.js → el-menu-item-0ee8ad18.js} +22 -22
  40. package/es/{el-message-box-05d8cf39.js → el-message-box-6db52b29.js} +11 -11
  41. package/es/{el-message-0df23ae7.js → el-message-e6c755df.js} +23 -23
  42. package/es/{el-overlay-cc9bc792.js → el-overlay-981f8d49.js} +56 -56
  43. package/es/{el-popconfirm-a6f66a0e.js → el-popconfirm-005013fa.js} +20 -20
  44. package/es/{el-popper-a38874f4.js → el-popper-fdc7c793.js} +109 -109
  45. package/es/{el-segmented-51b1c797.js → el-segmented-050d0090.js} +8 -8
  46. package/es/{el-select-1b149fab.js → el-select-23a1f302.js} +64 -64
  47. package/es/{el-table-column-3e30ebae.js → el-table-column-d0c374cf.js} +15 -15
  48. package/es/{el-tag-0a25efdf.js → el-tag-f13f463b.js} +15 -15
  49. package/es/{el-text-73d899ff.js → el-text-27cef2be.js} +2 -2
  50. package/es/{index-42e59bf5.js → index-09bd2621.js} +43 -43
  51. package/es/{index-94e43e0d.js → index-15b9603e.js} +3 -3
  52. package/es/{index-960806da.js → index-269b8a8c.js} +36 -36
  53. package/es/{index-54d289d1.js → index-4a3f30c5.js} +12 -12
  54. package/es/{index-6e967429.js → index-80a7ad32.js} +17 -17
  55. package/es/{index-d77a7336.js → index-93a8960e.js} +1 -1
  56. package/es/{index-4194c942.js → index-b937ea22.js} +2 -2
  57. package/es/{index-ac98a4d8.js → index-c266c23a.js} +10 -10
  58. package/es/{index-6806997d.js → index-e0901394.js} +34 -34
  59. package/es/{index-87b4bf61.js → index-ec7ad93f.js} +31 -31
  60. package/es/{python-a914569a.js → python-823b276b.js} +24 -24
  61. package/es/raf-8e05a7f4.js +6 -0
  62. package/es/{scroll-679bd6bf.js → scroll-41b4f625.js} +5 -5
  63. package/es/style.css +1 -1
  64. package/es/{use-form-common-props-47e50c10.js → use-form-common-props-631cacae.js} +65 -65
  65. package/es/{use-global-config-f52caea0.js → use-global-config-5d001623.js} +14 -14
  66. package/es/{validator-94c04152.js → validator-4160d9e7.js} +1 -1
  67. package/es/{vnode-5ddb7ed1.js → vnode-06571d5b.js} +1 -1
  68. package/es/{zh-cn-4921961d.js → zh-cn-5df98ac2.js} +2 -2
  69. package/lib/bundle.js +1 -1
  70. package/lib/bundle.umd.cjs +79 -79
  71. package/lib/{index-750ede1b.js → index-f00d1e1f.js} +4912 -4898
  72. package/lib/{python-e34a2958.js → python-0f34e2e6.js} +1 -1
  73. package/lib/style.css +1 -1
  74. package/package.json +1 -1
  75. package/packages/KlinePlus/index.vue +88 -62
  76. package/src/App.vue +15 -4
  77. package/src/pages/KlineNew/components/KlineAction/mockApi/index.js +1 -1
  78. package/src/pages/KlineNew/components/KlineBasic/utils.js +1 -1
  79. package/src/pages/KlineNew/components/KlineSlide/utils.js +1 -1
  80. package/src/pages/KlinePlus/KlineDialog/MultiCycle.vue +312 -0
  81. package/src/pages/KlinePlus/KlineDialog/api.js +108 -0
  82. package/src/pages/KlinePlus/KlineDialog/index.vue +582 -0
  83. package/src/pages/KlinePlus/KlineDialog/indicator.js +109 -0
  84. package/src/pages/KlinePlus/KlineDialog/tools.js +86 -0
  85. package/src/pages/KlinePlus/index.vue +23 -209
  86. package/es/raf-80ef0c0a.js +0 -6
@@ -0,0 +1,108 @@
1
+ import axios from "axios";
2
+
3
+ // 测试环境
4
+ // const userid = 103;
5
+ // const token = "490cebe77872589fc6f670d30983b268";
6
+ // export const host = "http://192.168.12.38:5173";
7
+
8
+ // 线上环境
9
+ const userid = 200;
10
+ const token = "02e233681c5cecaf788525e70c380ed5";
11
+ export const host = "//investapi.hzyotoy.com";
12
+
13
+ // 获取数据: 指标列表
14
+ export const getIndicator = async (data) => {
15
+ const res = await axios({
16
+ method: "post",
17
+ headers: { token, userid },
18
+ url: `${host}/middleLayer/kline/getIndicator`,
19
+ data,
20
+ });
21
+ return res.data;
22
+ };
23
+
24
+ // 获取周期列表
25
+ export const getCycleList = async () => {
26
+ const res = await axios({
27
+ method: "post",
28
+ headers: { token, userid },
29
+ url: `${host}/middleLayer/post/common/qt/getDict`,
30
+ data: { dictIds: [1002] },
31
+ });
32
+ return res.data;
33
+ };
34
+
35
+ // 查询品种是否股票
36
+ export const queryContractType = async (data) => {
37
+ const res = await axios({
38
+ method: "post",
39
+ headers: { token, userid },
40
+ url: `${host}/middleLayer/bjpost/invest/analysis/queryContractType`,
41
+ data,
42
+ });
43
+ return res.data;
44
+ };
45
+
46
+ // 获取净值曲线数据
47
+ export const queryVarietyNetPositionValue = async (data) => {
48
+ const res = await axios({
49
+ method: "post",
50
+ headers: { token, userid },
51
+ url: `${host}/middleLayer/bjpost/invest/analysis/queryVarietyNetPositionValue`,
52
+ data,
53
+ });
54
+ return res.data;
55
+ };
56
+
57
+ // 获取交易订单数据
58
+ export const queryPairedRecordByVariety = async (data) => {
59
+ const res = await axios({
60
+ method: "post",
61
+ headers: { token, userid },
62
+ url: `${host}/middleLayer/bjpost/invest/analysis/queryPairedRecordByVariety`,
63
+ data,
64
+ });
65
+ return res.data;
66
+ };
67
+
68
+ // 获取篮子品种对应的价差指数
69
+ export const queryJCVariety = async (data) => {
70
+ const res = await axios({
71
+ method: "post",
72
+ headers: { token, userid },
73
+ url: `${host}/middleLayer/bjpost/invest/analysis/queryJCVariety`,
74
+ data,
75
+ });
76
+ return res.data;
77
+ };
78
+
79
+ export const getUserConfig = async (data) => {
80
+ const res = await axios({
81
+ method: "post",
82
+ headers: { token, userid },
83
+ url: `${host}/middleLayer/bjpost/common/qt/getUserConfig`,
84
+ data,
85
+ });
86
+ return res.data;
87
+ };
88
+
89
+ // 获取配置
90
+ export const getConfig = async () => {
91
+ const res = await axios({
92
+ method: "get",
93
+ headers: { token, userid },
94
+ url: `${host}/middleLayer/get/invest/sys/frontconfig/info`,
95
+ });
96
+ return res.data;
97
+ };
98
+
99
+ // 设置配置
100
+ export const setConfig = async (data) => {
101
+ const res = await axios({
102
+ method: "post",
103
+ headers: { token, userid },
104
+ url: `${host}/middleLayer/post/invest/sys/frontconfig/save`,
105
+ data,
106
+ });
107
+ return res.data;
108
+ };
@@ -0,0 +1,582 @@
1
+ <script setup>
2
+ import { actionStat } from "st-func";
3
+ import { ref, reactive, onMounted, provide, nextTick, watch } from "vue";
4
+ import { ArrowLeftBold, ArrowRightBold, RefreshRight, CloseBold, Setting } from "@element-plus/icons-vue";
5
+ import { sellBuyOptions, rightTypeOptions, klineTypeOptions, formatLabel, getTimeRange } from "./tools.js";
6
+ import useIndicatorStore from "./indicator.js";
7
+ import { queryContractType, queryVarietyNetPositionValue, queryPairedRecordByVariety, queryJCVariety, getUserConfig, getCycleList } from "./api.js";
8
+ import MultiCycle from "./MultiCycle.vue";
9
+
10
+ const actionParams = ref({ pageName: null, other: null }); // 数据埋点
11
+
12
+ const stKlineConfigRef = ref(null);
13
+ const userKlineConfig = reactive({});
14
+ provide("userKlineConfig", userKlineConfig);
15
+
16
+ const indicatorStore = useIndicatorStore();
17
+ const cycleOptions = ref([]);
18
+
19
+ const visible = ref(false);
20
+ const loading = ref(false); // 初始数据载入, 参数变动等
21
+ const MultiCycleRef = ref(null);
22
+
23
+ const pageType = ref(1);
24
+ const analyseId = ref(null);
25
+ const varietyList = ref([]);
26
+ const varietyIndex = ref(0);
27
+
28
+ const varietyName = ref(null);
29
+ const varietyCode = ref(null);
30
+ const jcVarietyOptions = ref([]); // 价差品种数据源
31
+ const ifBasket = ref(0); // 1: 是篮子, 0: 不是篮子
32
+
33
+ // 品种参数
34
+ const varietyStock = ref(1); // 0: 期货, 1: 股票, 2: 期权
35
+ const tradeLog = ref([]);
36
+ const netPositionData = ref([]);
37
+
38
+ // 交互参数
39
+ const cycle = ref("6");
40
+ const sellBuy = ref(1);
41
+ const rightType = ref(1);
42
+ const klineType = ref(0);
43
+ const mainIndicator = ref("DKX_EMA");
44
+
45
+ /**
46
+ * @description: 首屏时间
47
+ * 1. 默认按照交易第一笔开仓 ~ 最后一笔平仓时间 (前后拓展200根)
48
+ * 2. 如果参数positionTime, 则以此时间为准 (前后拓展200根)
49
+ */
50
+ const initTimeRange = ref([]);
51
+ const positionTime = ref(null);
52
+
53
+ // 获取主品种类型
54
+ const getVarietyStock = async () => {
55
+ const params = { condition: varietyCode.value, conditionName: varietyName.value };
56
+ const { body } = await queryContractType(params);
57
+ varietyStock.value = body;
58
+ };
59
+ // 获取价差品种数据
60
+ const getJcVarietyOptions = async () => {
61
+ if (varietyStock.value === 1) {
62
+ const params = { condition: varietyCode.value, conditionName: varietyName.value };
63
+ const { body } = await queryJCVariety(params);
64
+ jcVarietyOptions.value = body ?? [];
65
+ } else {
66
+ jcVarietyOptions.value = [{ varietyName: varietyName.value, varietyCode: varietyCode.value }];
67
+ }
68
+ };
69
+
70
+ // 获取品种交易数据
71
+ const getTradeLog = async () => {
72
+ // 如果已经自带了交易数据, 说明是要聚焦这一笔明细的, 就不用拉取全部数据
73
+ if (tradeLog.value.length !== 0) return;
74
+ const params = {
75
+ analyseId: analyseId.value,
76
+ varietyName: varietyName.value,
77
+ varietyCode: varietyCode.value,
78
+ ifBasket: ifBasket.value, // 是否篮子
79
+ cycle: cycle.value,
80
+ };
81
+ const { body } = await queryPairedRecordByVariety(params);
82
+ tradeLog.value = body ?? [];
83
+ };
84
+ // 获取品种净值数据
85
+ const getNetPositionData = async () => {
86
+ // 如果没有交易数据, 就不用请求净值数据了
87
+ if (tradeLog.value.length === 0) return;
88
+ if (ifBasket.value === 1) return;
89
+ const params = {
90
+ analyseId: analyseId.value,
91
+ varietyCode: varietyCode.value,
92
+ startTime: tradeLog.value[0].openTime,
93
+ endTime: tradeLog.value.at(-1).closeTime,
94
+ };
95
+ const { body } = await queryVarietyNetPositionValue(params);
96
+ netPositionData.value = body;
97
+ };
98
+
99
+ // 顶栏: 时间控制
100
+ const handleTimeRange = async (type) => {
101
+ // 单周期
102
+ if (pageType.value === 1) {
103
+ const params = {
104
+ type,
105
+ cycle: cycle.value,
106
+ startTime: tradeLog.value[0]?.openTime,
107
+ endTime: positionTime.value ? positionTime.value : tradeLog.value.at(-1)?.closeTime,
108
+ };
109
+ initTimeRange.value = getTimeRange(params);
110
+ }
111
+ // 多周期
112
+ else if (pageType.value === 2) MultiCycleRef.value?.changeTimeRange(type);
113
+ };
114
+ // 顶栏: 主品种切换
115
+ const handleChangeVariety = async (type) => {
116
+ const oldIndex = varietyIndex.value;
117
+ const maxIndex = varietyList.value.length - 1;
118
+ switch (type) {
119
+ // 上一个品种
120
+ case "pre": {
121
+ if (oldIndex === 0) return ElMessage.warning("已是本页第一个品种");
122
+ varietyIndex.value -= 1;
123
+ break;
124
+ }
125
+ // 下一个品种
126
+ case "next": {
127
+ if (oldIndex === maxIndex) return ElMessage.warning("已是本页最后一个品种");
128
+ varietyIndex.value += 1;
129
+ break;
130
+ }
131
+ }
132
+ if (oldIndex !== varietyIndex.value) {
133
+ loading.value = true;
134
+ const varietyInfo = varietyList.value[varietyIndex.value];
135
+ varietyName.value = varietyInfo.varietyName;
136
+ varietyCode.value = varietyInfo.varietyCode;
137
+ ifBasket.value = varietyInfo.ifBasket;
138
+ tradeLog.value = varietyInfo.tradeLog ?? [];
139
+ netPositionData.value = [];
140
+ await getVarietyStock();
141
+ await getJcVarietyOptions();
142
+ await getTradeLog();
143
+ await getNetPositionData();
144
+ handleTimeRange("reset");
145
+ loading.value = false;
146
+ }
147
+ };
148
+ // 顶栏: 价差品种切换
149
+ const handleChangeJcVariety = (varietyCode) => {
150
+ const item = jcVarietyOptions.value.find((i) => i.varietyCode === varietyCode);
151
+ // 由于这里要修改其它响应式数据, select组件内部原因, 自动关闭下拉框这一行为会受到影响, 所以使用nextTick
152
+ nextTick(() => {
153
+ varietyName.value = item.varietyName;
154
+ handleTimeRange("reset");
155
+ });
156
+ };
157
+
158
+ // 多周期双击切到单周期
159
+ const goToSingleCycle = (item) => {
160
+ if (!userKlineConfig.enable_dbClickOpenSingel) return;
161
+ cycle.value = item.cycle;
162
+ pageType.value = 1;
163
+ };
164
+ // 用户自定义K线配置(获取, 更新)
165
+ const handleUserKlineConfig = async (action, formJson) => {
166
+ switch (action) {
167
+ case "get": {
168
+ const { body } = await getUserConfig({ appId: 1 });
169
+ Object.assign(userKlineConfig, stKlineConfigRef.value?.getDefaultUserKlineConfig(), body ? JSON.parse(body) : {});
170
+ console.log(userKlineConfig)
171
+ break;
172
+ }
173
+ case "update": {
174
+ loading.value = true;
175
+ // 更新配置数据
176
+ Object.assign(userKlineConfig, JSON.parse(formJson));
177
+ // 默认值 [自定义配置]
178
+ pageType.value = userKlineConfig.pageType;
179
+ cycle.value = userKlineConfig.singelCycle;
180
+ sellBuy.value = userKlineConfig.sellBuy;
181
+ mainIndicator.value = userKlineConfig.mainIndicator;
182
+ nextTick(() => (loading.value = false));
183
+ }
184
+ }
185
+ };
186
+
187
+ onMounted(async () => {
188
+ await indicatorStore.init();
189
+ handleUserKlineConfig("get");
190
+ cycleOptions.value = (await getCycleList()).body[1002].map((item) => ({ label: item.dictName, value: item.dictCode }));
191
+ });
192
+ watch(
193
+ () => pageType.value,
194
+ (newValue) => {
195
+ // 当切换到单周期的时候, 需要重置初始时间, 多周期业务组件内部自带了重置触发逻辑
196
+ if (newValue === 1) handleTimeRange("reset");
197
+ actionParams.value?.pageName && actionStat(actionParams.value?.pageName, "查看K线", pageType.value === 1 ? "单周期" : "多周期");
198
+ }
199
+ );
200
+ defineExpose({
201
+ /**
202
+ * @description: 打开K线弹窗组件
203
+ * @param {Object} params - 入参
204
+ * params.analyseId - 绩效记录id
205
+ * params.varietyInfo - 品种信息 { index, varietyName, varietyCode, ifBasket, positionTime, tradeLog }
206
+ * params.varietyList - 当页品种列表 <varietyInfo>
207
+ * params.actionParams - 行为埋点参数
208
+ */
209
+ open: async (params) => {
210
+ try {
211
+ loading.value = true;
212
+ visible.value = true;
213
+
214
+ // 外部传入
215
+ analyseId.value = params.analyseId;
216
+ varietyList.value = params.varietyList ?? [];
217
+ varietyIndex.value = params.varietyInfo.index ?? 0;
218
+ varietyName.value = params.varietyInfo.varietyName;
219
+ varietyCode.value = params.varietyInfo.varietyCode;
220
+ ifBasket.value = params.varietyInfo.ifBasket;
221
+ positionTime.value = params.varietyInfo.positionTime;
222
+ tradeLog.value = params.varietyInfo.tradeLog ?? [];
223
+
224
+ // 默认值 [内部固定]
225
+ varietyStock.value = 1;
226
+ rightType.value = 1;
227
+ klineType.value = 0;
228
+ initTimeRange.value = [];
229
+ netPositionData.value = [];
230
+
231
+ // 默认值 [自定义配置]
232
+ pageType.value = userKlineConfig.pageType;
233
+ cycle.value = userKlineConfig.singelCycle;
234
+ sellBuy.value = userKlineConfig.sellBuy;
235
+ mainIndicator.value = userKlineConfig.mainIndicator;
236
+
237
+ await getVarietyStock();
238
+ await getJcVarietyOptions();
239
+ await getTradeLog();
240
+ await getNetPositionData();
241
+ handleTimeRange("reset");
242
+ } catch (error) {
243
+ throw new Error(`打开K线弹窗异常: ${error}`);
244
+ } finally {
245
+ loading.value = false;
246
+ // 埋点
247
+ actionParams.value = params.actionParams;
248
+ actionParams.value?.pageName && actionStat(actionParams.value?.pageName, "查看K线", pageType.value === 1 ? "单周期" : "多周期");
249
+ }
250
+ },
251
+ });
252
+ </script>
253
+
254
+ <template>
255
+ <el-dialog
256
+ class="kline-dialog"
257
+ v-model="visible"
258
+ :fullscreen="true"
259
+ :show-close="false"
260
+ :destroy-on-close="true"
261
+ :z-index="2000"
262
+ >
263
+ <div class="main element-dark">
264
+ <template v-if="!loading">
265
+ <!-- 功能栏 -->
266
+ <div class="kline-header">
267
+ <!-- 标题 -->
268
+ <div class="kline-header-item kline-header-item-select">
269
+ <span> {{ varietyName }} {{ varietyCode }} </span>
270
+ <el-select
271
+ v-model="varietyCode"
272
+ popper-class="element-dark"
273
+ @change="handleChangeJcVariety"
274
+ >
275
+ <el-option
276
+ v-for="(item, index) in jcVarietyOptions"
277
+ :key="item.varietyCode"
278
+ :label="`${item.varietyName} ${item.varietyCode}`"
279
+ :value="item.varietyCode"
280
+ />
281
+ </el-select>
282
+ </div>
283
+ <!-- 周期 -->
284
+ <template v-if="pageType === 1">
285
+ <div class="kline-header-item kline-header-item-select">
286
+ <span>{{ formatLabel(cycle, cycleOptions) }}</span>
287
+ <el-select
288
+ v-model="cycle"
289
+ popper-class="element-dark"
290
+ >
291
+ <el-option
292
+ v-for="(item, index) in cycleOptions"
293
+ :key="index"
294
+ :label="item.label"
295
+ :value="item.value"
296
+ />
297
+ </el-select>
298
+ </div>
299
+ </template>
300
+ <!-- 指标 -->
301
+ <div class="kline-header-item kline-header-item-select">
302
+ <span>{{ mainIndicator }}</span>
303
+ <el-select
304
+ v-model="mainIndicator"
305
+ popper-class="element-dark"
306
+ >
307
+ <el-option
308
+ v-for="(item, index) in indicatorStore.mainIndicatorList"
309
+ :key="index"
310
+ :label="item.label"
311
+ :value="item.value"
312
+ />
313
+ <template #footer>
314
+ <el-button
315
+ text
316
+ :icon="Setting"
317
+ @click="indicatorStore.config"
318
+ >
319
+ 指标配置
320
+ </el-button>
321
+ </template>
322
+ </el-select>
323
+ </div>
324
+ <!-- 买卖 -->
325
+ <div class="kline-header-item kline-header-item-select">
326
+ <span>{{ formatLabel(sellBuy, sellBuyOptions) }}</span>
327
+ <el-select
328
+ v-model="sellBuy"
329
+ popper-class="element-dark"
330
+ >
331
+ <el-option
332
+ v-for="(item, index) in sellBuyOptions"
333
+ :key="index"
334
+ :label="item.label"
335
+ :value="item.value"
336
+ />
337
+ </el-select>
338
+ </div>
339
+ <!-- 复权选项 [股票] -->
340
+ <template v-if="varietyStock === 1">
341
+ <div class="kline-header-item kline-header-item-select">
342
+ <span>{{ formatLabel(rightType, rightTypeOptions) }}</span>
343
+ <el-select
344
+ v-model="rightType"
345
+ popper-class="element-dark"
346
+ >
347
+ <el-option
348
+ v-for="(item, index) in rightTypeOptions"
349
+ :key="index"
350
+ :label="item.label"
351
+ :value="item.value"
352
+ />
353
+ </el-select>
354
+ </div>
355
+ </template>
356
+ <!-- 常用选项 [期货] -->
357
+ <template v-if="varietyStock === 0">
358
+ <div class="kline-header-item kline-header-item-select">
359
+ <span>{{ formatLabel(klineType, klineTypeOptions) }}</span>
360
+ <el-select
361
+ v-model="klineType"
362
+ popper-class="element-dark"
363
+ >
364
+ <el-option
365
+ v-for="(item, index) in klineTypeOptions"
366
+ :key="index"
367
+ :label="item.label"
368
+ :value="item.value"
369
+ />
370
+ </el-select>
371
+ </div>
372
+ </template>
373
+ <!-- 品种切换 -->
374
+ <template v-if="varietyList.length">
375
+ <div class="kline-header-item">
376
+ <el-button
377
+ size="small"
378
+ :icon="ArrowLeftBold"
379
+ @click="handleChangeVariety('pre')"
380
+ >
381
+ 上一品种
382
+ </el-button>
383
+ <el-button
384
+ size="small"
385
+ @click="handleChangeVariety('next')"
386
+ >
387
+ 下一品种
388
+ <el-icon class="el-icon--right"><ArrowRightBold /></el-icon>
389
+ </el-button>
390
+ </div>
391
+ </template>
392
+ <!-- 时间控制 -->
393
+ <div class="kline-header-item">
394
+ <el-button
395
+ link
396
+ size="small"
397
+ @click="handleTimeRange('week')"
398
+ >本周</el-button
399
+ >
400
+ <el-button
401
+ link
402
+ size="small"
403
+ @click="handleTimeRange('month')"
404
+ >本月</el-button
405
+ >
406
+ <el-button
407
+ size="small"
408
+ :icon="RefreshRight"
409
+ @click="handleTimeRange('reset')"
410
+ >重置</el-button
411
+ >
412
+ </div>
413
+ <!-- 关闭 -->
414
+ <div class="kline-header-item-right">
415
+ <el-radio-group
416
+ size="small"
417
+ v-model="pageType"
418
+ >
419
+ <el-radio-button :value="1">单周期</el-radio-button>
420
+ <el-radio-button :value="2">多周期</el-radio-button>
421
+ </el-radio-group>
422
+ <el-icon
423
+ class="setting-icon"
424
+ title="K线自定义配置"
425
+ :size="20"
426
+ @click="stKlineConfigRef?.open"
427
+ >
428
+ <Setting />
429
+ </el-icon>
430
+ <el-button
431
+ size="small"
432
+ @click="() => (visible = false)"
433
+ >
434
+ 关闭窗口
435
+ <el-icon class="close-icon">
436
+ <CloseBold />
437
+ </el-icon>
438
+ </el-button>
439
+ </div>
440
+ </div>
441
+ <!-- 内容 -->
442
+ <div class="kline-body">
443
+ <!-- K线组件 [单周期] -->
444
+ <template v-if="pageType === 1">
445
+ <st-klinePlus
446
+ :varietyCode="varietyCode"
447
+ :varietyStock="varietyStock"
448
+ :indicatorStore="indicatorStore"
449
+ :userKlineConfig="userKlineConfig"
450
+ :cycle="cycle"
451
+ :sellBuy="sellBuy"
452
+ :rightType="rightType"
453
+ :klineType="klineType"
454
+ :initTimeRange="initTimeRange"
455
+ :mainIndicator="mainIndicator"
456
+ :tradeLog="tradeLog"
457
+ :netPositionData="netPositionData"
458
+ :positionTime="positionTime"
459
+ />
460
+ </template>
461
+ <!-- K线组件 [多周期] -->
462
+ <template v-else>
463
+ <MultiCycle
464
+ ref="MultiCycleRef"
465
+ :varietyCode="varietyCode"
466
+ :varietyStock="varietyStock"
467
+ :indicatorStore="indicatorStore"
468
+ :userKlineConfig="userKlineConfig"
469
+ :sellBuy="sellBuy"
470
+ :rightType="rightType"
471
+ :klineType="klineType"
472
+ :initTimeRange="initTimeRange"
473
+ :mainIndicator="mainIndicator"
474
+ :tradeLog="tradeLog"
475
+ :netPositionData="netPositionData"
476
+ :positionTime="positionTime"
477
+ @goToSingleCycle="goToSingleCycle"
478
+ />
479
+ </template>
480
+ </div>
481
+ </template>
482
+ <template v-else>
483
+ <div
484
+ class="user-kline-config-loading"
485
+ v-loading="loading"
486
+ />
487
+ </template>
488
+ </div>
489
+ </el-dialog>
490
+ <st-klineConfig
491
+ ref="stKlineConfigRef"
492
+ :indicatorStore="indicatorStore"
493
+ @callBack="(formJson) => handleUserKlineConfig('update', formJson)"
494
+ />
495
+ </template>
496
+
497
+ <style lang="scss">
498
+ .kline-dialog {
499
+ padding: 0;
500
+ background-color: black;
501
+ .el-dialog__header {
502
+ display: none !important;
503
+ }
504
+ .el-dialog__body {
505
+ padding: 0;
506
+ border: none;
507
+ }
508
+ }
509
+ </style>
510
+ <style lang="scss" scoped>
511
+ .kline-dialog {
512
+ .main {
513
+ width: 100vw;
514
+ height: 100vh;
515
+ color-scheme: dark;
516
+ background-color: black;
517
+ overflow: hidden;
518
+ position: relative;
519
+ .kline-header {
520
+ color: white;
521
+ font-size: 14px;
522
+ display: flex;
523
+ align-items: center;
524
+ border-bottom: 1px solid rgb(100, 100, 100);
525
+ position: relative;
526
+ .kline-header-item {
527
+ height: 32px;
528
+ line-height: 32px;
529
+ display: flex;
530
+ align-items: center;
531
+ border-right: 1px solid rgb(100, 100, 100);
532
+ padding: 0 6px;
533
+ box-sizing: border-box;
534
+ }
535
+ .kline-header-item-select {
536
+ :deep(.el-select) {
537
+ margin-left: 4px;
538
+ width: 16px;
539
+ .el-select__icon {
540
+ margin-left: 0;
541
+ color: black;
542
+ width: 16px;
543
+ height: 16px;
544
+ }
545
+ .el-select__wrapper {
546
+ border-radius: 50%;
547
+ background: #ccc;
548
+ padding: 0;
549
+ gap: 0;
550
+ min-height: 12px;
551
+ line-height: 12px;
552
+ }
553
+ }
554
+ }
555
+ .kline-header-item-right {
556
+ height: 100%;
557
+ position: absolute;
558
+ top: 0px;
559
+ right: 6px;
560
+ display: flex;
561
+ align-items: center;
562
+ gap: 10px;
563
+ .el-icon {
564
+ font-size: 18px;
565
+ cursor: pointer;
566
+ &:hover {
567
+ color: var(--el-color-primary);
568
+ }
569
+ }
570
+ }
571
+ }
572
+ .kline-body {
573
+ width: 100vw;
574
+ height: calc(100vh - 39px);
575
+ }
576
+ .user-kline-config-loading {
577
+ width: 100%;
578
+ height: 100%;
579
+ }
580
+ }
581
+ }
582
+ </style>