st-comp 0.0.48 → 0.0.49

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.48",
4
+ "version": "0.0.49",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -23,6 +23,7 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@vitejs/plugin-vue": "^4.2.3",
26
+ "@vitejs/plugin-vue-jsx": "^3.1.0",
26
27
  "sass": "^1.69.3",
27
28
  "ssh2": "^1.14.0",
28
29
  "ssh2-sftp-client": "^9.1.0",
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <div class="st-VarietySearch-checkBox">
3
+ <div class="st-VarietySearch-checkBox-label">
4
+ {{ config.label }}:
5
+ <el-button
6
+ text
7
+ size="small"
8
+ type="primary"
9
+ @click="checkList = []"
10
+ >
11
+ 不限
12
+ </el-button>
13
+ </div>
14
+ <div class="st-VarietySearch-checkBox-content">
15
+ <el-checkbox-group
16
+ size="small"
17
+ v-model="checkList"
18
+ >
19
+ <el-checkbox
20
+ v-for="item in config.options"
21
+ :key="item.value"
22
+ :label="item.value"
23
+ >
24
+ {{ item.label }}
25
+ </el-checkbox>
26
+ </el-checkbox-group>
27
+ </div>
28
+ </div>
29
+ </template>
30
+
31
+ <script setup>
32
+ import { ref, watch } from 'vue'
33
+
34
+ const emit = defineEmits(['change']);
35
+ const props = defineProps({
36
+ config: {
37
+ type: Object,
38
+ require: true,
39
+ default: () => ({}),
40
+ },
41
+ formData: {
42
+ type: Object,
43
+ require: true,
44
+ },
45
+ })
46
+
47
+ const checkList = ref([])
48
+
49
+ watch(() => props.formData, () => {
50
+ checkList.value = props.formData[props.config.key] || []
51
+ }, { deep: true })
52
+
53
+ watch(checkList, () => {
54
+ emit('change', props.config.key, checkList.value)
55
+ })
56
+ </script>
57
+
58
+ <style lang="scss" scoped>
59
+ .st-VarietySearch-checkBox {
60
+ &-label {
61
+ display: inline-block;
62
+ vertical-align: top;
63
+ width: 120px;
64
+ height: 24px;
65
+ line-height: 22px;
66
+ font-size: 12px;
67
+ &-clear {
68
+ color: #409eff;
69
+ }
70
+ }
71
+ &-content {
72
+ vertical-align: top;
73
+ width: calc(100% - 120px);
74
+ display: inline-block;
75
+ }
76
+ }
77
+ </style>
@@ -0,0 +1,256 @@
1
+ <template>
2
+ <div class="st-VarietySearch-factorFilter">
3
+ <div class="st-VarietySearch-factorFilter-label">
4
+ {{ config.label }}:
5
+ <el-button
6
+ text
7
+ size="small"
8
+ type="primary"
9
+ @click="clear"
10
+ >
11
+ 不限
12
+ </el-button>
13
+ </div>
14
+ <div class="st-VarietySearch-factorFilter-content">
15
+ <el-tag
16
+ v-for="item in tagList"
17
+ style="margin-right: 5px"
18
+ :key="item.key"
19
+ closable
20
+ type="info"
21
+ :disable-transitions="false"
22
+ @close="deleteFactor(item, true)"
23
+ >
24
+ {{ item.freqName || "" }}
25
+ {{ item.factorName || "" }}
26
+ {{ item.startScore === null ? " / " : item.startScore + "分" }}
27
+ <span>~</span>
28
+ {{ item.endScore === null ? " / " : item.endScore + "分" }}
29
+ </el-tag>
30
+ <el-button type="primary" plain size="small" @click="open">
31
+ + 添加因子
32
+ </el-button>
33
+ </div>
34
+ <el-dialog
35
+ v-model="visible"
36
+ class="st-VarietySearch-factorFilter-dialog"
37
+ title="因子筛选"
38
+ align-center
39
+ :draggable="true"
40
+ width="510"
41
+ >
42
+ <el-row
43
+ v-for="item in factorList"
44
+ style="margin-bottom: 10px;"
45
+ :key="item.key"
46
+ >
47
+ <el-col :span="6">
48
+ <el-select
49
+ v-model="item.freqId"
50
+ :style="{ width: '100px' }"
51
+ :class="!item.freqId && check ? 'st-VarietySearch-factorFilter-border-red' : ''"
52
+ size="small"
53
+ placeholder="选择周期"
54
+ >
55
+ <el-option
56
+ v-for="optionItem in config.freqList"
57
+ :key="optionItem.value"
58
+ :label="optionItem.label"
59
+ :value="optionItem.value"
60
+ />
61
+ </el-select>
62
+ </el-col>
63
+ <el-col :span="7">
64
+ <el-select
65
+ v-model="item.factorId"
66
+ :class="!item.factorId && check ? 'st-VarietySearch-factorFilter-border-red' : ''"
67
+ :style="{ width: '120px' }"
68
+ size="small"
69
+ placeholder="选择因子"
70
+ >
71
+ <el-option
72
+ v-for="optionItem in config.factorList"
73
+ :key="optionItem.value"
74
+ :label="optionItem.label"
75
+ :value="optionItem.value"
76
+ />
77
+ </el-select>
78
+ </el-col>
79
+ <el-col :span="10">
80
+ <el-input-number
81
+ v-model="item.startScore"
82
+ :class="!((item.startScore || item.startScore === 0) || (item.endScore || item.endScore === 0)) && check ? 'st-VarietySearch-factorFilter-border-red' : ''"
83
+ style="width: 85px"
84
+ :step="0.5"
85
+ :min="-999"
86
+ :max="999"
87
+ placeholder="分数"
88
+ controls-position="right"
89
+ size="small"
90
+ />
91
+ <span> ~ </span>
92
+ <el-input-number
93
+ v-model="item.endScore"
94
+ :class="!((item.startScore || item.startScore === 0) || (item.endScore || item.endScore === 0)) && check ? 'st-VarietySearch-factorFilter-border-red' : ''"
95
+ style="width: 85px"
96
+ :step="0.5"
97
+ :min="-999"
98
+ :max="999"
99
+ controls-position="right"
100
+ placeholder="分数"
101
+ size="small"
102
+ />
103
+ </el-col>
104
+ <el-col :span="1">
105
+ <el-text
106
+ type="info"
107
+ style="cursor: pointer; vertical-align: -3px;"
108
+ @click="deleteFactor(item)"
109
+ >
110
+ <el-icon><CircleCloseFilled /></el-icon>
111
+ </el-text>
112
+ </el-col>
113
+ </el-row>
114
+ <el-button type="primary" plain size="small" @click="addFactor">
115
+ + 添加因子
116
+ </el-button>
117
+ <template #footer>
118
+ <div class="dialog-footer">
119
+ <el-button size="small" @click="visible = false">取消</el-button>
120
+ <el-button size="small" type="primary" @click="submit">
121
+ 确认
122
+ </el-button>
123
+ </div>
124
+ </template>
125
+ </el-dialog>
126
+ </div>
127
+ </template>
128
+
129
+ <script setup>
130
+ import { ref, computed } from 'vue'
131
+ import { CircleCloseFilled } from "@element-plus/icons-vue";
132
+ import { ElMessage } from 'element-plus';
133
+
134
+ const emit = defineEmits(['change']);
135
+ const props = defineProps({
136
+ config: {
137
+ type: Object,
138
+ require: true,
139
+ default: () => ({ key: new Date() }),
140
+ },
141
+ formData: {
142
+ type: Object,
143
+ require: true,
144
+ },
145
+ })
146
+
147
+ const defauleItem = {
148
+ factorId: null, // 因子id
149
+ freqId: null, // 周期id
150
+ startScore: null, // 开始分值
151
+ endScore: null, // 结束分值
152
+ }
153
+
154
+ const visible = ref(false)
155
+ const factorList = ref([])
156
+ const check = ref(false)
157
+
158
+ // 标签列表
159
+ const tagList = computed(() => {
160
+ return props.formData[props.config.key].filter(item => item.factorId && item.freqId).map(item => {
161
+ return {
162
+ ...item,
163
+ freqName: props.config.freqList.find(i => i.value === item.freqId)?.label,
164
+ factorName: props.config.factorList.find(i => i.id === item.factorId)?.factorName,
165
+ }
166
+ })
167
+ })
168
+
169
+ // 打开弹窗
170
+ const open = () => {
171
+ if (factorList.value.length === 0) {
172
+ addFactor()
173
+ }
174
+ visible.value = true
175
+ }
176
+
177
+ // 添加因子
178
+ const addFactor = () => {
179
+ factorList.value.push({ ...defauleItem, key: new Date().getTime() })
180
+ }
181
+
182
+ // 删除因子
183
+ const deleteFactor = (item, isUpdate = false) => {
184
+ factorList.value = factorList.value.filter(i => i.key !== item.key)
185
+ if (isUpdate) {
186
+ emit('change', props.config.key, [...factorList.value])
187
+ }
188
+ }
189
+
190
+ // 不限
191
+ const clear = () => {
192
+ factorList.value = []
193
+ emit('change', props.config.key, [])
194
+ }
195
+
196
+ // 提交
197
+ const submit = () => {
198
+ for(let i = 0; i < factorList.value.length; i++) {
199
+ const item = factorList.value[i]
200
+ if (!(
201
+ item.factorId &&
202
+ item.freqId &&
203
+ ((item.startScore || item.startScore === 0) || (item.endScore || item.endScore === 0))
204
+ )) {
205
+ check.value = true
206
+ ElMessage.error('请检查列表参数后重试!')
207
+ return
208
+ }
209
+ }
210
+ emit('change', props.config.key, [...factorList.value])
211
+ check.value = false
212
+ visible.value = false
213
+ }
214
+ </script>
215
+
216
+ <style lang="scss">
217
+ .st-VarietySearch-factorFilter-border-red .el-input__wrapper,
218
+ .st-VarietySearch-factorFilter-border-red .el-select__wrapper {
219
+ box-shadow: 0 0 0 1px var(--el-color-danger) inset;
220
+ }
221
+ .st-VarietySearch-factorFilter-dialog {
222
+ .el-dialog__header {
223
+ padding-top: 10px;
224
+ .el-dialog__headerbtn {
225
+ width: 40px;
226
+ height: 40px;
227
+ }
228
+ }
229
+ .el-dialog__body {
230
+ border-top: 1px solid var(--el-border-color);
231
+ border-bottom: 1px solid var(--el-border-color);
232
+ padding: 15px 20px;
233
+ }
234
+ }
235
+ </style>
236
+
237
+ <style lang="scss" scoped>
238
+ .st-VarietySearch-factorFilter {
239
+ &-label {
240
+ display: inline-block;
241
+ vertical-align: top;
242
+ width: 120px;
243
+ height: 24px;
244
+ line-height: 22px;
245
+ font-size: 12px;
246
+ &-clear {
247
+ color: #409eff;
248
+ }
249
+ }
250
+ &-content {
251
+ vertical-align: top;
252
+ width: calc(100% - 120px);
253
+ display: inline-block;
254
+ }
255
+ }
256
+ </style>
@@ -0,0 +1,310 @@
1
+ <template>
2
+ <el-dialog
3
+ v-model="visible"
4
+ class="st-VarietySearch-modelSearch-dialog"
5
+ :title="data.label"
6
+ align-center
7
+ :draggable="true"
8
+ width="510"
9
+ >
10
+ <template v-if="data.type === 'default'">
11
+ <div class="st-VarietySearch-modelSearch-dialog-content">
12
+ <el-button
13
+ v-for="(item, index) in data.options"
14
+ class="st-VarietySearch-modelSearch-dialog-content-btn"
15
+ :key="index"
16
+ size="small"
17
+ :style="item.style"
18
+ :type="index === activeIndex ? 'primary' : ''"
19
+ @click="btnClick(item, index)"
20
+ >{{ item.btnText }}</el-button>
21
+ </div>
22
+ <div>
23
+ <span>自定义:</span>
24
+ <el-input
25
+ v-model="start"
26
+ :class="!(start || end) && check ? 'st-VarietySearch-factorFilter-border-red' : ''"
27
+ size="small"
28
+ style="width: 150px"
29
+ >
30
+ <template #append v-if="typeof unitOptions === 'string'">
31
+ {{ unitOptions }}
32
+ </template>
33
+ <template #append v-else-if="typeof unitOptions === 'object'">
34
+ <el-select
35
+ v-model="startUnit"
36
+ :style="{ width: '60px' }"
37
+ placeholder=""
38
+ size="small"
39
+ >
40
+ <el-option
41
+ v-for="item in unitOptions"
42
+ :key="item.value"
43
+ :label="item.label"
44
+ :value="item.value"
45
+ />
46
+ </el-select>
47
+ </template>
48
+ </el-input>
49
+ <span style="margin: 0 10px;">~</span>
50
+ <el-input
51
+ v-model="end"
52
+ :class="!(start || end) && check ? 'st-VarietySearch-factorFilter-border-red' : ''"
53
+ controls-position="right"
54
+ style="width: 150px"
55
+ size="small"
56
+ >
57
+ <template #append v-if="typeof unitOptions === 'string'">
58
+ {{ unitOptions }}
59
+ </template>
60
+ <template #append v-else-if="typeof unitOptions === 'object'">
61
+ <el-select
62
+ v-model="endUnit"
63
+ :style="{ width: '60px' }"
64
+ placeholder=""
65
+ size="small"
66
+ >
67
+ <el-option
68
+ v-for="item in unitOptions"
69
+ :key="item.value"
70
+ :label="item.label"
71
+ :value="item.value"
72
+ />
73
+ </el-select>
74
+ </template>
75
+ </el-input>
76
+ </div>
77
+ </template>
78
+ <template v-else-if="data.type === 'radio'">
79
+ <el-radio-group v-model="radio" class="ml-4">
80
+ <el-radio
81
+ v-for="item in data.options"
82
+ :label="item.value"
83
+ size="small"
84
+ >{{ item.label }}</el-radio>
85
+ </el-radio-group>
86
+ </template>
87
+ <template v-else-if="data.type === 'tFeaturelncomes'">
88
+ <div class="st-VarietySearch-modelSearch-dialog-content">
89
+ <el-button
90
+ v-for="(item, index) in data.options"
91
+ class="st-VarietySearch-modelSearch-dialog-content-btn"
92
+ :key="index"
93
+ size="small"
94
+ :style="item.style"
95
+ :type="index === activeIndex ? 'primary' : ''"
96
+ @click="btnClick(item, index)"
97
+ >{{ item.btnText }}</el-button>
98
+ </div>
99
+ <div style="margin-bottom: 10px">
100
+ <span>自定义:</span>
101
+ <el-input-number
102
+ v-model="withFewYears"
103
+ :class="!withFewYears && check ? 'st-VarietySearch-factorFilter-border-red' : ''"
104
+ size="small"
105
+ :min="-9999999"
106
+ :max="9999999"
107
+ controls-position="right"
108
+ style="width: 70px"
109
+ />
110
+ <span> 年内 </span>
111
+ <el-input-number
112
+ v-model="yearsCount"
113
+ size="small"
114
+ :min="0"
115
+ :max="9999999"
116
+ controls-position="right"
117
+ style="width: 70px"
118
+ />
119
+ <span>
120
+ 年以上盈利{{ rule === 1 ? "超" : "跌" }}过
121
+ </span>
122
+ <el-input-number
123
+ v-model="netProfit"
124
+ :class="!netProfit && check ? 'st-VarietySearch-factorFilter-border-red' : ''"
125
+ size="small"
126
+ :min="0"
127
+ :max="9999999"
128
+ controls-position="right"
129
+ style="width: 80px"
130
+ />
131
+ <span> 亿</span>
132
+ </div>
133
+ </template>
134
+ <template #footer>
135
+ <div class="dialog-footer">
136
+ <el-button size="small" @click="visible = false">取消</el-button>
137
+ <el-button size="small" type="primary" @click="submit">
138
+ 确认
139
+ </el-button>
140
+ </div>
141
+ </template>
142
+ </el-dialog>
143
+ </template>
144
+
145
+ <script setup>
146
+ import { ref, computed, watch } from 'vue'
147
+
148
+ const emit = defineEmits(['update:modelValue', 'submit']);
149
+ const props = defineProps({
150
+ modelValue: {
151
+ type: Boolean,
152
+ require: true,
153
+ },
154
+ data: {
155
+ type: Object,
156
+ default: () => ({}),
157
+ }
158
+ })
159
+
160
+ const activeIndex = ref(-1) // 快捷选中的index
161
+ const start = ref('') // default类型下的起始值
162
+ const end = ref('') // default类型下的结束值
163
+ const startUnit = ref('') // default类型下的起始值单位
164
+ const endUnit = ref('') // default类型下的结束值单位
165
+ const unitOptions = ref() // default类型下的自定义单位
166
+ const radio = ref() // radio类型下的单选值
167
+ const withFewYears = ref() // tFeaturelncomes类型下的几年内数据
168
+ const yearsCount = ref() // tFeaturelncomes类型下的几年上
169
+ const netProfit = ref() // tFeaturelncomes类型下的差值
170
+ const rule = ref() // tFeaturelncomes类型下的涨跌规则
171
+ const check = ref(false) // 表单校验
172
+
173
+ const visible = computed({
174
+ get() {
175
+ return props.modelValue;
176
+ },
177
+ set(val) {
178
+ emit('update:modelValue', val);
179
+ },
180
+ });
181
+
182
+ watch(visible, () => {
183
+ if (visible) {
184
+ activeIndex.value = -1
185
+ start.value = ''
186
+ end.value = ''
187
+ startUnit.value = ''
188
+ endUnit.value = ''
189
+ unitOptions.value = null
190
+ radio.value = null
191
+ withFewYears.value = null
192
+ yearsCount.value = null
193
+ netProfit.value = null
194
+ rule.value = null
195
+
196
+ if (props.data.type === 'default') {
197
+ start.value = props.data.start
198
+ end.value = props.data.end
199
+ startUnit.value = props.data.startUnit
200
+ endUnit.value = props.data.endUnit
201
+ unitOptions.value = props.data.unitOptions
202
+ }else if (props.data.type === 'radio') {
203
+ radio.value = props.data.radio
204
+ } else if (props.data.type === 'tFeaturelncomes') {
205
+ withFewYears.value = props.data.withFewYears
206
+ yearsCount.value = props.data.yearsCount
207
+ netProfit.value = props.data.netProfit
208
+ rule.value = props.data.rule
209
+ }
210
+ }
211
+ })
212
+
213
+ watch(
214
+ () => [start.value, end.value, startUnit.value, endUnit.value],
215
+ () => { activeIndex.value = -1 },
216
+ { deep: true }
217
+ )
218
+
219
+ const btnClick = (item, index) => {
220
+ activeIndex.value = index
221
+ if (props.data.type === 'default') {
222
+ start.value = item.start
223
+ end.value = item.end
224
+ startUnit.value = item.startUnit
225
+ endUnit.value = item.endUnit
226
+ } else if (props.data.type === 'tFeaturelncomes') {
227
+ withFewYears.value = item.withFewYears
228
+ yearsCount.value = item.yearsCount
229
+ netProfit.value = item.netProfit
230
+ rule.value = item.rule
231
+ }
232
+ }
233
+
234
+ const submit = () => {
235
+ const { type } = props.data
236
+ if (type === 'default') {
237
+ if (!(start.value || end.value)) {
238
+ check.value = true
239
+ ElMessage.error('请检查参数后重试!')
240
+ return
241
+ }
242
+ check.value = false
243
+ emit('submit', {
244
+ ...props.data,
245
+ isEmit: true,
246
+ start: start.value ? Number(start.value) : null,
247
+ end: end.value ? Number(end.value): null,
248
+ startUnit: startUnit.value,
249
+ endUnit: endUnit.value,
250
+ })
251
+ } else if (type === 'radio') {
252
+ if (radio.value === null) {
253
+ ElMessage.error('请检查参数后重试!')
254
+ return
255
+ }
256
+ emit('submit', {
257
+ ...props.data,
258
+ isEmit: true,
259
+ radio: radio.value,
260
+ radioLabel: props.data.options.find(item => item.value === radio.value).label
261
+ })
262
+ } else if (type === 'tFeaturelncomes') {
263
+ if (!(withFewYears.value || netProfit.value)) {
264
+ check.value = true
265
+ ElMessage.error('请检查参数后重试!')
266
+ return
267
+ }
268
+ check.value = false
269
+ emit('submit', {
270
+ ...props.data,
271
+ isEmit: true,
272
+ withFewYears: withFewYears.value,
273
+ yearsCount: yearsCount.value,
274
+ netProfit: netProfit.value,
275
+ rule: rule.value,
276
+ })
277
+ }
278
+ visible.value = false
279
+ }
280
+ </script>
281
+
282
+ <style lang="scss">
283
+ .st-VarietySearch-modelSearch-border-red .el-input__wrapper,
284
+ .st-VarietySearch-modelSearch-border-red .el-select__wrapper {
285
+ box-shadow: 0 0 0 1px var(--el-color-danger) inset;
286
+ }
287
+ .st-VarietySearch-modelSearch-dialog {
288
+ .el-dialog__header {
289
+ padding-top: 10px;
290
+ .el-dialog__headerbtn {
291
+ width: 40px;
292
+ height: 40px;
293
+ }
294
+ }
295
+ .el-dialog__body {
296
+ border-top: 1px solid var(--el-border-color);
297
+ border-bottom: 1px solid var(--el-border-color);
298
+ padding: 15px 20px;
299
+ }
300
+ }
301
+ </style>
302
+
303
+ <style lang="scss" scoped>
304
+ .st-VarietySearch-modelSearch-dialog-content {
305
+ &-btn {
306
+ margin-bottom: 10px;
307
+ margin-left: 0;
308
+ }
309
+ }
310
+ </style>