st-comp 0.0.80 → 0.0.82

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "st-comp",
3
3
  "public": true,
4
- "version": "0.0.80",
4
+ "version": "0.0.82",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -3,59 +3,118 @@
3
3
  import { ref } from "vue";
4
4
  import { Plus, CircleCloseFilled } from "@element-plus/icons-vue";
5
5
 
6
- const props = defineProps({ config: { type: Object, default: () => {} } });
7
- const data = defineModel("data", { default: [] }); // 父组件对应该组件字段的数据
6
+ // 组件点击确认后的数据
7
+ const data = defineModel("data", {
8
+ default: {
9
+ list: [],
10
+ sqlEnable: 0,
11
+ sqlValue: null,
12
+ },
13
+ });
14
+ const props = defineProps({
15
+ config: {
16
+ type: Object,
17
+ default: {
18
+ cycleShow: true, // 周期功能是否展示
19
+ cycleDefault: null, // 周期默认值
20
+ cycleOptions: [], // 周期下拉框选项
21
+ factorOptions: [], // 因子下拉框选项
22
+ sqlShow: false, // SQL功能是否展示
23
+ },
24
+ },
25
+ });
8
26
 
9
27
  // 弹窗开关
10
28
  const visible = ref(false);
11
-
12
- // 表单相关参数
13
29
  const dialogFormRef = ref(null);
14
- const dialogForm = ref({ factorScreen: [{ cycle: props.config.cycleDefault ?? null, factor: null, score: [null, null] }] });
15
- // 特殊校验: 分数
16
- const scoreValidator = (rule, value, callback) => {
17
- // 检查开始和结束的分是否都没填
18
- if (!value[0] && value[0] !== 0 && !value[1] && value[1] !== 0) {
19
- callback(new Error("至少填写一个分数"));
20
- } else {
21
- callback();
22
- }
23
- };
30
+ const dialogForm = ref({
31
+ // 筛选因子列表
32
+ list: [
33
+ {
34
+ cycle: props.config.cycleDefault ?? null, // 周期
35
+ factor: null, // 因子
36
+ score: [null, null], // 得分
37
+ },
38
+ ],
39
+ // 是否开启SQL功能 0关闭, 1开启
40
+ sqlEnable: 0,
41
+ // SQL语句
42
+ sqlValue: null,
43
+ });
24
44
 
25
- // 函数: 弹窗外-添加因子
45
+ // 打开弹窗
26
46
  const openDialog = () => {
27
- // 弹窗打开时, 重置表单
28
- if (data.value.length > 0) dialogForm.value.factorScreen = JSON.parse(JSON.stringify(data.value));
29
- else dialogForm.value.factorScreen = [{ cycle: props.config.cycleDefault ?? null, factor: null, score: [null, null] }];
47
+ const { list, sqlEnable, sqlValue } = data.value;
48
+ dialogForm.value = {
49
+ list: JSON.parse(JSON.stringify(list)),
50
+ sqlEnable,
51
+ sqlValue,
52
+ };
53
+ // 保证因子筛选最少一条
54
+ if (!dialogForm.value.list.length) addFactor();
30
55
  visible.value = true;
31
56
  };
32
- // 函数: 弹窗外-删除因子
57
+ // 删除因子[弹窗外]
33
58
  const deleteTag = (index) => {
34
- data.value.splice(index, 1);
59
+ data.value.list.splice(index, 1);
35
60
  };
36
-
37
- // 函数: 弹窗内-添加因子
61
+ // 删除SQL[弹窗外]
62
+ const deleteSQL = () => {
63
+ data.value.sqlValue = null;
64
+ };
65
+ // 添加因子
38
66
  const addFactor = () => {
39
- dialogForm.value.factorScreen.push({ cycle: props.config.cycleDefault ?? null, factor: null, score: [null, null] });
67
+ dialogForm.value.list.push({
68
+ cycle: props.config.cycleDefault ?? null,
69
+ factor: null,
70
+ score: [null, null],
71
+ });
40
72
  };
