diff --git a/src/views/admin/line-order-template-logs/index.vue b/src/views/admin/line-order-template-logs/index.vue index a912deb..0c7dbc0 100644 --- a/src/views/admin/line-order-template-logs/index.vue +++ b/src/views/admin/line-order-template-logs/index.vue @@ -150,7 +150,7 @@ /> - + @@ -428,109 +428,151 @@ @click="onCalculate" >计算 -
- - -
{{ item.addType === 1 ? '加仓类型' : '减仓类型' }}
- - 限价 - 市价 - -
- -
{{ item.addType === 1 ? '加仓方式' : '减仓方式' }}
- - 百分比 - 实际金额 - -
+ +
+ + +
{{ item.addType === 1 ? '加仓类型' : '减仓类型' }}
+ + 限价 + 市价 + +
+ +
{{ item.addType === 1 ? '加仓方式' : '减仓方式' }}
+ + 百分比 + 实际金额 + +
-
- - {{ item.addType === 1 ? '加仓下跌百分比' : '减仓下跌百分比' }} - - {{ item.addType === 1 ? '加仓数值' : '减仓百分比' }} - - - - 止盈/止损百分比 -
- - - - — - -
-
- - - - -
删除 - - -
+ + + + +
删除 + + +
+ + + + +
{{ item.addType === 1 ? '加仓类型' : '减仓类型' }}
+ + 限价 + 市价 + +
+ +
{{ item.addType === 1 ? '加仓方式' : '减仓方式' }}
+ + 百分比 + 实际金额 + +
- - -
删除 - - -
+ + +
删除 + + +
+ @@ -1118,7 +1155,7 @@ v-for="(item, index) in sideList" :key="'position_side' + index" :label="item.value" - :disabled="item.value=='SELL'&&positionForm.close_type==1" + :disabled="item.value === 'SELL' && positionForm.close_type === 1" >{{ item.label }} @@ -1331,18 +1368,51 @@ export default { }, // 表单校验 rules: { - reduce_price: [{ required: true, message: '主单亏损减仓百分比不能为空', trigger: 'blur' }], - reduce_num: [{ required: true, message: '主单减仓数量百分比不能为空', trigger: 'blur' }], - reduce_take_profit: [{ required: true, message: '主单减仓后止盈价百分比不能为空', trigger: 'blur' }], - // reduce_stop_price: [{ required: true, message: '主单减仓后止损价不能为空', trigger: 'blur' }], - buy_price: [{ required: true, message: '购买金额不能为空', trigger: 'blur' }], + profit: [{ required: true, message: '请输入止盈百分比', trigger: 'blur' }, { validator: this.validateProfit, trigger: 'blur' }], + reduce_price: [ + { required: true, message: '主单亏损减仓百分比不能为空', trigger: 'blur' }, + { validator: this.validateReducePrice, trigger: 'blur' }], + reduce_num: [ + { required: true, message: '主单减仓数量百分比不能为空', trigger: 'blur' }, + { validator: this.validateReduceNum, trigger: 'blur' }], + reduce_take_profit: [ + { required: true, message: '主单减仓后止盈价百分比不能为空', trigger: 'blur' }, + { validator: this.validateReduceTakeProfit, trigger: 'blur' }], + buy_price: [ + { required: true, message: '购买金额不能为空', trigger: 'blur' }, + { validator: this.validateBuyPrice, trigger: 'blur' } + ], exchange_type: [{ required: true, message: '交易所不能为空', trigger: 'blur' }], api_id: [{ required: true, message: 'api用户不能为空', trigger: 'blur' }], symbol: [{ required: true, message: '交易对不能为空', trigger: 'blur' }], symbol_group_id: [{ required: true, message: '交易对组不能为空', trigger: 'blur' }], quote_symbol: [{ required: true, message: '计价货币不能为空', trigger: 'blur' }], order_sn: [{ required: true, message: '订单号不能为空', trigger: 'blur' }], - profit_num_ratio: [{ required: true, message: '止盈数量百分比不能为空', trigger: 'blur' }] + profit_num_ratio: [ + { required: true, message: '止盈数量百分比不能为空', trigger: 'blur' }, + { validator: this.validateProfitNumRatio, trigger: 'blur' } + ], + profit_tp_tp_price_ratio: [{ validator: this.validateTptpPriceRatio, trigger: 'blur' }], + + priceRatio: [{ validator: this.validateExtPriceRatio, trigger: 'blur' }], + addPositionVal: [ + { required: true, message: '追加仓位不能为空', trigger: 'blur' }, + { validator: this.validateAddPosition, trigger: 'blur' }], + takeProfitRatio: [ + { required: true, message: '请输入止盈百分比', trigger: 'blur' }, + { type: 'number', message: '止盈百分比必须为数字', trigger: 'blur' }, + { min: 0, message: '止盈百分比不能小于 0', trigger: 'blur' } + ], + stopLossRatio: [ + { required: true, message: '请输入止损百分比', trigger: 'blur' }, + { type: 'number', message: '止损百分比必须为数字', trigger: 'blur' }, + { min: 0, message: '止损百分比不能小于 0', trigger: 'blur' } + ], + takeProfitNumRatio: [{ required: true, message: '止盈数量不能为空', trigger: 'blur' }, + { validator: this.validateExtTakeProfitNumRatio, trigger: 'blur' } + ], + tpTpPriceRatio: [{ required: true, message: '第二止盈价格百分比不能为空', trigger: 'blur' }], + slSlPriceRatio: [{ required: true, message: '第二止损价格百分比不能为空', trigger: 'blur' }] }, currentExpandId: undefined, cacheRefresh: {}, @@ -1382,7 +1452,6 @@ export default { positionRules: { exchangeType: [{ required: true, message: '交易所不能为空', trigger: 'blur' }], api_id: [{ required: true, message: 'api用户不能为空', trigger: 'blur' }] - // symbol: [{ required: true, message: '交易对不能为空', trigger: 'blur' }] }, searchLoding: false, // 取消委托 @@ -1523,7 +1592,7 @@ export default { takeProfitRatio: 0, stopLossRatio: 0, // 止盈数量百分比 止盈后止盈价格百分比 止盈后止损价格百分比 - takeProfitNumRatio: 0, + takeProfitNumRatio: 100, tpTpPriceRatio: 0, tpSlPriceRatio: 0 @@ -1914,6 +1983,146 @@ export default { } this.resetForm('form') }, + validateExtTakeProfitNumRatio(rule, value, callback) { + if (value === 0 || value === undefined || value === null || value === '') { + callback(new Error('止盈数量百分比必须大于0')) + } else { + callback() + } + }, + validateReducePrice(rule, value, callback) { + if (value === 0 || value === undefined || value === null || value === '') { + callback(new Error('亏损百分比必须大于0')) + } else { + callback() + } + }, + validateBuyPrice(rule, value, callback) { + if (value === 0) { + callback(new Error('购买金额必须大于0')) + } else { + callback() + } + }, + validateReduceTakeProfit(rule, value, callback) { + if (this.form.reduce_num > 0 && this.form.reduce_num < 100 && this.form.reduce_take_profit === 0) { + callback(new Error('主单减仓后止盈必须大于0')) + } else if (this.form.reduce_num === 100 && this.form.reduce_take_profit > 0) { + callback(new Error('主单减仓全部后无需止盈')) + } else { + callback() + } + }, + /** 主单减仓数量 */ + validateReduceNum(rule, value, callback) { + if (value <= 0) { + callback(new Error('主单减仓数量必须大于0')) + } else { + callback() + } + }, + /** 主单止盈数量 */ + validateProfitNumRatio(rule, value, callback) { + if (value <= 0) { + callback(new Error('止盈数量比例必须大于0')) + } else { + callback() + } + }, + /** 验证第二止盈止损 */ + validateTptpPriceRatio(rule, value, callback) { + if (!this.form) { + callback(new Error('表单未初始化')) + return + } + + if (this.form.profit_num_ratio > 0 && this.form.profit_num_ratio < 100 && (!value || value <= 0)) { + callback(new Error('第二止盈百分比不能为空且必须大于 0')) + } else if (this.form.profit_num_ratio === 100 && value > 0) { + callback(new Error('第一止盈已经全部止盈了,不需要第二止盈百分比')) + } else { + callback() + } + }, + validateProfit(rule, value, callback) { + console.log(this.form) + if (this.form.profit === '' || this.form.profit === undefined || this.form.profit === null) { + callback(new Error('止盈百分比不能为空')) + } else if (this.form.profit <= 0) { + callback(new Error('止盈百分比不能小于0')) + } else { + callback() + } + }, + validateExtPriceRatio(rule, value, callback) { + const index = rule.fullField.split('.')[1] // 获取索引 + const item = this.form.ext[index] + const message = item.addType === 1 ? '加仓下跌百分比' : '减仓下跌百分比' + + if (item.priceRatio === '') { + callback(new Error(message + '不能为空')) + } else if (isNaN(item.priceRatio)) { + callback(new Error('必须输入数字')) + } else if (item.priceRatio < 0) { + callback(new Error('百分比不能小于 0')) + } + + if (index === 0 && item.priceRatio <= this.form.reduce_price) { + callback(new Error('下跌百分比不能小于上一节点')) + } else if (index > 0 && item.priceRatio <= this.form.ext[index - 1].priceRatio) { + callback(new Error('下跌百分比不能小于上一节点')) + } else { + callback() + } + }, + validateAddPosition(rule, value, callback) { + const index = rule.fullField.split('.')[1] // 获取索引 + const item = this.form.ext[index] + const message = item.addType === 1 ? '加仓数值' : '减仓百分比' + + if (item.addPositionVal === '') { + callback(new Error(message + '不能为空')) + } else if (isNaN(item.addPositionVal)) { + callback(new Error('必须输入数字')) + } else if (item.addPositionVal <= 0) { + callback(new Error(message + '必须大于 0')) + } else { + callback() // 校验通过 + } + }, + // 自定义校验逻辑 + validateTakeProfitAndStopLoss(rule, value, callback) { + const index = rule.fullField.split('.')[1] // 获取索引 + const item = this.form.ext[index] + + if (item.takeProfitRatio === '' || item.stopLossRatio === '') { + callback(new Error('止盈和止损百分比都不能为空')) + } else if (isNaN(item.takeProfitRatio) || isNaN(item.stopLossRatio)) { + callback(new Error('必须输入数字')) + } else if (item.takeProfitRatio < 0 || item.stopLossRatio < 0) { + callback(new Error('百分比不能小于 0')) + } else if (item.takeProfitRatio === 0) { + callback(new Error('止盈百分比不能为0')) + } else { + callback() // 校验通过 + } + }, + // 自定义 第二止盈止损校验 + validateTp(rule, value, callback) { + const index = rule.fullField.split('.')[1] // 获取索引 + const item = this.form.ext[index] + if (item.tpTpPriceRatio === '' || item.tpSlPriceRatio === '') { + callback(new Error('第二止盈、止损百分比不能为空')) + } else if (isNaN(item.tpTpPriceRatio) || isNaN(item.tpSlPriceRatio)) { + callback(new Error('必须输入数字')) + } else if (item.tpTpPriceRatio < 0 || item.tpSlPriceRatio < 0) { + callback(new Error('百分比不能小于 0')) + } else if (item.takeProfitNumRatio < 100 && item.takeProfitNumRatio > 0 && item.tpTpPriceRatio <= 0) { + callback(new Error('第二止盈百分比必须大于0')) + } else { + callback() // 校验通过 + } + }, getImgList: function() { this.form[this.fileIndex] = this.$refs['fileChoose'].resultList[0].fullUrl }, @@ -1971,75 +2180,84 @@ export default { }) }, /** 提交按钮 */ - submitForm: function() { - this.$refs['form'].validate(valid => { - if (valid) { - this.formLoading = true - if (this.form.price) { - this.form.price = String(this.form.price) - } + submitForm: async function() { + const formValid = await Promise.all([ + this.$refs['form'].validate(), // 验证第一个表单 + this.$refs['extForm'].validate() // 验证第二个表单 + ]) - if (this.form.id !== undefined) { - updateLinePreOrder(this.form).then(response => { - if (response.code === 200) { - this.msgSuccess(response.msg) - this.open = false - this.getList() - } else { - this.msgError(response.msg) - } - }).finally(() => { - this.formLoading = false - }) - } else { - if (this.title === '批量添加') { - const params = JSON.parse(JSON.stringify({ - ...this.form, - symbol_group_id: String(this.form.symbol_group_id), - api_id: this.form.api_id.toString(), - profit_num_ratio: this.form.profit_num_ratio || 100, - profit_tp_tp_price_ratio: this.form.profit_tp_tp_price_ratio || 0, - profit_tp_sl_price_ratio: this.form.profit_tp_sl_price_ratio || 0 - })) - delete params.symbol - batchAddOrder(params).then(response => { - if (response.code === 200) { - this.msgSuccess(response.msg) - this.open = false - this.getList() - } else { - this.msgError(response.msg) - } - }).finally(() => { - this.formLoading = false - }) - return false + console.log(formValid) + if (formValid.every(valid => valid)) { + this.formLoading = true + if (this.form.price) { + this.form.price = String(this.form.price) + } + + if (this.form.id !== undefined) { + updateLinePreOrder(this.form).then(response => { + if (response.code === 200) { + this.msgSuccess(response.msg) + this.open = false + this.getList() + } else { + this.msgError(response.msg) } - addOrder({ + }).finally(() => { + this.formLoading = false + }) + } else { + if (this.title === '批量添加') { + const params = JSON.parse(JSON.stringify({ ...this.form, - reduce_price: this.form.reduce_price || 0, - reduce_num: this.form.reduce_num || 0, - reduce_take_profit: this.form.reduce_take_profit || 0, - reduce_stop_price: this.form.reduce_stop_price || 0, + symbol_group_id: String(this.form.symbol_group_id), + api_id: this.form.api_id.toString(), profit_num_ratio: this.form.profit_num_ratio || 100, profit_tp_tp_price_ratio: this.form.profit_tp_tp_price_ratio || 0, - profit_tp_sl_price_ratio: this.form.profit_tp_sl_price_ratio || 0, - api_id: this.form.api_id.toString() - }).then(response => { + profit_tp_sl_price_ratio: this.form.profit_tp_sl_price_ratio || 0 + })) + delete params.symbol + batchAddOrder(params).then(response => { if (response.code === 200) { this.msgSuccess(response.msg) this.open = false this.getList() } else { - this.formLoadng = false this.msgError(response.msg) } }).finally(() => { this.formLoading = false }) + return false } + addOrder({ + ...this.form, + reduce_price: this.form.reduce_price || 0, + reduce_num: this.form.reduce_num || 0, + reduce_take_profit: this.form.reduce_take_profit || 0, + reduce_stop_price: this.form.reduce_stop_price || 0, + profit_num_ratio: this.form.profit_num_ratio || 100, + profit_tp_tp_price_ratio: this.form.profit_tp_tp_price_ratio || 0, + profit_tp_sl_price_ratio: this.form.profit_tp_sl_price_ratio || 0, + api_id: this.form.api_id.toString() + }).then(response => { + if (response.code === 200) { + this.msgSuccess(response.msg) + this.open = false + this.getList() + } else { + this.formLoadng = false + this.msgError(response.msg) + } + }).finally(() => { + this.formLoading = false + }) } - }) + } + // this.$refs['form'].validate(valid => { + // if (valid) { + + // } + // }) }, onCancel() { this.cancelOpen = true @@ -2162,6 +2380,20 @@ export default { } } +::v-deep.ext-form-item { + .el-form-item__label { + padding: 0px !important; + } +} + +.el-form--label-top .el-form-item__label { + padding: 0px !important; +} + +.ext-form .el-form-item__content .el-input-group { + vertical-align: middle; +} + .page { .pagination-container { padding: 0 !important;