st-comp 0.0.215 → 0.0.216

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 (109) hide show
  1. package/es/CustomFunction.cjs +8 -1
  2. package/es/CustomFunction.js +532 -381
  3. package/es/FactorWarning.cjs +1 -1
  4. package/es/FactorWarning.js +28 -28
  5. package/es/Kline.cjs +1 -1
  6. package/es/Kline.js +10 -10
  7. package/es/KlineBasic.cjs +1 -1
  8. package/es/KlineBasic.js +18 -18
  9. package/es/KlineConfig.cjs +1 -1
  10. package/es/KlineConfig.js +15 -15
  11. package/es/KlineNew.cjs +1 -1
  12. package/es/KlineNew.js +9 -9
  13. package/es/KlinePlus.cjs +1 -1
  14. package/es/KlinePlus.js +11 -11
  15. package/es/Pagination.cjs +1 -1
  16. package/es/Pagination.js +13 -13
  17. package/es/PasswordPrompt.cjs +1 -1
  18. package/es/PasswordPrompt.js +2 -2
  19. package/es/Table.cjs +1 -1
  20. package/es/Table.js +29 -29
  21. package/es/User.cjs +1 -1
  22. package/es/User.js +18 -18
  23. package/es/VarSelectDialog.cjs +1 -1
  24. package/es/VarSelectDialog.js +17 -17
  25. package/es/VarietyAutoComplete.cjs +1 -1
  26. package/es/VarietyAutoComplete.js +22 -22
  27. package/es/VarietySearch.cjs +1 -1
  28. package/es/VarietySearch.js +26 -26
  29. package/es/VarietyTextCopy.cjs +1 -1
  30. package/es/VarietyTextCopy.js +9 -9
  31. package/es/VirtualTable.cjs +1 -1
  32. package/es/VirtualTable.js +5 -5
  33. package/es/{_initCloneObject-eaef9418.js → _initCloneObject-4f4401b6.js} +2 -2
  34. package/es/{_initCloneObject-52b6a510.cjs → _initCloneObject-6429d105.cjs} +1 -1
  35. package/es/{config-provider-a584d81e.cjs → config-provider-285ead82.cjs} +1 -1
  36. package/es/{config-provider-b16efd62.js → config-provider-e1736401.js} +3 -3
  37. package/es/{dropdown-071c5d7e.cjs → dropdown-6ba4a93d.cjs} +1 -1
  38. package/es/{dropdown-a59bba73.js → dropdown-73ca08ef.js} +2 -2
  39. package/es/{el-autocomplete-ba808eb6.js → el-autocomplete-2180fc5c.js} +5 -5
  40. package/es/{el-autocomplete-a07e9439.cjs → el-autocomplete-aeb7da33.cjs} +1 -1
  41. package/es/{el-button-eec58cff.cjs → el-button-0dbb2d4a.cjs} +1 -1
  42. package/es/{el-button-c95adb85.js → el-button-e8b725f0.js} +3 -3
  43. package/es/{el-checkbox-c25236a6.cjs → el-checkbox-b8c558ca.cjs} +1 -1
  44. package/es/{el-checkbox-7421ccd3.js → el-checkbox-df0def51.js} +3 -3
  45. package/es/{el-dialog-41ab8417.js → el-dialog-4330c5bd.js} +4 -4
  46. package/es/{el-dialog-ae86edb8.cjs → el-dialog-5028c704.cjs} +1 -1
  47. package/es/{el-form-item-c53c374d.js → el-form-item-b816e9f3.js} +5 -5
  48. package/es/{el-form-item-c3fe189b.cjs → el-form-item-f7e8255e.cjs} +1 -1
  49. package/es/{el-input-7fd293af.cjs → el-input-2e9268ac.cjs} +1 -1
  50. package/es/{el-input-2f75c4ba.js → el-input-bd1ce1e9.js} +4 -4
  51. package/es/{el-input-number-5193fe6d.js → el-input-number-088d2c66.js} +4 -4
  52. package/es/{el-input-number-22e21d16.cjs → el-input-number-153a3742.cjs} +1 -1
  53. package/es/{el-loading-cfd86c15.cjs → el-loading-03240202.cjs} +1 -1
  54. package/es/{el-loading-f6022062.js → el-loading-d0dac75f.js} +1 -1
  55. package/es/{el-menu-item-17dc717e.cjs → el-menu-item-b843f5ee.cjs} +1 -1
  56. package/es/{el-menu-item-7e881203.js → el-menu-item-c7202455.js} +4 -4
  57. package/es/{el-message-e544a8f5.js → el-message-290a93ff.js} +5 -5
  58. package/es/{el-message-5e6a6be9.cjs → el-message-3d8d9810.cjs} +1 -1
  59. package/es/{el-message-box-a93d2f6a.js → el-message-box-7a952ec7.js} +9 -9
  60. package/es/{el-message-box-c10adb52.cjs → el-message-box-aafae7ee.cjs} +1 -1
  61. package/es/{el-overlay-9e34965f.cjs → el-overlay-ab0b3c66.cjs} +1 -1
  62. package/es/{el-overlay-09ad71cd.js → el-overlay-f72f3f3d.js} +3 -3
  63. package/es/{el-popconfirm-70a976bf.cjs → el-popconfirm-a4a50f14.cjs} +1 -1
  64. package/es/{el-popconfirm-81dcd202.js → el-popconfirm-bdcb65fe.js} +4 -4
  65. package/es/{el-popper-b4f97157.js → el-popper-b0ef8ed3.js} +1 -1
  66. package/es/{el-popper-b6c99b28.cjs → el-popper-b37ec1ef.cjs} +1 -1
  67. package/es/{el-segmented-b868d074.js → el-segmented-d0a61f41.js} +2 -2
  68. package/es/{el-segmented-f8fce9ac.cjs → el-segmented-f505fd25.cjs} +1 -1
  69. package/es/{el-select-d8d91db1.cjs → el-select-91145989.cjs} +1 -1
  70. package/es/{el-select-95627997.js → el-select-d63dc0f6.js} +8 -8
  71. package/es/{el-table-column-c974cb96.cjs → el-table-column-4dae58f0.cjs} +1 -1
  72. package/es/{el-table-column-376cd907.js → el-table-column-5ad33084.js} +9 -9
  73. package/es/{el-tag-66cab138.js → el-tag-2da70fa3.js} +2 -2
  74. package/es/{el-tag-a33c4b22.cjs → el-tag-891b703d.cjs} +1 -1
  75. package/es/{el-text-c20a9f48.cjs → el-text-cfd2f326.cjs} +1 -1
  76. package/es/{el-text-ac60d0f2.js → el-text-d42a3be4.js} +1 -1
  77. package/es/{index-d91dc23f.js → index-0902dd2e.js} +2 -2
  78. package/es/{index-1f7d4f70.js → index-23d35abc.js} +1 -1
  79. package/es/{index-9b9ef5dd.cjs → index-25bc46bb.cjs} +1 -1
  80. package/es/{index-844bdd85.js → index-5108cae0.js} +2 -2
  81. package/es/{index-a871c3eb.js → index-598d418b.js} +92 -111
  82. package/es/{index-c108567d.cjs → index-6c252a43.cjs} +1 -1
  83. package/es/{index-f967d6c1.cjs → index-7a26fd8b.cjs} +1 -1
  84. package/es/index-7a85500c.cjs +1 -0
  85. package/es/{index-57672682.js → index-af3c738f.js} +2 -2
  86. package/es/{index-e5566b94.js → index-b99c0c42.js} +1 -1
  87. package/es/{index-88546436.js → index-d6a848ac.js} +2 -2
  88. package/es/{index-f3562b52.cjs → index-d7928b14.cjs} +1 -1
  89. package/es/{index-11547a0c.cjs → index-eb3ca89a.cjs} +1 -1
  90. package/es/{index-298075cf.cjs → index-f50a50b3.cjs} +1 -1
  91. package/es/style.css +1 -1
  92. package/es/{use-form-common-props-fd9b61a0.cjs → use-form-common-props-3b387353.cjs} +1 -1
  93. package/es/{use-form-common-props-815d48a6.js → use-form-common-props-b995a440.js} +12 -12
  94. package/es/{use-global-config-30d7d8ce.cjs → use-global-config-2a4156cd.cjs} +1 -1
  95. package/es/{use-global-config-b5e9d3d5.js → use-global-config-e20aee8c.js} +2 -2
  96. package/es/{validator-764a9db0.js → validator-6d23708b.js} +1 -1
  97. package/es/{validator-1b8a6128.cjs → validator-7dacff4f.cjs} +1 -1
  98. package/es/{zh-cn-e963c628.js → zh-cn-7530f035.js} +1 -1
  99. package/es/{zh-cn-90317f62.cjs → zh-cn-a3c3833a.cjs} +1 -1
  100. package/lib/bundle.js +1 -1
  101. package/lib/bundle.umd.cjs +169 -162
  102. package/lib/{index-5f11e3e4.js → index-19ce4b67.js} +20461 -20330
  103. package/lib/{python-e8c63eb9.js → python-033b059e.js} +1 -1
  104. package/lib/style.css +1 -1
  105. package/package.json +1 -1
  106. package/packages/CustomFunction/components/ManageDialog.vue +779 -0
  107. package/packages/CustomFunction/index.vue +17 -482
  108. package/packages/VarietyAutoComplete/index.vue +1 -1
  109. package/es/index-098c2447.cjs +0 -1