41
- // 函数: 弹窗内-删除因子
73
+ // 删除因子[弹窗内]
42
74
  const deleteFactor = (index) => {
43
- dialogForm.value.factorScreen.splice(index, 1);
75
+ dialogForm.value.list.splice(index, 1);
76
+ };
77
+ // 生成SQL
78
+ const createSQL = () => {
79
+ dialogFormRef.value.validate((valid) => {
80
+ if (!valid) return;
81
+ dialogForm.value.sqlValue = dialogForm.value.list.reduce((result, item, index) => {
82
+ let sql = `factor_id = ${item.factor} and `;
83
+ // 如果开启了周期选择
84
+ if (props.config.cycleShow) sql += `freq_id = ${item.cycle} and `;
85
+ // 分数的判断
86
+ if ((item.score[0] || item.score[0] === 0) && (item.score[1] || item.score[1] === 0)) {
87
+ sql += `score >= ${item.score[0]} and score <= ${item.score[1]}`;
88
+ } else if (item.score[0] || item.score[0] === 0) {
89
+ sql += `score >= ${item.score[0]}`;
90
+ } else if (item.score[1] || item.score[1] === 0) {
91
+ sql += `score <= ${item.score[1]}`;
92
+ }
93
+ // 格式化因子sql语句
94
+ sql = `(${sql})`;
95
+ // 如果不是第一条因子sql
96
+ if (index !== 0) sql = ` and ${sql}`;
97
+ result += sql;
98
+ return result;
99
+ }, "");
100
+ });
44
101
  };
45
- // 函数: 确定
102
+ // 确定
46
103
  const submit = () => {
47
- if (!dialogFormRef.value) return;
48
104
  dialogFormRef.value.validate((valid) => {
49
- if (valid) {
50
- data.value = JSON.parse(JSON.stringify(dialogForm.value.factorScreen));
51
- visible.value = false;
52
- } else {
53
- console.error("因子筛选-弹窗: 表单校验未通过");
54
- }
105
+ const { list, sqlEnable, sqlValue } = dialogForm.value;
106
+ if (!valid) return;
107
+ if (sqlEnable && !sqlValue) return ElMessage.error("SQL语句不能为空");
108
+ data.value = {
109
+ list: JSON.parse(JSON.stringify(list)),
110
+ sqlEnable,
111
+ sqlValue,
112
+ };
113
+ visible.value = false;
55
114
  });
56
115
  };
57
116
 
