st-comp 0.0.237 → 0.0.238
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components.d.ts +0 -1
- package/es/CustomFunction.cjs +1 -1
- package/es/CustomFunction.js +21 -21
- package/es/FactorWarning.cjs +1 -1
- package/es/FactorWarning.js +25 -25
- package/es/Kline.cjs +1 -1
- package/es/Kline.js +10 -10
- package/es/KlineBasic.cjs +1 -1
- package/es/KlineBasic.js +18 -18
- package/es/KlineConfig.cjs +1 -1
- package/es/KlineConfig.js +15 -15
- package/es/KlineNew.cjs +1 -1
- package/es/KlineNew.js +9 -9
- package/es/KlinePlus.cjs +1 -1
- package/es/KlinePlus.js +11 -11
- package/es/MonacoEditor.cjs +1 -1
- package/es/MonacoEditor.js +3 -31
- package/es/Pagination.cjs +1 -1
- package/es/Pagination.js +13 -13
- package/es/PasswordPrompt.cjs +1 -1
- package/es/PasswordPrompt.js +2 -2
- package/es/Table.cjs +1 -1
- package/es/Table.js +17 -17
- package/es/User.cjs +1 -1
- package/es/User.js +18 -18
- package/es/VarSelectDialog.cjs +3 -3
- package/es/VarSelectDialog.js +178 -122
- package/es/VarietyAutoComplete.cjs +1 -1
- package/es/VarietyAutoComplete.js +7 -7
- package/es/VarietySearch.cjs +17 -18
- package/es/VarietySearch.js +2592 -2705
- package/es/VarietyTextCopy.cjs +1 -1
- package/es/VarietyTextCopy.js +9 -9
- package/es/VirtualTable.cjs +1 -1
- package/es/VirtualTable.js +61 -61
- package/es/{_initCloneObject-3823a101.cjs → _initCloneObject-52b6a510.cjs} +1 -1
- package/es/{_initCloneObject-c34c65bc.js → _initCloneObject-eaef9418.js} +2 -2
- package/es/{config-provider-2182708a.cjs → config-provider-a584d81e.cjs} +1 -1
- package/es/{config-provider-06a63185.js → config-provider-b16efd62.js} +3 -3
- package/es/{dropdown-89b74bc9.cjs → dropdown-071c5d7e.cjs} +1 -1
- package/es/{dropdown-302f71e7.js → dropdown-a59bba73.js} +2 -2
- package/es/{el-autocomplete-b9a3054a.cjs → el-autocomplete-a07e9439.cjs} +1 -1
- package/es/{el-autocomplete-ed75a659.js → el-autocomplete-ba808eb6.js} +5 -5
- package/es/{el-button-d09ff85f.js → el-button-c95adb85.js} +3 -3
- package/es/{el-button-68baab7b.cjs → el-button-eec58cff.cjs} +1 -1
- package/es/{el-checkbox-64648e02.js → el-checkbox-7421ccd3.js} +3 -3
- package/es/{el-checkbox-b982e2ef.cjs → el-checkbox-c25236a6.cjs} +1 -1
- package/es/{el-dialog-6a80e3d8.js → el-dialog-41ab8417.js} +4 -4
- package/es/{el-dialog-ad7309e9.cjs → el-dialog-ae86edb8.cjs} +1 -1
- package/es/{el-form-item-4076e55f.cjs → el-form-item-c3fe189b.cjs} +1 -1
- package/es/{el-form-item-4eca95be.js → el-form-item-c53c374d.js} +5 -5
- package/es/{el-input-cae60510.js → el-input-2f75c4ba.js} +49 -49
- package/es/{el-input-172c49f8.cjs → el-input-7fd293af.cjs} +1 -1
- package/es/{el-input-number-c2e71528.cjs → el-input-number-22e21d16.cjs} +1 -1
- package/es/{el-input-number-c2499410.js → el-input-number-5193fe6d.js} +4 -4
- package/es/{el-loading-05826e64.cjs → el-loading-cfd86c15.cjs} +1 -1
- package/es/{el-loading-c738468d.js → el-loading-f6022062.js} +1 -1
- package/es/{el-menu-item-7f986598.cjs → el-menu-item-17dc717e.cjs} +1 -1
- package/es/{el-menu-item-f904f685.js → el-menu-item-7e881203.js} +4 -4
- package/es/{el-message-a86c0efa.cjs → el-message-5e6a6be9.cjs} +1 -1
- package/es/{el-message-box-05d8cf39.js → el-message-box-a93d2f6a.js} +9 -9
- package/es/{el-message-box-40ff2af5.cjs → el-message-box-c10adb52.cjs} +1 -1
- package/es/{el-message-0df23ae7.js → el-message-e544a8f5.js} +5 -5
- package/es/{el-overlay-cc9bc792.js → el-overlay-09ad71cd.js} +18 -18
- package/es/{el-overlay-d7a6e4a9.cjs → el-overlay-9e34965f.cjs} +1 -1
- package/es/{el-popconfirm-737a015b.cjs → el-popconfirm-70a976bf.cjs} +1 -1
- package/es/{el-popconfirm-a6f66a0e.js → el-popconfirm-81dcd202.js} +4 -4
- package/es/{el-popper-a38874f4.js → el-popper-b4f97157.js} +1 -1
- package/es/{el-popper-7ba87e05.cjs → el-popper-b6c99b28.cjs} +1 -1
- package/es/{el-segmented-51b1c797.js → el-segmented-b868d074.js} +2 -2
- package/es/{el-segmented-3fd66a0e.cjs → el-segmented-f8fce9ac.cjs} +1 -1
- package/es/{el-select-1b149fab.js → el-select-95627997.js} +8 -8
- package/es/{el-select-12f6deb7.cjs → el-select-d8d91db1.cjs} +1 -1
- package/es/{el-table-column-3e30ebae.js → el-table-column-376cd907.js} +9 -9
- package/es/{el-table-column-516a0ed9.cjs → el-table-column-c974cb96.cjs} +1 -1
- package/es/{el-tag-0a25efdf.js → el-tag-66cab138.js} +2 -2
- package/es/{el-tag-789f05d3.cjs → el-tag-a33c4b22.cjs} +1 -1
- package/es/{el-text-73d899ff.js → el-text-ac60d0f2.js} +1 -1
- package/es/{el-text-1470de46.cjs → el-text-c20a9f48.cjs} +1 -1
- package/es/{index-cebc7160.cjs → index-098c2447.cjs} +1 -1
- package/es/{index-c04f444f.cjs → index-11547a0c.cjs} +1 -1
- package/es/{index-4194c942.js → index-1f7d4f70.js} +1 -1
- package/es/{index-8de94a49.cjs → index-298075cf.cjs} +1 -1
- package/es/{index-94e43e0d.js → index-57672682.js} +2 -2
- package/es/{index-6806997d.js → index-844bdd85.js} +2 -2
- package/es/{index-6e967429.js → index-88546436.js} +2 -2
- package/es/{index-ee977f79.cjs → index-9b9ef5dd.cjs} +1 -1
- package/es/{index-87b4bf61.js → index-a871c3eb.js} +60 -75
- package/es/{index-ac98a4d8.js → index-bc8e277e.js} +12573 -12827
- package/es/{index-4f48940d.cjs → index-c108567d.cjs} +1 -1
- package/es/{index-2375023e.cjs → index-d725fef6.cjs} +137 -138
- package/es/{index-54d289d1.js → index-d91dc23f.js} +2 -2
- package/es/{index-42e59bf5.js → index-e5566b94.js} +1 -1
- package/es/{index-696b6a94.cjs → index-f3562b52.cjs} +1 -1
- package/es/{index-269b22da.cjs → index-f967d6c1.cjs} +1 -1
- package/es/{python-c67c8901.cjs → python-c27ba105.cjs} +2 -2
- package/es/{python-a914569a.js → python-ecde9ff2.js} +11 -39
- package/es/style.css +1 -1
- package/es/{use-form-common-props-47e50c10.js → use-form-common-props-815d48a6.js} +28 -28
- package/es/{use-form-common-props-344056f9.cjs → use-form-common-props-fd9b61a0.cjs} +1 -1
- package/es/{use-global-config-cf78ebac.cjs → use-global-config-30d7d8ce.cjs} +1 -1
- package/es/{use-global-config-f52caea0.js → use-global-config-b5e9d3d5.js} +4 -4
- package/es/{validator-3cad04b2.cjs → validator-1b8a6128.cjs} +1 -1
- package/es/{validator-94c04152.js → validator-764a9db0.js} +1 -1
- package/es/{zh-cn-aabfaa94.cjs → zh-cn-90317f62.cjs} +1 -1
- package/es/{zh-cn-4921961d.js → zh-cn-e963c628.js} +1 -1
- package/lib/bundle.js +1 -1
- package/lib/bundle.umd.cjs +225 -227
- package/lib/{index-c6d17ca2.js → index-f416420b.js} +31754 -32122
- package/lib/{python-09a6fcf8.js → python-766b93ca.js} +1 -1
- package/lib/style.css +1 -1
- package/package.json +1 -2
- package/packages/MonacoEditor/index.vue +70 -741
- package/packages/VarietySearch/components/AddTag/index.vue +86 -20
- package/packages/VarietySearch/components/FactorScreen/index.vue +12 -80
- package/packages/VarietySearch/components/FactorScreen/tools.js +0 -41
- package/src/main.ts +11 -16
- package/src/pages/MonacoEditor/index.vue +0 -1
- package/es/VarietySelect-2fd501da.cjs +0 -1
- package/es/VarietySelect-5a9dd50b.js +0 -68
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { debounce } from "st-func";
|
|
3
|
-
import { InfoFilled } from "@element-plus/icons-vue";
|
|
4
3
|
import { ref, onMounted, onUnmounted, nextTick, inject } from "vue";
|
|
5
|
-
import { extractVariables } from "./tools";
|
|
6
4
|
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
|
|
7
5
|
import "monaco-editor/esm/vs/basic-languages/python/python.contribution";
|
|
8
6
|
import "monaco-editor/esm/vs/basic-languages/lua/lua.contribution";
|
|
9
|
-
import
|
|
7
|
+
import { extractVariables } from "./tools";
|
|
10
8
|
|
|
11
9
|
const { request } = inject("stConfig"); // 组件库全局配置
|
|
12
10
|
|
|
13
11
|
const emit = defineEmits(["change"]);
|
|
14
12
|
const props = defineProps({
|
|
15
|
-
// 编辑器相关参数
|
|
16
13
|
defaultValue: {
|
|
17
14
|
type: String,
|
|
18
15
|
default: "",
|
|
@@ -30,16 +27,6 @@ const props = defineProps({
|
|
|
30
27
|
type: Boolean,
|
|
31
28
|
default: false,
|
|
32
29
|
},
|
|
33
|
-
// 变量列表开关
|
|
34
|
-
variableEnable: {
|
|
35
|
-
type: Boolean,
|
|
36
|
-
default: false,
|
|
37
|
-
},
|
|
38
|
-
// 变量列表类型
|
|
39
|
-
useCase: {
|
|
40
|
-
type: String,
|
|
41
|
-
default: "1", // 1-选股, 2-回测
|
|
42
|
-
},
|
|
43
30
|
});
|
|
44
31
|
|
|
45
32
|
let editorInstance = null;
|
|
@@ -52,209 +39,6 @@ const suggestionIndex = ref(-1);
|
|
|
52
39
|
const suggestionBoxRef = ref(null);
|
|
53
40
|
const isShowingSuggestions = ref(false);
|
|
54
41
|
|
|
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
42
|
// [建议列表] 数据获取
|
|
259
43
|
const getSuggestions = debounce(async (keyword = "") => {
|
|
260
44
|
if (!props.suggestionEnable) return;
|
|
@@ -271,7 +55,6 @@ const getSuggestions = debounce(async (keyword = "") => {
|
|
|
271
55
|
hideSuggestions();
|
|
272
56
|
}
|
|
273
57
|
}, 200);
|
|
274
|
-
|
|
275
58
|
// [建议列表] 展示
|
|
276
59
|
const showSuggestions = async (options) => {
|
|
277
60
|
if (!props.suggestionEnable) return;
|
|
@@ -280,7 +63,6 @@ const showSuggestions = async (options) => {
|
|
|
280
63
|
isShowingSuggestions.value = true;
|
|
281
64
|
updateSuggestionBoxPosition();
|
|
282
65
|
};
|
|
283
|
-
|
|
284
66
|
// [建议列表] 隐藏
|
|
285
67
|
const hideSuggestions = () => {
|
|
286
68
|
if (!props.suggestionEnable) return;
|
|
@@ -288,7 +70,6 @@ const hideSuggestions = () => {
|
|
|
288
70
|
suggestionIndex.value = -1;
|
|
289
71
|
isShowingSuggestions.value = false;
|
|
290
72
|
};
|
|
291
|
-
|
|
292
73
|
// [建议列表] 更新DOM位置
|
|
293
74
|
const updateSuggestionBoxPosition = () => {
|
|
294
75
|
if (!props.suggestionEnable) return;
|
|
@@ -301,7 +82,8 @@ const updateSuggestionBoxPosition = () => {
|
|
|
301
82
|
const editorDom = editorInstance.getDomNode();
|
|
302
83
|
const editorRect = editorDom.getBoundingClientRect();
|
|
303
84
|
|
|
304
|
-
|
|
85
|
+
// 计算相对于编辑器容器的位置
|
|
86
|
+
const left = cursorCoords.left + editorRect.left + 40; // 在光标右侧
|
|
305
87
|
const top = cursorCoords.top + editorRect.top + cursorCoords.height;
|
|
306
88
|
|
|
307
89
|
suggestionBoxRef.value.style.left = `${left}px`;
|
|
@@ -309,7 +91,6 @@ const updateSuggestionBoxPosition = () => {
|
|
|
309
91
|
}
|
|
310
92
|
});
|
|
311
93
|
};
|
|
312
|
-
|
|
313
94
|
// [建议列表] 插入内容到编辑器
|
|
314
95
|
const insertSelectedSuggestion = () => {
|
|
315
96
|
if (!props.suggestionEnable) return;
|
|
@@ -321,6 +102,7 @@ const insertSelectedSuggestion = () => {
|
|
|
321
102
|
if (varArray.length) {
|
|
322
103
|
const str = varArray.reduce((result, item, index, arry) => {
|
|
323
104
|
result += `${item}=`;
|
|
105
|
+
// 如果不是最后一个, 就需要加个逗号
|
|
324
106
|
if (index < arry.length - 1) result += ",";
|
|
325
107
|
return result;
|
|
326
108
|
}, "");
|
|
@@ -366,49 +148,9 @@ const insertSelectedSuggestion = () => {
|
|
|
366
148
|
|
|
367
149
|
hideSuggestions();
|
|
368
150
|
};
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
const scrollToSelectedSuggestion = () => {
|
|
151
|
+
// [建议列表] 随用户内容输入变动检查建议项
|
|
152
|
+
const checkForSuggestions = async () => {
|
|
372
153
|
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
154
|
const position = editorInstance.getPosition();
|
|
413
155
|
const model = editorInstance.getModel();
|
|
414
156
|
const lineContent = model.getLineContent(position.lineNumber);
|
|
@@ -416,140 +158,104 @@ const checkForCompletions = async () => {
|
|
|
416
158
|
const textBeforeCursor = lineContent.substring(0, position.column - 1);
|
|
417
159
|
const lastHashIndex = textBeforeCursor.lastIndexOf("#");
|
|
418
160
|
|
|
419
|
-
// 如果是#触发,显示建议列表
|
|
420
161
|
if (lastHashIndex !== -1) {
|
|
421
|
-
// 如果变量列表正在显示,先隐藏
|
|
422
|
-
if (isShowingVariables.value) hideVariables();
|
|
423
|
-
|
|
424
162
|
const keyword = textBeforeCursor.substring(lastHashIndex + 1);
|
|
425
163
|
if (lastCursorPosition && (lastCursorPosition.lineNumber !== position.lineNumber || lastCursorPosition.column !== position.column)) {
|
|
426
164
|
hideSuggestions();
|
|
427
165
|
}
|
|
428
166
|
lastCursorPosition = { ...position };
|
|
429
167
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
168
|
+
getSuggestions(keyword);
|
|
169
|
+
} else {
|
|
170
|
+
hideSuggestions();
|
|
433
171
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
172
|
+
};
|
|
173
|
+
// [建议列表] 选项自动滚动
|
|
174
|
+
const scrollToSelectedSuggestion = () => {
|
|
175
|
+
if (!props.suggestionEnable) return;
|
|
176
|
+
if (!suggestionBoxRef.value || suggestionIndex.value === -1) return;
|
|
438
177
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
const keyword = wordUntilPosition.word;
|
|
178
|
+
const suggestionList = suggestionBoxRef.value.querySelector(".suggestion-list");
|
|
179
|
+
const selectedItem = suggestionBoxRef.value.querySelector(".suggestion-item.selected");
|
|
442
180
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
lastCursorPosition = { ...position };
|
|
181
|
+
if (suggestionList && selectedItem) {
|
|
182
|
+
const listRect = suggestionList.getBoundingClientRect();
|
|
183
|
+
const itemRect = selectedItem.getBoundingClientRect();
|
|
447
184
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
185
|
+
// 如果选中项在可视区域上方
|
|
186
|
+
if (itemRect.top < listRect.top) {
|
|
187
|
+
suggestionList.scrollTop -= listRect.top - itemRect.top;
|
|
188
|
+
}
|
|
189
|
+
// 如果选中项在可视区域下方
|
|
190
|
+
else if (itemRect.bottom > listRect.bottom) {
|
|
191
|
+
suggestionList.scrollTop += itemRect.bottom - listRect.bottom;
|
|
452
192
|
}
|
|
453
193
|
}
|
|
454
194
|
};
|
|
455
195
|
|
|
456
196
|
// [代码编辑器] 键盘事件
|
|
457
197
|
const handleKeyDown = (e) => {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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;
|
|
198
|
+
if (!isShowingSuggestions.value) return;
|
|
199
|
+
switch (e.code) {
|
|
200
|
+
case "ArrowUp": {
|
|
201
|
+
e.preventDefault();
|
|
202
|
+
e.stopPropagation();
|
|
203
|
+
suggestionIndex.value = suggestionIndex.value <= 0 ? suggestions.value.length - 1 : suggestionIndex.value - 1;
|
|
204
|
+
nextTick(() => scrollToSelectedSuggestion());
|
|
205
|
+
break;
|
|
485
206
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
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;
|
|
207
|
+
case "ArrowDown": {
|
|
208
|
+
e.preventDefault();
|
|
209
|
+
e.stopPropagation();
|
|
210
|
+
suggestionIndex.value = suggestionIndex.value >= suggestions.value.length - 1 ? 0 : suggestionIndex.value + 1;
|
|
211
|
+
nextTick(() => scrollToSelectedSuggestion());
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
case "ArrowLeft": {
|
|
215
|
+
e.preventDefault();
|
|
216
|
+
e.stopPropagation();
|
|
217
|
+
break;
|
|
522
218
|
}
|
|
219
|
+
case "ArrowRight": {
|
|
220
|
+
e.preventDefault();
|
|
221
|
+
e.stopPropagation();
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
case "Enter": {
|
|
225
|
+
e.preventDefault();
|
|
226
|
+
e.stopPropagation();
|
|
227
|
+
insertSelectedSuggestion();
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
case "Escape": {
|
|
231
|
+
e.preventDefault();
|
|
232
|
+
e.stopPropagation();
|
|
233
|
+
hideSuggestions();
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
default:
|
|
237
|
+
break;
|
|
523
238
|
}
|
|
524
239
|
};
|
|
525
|
-
|
|
526
240
|
// [代码编辑器] 内容变化回调
|
|
527
241
|
const handleContentChange = (event) => {
|
|
528
242
|
if (!editorInstance) return;
|
|
529
243
|
emit("change", editorInstance.getValue());
|
|
530
|
-
|
|
244
|
+
checkForSuggestions();
|
|
531
245
|
};
|
|
532
|
-
|
|
533
246
|
// [代码编辑器] 光标变化回调
|
|
534
247
|
const handleCursorPositionChange = (event) => {
|
|
535
248
|
if (isShowingSuggestions.value) {
|
|
536
249
|
updateSuggestionBoxPosition();
|
|
537
250
|
}
|
|
538
|
-
if (isShowingVariables.value) {
|
|
539
|
-
updateVariableBoxPosition();
|
|
540
|
-
}
|
|
541
251
|
};
|
|
542
252
|
|
|
543
253
|
// [document] 全局监听的点击事件
|
|
544
254
|
const handleClickOutside = (event) => {
|
|
545
|
-
//
|
|
255
|
+
// 如果点击了建议列表外面的区域, 就自动关闭
|
|
546
256
|
if (suggestionBoxRef.value && !suggestionBoxRef.value.contains(event.target)) {
|
|
547
257
|
hideSuggestions();
|
|
548
258
|
}
|
|
549
|
-
// 如果点击了变量列表外面的区域,就自动关闭
|
|
550
|
-
if (variableBoxRef.value && !variableBoxRef.value.contains(event.target)) {
|
|
551
|
-
hideVariables();
|
|
552
|
-
}
|
|
553
259
|
};
|
|
554
260
|
|
|
555
261
|
onMounted(() => {
|
|
@@ -558,22 +264,15 @@ onMounted(() => {
|
|
|
558
264
|
language: props.language,
|
|
559
265
|
theme: props.theme,
|
|
560
266
|
});
|
|
561
|
-
|
|
562
267
|
editorInstance.onKeyDown(handleKeyDown);
|
|
563
268
|
editorInstance.onDidChangeModelContent(handleContentChange);
|
|
564
269
|
editorInstance.onDidChangeCursorPosition(handleCursorPositionChange);
|
|
565
|
-
|
|
566
270
|
document.addEventListener("click", handleClickOutside);
|
|
567
|
-
|
|
568
|
-
// 获取变量列表数据
|
|
569
|
-
fetchVariables();
|
|
570
271
|
});
|
|
571
|
-
|
|
572
272
|
onUnmounted(() => {
|
|
573
273
|
editorInstance?.dispose();
|
|
574
274
|
document.removeEventListener("click", handleClickOutside);
|
|
575
275
|
});
|
|
576
|
-
|
|
577
276
|
defineExpose({
|
|
578
277
|
resize: () => {
|
|
579
278
|
editorInstance.layout();
|
|
@@ -596,9 +295,11 @@ defineExpose({
|
|
|
596
295
|
const model = editorInstance.getModel();
|
|
597
296
|
if (!model) return;
|
|
598
297
|
|
|
298
|
+
// 获取最后一行
|
|
599
299
|
const lineCount = model.getLineCount();
|
|
600
300
|
const lastLine = model.getLineContent(lineCount);
|
|
601
301
|
|
|
302
|
+
// 设置光标位置到最后一行末尾
|
|
602
303
|
const position = {
|
|
603
304
|
lineNumber: lineCount,
|
|
604
305
|
column: lastLine.length + 1,
|
|
@@ -606,6 +307,8 @@ defineExpose({
|
|
|
606
307
|
|
|
607
308
|
editorInstance.setPosition(position);
|
|
608
309
|
editorInstance.focus();
|
|
310
|
+
|
|
311
|
+
// 滚动到光标位置
|
|
609
312
|
editorInstance.revealPositionInCenter(position);
|
|
610
313
|
},
|
|
611
314
|
});
|
|
@@ -618,7 +321,6 @@ defineExpose({
|
|
|
618
321
|
ref="editorContainer"
|
|
619
322
|
class="editor-container"
|
|
620
323
|
/>
|
|
621
|
-
|
|
622
324
|
<!-- 建议列表 -->
|
|
623
325
|
<Teleport
|
|
624
326
|
to="body"
|
|
@@ -648,157 +350,9 @@ defineExpose({
|
|
|
648
350
|
<div class="suggestion-footer">使用 ↑↓ 选择,Enter 确认,Esc 取消</div>
|
|
649
351
|
</div>
|
|
650
352
|
</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
353
|
</div>
|
|
781
354
|
</template>
|
|
782
355
|
|
|
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
356
|
<style scoped lang="scss">
|
|
803
357
|
.editor-wrapper {
|
|
804
358
|
position: relative;
|
|
@@ -809,8 +363,6 @@ defineExpose({
|
|
|
809
363
|
width: 100%;
|
|
810
364
|
height: 100%;
|
|
811
365
|
}
|
|
812
|
-
|
|
813
|
-
// 建议列表样式
|
|
814
366
|
.suggestion-box {
|
|
815
367
|
position: fixed;
|
|
816
368
|
background: #1e1e1e;
|
|
@@ -835,7 +387,6 @@ defineExpose({
|
|
|
835
387
|
transform: rotate(45deg);
|
|
836
388
|
z-index: -1;
|
|
837
389
|
}
|
|
838
|
-
|
|
839
390
|
.suggestion-header {
|
|
840
391
|
display: flex;
|
|
841
392
|
justify-content: space-between;
|
|
@@ -855,7 +406,6 @@ defineExpose({
|
|
|
855
406
|
opacity: 0.8;
|
|
856
407
|
}
|
|
857
408
|
}
|
|
858
|
-
|
|
859
409
|
.suggestion-list {
|
|
860
410
|
max-height: 200px;
|
|
861
411
|
overflow-y: auto;
|
|
@@ -908,7 +458,6 @@ defineExpose({
|
|
|
908
458
|
}
|
|
909
459
|
}
|
|
910
460
|
}
|
|
911
|
-
|
|
912
461
|
.suggestion-footer {
|
|
913
462
|
padding: 6px 12px;
|
|
914
463
|
background: #2d2d30;
|
|
@@ -918,224 +467,4 @@ defineExpose({
|
|
|
918
467
|
text-align: center;
|
|
919
468
|
}
|
|
920
469
|
}
|
|
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
470
|
</style>
|