@@ -0,0 +1,779 @@
1
+ <script setup>
2
+ import { ref, h, inject, onMounted, watch, reactive, nextTick, computed } from "vue";
3
+ import { Close, Edit, DocumentCopy, Delete, Document } from "@element-plus/icons-vue";
4
+ import { debounce } from "st-func";
5
+
6
+ const { request } = inject("stConfig"); // 组件库全局配置
7
+ const stMonacoEditorRef = ref(null);
8
+ const stVarSelectDialogRef = ref(null);
9
+
10
+ const emit = defineEmits(["refreshData"]);
11
+ const props = defineProps({
12
+ data: {
13
+ type: Array,
14
+ default: () => [],
15
+ },
16
+ });
17
+
18
+ const visible = ref(false);
19
+ const loading = reactive({
20
+ save: false,
21
+ test: false,
22
+ });
23
+
24
+ // 函数相关参数
25
+ const funcKeyWord = ref(null);
26
+ const funcList = computed(() => {
27
+ if (funcKeyWord.value) {
28
+ return props.data.filter((item) => item.funcName.includes(funcKeyWord.value));
29
+ } else {
30
+ return props.data;
31
+ }
32
+ });
33
+ const ruleForm = reactive({
34
+ id: null,
35
+ funcName: "",
36
+ funcExpression: "",
37
+ });
38
+
39
+ // 测试日志相关参数
40
+ const testVariety = ref("");
41
+ const testResult = reactive({
42
+ result: null,
43
+ detail: "",
44
+ code: "",
45
+ });
46
+ const testVarietyVisible = ref(false);
47
+ const testLogVisible = ref(false);
48
+
49
+ // 函数: 新建
50
+ const handleAdd = () => {
51
+ Object.assign(ruleForm, {
52
+ id: null,
53
+ funcName: "",
54
+ funcExpression: "",
55
+ });
56
+ testVariety.value = "";
57
+ stMonacoEditorRef.value?.setValue(ruleForm.funcExpression);
58
+ };
59
+ // 函数: 编辑
60
+ const handleEdit = (item) => {
61
+ Object.assign(ruleForm, {
62
+ id: item.id,
63
+ funcName: item.funcName,
64
+ funcExpression: item.funcExpression,
65
+ });
66
+ testVariety.value = "";
67
+ stMonacoEditorRef.value?.setValue(ruleForm.funcExpression);
68
+ };
69
+ // 函数: 复制
70
+ const handleCopy = (item) => {
71
+ Object.assign(ruleForm, {
72
+ id: null,
73
+ funcName: `${item.funcName}-复制`,
74
+ funcExpression: item.funcExpression,
75
+ });
76
+ testVariety.value = "";
77
+ stMonacoEditorRef.value?.setValue(ruleForm.funcExpression);
78
+ };
79
+
80
+ // 函数: 删除
81
+ const handleDelete = async (item) => {
82
+ // 如果删除的是当前正在操作的自定义函数, 则需要清空表单
83
+ if (item.id === ruleForm.id) {
84
+ Object.assign(ruleForm, {
85
+ id: null,
86
+ funcName: "",
87
+ funcExpression: "",
88
+ });
89
+ stMonacoEditorRef.value?.setValue(ruleForm.funcExpression);
90
+ }
91
+ await request.post("/common/qt/deleteSearchFunctionById", { id: item.id });
92
+ emit("refreshData");
93
+ };
94
+ // 函数: 保存
95
+ const handleSave = debounce(async () => {
96
+ try {
97
+ loading.save = true;
98
+ ruleForm.funcExpression = stMonacoEditorRef.value.getValue();
99
+ // 校验
100
+ if (!ruleForm.funcName) return ElMessage.error("函数名称不可为空");
101
+ if (!ruleForm.funcExpression) return ElMessage.error("函数内容不可为空");
102
+ // 调用接口
103
+ await request.post("/common/qt/saveOrUpdateSearchFunction", ruleForm);
104
+ ElMessage.success("操作成功");
105
+ emit("refreshData");
106
+ // 如果是复制, 或者新建则清空当前表单
107
+ if (!ruleForm.id) handleAdd();
108
+ } finally {
109
+ loading.save = false;
110
+ }
111
+ });
112
+
113
+ // 测试: 生成变量key和value的输入框
114
+ const showVariableInputDialog = (variables) => {
115
+ return new Promise((resolve) => {
116
+ const formData = ref(
117
+ variables.reduce((obj, variable) => {
118
+ obj[variable] = "";
119
+ return obj;
120
+ }, {}),
121
+ );
122
+ const errors = ref({});
123
+
124
+ // 验证函数
125
+ const validateForm = () => {
126
+ let isValid = true;
127
+ const newErrors = {};
128
+
129
+ variables.forEach((variable) => {
130
+ if (!formData.value[variable]?.trim()) {
131
+ newErrors[variable] = `请输入${variable}的值`;
132
+ isValid = false;
133
+ }
134
+ });
135
+
136
+ errors.value = newErrors;
137
+ return isValid;
138
+ };
139
+ // h语法表单组件
140
+ const FormComponent = {
141
+ setup() {
142
+ return () =>
143
+ h("div", [
144
+ h(
145
+ ElForm,
146
+ {
147
+ model: formData.value,
148
+ },
149
+ () =>
150
+ variables.map((variable) =>
151
+ h(
152
+ ElFormItem,
153
+ {
154
+ label: `${variable}: `,
155
+ prop: variable,
156
+ error: errors.value[variable],
157
+ "label-width": "90px",
158
+ },
159
+ () =>
160
+ h(ElInput, {
161
+ modelValue: formData.value[variable],
162
+ "onUpdate:modelValue": (val) => {
163
+ formData.value[variable] = val;
164
+ // 清除错误状态
165
+ if (errors.value[variable]) delete errors.value[variable];
166
+ },
167
+ placeholder: `请输入 ${variable} 的值`,
168
+ status: errors.value[variable] ? "error" : "",
169
+ }),
170
+ ),
171
+ ),
172
+ ),
173
+ ]);
174
+ },
175
+ };
176
+ ElMessageBox({
177
+ title: "填写变量值用于接口测试",
178
+ message: h(FormComponent),
179
+ showCancelButton: true,
180
+ confirmButtonText: "确定",
181
+ cancelButtonText: "取消",
182
+ customClass: "variable-input-dialog",
183
+ beforeClose: async (action, instance, done) => {
184
+ if (action !== "confirm") {
185
+ resolve(false);
186
+ done();
187
+ }
188
+ await nextTick();
189
+ if (validateForm()) {
190
+ resolve({ ...formData.value });
191
+ done();
192
+ }
193
+ },
194
+ }).catch(() => resolve(false));
195
+ });
196
+ };
197
+ const extractVariables = (expression) => {
198
+ const regex = /\$\{([^}]*)\}/g;
199
+ const matches = [];
200
+ let match;
201
+
202
+ while ((match = regex.exec(expression)) !== null) {
203
+ matches.push(match[1]);
204
+ }
205
+
206
+ return [...new Set(matches)];
207
+ };
208
+ const replaceVariables = (expression, variableValues) => {
209
+ return expression.replace(/\$\{([^}]*)\}/g, (match, variableName) => {
210
+ return variableValues[variableName] !== undefined ? variableValues[variableName] : match;
211
+ });
212
+ };
213
+ const extractCodesFromString = (str) => {
214
+ if (!str) return [];
215
+ return str.split("\n").reduce((result, next) => {
216
+ const code = next.trim().replace(/\s+/gi, " ").split(" ")[0];
217
+ code && result.push(code);
218
+ return result;
219
+ }, []);
220
+ };
221
+ // 测试: 打开/确认/日志
222
+ const handleTest = async (action) => {
223
+ switch (action) {
224
+ case "open": {
225
+ // 基础校验
226
+ if (!stMonacoEditorRef.value.getValue()) return ElMessage.error("函数内容不可为空");
227
+ testVarietyVisible.value = true;
228
+ break;
229
+ }
230
+ case "submit": {
231
+ let testContent = stMonacoEditorRef.value.getValue();
232
+ if (!testContent) return ElMessage.error("函数内容不可为空");
233
+ // 检测函数中是否使用的变量语法, 如果包含, 需要用户二次输入对应的值, 将其替换后进行测试
234
+ if (/\$\{[^}]*\}/.test(testContent)) {
235
+ const variables = extractVariables(testContent);
236
+ const variableValues = await showVariableInputDialog(variables);
237
+ if (!variableValues) return;
238
+ testContent = replaceVariables(testContent, variableValues);
239
+ }
240
+ testVarietyVisible.value = false;
241
+ try {
242
+ loading.test = true;
243
+ const params = {
244
+ codes: extractCodesFromString(testVariety.value),
245
+ factorSelectExpr: testContent,
246
+ };
247
+ const { body } = await request.post("/common/qt/testFactorSelect", params);
248
+ const { result, detail } = body;
249
+ Object.assign(testResult, { result, detail, code: params.factorSelectExpr });
250
+ if (result === 1) {
251
+ ElMessage.success("测试通过");
252
+ } else {
253
+ ElMessage.error("测试未能通过");
254
+ testLogVisible.value = true;
255
+ }
256
+ } finally {
257
+ loading.test = false;
258
+ }
259
+ break;
260
+ }
261
+ case "log": {
262
+ if (testResult.result === null) {
263
+ return ElMessage.warning("请先进行测试, 等待测试完成后可查看日志");
264
+ }
265
+ testLogVisible.value = true;
266
+ break;
267
+ }
268
+ }
269
+ };
270
+
271
+ // 变量选择器
272
+ const handleOpenVarSelectDialog = () => {
273
+ stVarSelectDialogRef.value.open(stMonacoEditorRef.value);
274
+ };
275
+ // 监视: 窗口开关
276
+ watch(
277
+ () => visible.value,
278
+ (newValue) => {
279
+ switch (newValue) {
280
+ case true: {
281
+ nextTick(() => {
282
+ stMonacoEditorRef.value?.resize();
283
+ // 初始默认值
284
+ funcKeyWord.value = null;
285
+ if (funcList.value.length) {
286
+ handleEdit(funcList.value[0]);
287
+ } else {
288
+ handleAdd();
289
+ }
290
+ // 重置测试结果
291
+ Object.assign(testResult, {
292
+ result: null,
293
+ detail: "",
294
+ code: "",
295
+ });
296
+ });
297
+ break;
298
+ }
299
+ case false: {
300
+ // 确保关闭内嵌窗口
301
+ stVarSelectDialogRef.value.close();
302
+ testVarietyVisible.value = false;
303
+ testLogVisible.value = false;
304
+ break;
305
+ }
306
+ }
307
+ },
308
+ );
309
+ defineExpose({
310
+ open: () => {
311
+ visible.value = true;
312
+ },
313
+ });
314
+ </script>
315
+
316
+ <template>
317
+ <el-dialog
318
+ modal-class="manage-dialog"
319
+ v-model="visible"
320
+ width="1600"
321
+ align-center
322
+ append-to-body
323
+ overflow
324
+ :modal="false"
325
+ :modal-penetrable="true"
326
+ :show-close="false"
327
+ >
328
+ <template #header="{ titleId, titleClass }">
329
+ <div class="custom-header">
330
+ <div class="left">
331
+ <span
332
+ :id="titleId"
333
+ :class="titleClass"
334
+ >
335
+ 自定义函数管理面板
336
+ </span>
337
+ </div>
338
+ <div class="right">
339
+ <el-icon @click="visible = false"><Close /></el-icon>
340
+ </div>
341
+ </div>
342
+ </template>
343
+ <div class="manage-dialog-body">
344
+ <!-- 函数列表 -->
345
+ <div class="func-list">
346
+ <div class="search">
347
+ <span>输入函数关键字</span>
348
+ <el-input
349
+ v-model="funcKeyWord"
350
+ clearable
351
+ />
352
+ <el-button
353
+ type="primary"
354
+ @click="handleAdd"
355
+ >新建</el-button
356
+ >
357
+ </div>
358
+ <el-scrollbar class="list">
359
+ <template v-if="funcList.length">
360
+ <div
361
+ v-for="item in funcList"
362
+ :key="item.id"
363
+ :class="{ 'active-list-item': ruleForm.id === item.id }"
364
+ class="list-item"
365
+ >
366
+ <span
367
+ class="func-name"
368
+ @click="handleEdit(item)"
369
+ >{{ item.funcName }}</span
370
+ >
371
+ <div class="icon-box">
372
+ <el-icon>
373
+ <DocumentCopy @click="handleCopy(item)" />
374
+ </el-icon>
375
+ <el-popconfirm
376
+ :title="`确认是否删除?`"
377
+ confirm-button-text="确认"
378
+ cancel-button-text="取消"
379
+ @confirm="handleDelete(item)"
380
+ >
381
+ <template #reference>
382
+ <el-icon @click.stop="() => {}"> <Delete /> </el-icon>
383
+ </template>
384
+ </el-popconfirm>
385
+ </div>
386
+ </div>
387
+ </template>
388
+ <el-empty
389
+ v-else
390
+ description="暂无数据"
391
+ />
392
+ </el-scrollbar>
393
+ </div>
394
+ <!-- 函数表单 -->
395
+ <div class="rule-form">
396
+ <div class="header">
397
+ <span>函数名称:</span>
398
+ <el-input v-model="ruleForm.funcName" />
399
+ <div class="right">
400
+ <el-button
401
+ type="primary"
402
+ @click="handleSave"
403
+ :loading="loading.save"
404
+ >
405
+ 保存
406
+ </el-button>
407
+ <el-button
408
+ :loading="loading.test"
409
+ @click="handleTest('open')"
410
+ >
411
+ 测试
412
+ </el-button>
413
+ <el-button
414
+ :icon="Document"
415
+ @click="handleTest('log')"
416
+ >
417
+ 日志明细
418
+ </el-button>
419
+ <el-button
420
+ type="primary"
421
+ @click="handleOpenVarSelectDialog"
422
+ >
423
+ 变量选择器
424
+ </el-button>
425
+ </div>
426
+ </div>
427
+ <!-- 注意事项 -->
428
+ <div class="tip-box">说明: 公式里可以使用变量, 变量名命名格式: ${变量名}, 后续可在应用函数时填写具体值, 系统会自动换算</div>
429
+ <!-- 内容 -->
430
+ <st-monacoEditor
431
+ ref="stMonacoEditorRef"
432
+ :language="'lua'"
433
+ style="width: 100%; height: calc(80vh - 75px)"
434
+ />
435
+ </div>
436
+ </div>
437
+
438
+ <!-- 变量选择器 -->
439
+ <st-varSelectDialog ref="stVarSelectDialogRef" />
440
+
441
+ <!-- 窗口: 选择测试所用的品种 -->
442
+ <el-dialog
443
+ modal-class="test-variety-dialog"
444
+ v-model="testVarietyVisible"
445
+ width="500"
446
+ align-center
447
+ append-to-body
448
+ overflow
449
+ :modal="false"
450
+ :modal-penetrable="true"
451
+ :show-close="false"
452
+ >
453
+ <template #header="{ titleId, titleClass }">
454
+ <div class="custom-header">
455
+ <div class="left">
456
+ <span
457
+ :id="titleId"
458
+ :class="titleClass"
459
+ >
460
+ 测试品种
461
+ </span>
462
+ </div>
463
+ <div class="right">
464
+ <st-varietyAutoComplete
465
+ label=""
466
+ @select="({ name, code }) => (testVariety += `${code} ${name} \n`)"
467
+ />
468
+ <el-icon @click="testVarietyVisible = false"><Close /></el-icon>
469
+ </div>
470
+ </div>
471
+ </template>
472
+ <el-input
473
+ class="full-height-textarea"
474
+ v-model="testVariety"
475
+ resize="none"
476
+ type="textarea"
477
+ :placeholder="`不填写时, 默认为000001 平安银行\n格式示例:\nhc8888\xa0\xa0\xa0\xa0热轧卷板期货指数\nsp8888\xa0\xa0\xa0\xa0纸浆期货指数\nbu8888\xa0\xa0\xa0\xa0石油沥青期货指数`"
478
+ />
479
+ <template #footer>
480
+ <div class="dialog-footer">
481
+ <el-button
482
+ type="primary"
483
+ @click="handleTest('submit')"
484
+ >
485
+ 确认
486
+ </el-button>
487
+ </div>
488
+ </template>
489
+ </el-dialog>
490
+ <!-- 窗口: 日志明细 -->
491
+ <el-dialog
492
+ modal-class="log-dialog"
493
+ v-model="testLogVisible"
494
+ width="830"
495
+ align-center
496
+ append-to-body
497
+ draggable
498
+ overflow
499
+ :modal="false"
500
+ :modal-penetrable="true"
501
+ :show-close="false"
502
+ >
503
+ <template #header="{ titleId, titleClass }">
504
+ <div class="custom-header">
505
+ <div class="left">
506
+ <span
507
+ :id="titleId"
508
+ :class="titleClass"
509
+ >
510
+ 日志明细
511
+ </span>
512
+ </div>
513
+ <!-- 关闭 -->
514
+ <div class="right">
515
+ <el-icon @click="testLogVisible = false"><Close /></el-icon>
516
+ </div>
517
+ </div>
518
+ </template>
519
+ <div class="content">
520
+ <!-- 代码 -->
521
+ <el-scrollbar
522
+ class="code"
523
+ height="600px"
524
+ >
525
+ <pre>{{ testResult.code }}</pre>
526
+ </el-scrollbar>
527
+ <!-- 分割线 -->
528
+ <el-divider direction="vertical" />
529
+ <!-- 日志 -->
530
+ <el-scrollbar height="600px">
531
+ <pre :class="testResult.result === 1 ? 'success-log' : 'error-log'">{{ testResult.result === 1 ? `✅️ 测试通过\n${testResult.detail}` : testResult.detail }}</pre>
532
+ </el-scrollbar>
533
+ </div>
534
+ <!-- 底部 -->
535
+ <template #footer>
536
+ <div class="dialog-footer">
537
+ <el-button @click="testLogVisible = false"> 关闭 </el-button>
538
+ </div>
539
+ </template>
540
+ </el-dialog>
541
+ </el-dialog>
542
+ </template>
543
+
544
+ <style lang="scss" scoped>
545
+ .manage-dialog {
546
+ .custom-header {
547
+ display: flex;
548
+ align-items: center;
549
+ justify-content: space-between;
550
+ .left,
551
+ .right {
552
+ display: flex;
553
+ align-items: center;
554
+ gap: 10px;
555
+ }
556
+ .el-icon {
557
+ cursor: pointer;
558
+ }
559
+ }
560
+ .manage-dialog-body {
561
+ height: 80vh;
562
+ display: flex;
563
+ align-items: center;
564
+ .func-list {
565
+ height: 100%;
566
+ width: 400px;
567
+ display: flex;
568
+ flex-direction: column;
569
+ box-sizing: border-box;
570
+ padding-right: 10px;
571
+ border-right: var(--el-border);
572
+ .search {
573
+ display: flex;
574
+ align-items: center;
575
+ justify-content: space-between;
576
+ margin-bottom: 10px;
577
+ .el-input {
578
+ flex: 1;
579
+ margin: 0 10px;
580
+ }
581
+ }
582
+ .list {
583
+ width: 100%;
584
+ height: 100%;
585
+ .list-item {
586
+ font-size: 16px;
587
+ width: 100%;
588
+ display: flex;
589
+ align-items: center;
590
+ justify-content: space-between;
591
+ position: relative;
592
+ border-radius: 4px;
593
+ &:hover {
594
+ background-color: #d9e7ff;
595
+ }
596
+ &::before {
597
+ content: "";
598
+ position: absolute;
599
+ left: -30px;
600
+ top: calc(50% - 2px);
601
+ width: 30px;
602
+ height: 16px;
603
+ background: var(--el-color-primary);
604
+ clip-path: polygon(
605
+ 0% 0%,
606
+ // 左上角
607
+ 50% 0%,
608
+ // 右上角缺点
609
+ 100% 100%,
610
+ // 缺点终点
611
+ 100% 100%,
612
+ // 右下角
613
+ 0% 100% // 左下角
614
+ );
615
+ transform: translateY(-50%);
616
+ transition: all 0.25s ease;
617
+ }
618
+ .func-name {
619
+ line-height: 32px;
620
+ flex: 1;
621
+ box-sizing: border-box;
622
+ overflow: hidden;
623
+ white-space: nowrap;
624
+ text-overflow: ellipsis;
625
+ transition: all 0.25s ease;
626
+ cursor: pointer;
627
+ &:hover {
628
+ color: var(--el-color-primary);
629
+ }
630
+ }
631
+ .icon-box {
632
+ font-size: 18px;
633
+ height: 20px;
634
+ padding-right: 10px;
635
+ .el-icon {
636
+ margin-left: 6px;
637
+ cursor: pointer;
638
+ &:hover {
639
+ color: var(--el-color-primary);
640
+ }
641
+ }
642
+ .delete {
643
+ &:hover {
644
+ color: var(--el-color-danger);
645
+ }
646
+ }
647
+ }
648
+ }
649
+ .active-list-item {
650
+ &::before {
651
+ left: 0;
652
+ }
653
+ &::after {
654
+ content: "";
655
+ position: absolute;
656
+ bottom: 0;
657
+ left: 0;
658
+ width: 100%;
659
+ height: 2px;
660
+ background: var(--el-color-primary);
661
+ transform: scaleX(0);
662
+ transform-origin: left center;
663
+ animation: borderGrow 0.25s ease forwards;
664
+ }
665
+ .func-name {
666
+ color: var(--el-color-primary);
667
+ font-weight: bold;
668
+ padding-left: 34px;
669
+ }
670
+ }
671
+ @keyframes borderGrow {
672
+ from {
673
+ transform: scaleX(0);
674
+ }
675
+ to {
676
+ transform: scaleX(1);
677
+ }
678
+ }
679
+ }
680
+ }
681
+ .rule-form {
682
+ flex: 1;
683
+ height: 100%;
684
+ box-sizing: border-box;
685
+ padding-left: 10px;
686
+ .header {
687
+ width: 100%;
688
+ display: flex;
689
+ align-items: center;
690
+ gap: 10px;
691
+ margin-bottom: 10px;
692
+ .el-input {
693
+ flex: 1;
694
+ }
695
+ }
696
+ .tip-box {
697
+ box-sizing: border-box;
698
+ padding: 4px 0 4px 8px;
699
+ margin-bottom: 4px;
700
+ border-left: 6px solid var(--el-color-info);
701
+ background-color: var(--el-color-info-light-8);
702
+ }
703
+ .el-empty {
704
+ height: 100%;
705
+ }
706
+ }
707
+ }
708
+ }
709
+ .test-variety-dialog {
710
+ .custom-header {
711
+ display: flex;
712
+ align-items: center;
713
+ justify-content: space-between;
714
+ .left,
715
+ .right {
716
+ display: flex;
717
+ align-items: center;
718
+ gap: 10px;
719
+ }
720
+ .el-icon {
721
+ cursor: pointer;
722
+ }
723
+ }
724
+ .full-height-textarea {
725
+ width: 100%;
726
+ height: 200px;
727
+ margin-top: 10px;
728
+ :deep(.el-textarea__inner) {
729
+ box-sizing: border-box;
730
+ height: 100%;
731
+ }
732
+ }
733
+ }
734
+ .log-dialog {
735
+ .custom-header {
736
+ display: flex;
737
+ align-items: center;
738
+ justify-content: space-between;
739
+ .left,
740
+ .right {
741
+ display: flex;
742
+ align-items: center;
743
+ gap: 10px;
744
+ }
745
+ .el-icon {
746
+ cursor: pointer;
747
+ }
748
+ }
749
+ .content {
750
+ display: flex;
751
+ background-color: var(--el-color-black);
752
+ .el-scrollbar {
753
+ flex: 1;
754
+ box-sizing: border-box;
755
+ padding: 8px;
756
+ }
757
+ .el-divider {
758
+ margin: 0;
759
+ height: 616px;
760
+ }
761
+ .code {
762
+ color: var(--el-color-info);
763
+ }
764
+ .success-log {
765
+ color: var(--el-color-success);
766
+ }
767
+ .error-log {
768
+ color: var(--el-color-danger);
769
+ }
770
+ pre {
771
+ margin: 0;
772
+ line-height: 1.5;
773
+ white-space: pre-wrap;
774
+ word-break: break-all;
775
+ word-wrap: break-word;
776
+ }
777
+ }
778
+ }
779
+ </style>