58
- // 映射
117
+ // Tag映射文案
59
118
  const handleTagName = (tag) => {
60
119
  const { cycle, factor, score } = tag;
61
120
  let str = "";
@@ -66,65 +125,177 @@ const handleTagName = (tag) => {
66
125
  str += ` ${score[1] || score[1] === 0 ? `${score[1]}分` : "∞"}`;
67
126
  return str;
68
127
  };
128
+ // 表单校验: 分数
129
+ const scoreValidator = (rule, value, callback) => {
130
+ // 检查开始和结束的分是否都没填
131
+ if (!value[0] && value[0] !== 0 && !value[1] && value[1] !== 0) {
132
+ callback(new Error("至少填写一个分数"));
133
+ } else {
134
+ callback();
135
+ }
136
+ };
69
137
  </script>
70
138
 
71
139
  <template>
72
140
  <div class="factor-screen">
73
- <!-- Tag展示区域 -->
74
- <template v-if="data.length">
75
- <el-tag v-for="(tag, index) in data" closable type="info" @close="deleteTag(index)">
141
+ <!-- 文案[开启sqlEnable] -->
142
+ <el-tag
143
+ v-if="data.sqlEnable && data.sqlValue"
144
+ closable
145
+ type="info"
146
+ :title="data.sqlValue"
147
+ @close="deleteSQL"
148
+ >
149
+ <el-text
150
+ type="info"
151
+ truncated
152
+ style="max-width: 500px"
153
+ >
154
+ {{ data.sqlValue }}
155
+ </el-text>
156
+ </el-tag>
157
+ <!-- 文案[关闭sqlEnable] -->
158
+ <template v-if="!data.sqlEnable && data.list.length">
159
+ <el-tag
160
+ v-for="(tag, index) in data.list"
161
+ closable
162
+ type="info"
163
+ @close="deleteTag(index)"
164
+ >
76
165
  {{ handleTagName(tag) }}
77
166
  </el-tag>
78
167
  </template>
79
- <!-- 添加按钮区域 -->
80
- <el-button class="screen-btn" type="primary" plain size="small" :icon="Plus" @click="openDialog"
168
+ <!-- 打开弹窗 -->
169
+ <el-button
170
+ class="screen-btn"
171
+ type="primary"
172
+ plain
173
+ size="small"
174
+ :icon="Plus"
175
+ @click="openDialog"
81
176
  >添加因子</el-button
82
177
  >
83
- <!-- Tag弹窗 -->
84
- <el-dialog v-model="visible" title="因子筛选" width="500" align-center destroy-on-close>
85
- <el-form ref="dialogFormRef" :model="dialogForm">
86
- <div v-for="(item, index) in dialogForm.factorScreen" class="form-row">
178
+ <!-- 弹窗 -->
179
+ <el-dialog
180
+ v-model="visible"
181
+ title="因子筛选"
182
+ width="500"
183
+ align-center
184
+ destroy-on-close
185
+ >
186
+ <el-form
187
+ ref="dialogFormRef"
188
+ :model="dialogForm"
189
+ >
190
+ <!-- 因子筛选功能 -->
191
+ <div
192
+ v-for="(item, index) in dialogForm.list"
193
+ class="form-row"
194
+ >
87
195
  <!-- 周期 -->
88
196
  <el-form-item
89
197
  v-if="config.cycleShow"
90
- :prop="'factorScreen.' + index + '.cycle'"
198
+ :prop="'list.' + index + '.cycle'"
91
199
  :rules="{ required: true, message: '周期不能为空', trigger: 'blur' }"
92
- style="width: 100px; margin-right: 10px;"
200
+ style="width: 100px; margin-right: 10px"
93
201
  >
94
- <el-select v-model="item.cycle" placeholder="选择周期" size="small">
95
- <el-option v-for="{ label, value } in config.cycleOptions" :label="label" :value="value" :key="value" />
202
+ <el-select
203
+ v-model="item.cycle"
204
+ placeholder="选择周期"
205
+ size="small"
206
+ >
207
+ <el-option
208
+ v-for="{ label, value } in config.cycleOptions"
209
+ :label="label"
210
+ :value="value"
211
+ :key="value"
212
+ />
96
213
  </el-select>
97
214
  </el-form-item>
98
215
  <!-- 因子 -->
99
216
  <el-form-item
100
- :prop="'factorScreen.' + index + '.factor'"
217
+ :prop="'list.' + index + '.factor'"
101
218
  :rules="{ required: true, message: '因子不能为空', trigger: 'blur' }"
102
- style="width: 100px; margin-right: 10px;"
219
+ style="width: 100px; margin-right: 10px"
103
220
  >
104
- <el-select v-model="item.factor" placeholder="选择因子" filterable size="small" no-match-text="无匹配数据">
105
- <el-option v-for="{ label, value } in config.factorOptions" :label="label" :value="value" :key="value" />
221
+ <el-select
222
+ v-model="item.factor"
223
+ placeholder="选择因子"
224
+ filterable
225
+ size="small"
226
+ no-match-text="无匹配数据"
227
+ >
228
+ <el-option
229
+ v-for="{ label, value } in config.factorOptions"
230
+ :label="label"
231
+ :value="value"
232
+ :key="value"
233
+ />
106
234
  </el-select>
107
235
  </el-form-item>
108
236
  <!-- 分数 -->
109
237
  <el-form-item
110
- :prop="'factorScreen.' + index + '.score'"
238
+ :prop="'list.' + index + '.score'"
111
239
  :rules="{ validator: scoreValidator, trigger: 'blur' }"
112
- style="width: 200px; margin-right: 10px;"
240
+ style="width: 200px; margin-right: 10px"
113
241
  >
114
- <div style="display: flex; align-items: center; width: 100%; height: 24px;">
115
- <el-input-number v-model="item.score[0]" size="small" controls-position="right" />
242
+ <div style="display: flex; align-items: center; width: 100%; height: 24px">
243
+ <el-input-number
244
+ v-model="item.score[0]"
245
+ size="small"
246
+ controls-position="right"
247
+ />
116
248
  <span>~</span>
117
- <el-input-number v-model="item.score[1]" size="small" controls-position="right" />
249
+ <el-input-number
250
+ v-model="item.score[1]"
251
+ size="small"
252
+ controls-position="right"
253
+ />
118
254
  </div>
119
255
  </el-form-item>
120
256
  <!-- 删除 -->
121
257
  <el-icon @click="deleteFactor(index)"><CircleCloseFilled /></el-icon>
122
258
  </div>
123
- <el-button type="primary" plain size="small" :icon="Plus" @click="addFactor">添加因子</el-button>
259
+ <el-button
260
+ type="primary"
261
+ plain
262
+ size="small"
263
+ :icon="Plus"
264
+ @click="addFactor"
265
+ style="margin-bottom: 10px"
266
+ >添加因子</el-button
267
+ >
268
+ <!-- SQL功能 -->
269
+ <template v-if="config.sqlShow">
270
+ <el-form-item label="SQL功能: ">
271
+ <el-radio-group v-model="dialogForm.sqlEnable">
272
+ <el-radio :label="0">关闭</el-radio>
273
+ <el-radio :label="1">启用</el-radio>
274
+ </el-radio-group>
275
+ <el-button
276
+ v-if="dialogForm.sqlEnable"
277
+ type="primary"
278
+ size="small"
279
+ @click="createSQL"
280
+ style="margin-left: auto"
281
+ >生成SQL</el-button
282
+ >
283
+ </el-form-item>
284
+ <el-input
285
+ v-if="dialogForm.sqlEnable"
286
+ v-model="dialogForm.sqlValue"
287
+ :autosize="{ minRows: 4 }"
288
+ type="textarea"
289
+ />
290
+ </template>
124
291
  </el-form>
125
292
  <template #footer>
126
293
  <div class="dialog-footer">
127
- <el-button type="primary" @click="submit">确定</el-button>
294
+ <el-button
295
+ type="primary"
296
+ @click="submit"
297
+ >确定</el-button
298
+ >
128
299
  </div>
129
300
  </template>
130
301
  </el-dialog>
@@ -148,5 +319,8 @@ const handleTagName = (tag) => {
148
319
  cursor: pointer;
149
320
  }
150
321
  }
322
+ :deep(.el-dialog__body) {
323
+ padding-top: 20px;
324
+ }
151
325
  }
152
326
  </style>
@@ -1,3 +1,4 @@
1
+ // 默认配置项
1
2
  export default {
2
3
  // 品种市场
3
4
  varietyMarket: {
@@ -40,10 +41,11 @@ export default {
40
41
  // 因子筛选
41
42
  factorScreen: {
42
43
  show: true,
43
- cycleDefault: null,
44
- cycleOptions: [],
45
- cycleShow: true,
46
- factorOptions: [],
44
+ cycleShow: true, // 周期功能是否展示
45
+ cycleDefault: null, // 周期默认值
46
+ cycleOptions: [], // 周期下拉框选项
47
+ factorOptions: [], // 因子下拉框选项
48
+ sqlShow: false, // SQL功能是否展示
47
49
  },
48
50
  // 常用指标
49
51
  commonIndicator: {