st-comp 0.0.160 → 0.0.161
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 +1 -0
- package/es/ChartLayout.js +3 -3
- package/es/Dialog.js +12 -12
- package/es/FactorWarning.cjs +1 -1
- package/es/FactorWarning.js +27 -27
- package/es/Kline.js +16 -16
- package/es/KlineBasic.cjs +1 -1
- package/es/KlineBasic.js +248 -251
- package/es/KlineNew.js +14 -14
- package/es/MonacoEditor.cjs +1 -1
- package/es/MonacoEditor.js +7 -2
- package/es/Pagination.cjs +1 -1
- package/es/Pagination.js +18 -18
- package/es/PasswordPrompt.js +3 -3
- package/es/Table.cjs +1 -1
- package/es/Table.js +196 -347
- package/es/User.cjs +1 -1
- package/es/User.js +21 -21
- package/es/VarietySearch.cjs +3 -1
- package/es/VarietySearch.js +4169 -1058
- package/es/VirtualTable.js +12 -12
- package/es/_commonjsHelpers-10dfc225.js +8 -0
- package/es/_commonjsHelpers-87b0abe8.cjs +1 -0
- package/es/{_initCloneObject-e3d8a9ab.js → _initCloneObject-7f4a9bd7.js} +3 -3
- package/es/{base-19787dfb.js → base-113d028b.js} +7 -7
- package/es/{castArray-8405000b.js → castArray-2b3f27ef.js} +1 -1
- package/es/{config-provider-0f6672af.js → config-provider-3ffe8f8f.js} +3 -3
- package/es/{debounce-6cb0781f.js → debounce-3517a4c7.js} +1 -1
- package/es/{dropdown-17b3ef6a.js → dropdown-ee1240ff.js} +4 -4
- package/es/{el-button-0bf1d532.js → el-button-de89fb60.js} +4 -4
- package/es/{el-checkbox-group-d53bc316.js → el-checkbox-group-17e4156a.js} +2 -2
- package/es/{el-empty-bd5343a7.js → el-empty-546e4106.js} +2 -2
- package/es/{el-form-item-05c0e335.js → el-form-item-73ecd9af.js} +8 -8
- package/es/{el-input-1e309239.js → el-input-c715d419.js} +9 -8
- package/es/{el-input-6a3805c5.cjs → el-input-cb340042.cjs} +1 -1
- package/es/{el-input-number-60ebc58f.js → el-input-number-02db11f6.js} +13 -13
- package/es/{el-input-number-96ff2e47.cjs → el-input-number-0f194f3f.cjs} +1 -1
- package/es/{el-menu-item-6c6236a1.js → el-menu-item-67fac653.js} +8 -8
- package/es/{el-message-7d927756.js → el-message-2eae949c.js} +7 -7
- package/es/{el-overlay-26bf0945.js → el-overlay-f94c4f3b.js} +8 -8
- package/es/{el-popover-17e2e66c.js → el-popconfirm-029f2c00.js} +12 -12
- package/es/{el-popover-7bd8a7c3.cjs → el-popconfirm-86503f8a.cjs} +1 -1
- package/es/{el-popper-b6527ae2.js → el-popper-b34ec18f.js} +9 -9
- package/es/{el-scrollbar-29bcab5f.js → el-scrollbar-c463eaff.js} +7 -7
- package/es/{el-select-7395562b.js → el-select-b77506ca.js} +13 -13
- package/es/{el-table-column-47d80736.js → el-table-column-4aea6b31.js} +12 -12
- package/es/{el-tag-7414e0c7.js → el-tag-1cf8487e.js} +3 -3
- package/es/index-2da94fd7.js +159 -0
- package/es/{index-273822d1.js → index-440d64f2.js} +7 -7
- package/es/{index-75cce588.js → index-496e80be.js} +2 -2
- package/es/index-58521b9e.cjs +1 -0
- package/es/{index-621b092b.js → index-7125c109.js} +1 -1
- package/es/{index-dc22ffe4.js → index-a777a57a.js} +2 -2
- package/es/{index-72151b24.js → index-dd5d4ae9.js} +6 -6
- package/es/{index-c066fe0d.js → index-f393f2d4.js} +3 -3
- package/es/{index-70372cdb.js → index-f905d74d.js} +1 -1
- package/es/{index-ad9f40cd.cjs → index.vue_vue_type_script_setup_true_lang-4024853c.cjs} +3 -3
- package/es/{index-015c420d.js → index.vue_vue_type_script_setup_true_lang-745718ff.js} +5 -9
- package/es/{python-81655341.cjs → python-6a3f6816.cjs} +2 -2
- package/es/{python-be1bd6d2.js → python-7fcad568.js} +1 -1
- package/es/{raf-a532c514.js → raf-5d53429d.js} +1 -1
- package/es/{scroll-d787d648.js → scroll-9ec370f4.js} +1 -1
- package/es/style.css +1 -1
- package/es/{use-form-common-props-5ff2f51b.js → use-form-common-props-d20ca09c.js} +8 -8
- package/es/{vnode-6a0c7411.js → vnode-2d8e2f0e.js} +1 -1
- package/es/{zh-cn-f37255ae.js → zh-cn-4d2bbda7.js} +2 -2
- package/lib/bundle.js +1 -1
- package/lib/bundle.umd.cjs +222 -220
- package/lib/{index-8b2455d8.js → index-c0cfb828.js} +45193 -42087
- package/lib/{python-28c4c3e3.js → python-4a34bda1.js} +1 -1
- package/lib/style.css +1 -1
- package/package.json +2 -1
- package/packages/VarietySearch/components/FactorScreen/ScriptSelect.vue +300 -0
- package/packages/VarietySearch/components/FactorScreen/VarietySelect.vue +78 -0
- package/packages/VarietySearch/components/FactorScreen/index.vue +123 -21
- package/packages/VarietySearch/index.vue +7 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "st-comp",
|
|
3
3
|
"public": true,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.161",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "vite",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"dayjs": "^1.11.10",
|
|
19
19
|
"echarts": "^5.4.3",
|
|
20
20
|
"element-plus": "^2.9.4",
|
|
21
|
+
"interactjs": "^1.10.27",
|
|
21
22
|
"monaco-editor": "0.47.0",
|
|
22
23
|
"pinia": "^2.1.6",
|
|
23
24
|
"st-func": "^0.0.59",
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import interact from "interactjs";
|
|
3
|
+
import { computed, onMounted, ref, inject } from "vue";
|
|
4
|
+
import { Close, InfoFilled } from "@element-plus/icons-vue";
|
|
5
|
+
import VarietySelect from './VarietySelect.vue'
|
|
6
|
+
|
|
7
|
+
const stConfig = inject("stConfig");
|
|
8
|
+
|
|
9
|
+
const dialogRef = ref(null); // 弹窗主体Ref
|
|
10
|
+
const dialogTop = ref((window.innerHeight - 542) / 2 - 220 > 0 ? (window.innerHeight - 542) / 2 - 220 : 0);
|
|
11
|
+
const dialogRight = ref((window.innerWidth - 1000) / 2 > 0 ? (window.innerWidth - 1000) / 2 : 0);
|
|
12
|
+
|
|
13
|
+
const editorRef = ref(null); // 编辑器Ref
|
|
14
|
+
const visible = ref(false);
|
|
15
|
+
|
|
16
|
+
const varName = ref(null);
|
|
17
|
+
const varList = ref([]);
|
|
18
|
+
const formatList = computed(() => {
|
|
19
|
+
return varList.value.find((item) => item.varName === varName.value)?.formatList ?? [];
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// 格式化配置项的下拉框数据源
|
|
23
|
+
const handleOptionsStrToArray = (str) => {
|
|
24
|
+
const trimmedStr = str.replace(/^\[|\]$/g, "");
|
|
25
|
+
// 分割字符串为多个数组项
|
|
26
|
+
const items = trimmedStr.split("],[");
|
|
27
|
+
|
|
28
|
+
return items.map((item) => {
|
|
29
|
+
// 移除每个项两端的方括号(如果有)
|
|
30
|
+
const cleanItem = item.replace(/\[|\]/g, "");
|
|
31
|
+
// 分割标签和值
|
|
32
|
+
const [label, value] = cleanItem.split(",");
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
label: label.trim(),
|
|
36
|
+
value: value.trim(),
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// 插入变量值
|
|
42
|
+
const handleInsetVarContent = (configList) => {
|
|
43
|
+
// 1.校验是否填写完整 + 生成输出值
|
|
44
|
+
const result = [];
|
|
45
|
+
for (let index = 0; index < configList.length; index++) {
|
|
46
|
+
const item = configList[index];
|
|
47
|
+
console.log(item)
|
|
48
|
+
switch (item.vtype) {
|
|
49
|
+
case "text": {
|
|
50
|
+
result.push(item.param);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
default: {
|
|
54
|
+
if (!item.modelValue) return ElMessage.error("请检查插入格式内是否填写完整");
|
|
55
|
+
result.push(item.suffix ? `${item.modelValue}${item.suffix}` : `${item.modelValue}`);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// 2.插入内容
|
|
61
|
+
const content = result.join("_");
|
|
62
|
+
|
|
63
|
+
const editorIns = editorRef.value.getInstance();
|
|
64
|
+
const position = editorIns.getPosition();
|
|
65
|
+
|
|
66
|
+
const currentValue = editorRef.value.getValue();
|
|
67
|
+
const lines = currentValue.split("\n");
|
|
68
|
+
// 如果光标位置有效
|
|
69
|
+
if (position.lineNumber <= lines.length) {
|
|
70
|
+
const lineIndex = position.lineNumber - 1;
|
|
71
|
+
const line = lines[lineIndex];
|
|
72
|
+
|
|
73
|
+
// 在光标位置插入内容
|
|
74
|
+
const newLine = line.substring(0, position.column - 1) + content + line.substring(position.column - 1);
|
|
75
|
+
lines[lineIndex] = newLine;
|
|
76
|
+
|
|
77
|
+
// 更新编辑器内容
|
|
78
|
+
const newValue = lines.join("\n");
|
|
79
|
+
editorRef.value.setValue(newValue);
|
|
80
|
+
|
|
81
|
+
// 将光标移动到插入内容之后
|
|
82
|
+
const newColumn = position.column + content.length;
|
|
83
|
+
editorIns.setPosition({
|
|
84
|
+
lineNumber: position.lineNumber,
|
|
85
|
+
column: newColumn,
|
|
86
|
+
});
|
|
87
|
+
editorIns.focus();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
onMounted(async () => {
|
|
92
|
+
const { body } = await stConfig.request.post('/common/conf/queryAllBackVariables', { useCase: "2" });
|
|
93
|
+
varList.value = body;
|
|
94
|
+
});
|
|
95
|
+
defineExpose({
|
|
96
|
+
open: (editor) => {
|
|
97
|
+
editorRef.value = editor;
|
|
98
|
+
visible.value = true;
|
|
99
|
+
// 支持拖拽
|
|
100
|
+
const dragArea = document.querySelector("body");
|
|
101
|
+
interact(dialogRef.value).draggable({
|
|
102
|
+
allowFrom: ".custom-header", // 只有 .custom-header 元素可以触发拖拽
|
|
103
|
+
// 限制拖拽范围
|
|
104
|
+
modifiers: [
|
|
105
|
+
interact.modifiers.restrictRect({
|
|
106
|
+
restriction: dragArea, // 限制在拖拽区域内
|
|
107
|
+
endOnly: false, // 实时限制
|
|
108
|
+
}),
|
|
109
|
+
],
|
|
110
|
+
listeners: {
|
|
111
|
+
move(event) {
|
|
112
|
+
dialogRight.value -= event.dx;
|
|
113
|
+
dialogTop.value += event.dy;
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
close: () => {
|
|
119
|
+
visible.value = false;
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<template>
|
|
125
|
+
<div
|
|
126
|
+
v-show="visible"
|
|
127
|
+
class="var-select-dialog"
|
|
128
|
+
ref="dialogRef"
|
|
129
|
+
:style="{ right: `${dialogRight}px`, top: `${dialogTop}px` }"
|
|
130
|
+
>
|
|
131
|
+
<div class="custom-header">
|
|
132
|
+
<div class="left">
|
|
133
|
+
<span> 选择变量 </span>
|
|
134
|
+
<el-select
|
|
135
|
+
v-model="varName"
|
|
136
|
+
placeholder="选择变量"
|
|
137
|
+
filterable
|
|
138
|
+
clearable
|
|
139
|
+
>
|
|
140
|
+
<el-option
|
|
141
|
+
v-for="(item, index) in varList"
|
|
142
|
+
:key="index"
|
|
143
|
+
:label="item.varName"
|
|
144
|
+
:value="item.varName"
|
|
145
|
+
/>
|
|
146
|
+
</el-select>
|
|
147
|
+
</div>
|
|
148
|
+
<div class="right">
|
|
149
|
+
<el-icon
|
|
150
|
+
class="el-icon--left"
|
|
151
|
+
@click="visible = false"
|
|
152
|
+
>
|
|
153
|
+
<Close />
|
|
154
|
+
</el-icon>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
<div class="custom-body">
|
|
158
|
+
<template v-if="formatList.length">
|
|
159
|
+
<div
|
|
160
|
+
class="format-item"
|
|
161
|
+
v-for="(formatItem, formatIndex) in formatList"
|
|
162
|
+
:key="formatIndex"
|
|
163
|
+
>
|
|
164
|
+
<span>格式{{ formatIndex + 1 }}:</span>
|
|
165
|
+
|
|
166
|
+
<!-- 配置项 -->
|
|
167
|
+
<div class="config-list">
|
|
168
|
+
<template v-for="(config, configIndex) in formatItem.configList">
|
|
169
|
+
<div class="config-item">
|
|
170
|
+
<!-- 类型: 固定值 -->
|
|
171
|
+
<template v-if="config.vtype === 'text'">
|
|
172
|
+
<span>{{ config.param }}</span>
|
|
173
|
+
</template>
|
|
174
|
+
<template v-if="config.vtype === 'inputVariety'">
|
|
175
|
+
<VarietySelect
|
|
176
|
+
size="small"
|
|
177
|
+
:placeholder="config.param"
|
|
178
|
+
:selectClearEnable="false"
|
|
179
|
+
:labelShowEnable="false"
|
|
180
|
+
@select="({ name, code }) => (config.modelValue = code)"
|
|
181
|
+
@change="(value) => (config.modelValue = value)"
|
|
182
|
+
style="width: 100px"
|
|
183
|
+
/>
|
|
184
|
+
</template>
|
|
185
|
+
<template v-if="config.vtype === 'input'">
|
|
186
|
+
<el-input
|
|
187
|
+
v-model="config.modelValue"
|
|
188
|
+
:placeholder="config.param"
|
|
189
|
+
size="small"
|
|
190
|
+
/>
|
|
191
|
+
<span v-if="config.suffix">{{ config.suffix }}</span>
|
|
192
|
+
</template>
|
|
193
|
+
<template v-if="config.vtype === 'select'">
|
|
194
|
+
<el-select
|
|
195
|
+
v-model="config.modelValue"
|
|
196
|
+
:placeholder="config.param"
|
|
197
|
+
clearable
|
|
198
|
+
size="small"
|
|
199
|
+
>
|
|
200
|
+
<el-option
|
|
201
|
+
v-for="item in handleOptionsStrToArray(config.optionsStr)"
|
|
202
|
+
:key="item.value"
|
|
203
|
+
:label="item.label"
|
|
204
|
+
:value="item.value"
|
|
205
|
+
/>
|
|
206
|
+
</el-select>
|
|
207
|
+
</template>
|
|
208
|
+
</div>
|
|
209
|
+
<span v-if="configIndex !== formatItem.configList.length - 1">_</span>
|
|
210
|
+
</template>
|
|
211
|
+
</div>
|
|
212
|
+
<!-- 插入变量 -->
|
|
213
|
+
<el-button
|
|
214
|
+
type="primary"
|
|
215
|
+
plain
|
|
216
|
+
size="small"
|
|
217
|
+
@click="handleInsetVarContent(formatItem.configList)"
|
|
218
|
+
>
|
|
219
|
+
插入变量
|
|
220
|
+
</el-button>
|
|
221
|
+
<!-- Tip示例 -->
|
|
222
|
+
<el-tooltip
|
|
223
|
+
effect="dark"
|
|
224
|
+
:content="formatItem.tip"
|
|
225
|
+
placement="top-start"
|
|
226
|
+
>
|
|
227
|
+
<el-icon><InfoFilled /></el-icon>
|
|
228
|
+
</el-tooltip>
|
|
229
|
+
</div>
|
|
230
|
+
</template>
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
</template>
|
|
234
|
+
|
|
235
|
+
<style lang="scss" scoped>
|
|
236
|
+
.var-select-dialog {
|
|
237
|
+
min-width: 660px;
|
|
238
|
+
max-width: 1000px;
|
|
239
|
+
border-radius: 4px;
|
|
240
|
+
box-sizing: border-box;
|
|
241
|
+
box-shadow: var(--el-box-shadow-light);
|
|
242
|
+
background-color: var(--el-bg-color);
|
|
243
|
+
z-index: 2006;
|
|
244
|
+
position: fixed;
|
|
245
|
+
.custom-header {
|
|
246
|
+
display: flex;
|
|
247
|
+
align-items: center;
|
|
248
|
+
justify-content: space-between;
|
|
249
|
+
padding: 10px;
|
|
250
|
+
.left {
|
|
251
|
+
display: flex;
|
|
252
|
+
align-items: center;
|
|
253
|
+
flex: 1;
|
|
254
|
+
span {
|
|
255
|
+
margin-right: 10px;
|
|
256
|
+
}
|
|
257
|
+
.el-select {
|
|
258
|
+
width: 140px;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
.right {
|
|
262
|
+
display: flex;
|
|
263
|
+
align-items: center;
|
|
264
|
+
.el-button {
|
|
265
|
+
margin-right: 10px;
|
|
266
|
+
}
|
|
267
|
+
.el-icon {
|
|
268
|
+
cursor: pointer;
|
|
269
|
+
&:hover {
|
|
270
|
+
color: var(--el-color-primary);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
.custom-body {
|
|
276
|
+
min-height: 160px;
|
|
277
|
+
box-sizing: border-box;
|
|
278
|
+
border-top: var(--el-border);
|
|
279
|
+
padding: 20px 10px;
|
|
280
|
+
.format-item {
|
|
281
|
+
font-size: 12px;
|
|
282
|
+
display: flex;
|
|
283
|
+
align-items: center;
|
|
284
|
+
flex-wrap: wrap;
|
|
285
|
+
gap: 10px;
|
|
286
|
+
margin-bottom: 10px;
|
|
287
|
+
.config-list {
|
|
288
|
+
display: flex;
|
|
289
|
+
align-items: center;
|
|
290
|
+
.el-input {
|
|
291
|
+
width: 100px;
|
|
292
|
+
}
|
|
293
|
+
.el-select {
|
|
294
|
+
width: 100px;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
</style>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<!-- 组件: 品种自动补全搜索 -->
|
|
2
|
+
<script setup>
|
|
3
|
+
import { ref, inject } from "vue";
|
|
4
|
+
import { getUserData } from "st-func";
|
|
5
|
+
|
|
6
|
+
const stConfig = inject("stConfig");
|
|
7
|
+
|
|
8
|
+
const emit = defineEmits(["select", "change"]);
|
|
9
|
+
const props = defineProps({
|
|
10
|
+
size: { type: String, default: "default" },
|
|
11
|
+
placeholder: { type: String, default: "请输入品种名称或代码" },
|
|
12
|
+
labelShowEnable: { type: Boolean, default: true }, // 是否开启展示label
|
|
13
|
+
selectClearEnable: { type: Boolean, default: true }, // 是否开启选择回调后清除输入框值
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const inputValue = ref("");
|
|
17
|
+
const fetchSuggestions = async (value, callback) => {
|
|
18
|
+
if (value === "" || value === "null") {
|
|
19
|
+
callback([]);
|
|
20
|
+
} else {
|
|
21
|
+
const params = {
|
|
22
|
+
keyWord: value,
|
|
23
|
+
pageNum: 1,
|
|
24
|
+
pageSize: 999,
|
|
25
|
+
userId: getUserData("id"),
|
|
26
|
+
hotSearchFlag: 1,
|
|
27
|
+
};
|
|
28
|
+
const { body } = await stConfig.request.post("/common/qt/getFeatureInfosByPage", params);
|
|
29
|
+
const result = body.list.map(({ code, featureName }) => ({
|
|
30
|
+
label: `${code}\xa0\xa0\xa0${featureName}`,
|
|
31
|
+
value: code,
|
|
32
|
+
}));
|
|
33
|
+
callback(result);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const handleSelect = ({ label, value }) => {
|
|
37
|
+
const name = label.split("\xa0").at(-1);
|
|
38
|
+
const code = value;
|
|
39
|
+
emit("select", { name, code });
|
|
40
|
+
if (props.selectClearEnable) inputValue.value = "";
|
|
41
|
+
};
|
|
42
|
+
const handleChange = (value) => {
|
|
43
|
+
emit("change", value);
|
|
44
|
+
}
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template>
|
|
48
|
+
<div class="variety-auto-complete">
|
|
49
|
+
<span v-if="labelShowEnable">品种搜索:</span>
|
|
50
|
+
<el-autocomplete
|
|
51
|
+
v-model="inputValue"
|
|
52
|
+
clearable
|
|
53
|
+
:size="props.size"
|
|
54
|
+
:placeholder="props.placeholder"
|
|
55
|
+
:fetch-suggestions="fetchSuggestions"
|
|
56
|
+
@select="handleSelect"
|
|
57
|
+
@change="handleChange"
|
|
58
|
+
>
|
|
59
|
+
<template #default="{ item }">
|
|
60
|
+
<div class="label">{{ item.label }}</div>
|
|
61
|
+
</template>
|
|
62
|
+
</el-autocomplete>
|
|
63
|
+
</div>
|
|
64
|
+
</template>
|
|
65
|
+
|
|
66
|
+
<style lang="scss" scoped>
|
|
67
|
+
.variety-auto-complete {
|
|
68
|
+
width: 100%;
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
span {
|
|
72
|
+
width: 80px;
|
|
73
|
+
}
|
|
74
|
+
.el-autocomplete {
|
|
75
|
+
flex: 1;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
</style>
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<!-- 因子筛选组件 -->
|
|
2
2
|
<script setup name="FactorScreen">
|
|
3
|
-
import { ref } from "vue";
|
|
3
|
+
import { nextTick, ref, watch } from "vue";
|
|
4
4
|
import { Plus, CircleCloseFilled, InfoFilled } from "@element-plus/icons-vue";
|
|
5
5
|
import { handleVerifyScore, extractConditionDetails } from "./tools.js";
|
|
6
6
|
import FactorDescription from "./FactorDescription.vue";
|
|
7
|
+
import ScriptSelect from "./ScriptSelect.vue";
|
|
8
|
+
import MonacoEditor from "../../../MonacoEditor/index.vue"
|
|
7
9
|
|
|
8
10
|
const props = defineProps({
|
|
9
11
|
config: {
|
|
@@ -26,9 +28,12 @@ const data = defineModel("data", {
|
|
|
26
28
|
},
|
|
27
29
|
});
|
|
28
30
|
|
|
31
|
+
const monacoEditorRef = ref();
|
|
32
|
+
const scriptSelectRef = ref();
|
|
29
33
|
// 弹窗开关
|
|
30
34
|
const visible = ref(false);
|
|
31
35
|
const visibleDescriptions = ref(false);
|
|
36
|
+
const factorType = ref("模版");
|
|
32
37
|
// 弹窗表单
|
|
33
38
|
const dialogFormRef = ref(null);
|
|
34
39
|
const dialogForm = ref({
|
|
@@ -44,43 +49,73 @@ const dialogForm = ref({
|
|
|
44
49
|
sqlEnable: 0,
|
|
45
50
|
// SQL语句
|
|
46
51
|
sqlValue: null,
|
|
52
|
+
// 脚本语句
|
|
53
|
+
factorSelectExpr: '',
|
|
47
54
|
});
|
|
48
55
|
|
|
56
|
+
watch(() => [factorType.value, visible.value], () => {
|
|
57
|
+
if (factorType.value === '模版' || visible.value === false) {
|
|
58
|
+
scriptSelectRef.value.close();
|
|
59
|
+
}
|
|
60
|
+
}, { deep: true })
|
|
61
|
+
|
|
49
62
|
// 打开
|
|
50
63
|
const handleOpenDialog = () => {
|
|
51
|
-
const { list, sqlEnable, sqlValue } = data.value;
|
|
64
|
+
const { list, sqlEnable, sqlValue, factorSelectExpr } = data.value;
|
|
52
65
|
dialogForm.value = {
|
|
53
66
|
list: JSON.parse(JSON.stringify(list)),
|
|
54
67
|
sqlEnable,
|
|
55
68
|
sqlValue,
|
|
69
|
+
factorSelectExpr,
|
|
56
70
|
};
|
|
57
71
|
// 保证因子筛选最少一条
|
|
58
72
|
if (!dialogForm.value.list.length) handleAppendFactor();
|
|
59
73
|
visible.value = true;
|
|
74
|
+
// 解决初次访问样式错乱问题
|
|
75
|
+
nextTick(() => {
|
|
76
|
+
if (factorSelectExpr) {
|
|
77
|
+
factorType.value = '脚本'
|
|
78
|
+
monacoEditorRef.value.setValue(factorSelectExpr);
|
|
79
|
+
} else factorType.value = '模版';
|
|
80
|
+
monacoEditorRef.value.resize();
|
|
81
|
+
})
|
|
60
82
|
};
|
|
61
83
|
// 确定
|
|
62
84
|
const handleSubmit = () => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
if (factorType.value === '模版') {
|
|
86
|
+
dialogFormRef.value.validate((valid) => {
|
|
87
|
+
const { list, sqlEnable, sqlValue } = dialogForm.value;
|
|
88
|
+
if (!valid) return;
|
|
89
|
+
// 针对开启了SQL功能后的字段校验
|
|
90
|
+
if (sqlEnable) {
|
|
91
|
+
if (!sqlValue) return ElMessage.error("SQL语句不能为空");
|
|
92
|
+
// 提取SQL语句中的条件1, 条件2, ...
|
|
93
|
+
const sqlConditions = extractConditionDetails(sqlValue);
|
|
94
|
+
// 生成因子表格中的条件1, 条件2, ...
|
|
95
|
+
const factorConditions = list.map((item, index) => `条件${index + 1}`);
|
|
96
|
+
// 校验SQL中是否全部都能在因子表格中找到
|
|
97
|
+
const noSaveConditions = sqlConditions.filter((item) => !factorConditions.includes(item));
|
|
98
|
+
if (noSaveConditions.length) return ElMessage.error(`请检查SQL语句, 不存在[${noSaveConditions}]`);
|
|
99
|
+
}
|
|
100
|
+
data.value = {
|
|
101
|
+
list: JSON.parse(JSON.stringify(list)),
|
|
102
|
+
sqlEnable,
|
|
103
|
+
sqlValue,
|
|
104
|
+
factorSelectExpr: '',
|
|
105
|
+
};
|
|
106
|
+
visible.value = false;
|
|
107
|
+
});
|
|
108
|
+
} else {
|
|
109
|
+
const script = monacoEditorRef.value.getValue();
|
|
110
|
+
if (!script) return ElMessage.error("请输入脚本语句");
|
|
77
111
|
data.value = {
|
|
78
|
-
list:
|
|
79
|
-
sqlEnable,
|
|
80
|
-
sqlValue,
|
|
112
|
+
list: [],
|
|
113
|
+
sqlEnable: 0,
|
|
114
|
+
sqlValue: null,
|
|
115
|
+
factorSelectExpr: script,
|
|
81
116
|
};
|
|
82
117
|
visible.value = false;
|
|
83
|
-
}
|
|
118
|
+
}
|
|
84
119
|
};
|
|
85
120
|
|
|
86
121
|
// 表单: 删除因子
|
|
@@ -185,8 +220,22 @@ const handleDeleteTag = (aciton, index) => {
|
|
|
185
220
|
data.value.list.splice(index, 1);
|
|
186
221
|
break;
|
|
187
222
|
}
|
|
223
|
+
case "scriptTag": {
|
|
224
|
+
data.value = {
|
|
225
|
+
list: [],
|
|
226
|
+
sqlEnable: 0,
|
|
227
|
+
sqlValue: null,
|
|
228
|
+
factorSelectExpr: '',
|
|
229
|
+
};
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
188
232
|
}
|
|
189
233
|
};
|
|
234
|
+
|
|
235
|
+
// 打开变量选择器
|
|
236
|
+
const open = () => {
|
|
237
|
+
scriptSelectRef.value.open(monacoEditorRef.value);
|
|
238
|
+
}
|
|
190
239
|
</script>
|
|
191
240
|
|
|
192
241
|
<template>
|
|
@@ -221,6 +270,25 @@ const handleDeleteTag = (aciton, index) => {
|
|
|
221
270
|
{{ handleFormatTag(tag) }}
|
|
222
271
|
</el-tag>
|
|
223
272
|
</template>
|
|
273
|
+
<!-- 脚本模式 -->
|
|
274
|
+
<el-popover
|
|
275
|
+
v-if="data.factorSelectExpr"
|
|
276
|
+
width="500"
|
|
277
|
+
placement="bottom-start"
|
|
278
|
+
>
|
|
279
|
+
<div style="white-space: pre-line;">
|
|
280
|
+
{{ data.factorSelectExpr }}
|
|
281
|
+
</div>
|
|
282
|
+
<template #reference>
|
|
283
|
+
<el-tag
|
|
284
|
+
closable
|
|
285
|
+
type="info"
|
|
286
|
+
@close="handleDeleteTag('scriptTag')"
|
|
287
|
+
>
|
|
288
|
+
脚本模式
|
|
289
|
+
</el-tag>
|
|
290
|
+
</template>
|
|
291
|
+
</el-popover>
|
|
224
292
|
<!-- 添加按钮 -->
|
|
225
293
|
<el-button
|
|
226
294
|
class="screen-btn"
|
|
@@ -236,7 +304,7 @@ const handleDeleteTag = (aciton, index) => {
|
|
|
236
304
|
<!-- 因子筛选弹窗 -->
|
|
237
305
|
<el-dialog
|
|
238
306
|
v-model="visible"
|
|
239
|
-
width="
|
|
307
|
+
width="1000"
|
|
240
308
|
align-center
|
|
241
309
|
destroy-on-close
|
|
242
310
|
>
|
|
@@ -255,9 +323,27 @@ const handleDeleteTag = (aciton, index) => {
|
|
|
255
323
|
>
|
|
256
324
|
<el-icon @click="visibleDescriptions = true"><InfoFilled /></el-icon>
|
|
257
325
|
</el-tooltip>
|
|
326
|
+
<el-radio-group
|
|
327
|
+
v-model="factorType"
|
|
328
|
+
size="small"
|
|
329
|
+
style="margin-left: 12px;"
|
|
330
|
+
>
|
|
331
|
+
<el-radio-button label="模版" value="模版" />
|
|
332
|
+
<el-radio-button label="脚本" value="脚本" />
|
|
333
|
+
</el-radio-group>
|
|
334
|
+
<!-- 变量选择器 -->
|
|
335
|
+
<div style="flex: 1; text-align: right;" v-if="factorType === '脚本'">
|
|
336
|
+
<el-button
|
|
337
|
+
size="small"
|
|
338
|
+
type="primary"
|
|
339
|
+
@click="open"
|
|
340
|
+
>变量选择器</el-button>
|
|
341
|
+
</div>
|
|
258
342
|
</div>
|
|
259
343
|
</template>
|
|
344
|
+
<!-- 模版模式 -->
|
|
260
345
|
<el-form
|
|
346
|
+
v-if="factorType === '模版'"
|
|
261
347
|
ref="dialogFormRef"
|
|
262
348
|
:model="dialogForm"
|
|
263
349
|
>
|
|
@@ -485,6 +571,20 @@ const handleDeleteTag = (aciton, index) => {
|
|
|
485
571
|
</template>
|
|
486
572
|
</template>
|
|
487
573
|
</el-form>
|
|
574
|
+
<!-- 脚本模式 -->
|
|
575
|
+
<div
|
|
576
|
+
style="width: 968px; height: 400px"
|
|
577
|
+
:style="
|
|
578
|
+
factorType === '脚本' ?
|
|
579
|
+
null :
|
|
580
|
+
{ position: 'fixed', top: '-400px', zIndex: -1 }
|
|
581
|
+
"
|
|
582
|
+
>
|
|
583
|
+
<MonacoEditor
|
|
584
|
+
ref="monacoEditorRef"
|
|
585
|
+
:language="'lua'"
|
|
586
|
+
/>
|
|
587
|
+
</div>
|
|
488
588
|
<template #footer>
|
|
489
589
|
<div class="dialog-footer">
|
|
490
590
|
<el-button
|
|
@@ -501,6 +601,8 @@ const handleDeleteTag = (aciton, index) => {
|
|
|
501
601
|
v-model:visible="visibleDescriptions"
|
|
502
602
|
:data="config.factorDescriptions?.filter((item) => [1, 3].includes(item.type))"
|
|
503
603
|
/>
|
|
604
|
+
<!-- 变量选择器 -->
|
|
605
|
+
<ScriptSelect ref="scriptSelectRef" />
|
|
504
606
|
</template>
|
|
505
607
|
|
|
506
608
|
<style lang="scss" scoped>
|
|
@@ -26,6 +26,7 @@ searchData.value = Object.assign(searchData.value, {
|
|
|
26
26
|
list: [],
|
|
27
27
|
sqlEnable: 0,
|
|
28
28
|
sqlValue: null,
|
|
29
|
+
factorSelectExpr: '',
|
|
29
30
|
},
|
|
30
31
|
// 常用指标
|
|
31
32
|
commonIndicator: [],
|
|
@@ -114,6 +115,7 @@ const clearRow = (key) => {
|
|
|
114
115
|
list: [],
|
|
115
116
|
sqlEnable: 0,
|
|
116
117
|
sqlValue: null,
|
|
118
|
+
factorSelectExpr: '',
|
|
117
119
|
};
|
|
118
120
|
break;
|
|
119
121
|
}
|
|
@@ -260,6 +262,10 @@ defineExpose({
|
|
|
260
262
|
}
|
|
261
263
|
// enableSql参数整理
|
|
262
264
|
params.enableSql = factorScreen.sqlEnable === 1 ? 2 : 1;
|
|
265
|
+
// 2.因子筛选表达式
|
|
266
|
+
if (factorScreen.factorSelectExpr) {
|
|
267
|
+
params.factorSelectExpr = factorScreen.factorSelectExpr;
|
|
268
|
+
}
|
|
263
269
|
}
|
|
264
270
|
// 7.常用指标
|
|
265
271
|
{
|
|
@@ -451,6 +457,7 @@ defineExpose({
|
|
|
451
457
|
list: [],
|
|
452
458
|
sqlEnable: 0,
|
|
453
459
|
sqlValue: null,
|
|
460
|
+
factorSelectExpr: '',
|
|
454
461
|
},
|
|
455
462
|
// 常用指标
|
|
456
463
|
commonIndicator: [],
|