//客户选择组件 const vueClient = function () { return { props: ['value'], data() { return { current: { id: 0, Name: '' } }; }, mounted() { var self = this; var id = parseInt(this.value); if (id) { this.current = _.clone(ylotc.clients.find(x => x.id === id)); } var width = 152; for (var i = 0; i < ylotc.clients.length; i++) { let ele = document.createElement('span') ele.innerText = ylotc.clients[i].Name; ele.style.fontSize = '14px'; document.documentElement.append(ele); var charLength = ele.offsetWidth + 28;//滚动条 document.documentElement.removeChild(ele); if (charLength > width) { width = charLength } } FastVue.autocomplete(this.$el, { valueField: 'Name', searchField: ['Name', 'PinYin'], lookup: ylotc.clients, width: width, onSelect(data) { self.current = _.clone(data); if (self.value !== data.id) { self.value = data.id; self.$emit('input', self.value); } $(self.$el).blur(); } }); }, watch: { value(val, old) { if (val !== old) { var id = parseInt(val); if (id !== this.current.id) { this.current = _.clone(ylotc.clients.find(x => x.id === id) || { id: 0, Name: '' }); } $(this.$el).data('select', '').attr("placeholder", ''); } } }, destroyed() { FastVue.autocomplete.dispose(this.$el); }, template: '' }; }; //品种选择组件 const vueVariety = function () { return { props: ['variety'], mounted() { var self = this; FastVue.autocomplete(this.$el, { valueField: 'Name', searchField: ['Name', 'Code', 'PinYin'], lookup: ylotc.varieties, onSelect(data) { if (self.variety !== data) { self.$emit('change-variety', data); } } }); }, destroyed() { FastVue.autocomplete.dispose(this.$el); }, template: '' }; }; //期权类型选择组件 const vueTradeType = function () { return { props: ['value'], mounted() { var self = this; FastVue.autocomplete(this.$el, { valueField: 'value', searchField: ['value', 'pinyin'], lookup: tradeHelper.OptionTradeTypes, onSelect(data) { if (self.value !== data.value) { self.value = data.value; self.$emit('input', self.value); } } }); this.$el.value = this.value || ''; }, watch: { value(val, old) { if (val !== old) { $(this.$el).val(this.value).data('select', '').attr("placeholder", ''); } } }, destroyed() { FastVue.autocomplete.dispose(this.$el); }, template: '' }; }; //标的选择组件(EQD-7049:改为服务端搜索,不再依赖全量 ylotc.underlyings,避免十几万标的整段下载卡死) const vueUnderlying = function () { const _suggestionTpl = _.template($('#underlyingSuggestionTpl').html()); // 标的缓存(同品种各实例共享):_cache 为最近一次服务端结果,_fresh 记录其对应的 品种|关键词, // _seq 单调递增丢弃乱序/过期响应,_inflight 防同关键词重复请求(helper 收在函数内,避免全局绑定冲突) const _cache = {}; const _fresh = {}; const _seq = {}; const _inflight = {}; function _fetch(varietyId, query, cb) { var vid = varietyId || 0; var q = query || ''; var key = vid + '|' + q; if (_inflight[key]) return; var seq = (_seq[vid] = (_seq[vid] || 0) + 1); _inflight[key] = true; var postData = { FilterCode: q.toUpperCase(), VarietyId: vid, MaxShowLength: 20, BlackLimit: 1, UseForTrading: true, IncludeMatured: true, CheckLaunch: true }; main.post('/frontdata/AjaxGetUnderlyingSelect', postData).done(function (res) { delete _inflight[key]; if (_seq[vid] !== seq) return; // 已有更新的关键词发起请求,丢弃本响应 var arr = (res && (res.obj || res.data)) || []; var norm = arr.map(function (x) { return { Code: x.Code, Name: x.Name, InstrumentType: x.InstrumentType, VarietyId: x.VarietyId, Disallow: !!x.Disallow, IsCombined: !!x.IsSynthetic || !!x.IsBasket, BlackWhiteState: x.BlackWhiteState || 0, PinYin: x.PinYin || '' }; }); _cache[vid] = norm; _fresh[vid] = key; cb && cb(norm, q); }).fail(function () { delete _inflight[key]; }); } function _filter(list, query, varietyId) { if (!query) return (list || []).slice(0, 20); query = query.toUpperCase(); return (list || []).filter(function (x) { if (varietyId && x.VarietyId !== varietyId) return false; if (x.IsCombined) return false; // 与原逻辑一致:搜索时排除组合标的 return (x.Code && x.Code.toUpperCase().indexOf(query) !== -1) || (x.PinYin && x.PinYin.toUpperCase().indexOf(query) !== -1); }).slice(0, 20); } return { props: ['underlying'], data() { return { jqInput: null, autoctrl: null }; }, mounted() { var self = this; this.jqInput = $(this.$el).children(0); // EQD-7049:预拉默认20条(当前品种),获得焦点时由插件自身的 onValueChange 呈现 _fetch(self.underlying.VarietyId, ''); this.autoctrl = FastVue.autocomplete(this.jqInput, { valueField: 'Code', lookup(query) { var varietyId = self.underlying.VarietyId; var vid = varietyId || 0; var key = vid + '|' + (query || ''); if (_fresh[vid] === key) { // 命中当前关键词的服务端结果:直接展示(服务端已按 StartsWith+品种/黑名单过滤,不再前端二次过滤) return (_cache[vid] || []).slice(0, 20); } // 异步搜索。FastVue 包装的 lookup 只同步取返回值渲染,服务端结果到达后必须重新触发 // onValueChange 才会显示;重走 lookup 时命中上面的 _fresh 分支直接返回,不会循环请求 _fetch(varietyId, query, function (list, q) { var inst = self.jqInput.autocomplete(); if (!inst || !inst.visible) return; // 下拉已关闭:留待下次获得焦点时呈现 if ((self.jqInput.val() || '').toLowerCase() !== q.toLowerCase()) return; // 输入已变化:等新关键词的响应 inst.onValueChange(); }); // 过渡兜底:服务端响应到达前用旧缓存按关键词过滤,避免搜索期间下拉空白 return _filter(_cache[vid] || [], query, varietyId); }, onSelect(data) { if (self.underlying !== data) { self.$emit('change-underlying', data); } self.jqInput.blur(); }, formatResult(suggestion, currentValue) { return _suggestionTpl(suggestion.data); } }); this.jqInput.val(this.underlying.Code); }, methods: { showInput() { this.jqInput.show().focus().next().hide(); }, hideInput() { this.jqInput.hide().next().show(); } }, computed: { showName() { return (this.underlying.InstrumentType === 'Stock' || this.underlying.InstrumentType === 'StockIndex') ? this.underlying.Name : ' '; } }, destroyed() { FastVue.autocomplete.dispose(this.jqInput); }, template: '
' + '{{underlying.Code}}{{showName}}
' }; }; //预付金模板 const vueMarginTemplateName = function () { return { props: ['value'], data() { return { autoCtrl: null }; }, mounted() { var self = this; this.autoctrl = FastVue.autocomplete(this.$el, { valueField: 'Value', searchField: ['Value'], lookup: ylotc.tradeMarginTemplateItems, onSelect(data) { if (self.value !== data.Value) { self.value = data.Value; self.$emit('input', self.value); } } }); value = self.value || "系统默认"; this.autoctrl.setData({ Text: value, Value: value }) }, watch: { value(newVal, oldVal) { if (newVal !== oldVal) { let data = ylotc.tradeMarginTemplateItems.find(x => x.Value === newVal); this.autoctrl.setData(data || { Text: "系统默认", Value: "系统默认" }) } } }, destroyed() { FastVue.autocomplete.dispose(this.$el); }, template: '' }; } //计算结果字段 const consCalcFields = Object.freeze(['TotalMargin', 'Pv', 'Delta', 'Gamma', 'Vega', 'Theta', 'Rho', 'PvContainsKnockOut', 'DeltaContainsKnockOut', 'DeltaInLots', 'GammaInLots', 'DeltaCash', 'GammaCash', 'VegaCash', 'GammaContainsKnockOut', 'Delta_r', 'Delta_r_1bp', 'Dv01', 'Gamma_r', 'Gamma_r_1bp', 'Vega_r', 'Vega_r_1bp', 'Vega_1bp']); var _trades, _tradeVues, _salesCommissionCtrl; //交易保存 const tradeSaver = (function () { const needClient = !pageVue.ClientUsedForCalc; function showTradeView(items) { let item = items.shift(); if (!item) return; let url = "/trade/tradeview?abstract=1&enid=" + item.EncryptId; main.open("查看交易", url, { end: function () { showTradeView(items); } }); } function _saveAccumulator() { if (!_trades) return; let AssetId = parseInt($('#accumulatorAssetId').data('id')); let TraderId = parseInt($('#accumulatorTradeID').data('id')); let ClientId = parseInt($('#accumulatorClientId').data('id')); if (!AssetId) { return main.alert("未设置簿记账户"); } if (!TraderId) { return main.alert("未设置交易员"); } if (needClient && !ClientId) { return main.alert("未设置客户"); } let TradeNumber = $('#accumulatorTradeNumber').val(); let AssetBookName = $('#accumulatorAssetId').val(); let TraderName = $('#accumulatorTradeID').val(); let ClientName = $('#accumulatorClientId').val(); let TradingPlace = $("#accumulatorTradingPlace").val(); let ClearingAgency = $("#accumulatorClearingAgency").val(); let MainProtocolCode = $("#accumulatorMainProtocolCode").val(); let SupProtocolCode = $("#accumulatorSupProtocolCode").val(); let OpponentRole = $("#accumulatorOpponentRole").val(); let InitialAdvance = parseFloat($("#accumulatorInitialAdvance").val()) || 0; let PeriodAdvance = parseFloat($("#accumulatorPeriodAdvance").val()) || 0; let FontEarning = parseFloat($("#accumulatorFontEarning").val()) || 0; let ConfirmedLine = parseFloat($("#accumulatorConfirmedLine").val()) || 0; let ConfirmedFloor = parseFloat($("#accumulatorConfirmedFloor").val()) || 0; let salesCommission = _salesCommissionCtrl.getValue(); let IsCentralClearing = $("#accumulatorIsCentralClearing").val(); let CentralClearingPaltform = $("#accumulatorCentralClearingPaltform").val(); let TradingPaltform = $("#accumulatorTradingPaltform").val(); let ExchangeRate = $("#accumulatorExchangeRate").val(); let QuoteCurrency = $("#accumulatorQuoteCurrency").val(); let SettlementMode = $("#SettlementMode").val(); let ForwardPriceType = $("#ForwardPriceType").val(); let ForwardDateType = $("#ForwardDateType").val(); let SettlementMode1 = $("#SettlementMode1").val(); let ForwardPriceType1 = $("#ForwardPriceType1").val(); let ForwardDateType1 = $("#ForwardDateType1").val(); let SettlementMode2 = $("#SettlementMode2").val(); let ForwardPriceType2 = $("#ForwardPriceType2").val(); let ForwardDateType2 = $("#ForwardDateType2").val(); let SettlementMode3 = $("#SettlementMode3").val(); let ForwardPriceType3 = $("#ForwardPriceType3").val(); let ForwardDateType3 = $("#ForwardDateType3").val(); let AccumuType = $("#AccumuType").val(); var tags = getSelectTags(); if (SettlementMode === '现金期末'&& _trades.some(x => x.EarlyTerminate && (x.AccumulatorStructureType + '') !== '1')) { return main.alert("结算方式为'现金结算(期末)'时,需要将'敲出是否终止'设为'否'"); } _trades.forEach(x => { x.AssetId = AssetId; x.AssetBookName = AssetBookName; x.TraderId = TraderId; x.TraderName = TraderName; x.TradeNumber = TradeNumber; x.SalesCommission = salesCommission; if (needClient) { x.ClientId = ClientId; x.ClientName = ClientName; } if (x.TradePremium) { x.MetaDic["交易溢价"] = x.TradePremium; } x.MetaDic["交易场所"] = TradingPlace; x.MetaDic["清算机构"] = ClearingAgency; x.MetaDic["主协议编号"] = MainProtocolCode; x.MetaDic["补充协议编号"] = SupProtocolCode; x.MetaDic["中央对手方清算"] = IsCentralClearing; x.MetaDic["中央清算平台"] = CentralClearingPaltform; x.MetaDic["ExchangeRate"] = ExchangeRate; x.MetaDic["交易平台"] = TradingPaltform; if (pageData.showCCR) { //if (x.MarginType == 0) { x.MetaDic["ccr_k"] = x.ccr_k || "0"; //} x.MetaDic["ignoreRiskExposure"] = x.ignoreRiskExposure || "0"; } x.TradeType === '现金流交易' && tradeUtils.resetCashFlow(x); if (x.TradeType == '累计期权') { if (x.AccumulatorStructureType.toString() === '1') { x.SettlementMode = SettlementMode1; x.ForwardPriceType = ForwardPriceType1; x.ForwardDateType = ForwardDateType1; x.SettlementMode2 = SettlementMode2; x.ForwardPriceType2 = ForwardPriceType2; x.ForwardDateType2 = ForwardDateType2; x.SettlementMode3 = SettlementMode3; x.ForwardPriceType3 = ForwardPriceType3; x.ForwardDateType3 = ForwardDateType3; } else { x.AccumuType = AccumuType; x.SettlementMode = SettlementMode; x.ForwardPriceType = ForwardPriceType; x.ForwardDateType = ForwardDateType; } } x.OpponentRole = OpponentRole; x.QuoteCurrency = QuoteCurrency; x.InitialAdvance = InitialAdvance; x.PeriodAdvance = PeriodAdvance; x.FontEarning = FontEarning; x.ConfirmedLine = ConfirmedLine; x.ConfirmedFloor = ConfirmedFloor; x.IsUsePremiumRate = (x.IsUsePremiumRate == "" || x.IsUsePremiumRate == null) ? false : x.IsUsePremiumRate; x.Tags = tags; x.IsUsePremiumRate = false; extendVue2.setExtendInfo(x); }); main.post("/pricing/AjaxSaveTrades", { trades: _trades }).done(function (resp) { if (pageVue.IsImport) { let url = "#/trade/tradeview?abstract=1&enid=" + resp.obj[0].EncryptId; layer.closeMe(url);//必须以#开头 } else { floatVue.hide(); $('#accumulatormodalTradeSave').modal('hide'); showTradeView(resp.obj); _.each(_tradeVues, x => x.remove(true)); } $(".tag-context .tag-item").remove(); }); } //保存 录入增加字段时 ,累计也需要 增加html、js都要在对应字段保存,因时间仓促目前实现方式不好 function _save() { if (!_trades) return; let AssetId = parseInt($('#AssetId').data('id')); let TraderId = parseInt($('#TraderId').data('id')); let ClientId = parseInt($('#ClientId').data('id')); if (!AssetId) { return main.alert("未设置簿记账户"); } if (!TraderId) { return main.alert("未设置交易员"); } if (needClient && !ClientId) { return main.alert("未设置客户"); } let TradeNumber = $('#TradeNumber').val(); let AssetBookName = $('#AssetId').val(); let TraderName = $('#TraderId').val(); let ClientName = $('#ClientId').val(); let TradingPlace = $("#TradingPlace").val(); let ClearingAgency = $("#ClearingAgency").val(); let MainProtocolCode = $("#MainProtocolCode").val(); let SupProtocolCode = $("#SupProtocolCode").val(); let OpponentRole = $("#OpponentRole").val(); let InitialAdvance = parseFloat($("#InitialAdvance").val()) || 0; let PeriodAdvance = parseFloat($("#PeriodAdvance").val()) || 0; let FontEarning = parseFloat($("#FontEarning").val()) || 0; let ConfirmedLine = parseFloat($("#ConfirmedLine").val()) || 0; let ConfirmedFloor = parseFloat($("#ConfirmedFloor").val()) || 0; let salesCommission = _salesCommissionCtrl.getValue(); let IsCentralClearing = $("#IsCentralClearing").val(); let CentralClearingPaltform = $("#CentralClearingPaltform").val(); let TradingPaltform = $("#TradingPaltform").val(); let ExchangeRate = $("#ExchangeRate").val(); let QuoteCurrency = $("#QuoteCurrency").val(); var tags = getSelectTags(); _trades.forEach(x => { x.AssetId = AssetId; x.AssetBookName = AssetBookName; x.TraderId = TraderId; x.TraderName = TraderName; x.TradeNumber = TradeNumber; x.SalesCommission = salesCommission; if (needClient) { x.ClientId = ClientId; x.ClientName = ClientName; } if (x.TradePremium) { x.MetaDic["交易溢价"] = x.TradePremium; } x.MetaDic["交易场所"] = TradingPlace; x.MetaDic["清算机构"] = ClearingAgency; x.MetaDic["主协议编号"] = MainProtocolCode; x.MetaDic["补充协议编号"] = SupProtocolCode; x.MetaDic["中央对手方清算"] = IsCentralClearing; x.MetaDic["中央清算平台"] = CentralClearingPaltform; x.MetaDic["ExchangeRate"] = ExchangeRate; x.MetaDic["交易平台"] = TradingPaltform; if (pageData.showCCR) { //if (x.MarginType == 0) { x.MetaDic["ccr_k"] = x.ccr_k || "0"; //} x.MetaDic["ignoreRiskExposure"] = x.ignoreRiskExposure || "0"; } x.TradeType === '现金流交易' && tradeUtils.resetCashFlow(x); x.OpponentRole = OpponentRole; x.QuoteCurrency = QuoteCurrency; x.InitialAdvance = InitialAdvance; x.PeriodAdvance = PeriodAdvance; x.FontEarning = FontEarning; x.ConfirmedLine = ConfirmedLine; x.ConfirmedFloor = ConfirmedFloor; x.IsUsePremiumRate = (x.IsUsePremiumRate == "" || x.IsUsePremiumRate == null) ? false : x.IsUsePremiumRate; x.Tags = tags; extendVue.setExtendInfo(x); }); main.post("/pricing/AjaxSaveTrades", { trades: _trades }).done(function (resp) { if (pageVue.IsImport) { let url = "#/trade/tradeview?abstract=1&enid=" + resp.obj[0].EncryptId; layer.closeMe(url);//必须以#开头 } else { floatVue.hide(); $('#modalTradeSave').modal('hide'); showTradeView(resp.obj); _.each(_tradeVues, x => x.remove(true)); } $(".tag-context .tag-item").remove(); }); } //保存 function _saveTrades(tradeVues) { _tradeVues = tradeVues; if (!Array.isArray(_tradeVues)) { throw "参数错误:tradeVues"; } if (!_tradeVues.length) { return main.alert("请至少勾选一条交易"); } _trades = _.flatMap(_tradeVues, x => x.datas).map(x => { x.viewState.synthetic && (x.trade.MetaDic["组合标的"] = JSON.stringify(x.viewState.synthetic)); return x.trade; }); var viewStates = _.flatMap(_tradeVues, x => x.datas).map(x => x.viewState).filter(x => x.variety && x.variety.Code); $("#QuoteCurrency").val(viewStates[0]?.variety.QuoteCurrency); if ($("#QuoteCurrency").val() && $("#QuoteCurrency").val() != "CNY") { $("#ExchangeRateDiv").show(); } else { $("#ExchangeRateDiv").hide(); } _trades = tradeUtils.prepareTrades(_trades, pageVue.getVolType(), true); if (_trades) { $('#TradeNumber').val('').parent().toggle(_tradeVues.length === 1); var accumulatorStandard = _trades.filter(x => x.TradeType == "累计期权" && x.AccumulatorStructureType == "0"); var accumulatorSegmented = _trades.filter(x => x.TradeType == "累计期权" && x.AccumulatorStructureType == "1"); if (accumulatorSegmented.length > 0 && accumulatorStandard.length > 0) { return main.alert("因累计结构类型不一致,不支持快速录入"); } else if (accumulatorStandard.length > 0) { var accumulatorPayoffType = accumulatorStandard.filter(x => x.PayoffType == "浮动"); if (accumulatorPayoffType.length != 0 && accumulatorPayoffType.length != accumulatorStandard.length) { return main.alert("因上端收益类型不一致,不支持快速录入"); } } if (accumulatorSegmented.length > 0 || accumulatorStandard.length > 0) { $('#accumulatormodalTradeSave').modal('show'); if (accumulatorSegmented.length > 0) { $("#leiji").hide(); $("#leijisanduanshi").show(); } else { $("#leijisanduanshi").hide(); $("#leiji").show(); var accumulatorPayoffTypeF = accumulatorStandard.filter(x => x.PayoffType == "固定"); $("#SettlementMode option").each(function (i, el) { if ($(el).text() == "现金结算(期末)" && accumulatorPayoffTypeF.length > 0) { $(this).attr("disabled", true); } else { $(this).attr("disabled", false); } }) } } else { $('#modalTradeSave').modal('show'); } _setSalesman(); if (pageVue.SecuritiesEnvironment && !pageVue.ClientUsedForCalc) { var clientId = parseInt($('#ClientId').data('id')) || _trades[0].ClientId; _getMainProtocolCode(clientId); } return true; } return false; } function _setAutocomplete(elId, datas, initData, onSelectFn, width) { initData = initData || datas[0] || {}; FastVue.autocomplete(document.getElementById(elId), { valueField: 'Name', searchField: ['Name', 'PinYin'], lookup: datas, width: width, onSelect(data) { $('#' + elId).data('id', data.id); if (elId === "ClientId") { if (!pageVue.ClientUsedForCalc) { $("#IsCentralClearing").val(data.IsCentralClearing); $("#CentralClearingPaltform").val(data.CentralClearingPaltform); $("#TradingPaltform").val(data.TradingPaltform); } _setSalesman(); } onSelectFn && onSelectFn(data); }, zIndex: 300000 }).setData(initData); $('#' + elId).data('id', initData.id); } //保存组合交易 function _saveGroupTrades(tradeVues) { _tradeVues = tradeVues; if (!Array.isArray(_tradeVues)) { throw "参数错误:tradeVues"; } if (!_tradeVues.length) { return main.alert("请至少勾选一条交易"); } _trades = _.flatMap(_tradeVues, x => x.datas).map(x => { x.viewState.synthetic && (x.trade.MetaDic["组合标的"] = JSON.stringify(x.viewState.synthetic)); return x.trade; }); var viewStates = _.flatMap(_tradeVues, x => x.datas).map(x => x.viewState).filter(x => x.variety && x.variety.Code); //验证分组交易是否是同标的同期初价格 $("#selQuoteCurrency").val(viewStates[0].variety.QuoteCurrency); if ($("#selQuoteCurrency").val() && $("#selQuoteCurrency").val() != "CNY") { $("#selExchangeRateDiv").show(); } else { $("#selExchangeRateDiv").hide(); } var underlyingId = 0; var hasDiffUnderlying = false; var spotPrice = 0; var hasDiffPrice = false; var tradeDate = null; var exerciseDate = null; var hasDiffTradeDate = false; var buySell = groupVue.trade.BuySell; var tradePrice = 0; var clientIdArr = []; _trades.forEach(x => { if (x.TradeType != "现金流交易") { if (underlyingId && underlyingId != x.UnderlyingId) { hasDiffUnderlying = true; } else { underlyingId = x.UnderlyingId; } if (spotPrice && parseFloat(spotPrice) != parseFloat(x.SpotPrice)) { hasDiffPrice = true; } else { spotPrice = x.SpotPrice; } if (!buySell) { buySell = x.BuySell; } } tradePrice += x.TradePrice * (x.BuySell == "卖出" ? 1 : -1); if (tradeDate != null && tradeDate != x.TradeDate) { hasDiffTradeDate = true; } else { tradeDate = x.TradeDate; } if (exerciseDate == null || exerciseDate < x.ExerciseDate) { exerciseDate = x.ExerciseDate; } if (clientIdArr.indexOf(x.ClientId) == -1 && x.ClientId > 0) { clientIdArr.push(x.ClientId); } }); if (hasDiffUnderlying) { main.alert("分组交易必须要保持相同的标的"); return false; } if (hasDiffPrice) { main.alert("分组交易必须要保持相同的期初价格"); return false; } if (hasDiffTradeDate) { main.alert("分组交易必须要保持相同的交易日期"); return false; } if (clientIdArr.length > 1) { main.alert("分组交易必须要保持相同的客户"); return false; } _trades = tradeUtils.prepareTrades(_trades, pageVue.getVolType(), true); if (_trades) { $('#TradeNumber').val('').parent().toggle(_tradeVues.length === 1); groupVue.viewState = viewStates[0]; groupVue.trade.TradeDate = tradeDate; groupVue.trade.ExerciseDate = exerciseDate; groupVue.trade.BuySell = buySell; if (groupVue.trade.IsUsePremiumRate == null) { groupVue.trade.IsUsePremiumRate = true } if (groupVue.trade.IsMoneynessOption == null) { groupVue.trade.IsMoneynessOption = "是"; } groupVue.trade.IsTradePricePayType = true; groupVue.trade.TradePrice = tradePrice * (buySell == "卖出" ? 1 : -1); groupVue.changeIsUsePremiumRate(); groupVue.trade.SpotPrice = spotPrice; if (!groupVue.trade.StructureType) { groupVue.trade.StructureType = "气囊结构"; groupVue.trade.OptionType = "看涨"; groupVue.trade.trade_airbag.Barrier = 0.8; groupVue.trade.Strike = 1; groupVue.trade.trade_airbag.NotKIParticipationRate = 1; groupVue.trade.trade_airbag.KIParticipationRate = 1; } let stockEqvNotionalArrs = _trades.map((value, index, array) => { return value.StockEqvNotional }); groupVue.trade.StockEqvNotional = Math.max(...stockEqvNotionalArrs); groupVue.changeStockEqvNotional(); if (clientIdArr.length > 0) { groupVue.trade.ClientId = clientIdArr[0]; } $('#modalGroupTradeSave').modal('show'); groupVue.init(); _setSalesman(); return true; } return false; } return { saveTrades: _saveTrades, saveGroupTrades: _saveGroupTrades, init() { _setAutocomplete('AssetId', ylotc.assetunits); if (pageVue.CanSelectTrader) { let trader = pageVue.Trade.TraderId > 0 ? ylotc.traders.find(x => x.id === pageVue.Trade.TraderId) : null; if (!trader) { trader = { Name: "", id: 0 } } _setAutocomplete('TraderId', ylotc.traders, { Name: trader.Name }); } if (!pageVue.ClientUsedForCalc) { var width = 300; for (var i = 0; i < ylotc.clients.length; i++) { let ele = document.createElement('span') ele.innerText = ylotc.clients[i].Name; ele.style.fontSize = '14px'; document.documentElement.append(ele); var charLength = ele.offsetWidth + 28;//滚动条 document.documentElement.removeChild(ele); if (charLength > width) { width = charLength } } _setAutocomplete('ClientId', ylotc.clients, null, (pageVue.SecuritiesEnvironment ? _getMainProtocolCode : null), width); } //组合标的控件 synthenticPriceCtrl.init({ getSynthetic(input) { return consSyntheticMap[input.dataset.calcid]; }, setSynthetic(input, synthetic) { var calcid = input.dataset.calcid; _.each(pricingVue.getTradeVues(), x => !x.updateSynthetic(calcid, synthetic)); } }); //销售提成控件 _salesCommissionCtrl = new SalesCommissionCtrl(document.getElementById('salesCommissionCtrl'), pageVue.SalesCommission); //累计 _setAutocomplete('accumulatorAssetId', ylotc.assetunits); if (pageVue.CanSelectTrader) { let trader = pageVue.Trade.TraderId > 0 ? ylotc.traders.find(x => x.id === pageVue.Trade.TraderId) : null; if (!trader) { trader = { Name: "", id: 0 } } _setAutocomplete('accumulatorTradeID', ylotc.traders, { Name: trader.Name }); } if (!pageVue.ClientUsedForCalc) { var width = 300; for (var i = 0; i < ylotc.clients.length; i++) { let ele = document.createElement('span') ele.innerText = ylotc.clients[i].Name; ele.style.fontSize = '14px'; document.documentElement.append(ele); var charLength = ele.offsetWidth + 28;//滚动条 document.documentElement.removeChild(ele); if (charLength > width) { width = charLength } } _setAutocomplete('accumulatorClientId', ylotc.clients, null, (pageVue.SecuritiesEnvironment ? _getMainProtocolCode : null), width); } //销售提成控件 _salesCommissionCtrl = new SalesCommissionCtrl(document.getElementById('salesaccumulatorCommissionCtrl'), pageVue.SalesCommission); _setSalesman(); $('#btnSave').on('click', _save); $('#btnAccumulatorSave').on('click', _saveAccumulator); if (pageData.is厦门象屿) { $("#SettlementMode").val("现金实物合并结算"); $("#SettlementMode1").val("现金实物合并结算"); $("#SettlementMode2").val("现金实物合并结算"); $("#SettlementMode3").val("现金实物合并结算"); $("#ForwardPriceType").val("远期开仓现价"); $("#ForwardPriceType1").val("远期开仓现价"); $("#ForwardPriceType2").val("远期开仓现价"); $("#ForwardPriceType3").val("远期开仓现价"); $("#ForwardDateType option").each(function (i, el) { if ($(el).text() == "标的交割月前一交易日") { $("#ForwardDateType").val("标的交割月前一交易日"); } }) $("#ForwardDateType1 option").each(function (i, el) { if ($(el).text() == "标的交割月前一交易日") { $("#ForwardDateType1").val("标的交割月前一交易日"); } }) $("#ForwardDateType2 option").each(function (i, el) { if ($(el).text() == "标的交割月前一交易日") { $("#ForwardDateType2").val("标的交割月前一交易日"); } }) $("#ForwardDateType3 option").each(function (i, el) { if ($(el).text() == "标的交割月前一交易日") { $("#ForwardDateType3").val("标的交割月前一交易日"); } }) $("#AccumuType").attr("disabled", false); $("#AccumuType option").each(function (i, el) { if ($(el).text() == "子弹") { $(this).attr("disabled", true); } else { $(this).attr("disabled", false); } }) } else { $("#ForwardPriceType").attr("disabled", true); $("#ForwardDateType").attr("disabled", true); $("#ForwardPriceType1").attr("disabled", true); $("#ForwardDateType1").attr("disabled", true); $("#ForwardPriceType2").attr("disabled", true); $("#ForwardDateType2").attr("disabled", true); $("#ForwardPriceType3").attr("disabled", true); $("#ForwardDateType3").attr("disabled", true); $("#AccumuType").attr("disabled", true); } $("#SettlementMode").change(function () { $("#AccumuType").val(''); $("#AccumuType").attr("selected", true); if ($("#SettlementMode").val() == "实物交割" || $("#SettlementMode").val() == "现金实物合并结算") { $("#AccumuType").attr("disabled", false); $("#ForwardPriceType").attr("disabled", false); $("#ForwardDateType").attr("disabled", false); $("#AccumuType option").each(function (i, el) { if ($(el).text() == "子弹") { $(this).attr("disabled", true); } else { $(this).attr("disabled", false); } }) } else { $("#AccumuType").attr("disabled", true); $("#ForwardPriceType").attr("disabled", true); $("#ForwardDateType").attr("disabled", true); } if ($("#SettlementMode").val() == "现金期末") { $("#AccumuType").attr("disabled", false); $("#AccumuType option").each(function (i, el) { if ($(el).text() == "区间现金结算") { $(this).attr("disabled", true); } else { $(this).attr("disabled", false); } }) } }) $("#SettlementMode1").change(function () { if ($("#SettlementMode1").val() == "实物交割" || $("#SettlementMode1").val() == "现金实物合并结算") { $("#ForwardPriceType1").attr("disabled", false); $("#ForwardDateType1").attr("disabled", false); } else { $("#ForwardPriceType1").attr("disabled", true); $("#ForwardDateType1").attr("disabled", true); } }) $("#SettlementMode2").change(function () { if ($("#SettlementMode2").val() == "实物交割" || $("#SettlementMode2").val() == "现金实物合并结算") { $("#ForwardPriceType2").attr("disabled", false); $("#ForwardDateType2").attr("disabled", false); } else { $("#ForwardPriceType2").attr("disabled", true); $("#ForwardDateType2").attr("disabled", true); } }) $("#SettlementMode3").change(function () { if ($("#SettlementMode3").val() == "实物交割" || $("#SettlementMode3").val() == "现金实物合并结算") { $("#ForwardPriceType3").attr("disabled", false); $("#ForwardDateType3").attr("disabled", false); } else { $("#ForwardPriceType3").attr("disabled", true); $("#ForwardDateType3").attr("disabled", true); } }) $("#btnCloseInputTrade").click(function () { $('#modalTradeSave').modal('hide'); $(".tag-context .tag-item").remove(); }); $("#btnAccumulatorCloseInputTrade").click(function () { $('#accumulatormodalTradeSave').modal('hide'); $(".tag-context .tag-item").remove(); }) $('#MainProtocolCode').on('change', _changeMainProtocolCode); $('#modalTradeSave').on('show.bs.modal', function () { $('#TradeNumber').val(''); _salesCommissionCtrl.reset(); }); $('#accumulatormodalTradeSave').on('show.bs.modal', function () { $('#TradeNumber').val(''); _salesCommissionCtrl.reset(); }); } }; }()); //截图 const screenshoter = (function () { var _layerIndex; function execute(tradeVue) { if (!tradeVue.floating) { floatVue.show(tradeVue, true); } pageVue.viewState.SS_SinglePrincipalWrite = tradeVue.datas.reduce((p, x) => p + (parseFloat(x.trade.SinglePrincipalWrite) || 0), 0); pageVue.viewState.SS_PrincipalSum = tradeVue.datas.reduce((p, x) => p + (parseFloat(x.trade.OriginalPrincipalSum) || 0), 0); var $fs = $('#for-screenshot'); $fs.parent().children().addClass('for-screenshot'); $fs.closest('.modal').css('margin-top', -999999); setTimeout(function () {//OTC-8517 在结构跟香草之间来回切换生成截图时,香草的高度会变成结构的高度,页面需要过段时间才会更新 var opts = { bgcolor: '#fff', width: tradeVue.datas.length * 200 + 140, height: $fs.height() }; domtoimage.toPng($fs[0], opts).then(function (dataUrl) { $('#screenshot-img').attr('src', dataUrl); _layerIndex = layer.open({ type: 1, closeBtn: 0, title: false, scrollbar: false, shadeClose: true, area: ['auto', '50%'], content: $('#screenshot'), offset: '100px', success: function (layero, index) { setTimeout(function () { let height = $('#screenshot-img').height(); height > 100 && layero.children('.layui-layer-content').css('height', height + 100); }, 100); } }); }).catch(function (error) { main.alert('截图发生错误:' + error); }).finally(function () { $fs.closest('.modal').css('margin-top', 0); $fs.parent().children().removeClass('for-screenshot'); if (!tradeVue.floating) { $('#floatModal').modal('hide'); } }); }, 10) } function closeShow() { layer.close(_layerIndex); } //保存截图 function download() { domtoimage.toBlob(document.getElementById('screenshot-img')) .then(function (blob) { moment().format(); window.saveAs(blob, '报价' + moment().format('YYYYMMDDHHmmss') + '.png'); }); } return { execute: execute, download: download, closeShow: closeShow }; }()); //#singleprice const singlePricer = (function () { const _sumDatas = []; //datas:[{Pv,Notional}] function _calcSinglePrice(datas) { let tradeSinglePrice = 0; var result = _.reduce(datas, (acc, data) => { if (Array.isArray(data)) { _.each(data, item => { acc.totalPv += parseFloat(item.Pv) || 0; var notional = parseFloat(item.Notional) || 0; tradeSinglePrice += parseFloat(pricingFormat.tradeSinglePrice((parseFloat(item.Pv) || 0) / notional)); if (acc.minNotional > notional) { acc.minNotional = notional; } }); } else if (data) { acc.totalPv += parseFloat(data.Pv) || 0; var notional = parseFloat(data.Notional) || 0; tradeSinglePrice += parseFloat(pricingFormat.tradeSinglePrice((parseFloat(data.Pv) || 0) / notional)); if (acc.minNotional > notional) { acc.minNotional = notional; } } return acc; }, { totalPv: 0, minNotional: Number.MAX_SAFE_INTEGER }); var singlePrice = Math.abs(result.minNotional) < 1e-5 ? "0.00" : pricingFormat.tradeSinglePrice(Math.abs(result.totalPv) / result.minNotional); if (pageObj.IsTradeSinglePriceCalcu) { return pageVue.CompanyName + (tradeSinglePrice >= 0 ? "付" : "收") + pricingFormat.tradeSinglePrice(Math.abs(tradeSinglePrice)); } else { return pageVue.CompanyName + (result.totalPv >= 0 ? "付" : "收") + singlePrice; } } //重设统计单价 function _reset() { var singlePrice = _calcSinglePrice(_sumDatas); $('#singleprice').text(singlePrice); } const _debounceReset = _.debounce(_reset, 300); return { //data:[{Pv,Notional}] reset(index, data) { _sumDatas[index] = !data || Array.isArray(data) ? data : [data]; _debounceReset(); }, //datas:[{Pv,Notional}] calcSinglePrice: _calcSinglePrice }; }()); //pageVue状态 (function () { const viewState = { VolType: '交易', structureType: '', SS_PrincipalSum: 0, SS_SinglePrincipalWrite: 0 }; _.extend(pageVue, { viewState: viewState, getVolType() { return viewState.VolType; }, setVolType(value) { viewState.VolType = value; }, getStructureType() { return viewState.structureType; }, setStructureType(value) { viewState.structureType = value; } }); //冻结修改 _.each([pageVue], x => Object.freeze(x)); }()); //一个简单的事件总线 const EventBus = (new function () { var _bus; function getBus() { return _bus || (_bus = document.createElement('div')); } //增加事件监听 this.addEventListener = function (event, callback) { getBus().addEventListener(event, callback); }; //移除事件监听 this.removeEventListener = function (event, callback) { getBus().removeEventListener(event, callback); }; //激发事件 this.triggerEvent = function (event, detail = {}) { getBus().dispatchEvent(new CustomEvent(event, { detail })); }; //仅供调试用 this.getEventListeners = function () { return getEventListeners(getBus()); }; }()) //顶部组件 const topVue = (function () { return new Vue({ el: '#pricing-top', data: { viewState: pageVue.viewState, simpleMode: pageVue.SimpleMode, calcMargin: pageVue.CalcMargin && pageVue.ShowInitialMargin, calcAutocallGreeks: pageVue.CalcAutocallGreeks, }, mounted() { }, methods: { changeVolType() { pricingVue.changeVolType(); }, addStructure(type, typeCn) { pageVue.setStructureType(typeCn); var url = "/trade/structureoptionV2?name=" + type; main.open("添加策略", url, { area: ['500px', '800px'] }); }, normOtcTrade(td) { if (!pageData.is厦门象屿 && td.TradeType !== "Risky期权") { td.PremiumPayDate = ''; } td.Notional = pricingFormat.notional(td.Notional); td.TradeAmount = pricingFormat.notional(td.TradeAmount); td.TradePrice = pricingFormat.tradePrice(td.TradePrice); td.StockEqvNotional = pricingFormat.StockEqvNotional(td.StockEqvNotional); td.StockEqvNotionalReal = pricingFormat.StockEqvNotional(td.StockEqvNotionalReal); tradeUtils.normalizeTrade(td); return td; }, importTrade() { let tradeNumber = $('#importTradeNumber').val().trim(); if (!tradeNumber) return; var self = this; main.post('/pricing/AjaxGetOtcTradeFull?tradeNumber=' + encodeURIComponent(tradeNumber)).done(function (resp) { if (resp.obj) { pricingVue.addTrade(self.normOtcTrade(resp.obj)); } else { main.alert('没有找到交易数据'); } }).always(function () { }); }, toggleSimpleMode() { this.simpleMode = !this.simpleMode; EventBus.triggerEvent('simpleMode.changed'); main.post("/sysuserConfig/AjaxSaveOtcWebConfig", { name: 'Pricing_SimpleMode', value: this.simpleMode }, false); }, toggleCalcMargin() { this.calcMargin = !this.calcMargin; main.post("/sysuserConfig/AjaxSaveOtcWebConfig", { name: 'Pricing_CalcMargin', value: this.calcMargin }, false); }, toggleCalcAutocallGreeks() { this.calcAutocallGreeks = !this.calcAutocallGreeks; main.post("/sysuserConfig/AjaxSaveOtcWebConfig", { name: 'Pricing_CalcAutocallGreeks', value: this.calcAutocallGreeks }, false); } } }) }()); //统计组件 const summaryVue = (function () { const _summaryDatas = []; const summary = _.reduce(consCalcFields, (acc, cur) => { acc[cur] = 0; return acc; }, {}); //重设统计合计 function _resetSummary() { var datas = _.flatMap(_summaryDatas, x => x && x.length > 0 ? x : []); var UnderlyingCode = ''; var isSameCode = _.every(datas, x => { return !x.UnderlyingCode ? true : (UnderlyingCode ? x.UnderlyingCode === UnderlyingCode : UnderlyingCode = x.UnderlyingCode); }); if (isSameCode) { _.each(summary, (val, key) => { summary[key] = 0; }); _.each(datas, data => _.each(consCalcFields, field => summary[field] += parseFloat(data[field]) || 0) ); } else { _.each(summary, (val, key) => { summary[key] = 'NaN'; }); summary.Pv = summary.TotalMargin = summary.Rho = 0; _.each(datas, data => { summary.Pv += parseFloat(data.Pv) || 0; summary.TotalTradePrice += parseFloat(data.TradePrice) || 0; summary.Rho += parseFloat(data.Rho) || 0; summary.TotalMargin += parseFloat(data.TotalMargin) || 0; }); } if (!pageVue.TwoSideMargin) { //如果为负数,则显示0 summary.TotalMargin < 0 && (summary.TotalMargin = 0); } } const _debounceReset = _.debounce(_resetSummary, 300); const _vue = new Vue({ el: '#pricing-summary', data: { summary: summary }, computed: { DeltaHands() { var delta = this.summary.DeltaInLots; return typeof delta !== 'number' ? delta : (delta > 0 ? "卖" : "买") + pricingFormat.greek(Math.abs(delta)) + '手'; } }, filter: { greekFmt(val) { return typeof val !== 'number' ? val : pricingFormat.greek(val); } } }); return { getVue() { return _vue; }, //data:consCalcFields reset(index, data) { _summaryDatas[index] = !data || Array.isArray(data) ? data : [data]; _debounceReset(); } }; }()); //视图呈现器 const renders = (function () { function _getHtml($tpl, removeClass) { var html = $tpl.html(); var $temp = $('
').append(html); $temp.find(removeClass).remove(); $temp.find('template').each(function () { html = _getHtml($(this), removeClass); $(this).html(html); }); return $temp.html(); } //定价视图呈现器 const title = Vue.compile(_getHtml($('#pricingItem_tpl'), '.pitem,.pitem-cash')); const item = Vue.compile(_getHtml($('#pricingItem_tpl'), '.ptitle,.pitem-cash:not(.pitem)')); const itemCash = Vue.compile(_getHtml($('#pricingItem_tpl'), '.ptitle,.pitem:not(.pitem-cash)')); const items = Vue.compile($('#pricingItems_tpl').html() || ''); return { title(forStatic) { return forStatic ? title.staticRenderFns : title.render; }, item(forStatic) { return forStatic ? item.staticRenderFns : item.render; }, itemCash(forStatic) { return forStatic ? itemCash.staticRenderFns : itemCash.render; }, items(forStatic) { return forStatic ? items.staticRenderFns : items.render; } }; }()); //单个定价组件 const vueTrade = function () { return { props: ['trade', 'viewState', 'calcResult', 'floating'], data() { return { isTitle: false, canEditEngineName: true, ...consVueTrade.data(), fieldState: tradeFieldMgr.getFieldState(this.floating), tradeMarginTemplates: ylotc.tradeMarginTemplates, binaryPayoffTypes: this.trade.ExerciseMode === 'European' ? consBinaryPayoffTypes.European : consBinaryPayoffTypes.American, engineNames: tradeUtils.getEngineNames(this.trade), ExerciseModes: this.trade.TradeType === '障碍期权' ? [{ value: 'European', text: '欧式' }] : tradeHelper.ExerciseModes }; }, watch: { 'trade.Notional': { handler(newVal, oldVal) { this.resetSummary(resetSummaryFlags.notional); }, immediate: false }, 'trade.TradeType': { handler(newVal, oldVal) { this.updateKey.KIPayoffType = new Date().getTime(); this.fieldState.onTradeTypeChanged(this.trade, oldVal, this); this.fieldState.setFieldState('TradeAmount', (newVal === '累计期权')); if (this.trade.TradeType === '累计期权') { this.trade.IsUsePremiumRate = false; if (this.trade.AccumulatorStructureType == '1') { this.trade.EarlyTerminate = false; if (this.trade.PayoffType === '固定' && this.trade.OptionType === '看涨') { this.trade.Multiplier2 = 1; this.trade.Multiplier3 = 1; } if (this.trade.PayoffType === '固定' && this.trade.OptionType === '看跌') { this.trade.Multiplier1 = 1; this.trade.Multiplier2 = 1; } } } if (this.trade.TradeType === '障碍期权') { this.ExerciseModes = [{ value: 'European', text: '欧式' }]; } else { this.ExerciseModes = tradeHelper.ExerciseModes; } this.changeEngineName(); }, immediate: true }, 'trade.ExerciseDate': { handler(newVal, oldVal) { this.trade.SettlementDate = newVal; this.changeIsAnnualized(); }, immediate: false }, 'trade.AccumulatorStructureType': { handler(newVal, oldVal) { if (this.trade.AccumulatorStructureType == '1') { this.trade.EarlyTerminate = false; } }, immediate: false }, 'trade.PayoffType': { handler(newVal, oldVal) { if (this.trade.TradeType == "累计期权" && this.trade.AccumulatorStructureType == '1' && this.trade.PayoffType === '固定') { if (this.trade.OptionType === '看涨') { this.trade.Multiplier = 1; this.trade.Multiplier2 = 1; this.trade.Multiplier3 = 1; } if (this.trade.OptionType === '看跌') { this.trade.Multiplier = 1; this.trade.Multiplier2 = 1; this.trade.Multiplier3 = 1; } } this.changeEngineName(); }, immediate: false }, 'trade.OptionType': { handler(newVal, oldVal) { if (this.trade.TradeType == "累计期权" && this.trade.AccumulatorStructureType == '1' && this.trade.PayoffType === '固定') { if (this.trade.OptionType === '看涨') { this.trade.Multiplier = 1; this.trade.Multiplier2 = 1; this.trade.Multiplier3 = 1; } if (this.trade.OptionType === '看跌') { this.trade.Multiplier = 1; this.trade.Multiplier2 = 1; this.trade.Multiplier3 = 1; } } }, immediate: false }, 'trade.EnhancedPrice': { handler(newVal, oldVal) { this.changeEngineName(); }, immediate: true }, 'trade.StrikeType': { handler(newVal, oldVal) { this.changeEngineName(); }, immediate: false } }, created: consVueTrade.created, mounted() { consSyntheticMap[this.trade.CalcId] = this.viewState.synthetic; if (pageVue.ClientUsedForCalc) { if (!this.trade.ClientId) { ylotc.clients.length && (this.trade.ClientId = ylotc.clients[0].id); if (this.trade.ClientId) { this.changeClient(); } } else { this.updateKey.client = new Date().getTime(); } } this.$nextTick(function () { switch (this.viewState.initFlag) { case 'first': this.viewState.initFlag = ''; this.changeInstrumentType(); break; case 'import1': case 'import2': case 'template': !this.floating && this.updateUnderlying({ UnderlyingCode: this.trade.UnderlyingCode }); break; } }); topVue.simpleMode && (this.trade.UnderlyingPrice = ''); !this.floating && EventBus.addEventListener('simpleMode.changed', this.onSimpleModeChanged); }, methods: { ...consVueTrade.methods, //变更客户 changeClient() { this.$emit('change-client', this.trade.ClientId); }, //变更期权类型 changeTradeType() { this.viewState.Observation.hasValue = false; this.viewState.KOObservation.hasValue = false; this.changeExerciseMode('TradeType'); this.refreshEngineNames(); if (this.trade.TradeType === "现金流交易") { tradeUtils.resetCashFlow(this.trade); } else if (this.trade.TradeType === "Risky期权") { tradeUtils.resetRisky(this.trade); } }, //变更标的类型 changeInstrumentType() { if (new Date().getTime() < this.updateKey.underlying + 300) return; let instType = this.trade.UnderlyingInstrumentType; this.viewState.variety = tradeHelper.getEmptyVariety(instType); this.updateUnderlying({ InstrumentType: instType }); }, //变更标的品种 changeVariety(variety) { this.viewState.variety = variety; $("#QuoteCurrency").val(this.viewState.variety.QuoteCurrency); this.updateUnderlying({ VarietyId: variety.id }); }, //变更标的 changeUnderlying(underlying) { if (underlying.Disallow) { if (underlying.IsCombined) { main.alert(underlying.BlackWhiteState === 1 ? "该组合中包含存在于黑名单的标的" : "该组合中包含不在白名单中的标的"); } else { main.alert(underlying.BlackWhiteState === 1 ? "该标的存在于黑名单中" : "该标的不在白名单中"); return; } } this.viewState.underlying = underlying; this.updateUnderlying({ UnderlyingCode: underlying.Code }, true); this.changeEffectRatio(); }, //变更定价模型 changeEngineName() { // 增强亚式期权,在执行价格和增强价格不一致的情况下,默认只支持使用蒙特卡洛计算引擎 if (tradeUtils.changeEngineName(this.trade)) { this.canEditEngineName = false; } else { this.canEditEngineName = true; } }, //更新标的 updateUnderlying(reqData, fromSelect) { let self = this; // EQD-7049:新建空白页未选标的/品种/类型时,跳过必然失败的后端默认标的查询,避免报“标的信息缺失” var hasQueryKey = !!(reqData.UnderlyingCode || reqData.InstrumentType || reqData.VarietyId > 0); if (!hasQueryKey) { !fromSelect && (self.viewState.underlying = tradeHelper.getEmptyUnderlying()); return; } var instTypeChanged = !!reqData.InstrumentType; !fromSelect && (self.viewState.underlying = tradeHelper.getEmptyUnderlying()); main.post("/pricing/AjaxGetUnderlying", reqData).done(function (resp) { let trade = self.trade; let um = resp.obj.underlying; if (!fromSelect) { self.viewState.underlying = { id: um.id, Code: um.UnderlyingCode, Name: um.UnderlyingName, InstrumentType: um.UnderlyingInstrumentType, VarietyId: um.UnderlyingTypeId, QuoteUnitString: um.QuoteUnitString }; } self.updateKey.underlying = new Date().getTime(); instTypeChanged || (instTypeChanged = trade.UnderlyingInstrumentType !== um.UnderlyingInstrumentType); trade.UnderlyingId = um.id; trade.UnderlyingCode = um.UnderlyingCode; trade.UnderlyingName = um.UnderlyingName; trade.UnderlyingInstrumentType = um.UnderlyingInstrumentType; trade.VarietyId = um.UnderlyingTypeId; trade.CountRatio = um.CountRatio; self.viewState.variety = _.clone(ylotc.varieties.find(x => x.id === um.UnderlyingTypeId)) || tradeHelper.getEmptyVariety(trade.UnderlyingInstrumentType); self.updateKey.variety = new Date().getTime(); if (self.viewState.initFlag === 'import1') { self.getTTM(false, false); return self.viewState.initFlag = ''; } if (self.viewState.initFlag === 'template') { return self.viewState.initFlag = ''; } trade.DividendRate = um.DividendRate; self.viewState.synthetic = consSyntheticMap[trade.CalcId] = resp.obj.synthetic; //初始预付金 trade.InitialMargin = 0; //加载结构化交易 if (self.viewState.initFlag === 'import2') { trade.SettlementDate = trade.ExerciseDate; (trade.TradeOpenVolatility !== '') && (self.viewState.VolState = 'user'); (trade.TradeCloseVolatility !== '') && (self.viewState.CloseVolState = 'user'); self.changeTradeDate('import2'); if (trade.PremiumRate !== '' || trade.TradeSinglePrice !== '') { trade.PremiumRate !== '' ? self.changePremiumRate() : self.changeTradeSinglePrice(); } else { trade.PremiumRate = trade.TradeSinglePrice = trade.TradePrice = 0; } return self.viewState.initFlag = ''; } //重置权利金 trade.PremiumRate = trade.TradeSinglePrice = trade.TradePrice = 0; trade.SpotPrice = pricingFormat.umprice(um.Price); //重置视图状态 _.each(tradeFieldMgr.defaultData.viewState, (val, key) => { if (key === 'VolState' && self.viewState['VolLockState'] !== 'system') { val = 'user'; } else if (key !== 'VolLockState') { val === 'system' && (self.viewState[key] = "system"); } }); //根据标的类型切换,权益类默认名义本金成交方式 if (um.UnderlyingInstrumentType === "Stock" || um.UnderlyingInstrumentType === "StockIndex") { if (!trade.DividendRate) { trade.DividendRate = 0; } trade.IsUsePremiumRate = trade.TradeType!=='累计期权'; //名义本金影响交易数量 self.changeStockEqvNotional(1e6); if (trade.IsMoneynessOption !== "是" || !trade.Strike) { trade.Strike = pricingFormat.umprice(um.Price); self.showPercentStrike(); instTypeChanged = true; } } else { trade.IsUsePremiumRate = false; self.changeTradeAmount(instTypeChanged ? 1 : null); if (trade.IsMoneynessOption === "是" || !trade.Strike) { trade.Strike = "1"; self.showAbsStrike(); instTypeChanged = true; } } //如果资产大类变更则清除掉IsMoneynessOption和IsUsePremiumRate关联的字段值 instTypeChanged && tradeUtils.onChangeInstrumentType(trade); //到期日ExerciseDate默认为1个月之后,股票到期日不显示 trade.TradeDate = pageVue.SysDate; trade.ExerciseDate = new moment(um.ExerciseDate).format("YYYY-MM-DD"); trade.MaturityDate = new moment(um.MaturityDate || "2029-01-01").format("YYYY-MM-DD"); trade.TradeDate > trade.ExerciseDate && (trade.TradeDate = trade.ExerciseDate); if (trade.TradeType === "Risky期权") { if (trade.IsMoneynessOption === "是") { trade.Strike1 = ""; trade.Strike2 = ""; trade.Strike3 = 1; } else { trade.Strike1 = ""; trade.Strike2 = ""; trade.Strike3 = um.Price; } } self.changeTradeDate(true, true); if (pageData.is厦门象屿 || trade.TradeType === "Risky期权") { trade.PremiumPayDate = trade.ExerciseDate; } //重置计算结果 self.calcResult.reset(); if (fromSelect) { self.resetSummary(resetSummaryFlags.all); } }); }, //刷新波动率,影响波动率的属性:SpotPrice,Strike,TradeDate,ExerciseDate,UnderlyingId getVol(debounce) { if (this.trade.TradeType === "现金流交易") return; if (pageVue.IsTradeVol) { let flag = 0; if (!pageVue.SkewMapVol) { this.viewState.VolState !== 'user' && (flag |= 1); this.viewState.CloseVolState !== 'user' && (flag |= 2); if (flag === 0) return; } else { flag = 1 | 2; } if (debounce === true) { if (!this.debounceGetVol) { this.debounceGetVol = _.debounce(function (t) { (t.flag & 1) > 0 && t.vue.getTradeOpenVolatility(); (t.flag & 2) > 0 && t.vue.getTradeCloseVolatility(); }, 1000, { trailing: true }); } this.debounceGetVol({ vue: this, flag: flag }); } else { (flag & 1) > 0 && this.getTradeOpenVolatility(); (flag & 2) > 0 && this.getTradeCloseVolatility(); } } else if (this.viewState.VolState !== 'user') { this.getTradeOpenVolatility(); } }, //重置统计数据 resetSummary(flag) { this.$emit('reset-summary', flag); }, //获取标的价格(计算用) getUnderlyingPrice() { var self = this; return main.post("/pricing/AjaxGetUnderlyingPrice", { underlyingCode: this.trade.UnderlyingCode, tradeDate: this.trade.ValueDate }) .done(function (resp) { self.trade.UnderlyingPrice = pricingFormat.umprice(resp.obj.price); }); }, //精简模式切换时的处理 onSimpleModeChanged() { this.trade.UnderlyingPrice = ''; } }, computed: { ...consVueTrade.computed }, components: { 'vue-margintemplatename': vueMarginTemplateName(), 'vue-niceselect': FastVue.vueNiceSelect(), 'vue-variety': vueVariety(), 'vue-tradetype': vueTradeType(), 'vue-underlying': vueUnderlying(), 'vue-datepicker': FastVue.vueDatePicker(), 'vue-number-input': FastVue.vueNumberInput(), 'vue-daycount': vueDayCount(), 'vue-client': vueClient(), }, render: renders.item(), staticRenderFns: renders.item(true), destroyed() { delete consSyntheticMap[this.trade.calcId]; topVue.simpleMode && (this.trade.UnderlyingPrice = ''); EventBus.removeEventListener('simpleMode.changed', this.onSimpleModeChanged); } }; }; //单个定价组件(现金流) const vueTrade2 = function () { return { props: ['trade', 'viewState', 'calcResult', 'floating'], data() { return { isTitle: false, ...consVueTrade.data(), fieldState: tradeFieldMgr.getFieldState(this.floating), }; }, watch: { 'trade.ExerciseDate': { handler(newVal, oldVal) { this.trade.SettlementDate = newVal; }, immediate: false } }, mounted() { if (pageVue.ClientUsedForCalc) { if (!this.trade.ClientId) { ylotc.clients.length && (this.trade.ClientId = ylotc.clients[0].id); if (this.trade.ClientId) { this.changeClient(); } } else { this.updateKey.client = new Date().getTime(); } } this.fieldState.onTradeTypeChanged(this.trade, null, this); this.trade.IsUsePremiumRate = true; }, methods: { ...consVueTrade.methods, //变更客户 changeClient() { this.$emit('change-client', this.trade.ClientId); }, //重置统计数据 resetSummary(flag) { this.$emit('reset-summary', flag); } }, computed: { ...consVueTrade.computed }, components: { 'vue-niceselect': FastVue.vueNiceSelect(), 'vue-client': vueClient(), 'vue-datepicker': FastVue.vueDatePicker(), 'vue-number-input': FastVue.vueNumberInput(), 'vue-daycount': vueDayCount(), }, render: renders.itemCash(), staticRenderFns: renders.itemCash(true), destroyed() { } }; }; //主视图定价头部拖动处理 const mainDragScroll = dragScroll.create({ container: '.pricing-main', yscroll: false, throttle: _.throttle }); //定价组件组合 function createVue(index, baseVue, floating) { var datas = baseVue.datas; var fromLocal = baseVue.fromLocal === true; if (datas.length < 1) { return main.alert('缺少数据'); } var structureType = baseVue.combining && datas.length > 1 ? '结构化交易' : baseVue.structureType || ''; _.each(datas, (data, index2) => { data.trade.CalcId = index + '-' + (index2 + 1); if (!data.calcResult) { data.calcResult = { sourceData: null, reset(data) { this.sourceData = data; if (!data) { _.each(consCalcFields, x => this[x] = ''); } } }; _.each(consCalcFields, x => data.calcResult[x] = ''); } else if (baseVue.combining) { data.calcResult = _.cloneDeep(data.calcResult); } if (!data.trade.UnderlyingInstrumentType) { data.trade.UnderlyingInstrumentType = pageVue.StockFirst ? 'Stock' : 'CommodityFutures'; } data.trade.StructureType = structureType; }); if (datas.length === 1) { datas[0].trade.CalcId = index.toString(); } var debounceFloatSinglePrice = _.debounce(singlePricer.calcSinglePrice, 300); var vue = new Vue({ data: { index: index, datas: datas, floating: floating, isSelected: !!baseVue.isSelected, structureType: structureType, showFloatingIcon: !structureType || datas.every(x => x.trade.TradeType === '香草期权') }, computed: { }, mounted() { if (this.floating) { var singlePrice = singlePricer.calcSinglePrice(this.convertForSinglePrice()); singlePrice && $('#singleprice2').text(singlePrice); } else { pricingVue.onMountd(this); } }, methods: { getData(index) { return this.datas[index || 0]; }, getVol() { _.each(this.$children, x => x.getVol()); }, remove(blRemoveChain) { this.$destroy(); this.$el.remove(); pricingVue.remove(this, blRemoveChain); }, saveTrade() { tradeSaver.saveTrades([this]); }, showFloatVue() { floatVue.show(this); let td = this.getData(0); setTimeout(function () {//交易详情页-定价增强价格不显示问题 if (td && td.trade.TradeType == "亚式期权" && td.trade.StrikeType != "Floating" && td.trade.PayoffType == 'EnhancedArithmeticAverage') { $("#EnhancedPriceTitle").show(); } }, 500); }, screenshot() { screenshoter.execute(this); }, uncouple() { pricingVue.uncouple(this); }, convertForSinglePrice() { return _.reduce(this.datas, (result, data) => { var sdata = data.calcResult.sourceData; sdata && (result || (result = [])).push({ Pv: sdata.Pv, Notional: data.trade.Notional }); return result; }, null); }, //重置统计数据 resetSummary(flag) { //浮窗页面 if (this.floating && flag < resetSummaryFlags.ten) { var singlePrice = singlePricer.calcSinglePrice(this.convertForSinglePrice()); singlePrice && $('#singleprice2').text(singlePrice); } //主页面 if (this.isSelected) { if (flag === resetSummaryFlags.initialMargin) { var data = this.datas[this.datas.length - 1]; data.calcResult.TotalMargin = pageVue.GetTotalMargin(_.map(this.datas, x => x.trade), this.structureType); return summaryVue.reset(this.index, this.datas.map(x => x.calcResult)); } singlePricer.reset(this.index, this.convertForSinglePrice()); if (flag !== resetSummaryFlags.notional) { summaryVue.reset(this.index, this.datas.map(x => x.calcResult)); } } else if (flag === true) { summaryVue.reset(this.index, null); singlePricer.reset(this.index, null); } }, setCalcResult(result) { var data = _.find(this.datas, x => x.trade.CalcId === result.CalcId); if (!data) { return main.alert('系统错误'); } var trade = data.trade; if (topVue.calcMargin) { if (data.viewState.InitialMargin !== 'user' || (data.viewState.InitialMargin === 'user' && trade.InitialMargin === '')) { if (pageVue.ClientUsedForCalc && pageVue.TwoSideMargin && !data.viewState.TwoSideMargin && result.initialMargin < 0 && !trade.StructureType) { trade.InitialMargin = 0; } else { trade.InitialMargin = pricingFormat.tradePrice(result.initialMargin); } data.viewState.InitialMargin = "system"; } } else { trade.InitialMargin = ''; } var calcResult = data.calcResult; var contractSize = result.contractSize; //对象缩小为具体计算结果 result = result.calcResult; calcResult.reset(result); //用于统计 calcResult.UnderlyingCode = trade.UnderlyingCode; if (trade.IsUsePremiumRate) { trade.TradePrice = result.Pv * (trade.BuySell == "买入" ? 1 : -1); if (trade.TradeType !== "现金流交易") { //根据总额算出期权费率 tradePricing.tradeCalc(trade, tradePricing.calcReason.Pv); //由于期权费率会有精度损失,进行了四舍五入处理,需要再根据期权费率反算出期权费总额 //因为录入交易时是根据期权费率作为标准的 tradePricing.tradeCalc(trade, tradePricing.calcReason.PremiumRate); } else { trade.TradePrice = pricingFormat.tradePrice(trade.TradePrice); } } else { let notional = trade.Notional; if (trade.TradeType == "累计期权") { var datas = { kOObservationDates: trade.KOObservationDates, valueDate: trade.ValueDate || trade.TradeDate, tradeDate: trade.TradeDate, exerciseDate: trade.ExerciseDate, } var dayCount = 0; main.post("/trade_cash/GetAccTradeUnwindDayCount", datas, { async: false }).done( function (res) { dayCount = res.obj; } ); notional = dayCount * trade.AccumuTradeAmount; trade.Notional = notional; } var pv = result.Pv * (trade.BuySell == "买入" ? 1 : -1); trade.TradeSinglePrice = notional ? pv / notional : 0; tradePricing.tradeCalc(trade, tradePricing.calcReason.TradeSinglePrice); } if (pageObj.IsPVIncludePrincipal && trade.OriginalPrincipalSum > 0) { result.Pv += trade.OriginalPrincipalSum * (trade.BuySell === '卖出' ? -1 : 1); result.PvContainsKnockOut += trade.OriginalPrincipalSum * (trade.BuySell === '卖出' ? -1 : 1); } //todo:光子模式下是否要重设TradeOpenVolatility的值 // delta gamma 用手数,其它份额 Vega,pho份额*100 qdp用的是份额计算 //现在计算的是数量 份额数量比 //手数 = 交易数量 / 交易单位 (5吨 / 手) //交易数量 = 份额 / 比率 //手数 = 份额 / (比率 * 交易单位) //TradeUnitValue 是手数对份额的比率 鸡蛋时为 10 var variety = data.viewState.variety; var fe_ration = 1; !contractSize && (contractSize = variety && variety.ContractSize ? variety.ContractSize : 1); calcResult.Pv = pricingFormat.tradePrice(result.Pv); calcResult.Delta = pricingFormat.greek(result.Delta); calcResult.Gamma = pricingFormat.greek(result.Gamma); calcResult.DeltaInLots = pricingFormat.greek(result.Delta / contractSize); calcResult.GammaInLots = pricingFormat.greek(result.Gamma / contractSize); calcResult.Theta = pricingFormat.greek(fe_ration * result.Theta); calcResult.Vega = pricingFormat.greek(fe_ration * result.Vega); calcResult.Rho = pricingFormat.greek(fe_ration * result.Rho * 100); calcResult.DeltaCash = pricingFormat.greek(result.DeltaCash); calcResult.GammaCash = pricingFormat.greek(result.GammaCash); calcResult.VegaCash = pricingFormat.greek(result.VegaCash); calcResult.PvContainsKnockOut = pricingFormat.tradePrice(result.PvContainsKnockOut); calcResult.DeltaContainsKnockOut = pricingFormat.greek(result.DeltaContainsKnockOut); calcResult.GammaContainsKnockOut = pricingFormat.greek(result.GammaContainsKnockOut); calcResult.Delta_r = result.Delta_r != null ? pricingFormat.greek(result.Delta_r) : ""; calcResult.Delta_r_1bp = result.Delta_r_1bp != null ? pricingFormat.greek(result.Delta_r_1bp) : ""; calcResult.Dv01 = result.Dv01 != null ? pricingFormat.greek(result.Dv01) : ""; calcResult.Gamma_r = result.Gamma_r != null ? pricingFormat.greek(result.Gamma_r) : ""; calcResult.Gamma_r_1bp = result.Gamma_r_1bp != null ? pricingFormat.greek(result.Gamma_r_1bp) : ""; calcResult.Vega_r = result.Vega_r != null ? pricingFormat.greek(result.Vega_r) : ""; calcResult.Vega_r_1bp = result.Vega_r_1bp != null ? pricingFormat.greek(result.Vega_r_1bp) : ""; calcResult.Vega_1bp = result.Vega_1bp != null ? pricingFormat.greek(result.Vega_1bp) : ""; calcResult.TotalMargin = 0; if (data === this.datas[this.datas.length - 1]) { calcResult.TotalMargin = pageVue.GetTotalMargin(_.map(this.datas, x => x.trade), this.structureType); } this.resetSummary(resetSummaryFlags.all); }, changeClient(clientId) { let client = null; if (pageVue.ClientUsedForCalc && pageVue.TwoSideMargin) { client = ylotc.clients.find(y => y.id === clientId); } _.each(this.datas, x => { x.trade.ClientId = clientId; x.trade.MarginOptionType = client.MarginOptionType; x.viewState.TwoSideMargin = client && client.MarginOptionType === 1; x.trade.MarginTemplateName = client.MarginOptionType === 3 ? "无预付金" : "系统默认"; tradeUtils.changeMarginTemplate(x.trade, []); }); }, updateSynthetic(calcId, synthetic) { var index = this.datas.findIndex(x => x.trade.CalcId === calcId); if (index < 0) return false; this.datas[index].trade.SpotPrice = synthetic.Price; this.$children[index].changeSpotPrice(true); return true; }, copyThis() { pricingVue.copyItem(this); } }, components: { 'vue-trade': vueTrade(), 'vue-trade2': vueTrade2(), }, destroyed() { if (!this.floating && this.isSelected) { summaryVue.reset(this.index, null); singlePricer.reset(this.index, null); } }, render: renders.items(), staticRenderFns: renders.items(true) }); if (!baseVue.combining && !baseVue.selfMount) { if (vue.floating) { vue.$mount($('
').appendTo('#pricing-items2').get(0)); } else if (fromLocal) { vue.$mount($('
').appendTo('#pricing-items').get(0)); } else { vue.$mount($('
').prependTo('#pricing-items').get(0)); } } !floating && mainDragScroll.reset(); return vue; } function _setAutocomplete(elId, datas, initData, onSelectFn) { initData = initData || {}; if (elId === "GroupClientId") { groupVue.trade.ClientId = initData.id; groupVue.trade.ClientName = initData.Name; } else if (elId === "GroupAssetId") { groupVue.trade.AssetId = initData.id; groupVue.trade.AssetBookName = initData.Name; } else if (elId === "GroupTraderId") { groupVue.trade.TraderId = initData.id; groupVue.trade.TraderName = initData.Name; } FastVue.autocomplete(document.getElementById(elId), { valueField: 'Name', searchField: ['Name', 'PinYin'], lookup: datas, onSelect(data) { $('#' + elId).data('id', data.id); if (elId === "ClientId" || elId === "GroupClientId") { if (!pageVue.ClientUsedForCalc || elId === "GroupClientId") { $("#selIsCentralClearing").val(data.IsCentralClearing); $("#selCentralClearingPaltform").val(data.CentralClearingPaltform); $("#selTradingPaltform").val(data.TradingPaltform); } _setSalesman(); } onSelectFn && onSelectFn(data); }, zIndex: 300000 }).setData(initData); $('#' + elId).data('id', initData.id); } function _setSalesman() { if (pageVue.ClientUsedForCalc) { var IsCentralClearing = $("#txtCurrentClient").attr("data-IsCentralClearing"); var CentralClearingPaltform = $("#txtCurrentClient").attr("data-CentralClearingPaltform"); var TradingPaltform = $("#txtCurrentClient").attr("data-TradingPaltform"); $("#IsCentralClearing").val(IsCentralClearing); $("#CentralClearingPaltform").val(CentralClearingPaltform); $("#TradingPaltform").val(TradingPaltform); } if ($("#ClientId").data('id') && _salesCommissionCtrl) { _salesCommissionCtrl.changeSalesmen($("#ClientId").data('id')); _getMainProtocolCode($("#ClientId").data('id')); } } function _changeMainProtocolCode() { _getSupProtocolCode(); } function _getMainProtocolCode(client) { $("#MainProtocolCode option").remove(); if (client) { let clientId = typeof client === 'object' ? client.id : client; main.post("/Client/getMainProtocolCodes", { clientId: clientId }, { async: false }).done(function (resp) { var obj = $("#MainProtocolCode"); _.forEach(resp, (v) => { obj.append(""); }) }); } _getSupProtocolCode() } function getSelectTags() { var tags = new Array(); $(".tag-context .tag-item").each(function (i, v) { var exist = false; var name = $(v).data("name"); tags.forEach(function (o) { if (o.Name == name) { exist = true; } }); if (!exist) { tags.push({ Id: $(v).data("id"), Name: name }); } }); return tags; } function _getSupProtocolCode() { $("#SupProtocolCode option").remove(); if ($("#MainProtocolCode").val()) { main.post("/Client/getSideProtocols", { mainProtocol: $("#MainProtocolCode").val() }, { async: false }).done(function (resp) { var obj = $("#SupProtocolCode"); _.forEach(resp, (v) => { obj.append(""); }) }); } } function CalcResultShowCfg() { var srcurl = "/CalcPriceShowCfg/Index"; main.open("计算指标显示设置", srcurl, { area: ["800px", "700px"] }); } //定价组件 const pricingVue = (function () { //创建定价标题组件 function createTitleVue(el, floating) { var vue = new Vue({ el: el, data: { trade: {}, isTitle: true, floating: floating, fieldState: tradeFieldMgr.getTitleState(floating) }, render: renders.title(), staticRenderFns: renders.title(true) }); return vue; } createTitleVue('#pricing-titles', false); createTitleVue('#pricing-titles2', true); var _index = 1; //定价组件集合 const _tradeVues = []; function __clear() { if (!_tradeVues.length) return; _index = 0; _tradeVues.splice(0, _tradeVues.length).forEach(x => x.remove()); $('#pricing-items').parent().floatingScroll('update'); } //清空 function clear(force) { if (!_tradeVues.length) return; if (force) { __clear(); } else { main.confirmV2("确认清空吗?").done(__clear); } } //移除 function remove(tradeVue, blRemoveChain) { if (blRemoveChain && tradeVue.floating) { var baseVue = _tradeVues.find(x => x.index === tradeVue.index); baseVue && baseVue.remove(); } _.pull(_tradeVues, tradeVue); $('#pricing-items').parent().floatingScroll('update'); } //新增单腿 function addTrade(trade, tradeType) { _index += 1; let baseVue = _tradeVues[0] || { datas: [tradeFieldMgr.defaultData] }; if (trade && typeof trade === 'object') { let viewState = _.cloneDeep(tradeFieldMgr.defaultData.viewState); viewState.initFlag = 'import1'; baseVue = { datas: [{ trade: trade, viewState: viewState }] }; } else if (tradeType === "现金流交易") { let data = tradeFieldMgr.defaultData; data = { trade: _.cloneDeep(data.trade), viewState: _.cloneDeep(data.viewState) }; _tradeVues.length < 1 && (data.viewState.initFlag = 'first'); data.trade.IsUsePremiumRate = true; baseVue = { datas: [data] }; trade = data.trade; } else { let data = baseVue.datas[0]; data = { trade: _.cloneDeep(data.trade), viewState: _.cloneDeep(data.viewState) }; _tradeVues.length < 1 && (data.viewState.initFlag = 'first'); baseVue = { datas: [data] }; trade = data.trade; } if (typeof tradeType === 'string' && trade.TradeType !== tradeType) { trade.TradeType = tradeType; tradeFieldMgr.initFieldValue(trade); } if (trade.TradeAmount && !trade.TradeAmountV) { trade.TradeAmountV = tradeHelper.getTradeAmountV(trade); } let vue = createVue(_index, baseVue); _tradeVues.unshift(vue); if (pageVue.IsImport || !new Array('香草期权', '合成价差期权').includes(trade.TradeType)) { floatVue.show(vue); } } //复制项目 function copyItem(tradeVue) { var arrIndex = _.indexOf(_tradeVues, tradeVue); if (arrIndex < 0) { throw '系统错误'; } _index += 1; let baseVue = tradeVue; baseVue = { datas: _.cloneDeep(baseVue.datas), structureType: baseVue.structureType, selfMount: true }; var vue = createVue(_index, baseVue); vue.$mount($('
').insertBefore(tradeVue.$el).get(0)); _tradeVues.splice(arrIndex, 0, vue); } //新增策略 function addTrades(trades) { var datas = _.map(trades, trade => { trade = _.transform(trade, (result, val, key) => { key in result && (result[key] = val); }, _.cloneDeep(pageVue.Trade)); if (trade.UnderlyingInstrumentType !== 'Stock' && trade.UnderlyingInstrumentType !== 'StockIndex') { trade.StockEqvNotionalReal = pricingFormat.StockEqvNotional(trade.Notional * trade.SpotPrice); trade.StockEqvNotional = trade.StockEqvNotionalReal; } else { trade.StockEqvNotionalReal = trade.StockEqvNotional; } trade.SpotPrice = trade.UnderlyingPrice; trade.NoRiskRate = null; trade.DividendRate = 0; trade.ParticipationRate = 1; trade.AnnualizeFactor = 1; if (pageVue.NumOfSmoothingDaysCfg === 'ONE' && pageVue.IsTradeVol) { trade.NumOfSmoothingDays = 1; } tradeUtils.normalizeTrade(trade); let viewState = _.cloneDeep(tradeFieldMgr.defaultData.viewState); viewState.initFlag = 'import2'; return { trade: trade, viewState: viewState }; }); _index += 1; var vue = createVue(_index, { datas: datas, structureType: pageVue.getStructureType() }); _tradeVues.unshift(vue); } //自由组合 function combine() { var comVues = _.filter(_tradeVues, x => x.isSelected); if (comVues.length < 2) { return main.alert('请选择至少两项进行组合!'); } var firstVue = comVues[0]; var datas = _.flatMap(comVues.map(x => x.datas)); if (pageVue.ClientUsedForCalc) { var clientId = parseInt(datas[0].trade.ClientId); if (!_.every(datas, x => parseInt(x.trade.ClientId) === clientId)) { return main.alert('所选项客户必须一致!'); } } var vue = createVue(firstVue.index, { combining: true, datas: datas, fromLocal: true }); vue.$mount($('
').insertBefore(firstVue.$el).get(0)); var index = _.indexOf(_tradeVues, firstVue); _tradeVues[index] = vue; _.pullAll(_tradeVues, comVues); comVues.forEach(x => x.remove()); } //取消组合 function uncouple(tradeVue) { if (!tradeVue || tradeVue.floating) { throw '系统错误'; } var arrIndex = _.indexOf(_tradeVues, tradeVue); if (arrIndex < 0) { throw '系统错误'; } var index = _index += tradeVue.datas.length; var map = _.map(tradeVue.datas, data => { var vue = createVue(index--, { combining: true, datas: [data], fromLocal: true }); vue.$mount($('
').insertBefore(tradeVue.$el).get(0)); return vue; }); var args = [arrIndex, 1].concat(map); Array.prototype.splice.apply(_tradeVues, args); tradeVue.remove(); } //波动率类型变更 function changeVolType() { _tradeVues.forEach(x => x.getVol()); } //获取所有交易数据 function getTrades() { return _.flatMap(_tradeVues.map(x => x.datas)).map(x => x.trade); } //录入交易 function saveTrades() { tradeSaver.saveTrades(_tradeVues.filter(x => x.isSelected)); } //录入组合交易 function saveGroupTrades() { tradeSaver.saveGroupTrades(_tradeVues.filter(x => x.isSelected)); } //定价计算 function calcPrice(tradeVues) { !tradeVues && (tradeVues = _tradeVues); if (!tradeVues.length) { return main.alert("请至少录入一个交易"); } var trades = _.flatMap(tradeVues, x => x.datas).map(x => x.trade); //检查并转换数据 trades = tradeUtils.prepareTrades(trades, pageVue.getVolType(), false); if (trades) { let data = { version: pageVue.CalcVersion, trades: trades, calcMargin: topVue.calcMargin, calcAutocallGreeks: topVue.calcAutocallGreeks }; main.post("/pricing/ajaxCalcPrices", data).done(function (resp) { //tradeVues转换为calcId为key的字典 var map = tradeVues.reduce((result, cur) => { _.each(cur.datas, x => { result[x.trade.CalcId] = cur; }); return result; }, {}); //设置计算结果 _.each(resp.obj, item => { map[item.CalcId].setCalcResult(item); }); }); } } //显示组合到期收益曲线图形 function showPayoffLineChart(tradeVues) { var selectVues = _.filter(_tradeVues, x => x.isSelected); !tradeVues && (tradeVues = selectVues); if (!tradeVues.length) { return main.alert("请至少录入一个交易"); } var trades = _.flatMap(tradeVues, x => x.datas).map(x => x.trade); //检查并转换数据 trades = tradeUtils.prepareTrades(trades, pageVue.getVolType(), false); window.sessionStorage.removeItem("pricing_payoff_line"); if (trades) { main.post("/pricing/GetTradesPayoffLine", { trades: trades }).done(function (resp) { //resp.obj window.sessionStorage.setItem("pricing_payoff_line", JSON.stringify(resp)); window.open("/Statics/html/PayoffChart.html"); }); } } //显示组合Pv曲线 function showPvChart(tradeVues) { var selectVues = _.filter(_tradeVues, x => x.isSelected); !tradeVues && (tradeVues = selectVues); if (!tradeVues.length) { return main.alert("请至少录入一个交易"); } var trades = _.flatMap(tradeVues, x => x.datas).map(x => x.trade); //检查并转换数据 trades = tradeUtils.prepareTrades(trades, pageVue.getVolType(), false); window.sessionStorage.removeItem("pricing_pv_line"); if (trades) { main.post("/pricing/GetTradesPvLine", { trades: trades }).done(function (resp) { //resp.obj window.sessionStorage.setItem("pricing_pv_line", JSON.stringify(resp)); window.open("/Statics/html/PvChart.html"); }); } } function showLifeLineChart(tradeVues) { var selectVues = _.filter(_tradeVues, x => x.isSelected); !tradeVues && (tradeVues = selectVues); if (!tradeVues.length) { return main.alert("请至少选择一笔交易"); } var trades = _.flatMap(tradeVues, x => x.datas).map(x => x.trade); //检查并转换数据 trades = tradeUtils.prepareTrades(trades, pageVue.getVolType(), false); window.sessionStorage.removeItem("pricing_life_lines"); if (trades) { main.post("/pricing/GetTradesLifePvLine", { trades: trades }).done(function (resp) { //resp.obj window.sessionStorage.setItem("pricing_life_lines", JSON.stringify(resp)); window.open("/Statics/html/PvLifeChart.html"); }); } } //显示Greeks变化曲线 function showGreeksChart(tradeVues) { var selectVues = _.filter(_tradeVues, x => x.isSelected); !tradeVues && (tradeVues = selectVues); if (!tradeVues.length) { return main.alert("请至少选择一笔交易"); } var trades = _.flatMap(tradeVues, x => x.datas).map(x => x.trade); //检查并转换数据 trades = tradeUtils.prepareTrades(trades, pageVue.getVolType(), false); window.sessionStorage.removeItem("pricing_greeks_line"); if (trades) { main.post("/pricing/GetTradesGreeksForLifetime", { trades: trades }).done(function (resp) { //resp.obj window.sessionStorage.setItem("pricing_greeks_line", JSON.stringify(resp)); window.open("/Statics/html/GreeksChart.html"); }); } } //打开历史回测页面 function openHistoricalBacktest(tradeVues) { layer.open({ type: 2, title: "报价管理-历史回测工具", shadeClose: false, shade: 0.4, area: ['1200px', '560px'], content: "/pricing/HistoricalBacktest?isLayer=true" }); } //设置观察数据 function setObservation(observationNum, observationUnit, observationHolidayType, observationDates, alignEnd, calcId, couponDayInterval) { if (!calcId) return; let _data = null, calcId2 = calcId.replace(/#.*$/, ""); _.each(_tradeVues, vue => { return !(_data = _.find(vue.datas, data => data.trade.CalcId === calcId2)); }); _data && consVueTrade.methods.setObservation.apply(_data, arguments); } //对冲下单 function hedgingOrder() { var comVues = _.filter(_tradeVues, x => x.isSelected); if (comVues.length < 1) { return main.alert('请至少选择一项!'); } var datas = _.flatMap(comVues.map(x => x.datas)); var instType = datas[0].trade.UnderlyingInstrumentType; if (!_.every(datas, x => x.trade.UnderlyingInstrumentType === instType)) { return main.alert('所选项标的类型必须一致!'); } var rd = _.reduce(datas, (acc, cur) => { var code = cur.trade.UnderlyingCode; var delta = acc[code]; acc[code] = (delta || 0) + (parseFloat(cur.calcResult.Delta) || 0); return acc; }, {}); var items = _.reduce(rd, (acc, value, key) => { var index = acc.length / 2; acc.push(''); acc.push(''); return acc; }, []); items.push(''); $('#orderForm').html(items.join("")).submit(); } //浏览器本地数据缓存 const localData = (new function () { if (pageVue.IsImport) { this.save = $.noop; this.load = $.noop; return; } this.save = function () { var vueDatas = _tradeVues.map(x => new Object({ index: x.index, structureType: x.structureType, datas: x.datas.map(data => new Object({ trade: data.trade, viewState: data.viewState })) })); var data = { index: _index, VolType: pageVue.getVolType(), SysDate: pageVue.SysDate, vueDatas: vueDatas, time: new Date().getTime() }; var json = JSON.stringify(data); localStorage.setItem("pricing-structure-" + pageVue.UserId, json); }; this.load = function () { //设置默认值 var saveKey = "pricing-structure-" + pageVue.UserId; var storage = localStorage.getItem(saveKey); if (!storage) return; var data = JSON.parse(storage); if (pageVue.SysDate !== data.SysDate || new Date().getHours > 18 && new Date(data.time).getHours() < 18) { //需要清空缓存 localStorage.removeItem(saveKey); } else { _index = data.index; pageVue.setVolType(data.VolType); _.each(data.vueDatas, function (x) { x.fromLocal = true; var vue = createVue(x.index, x); _tradeVues.push(vue); }); } }; }()); //持久化定价数据 $(window).on('beforeunload', localData.save); $(localData.load); return { clear: clear, remove: remove, addTrade: addTrade, copyItem: copyItem, combine: combine, changeVolType: changeVolType, saveTrades: saveTrades, saveGroupTrades: saveGroupTrades, calcPrice: calcPrice, showPayoffLineChart: showPayoffLineChart, showPvChart: showPvChart, showGreeksChart: showGreeksChart, showLifeLineChart: showLifeLineChart, openHistoricalBacktest: openHistoricalBacktest, getTradeVues(onlySelected) { return onlySelected ? _tradeVues.filter(x => x.isSelected) : _tradeVues; }, getTradeVue(index) { return _tradeVues[index || 0]; }, saveLocalData: localData.save, setOption: addTrades, //用于和老版兼容 setObservation: setObservation, uncouple: uncouple, hedgingOrder: hedgingOrder, onMountd(vue) { _tradeVues.length && $('#pricing-items').parent().floatingScroll(); }, swap(oldIndex, newIndex) { if (oldIndex === newIndex) return; let vue = _tradeVues[oldIndex]; _tradeVues.splice(oldIndex, 1); _tradeVues.splice(newIndex, 0, vue); }, //新增模板 addTemplate(tplItems) { tplItems.forEach(x => { x.datas.forEach(d => { d.viewState = _.cloneDeep(tradeFieldMgr.defaultData.viewState); d.viewState.initFlag = 'template'; }); _index += 1; var vue = createVue(_index, x); _tradeVues.unshift(vue); }); } }; }()); //浮窗定价组件 const floatVue = (function () { var _tradeVue; //关闭浮窗 function hide() { if (_tradeVue) { _tradeVue.remove(); _tradeVue = null; } $('#floatModal').modal('hide'); $(document.body).removeClass('has-float'); if (pageVue.IsImport) { layer.closeMe(); } } //显示浮窗index, trade, viewState function show(baseVue, forScreenshot) { _tradeVue && _tradeVue.remove(); _tradeVue = createVue(baseVue.index, baseVue, true); $(document.body).toggleClass('has-float', !forScreenshot); $('#floatModal').modal('show'); } function screenshot() { screenshoter.execute(_tradeVue); } return { show: show, hide: hide, calcPrice() { _tradeVue && pricingVue.calcPrice([_tradeVue]); }, saveTrade() { _tradeVue && _tradeVue.saveTrade(); }, screenshot: screenshot, getVue() { return _tradeVue; } }; }()); //dom ready function $(function () { tradeSaver.init(); groupVue.init(); //解决上层popover不能编辑的问题 $('#floatModal').on('shown.bs.modal', function () { $(document).off('focusin.modal'); }); $(".search-label").addClass("formlabel"); $(".formlabel").addClass("search-label"); var sortable = Sortable.create(document.getElementById('pricing-items'), { handle: '.pricing-index-drag', onEnd: function (evt) { pricingVue.swap(evt.oldIndex, evt.newIndex); }, }); if (pageVue.IsImport) { let trade = _.cloneDeep(pageVue.Trade); pricingVue.addTrade(trade); setTimeout(function () {//交易详情页-定价增强价格不显示问题 if (trade.TradeType == "亚式期权" && trade.StrikeType != "Floating" && trade.PayoffType == 'EnhancedArithmeticAverage') { $("#EnhancedPriceTitle").show(); } }, 500); } //#OTC-2651 $('#floatModal>.modal-dialog>.modal-content>.modal-body').on('scroll', _.debounce(function () { $(this).find('input.hasDatepicker').blur().datepicker('hide'); }, 500, { 'leading': true, 'trailing': false })); }); //用于和老版兼容 window.vue = pricingVue; //兼容定价计算页面观察日设置 var getObservationDatesSetting = pricingVue.setObservation; //连离类型:障碍(Discrete),二元(MonitorType,美式) //补偿类型:障碍(RebateType),二元(RebateType,美式) //定价模板 var templateVue = (function () { if (pageVue.IsImport) return; var debounceSearch; return new Vue({ el: '#modalTemplate', data: { saveMode: true, saveData: { name: '', id: 0, _override: true, _CommonTemplate: false }, listData: [], searchText: '' }, mounted() { this.refreshList(); debounceSearch = _.debounce(this.searchInner, 500); }, methods: { showSave() { let selVues = pricingVue.getTradeVues(true); if (!selVues.length) { return main.alert('请勾选要保存的定价数据'); } this.saveMode = true; this.saveData.name = ''; this.saveData.json = ''; $('#modalTemplate').modal('show'); }, showList() { this.saveMode = false; $('#modalTemplate').modal('show'); }, saveTemplate() { let selVues = pricingVue.getTradeVues(true); if (!selVues.length) { return main.alert('没有可保存的定价数据'); } let name = (this.saveData.name).trim(); if (!name) { return main.alert('请填写模板名称'); } let self = this; let vueDatas = selVues.map(x => new Object({ structureType: x.structureType, datas: x.datas.map(data => new Object({ trade: data.trade })) })); let dataJson = JSON.stringify(vueDatas); main.post('/pricing/AjaxSaveTemplate/v2', { name, dataJson, _override: this.saveData._override, _CommonTemplate: this.saveData._CommonTemplate }).done(function () { $('#modalTemplate').modal('hide'); self.refreshList(); self.searchInner(); }); }, removeTemplate(sysUserConfigId) { let $item = $(event.target).closest('.yt-template-item'); if (!$item) { return main.alert('系统错误,没有找到所选项'); } let self = this; let index = $item.prevAll().length; let names = [$item.children('a').text()]; main.confirmPost('确认要删除所选项"' + names[0] + '"吗?', '/pricing/AjaxRemoveTemplate', { sysUserConfigId }).done(function () { self.listData.splice(index, 1); }); }, loadTemplate() { let name = $(event.target).text(); let TemplateType = $(event.target).next().text(); function __do() { pricingVue.clear(true); main.post('/pricing/ajaxGetTemplate/v2', { name, TemplateType }).done(function (resp) { let items = JSON.parse(resp.obj); pricingVue.addTemplate(items); $('#modalTemplate').modal('hide'); }); } if (pricingVue.getTradeVues().length) { main.confirm("加载自定义模板将清空页面现有交易,是否继续?", __do); } else { __do(); } }, refreshList() { let self = this; this.searchText = ''; main.post('/pricing/AjaxGetTemplateList').done(function (resp) { self.listData = resp.obj.map(x => new Object({ id: x.id, name: x.ConfigName, show: true, UserId: x.UserId, ConfigType: x.ConfigType })); }); }, searchInner() { console.log('searchInner'); let text = this.searchText ? this.searchText.toLowerCase() : ''; this.listData.forEach(x => { x.show = !text || x.name.toLowerCase().indexOf(text) >= 0; }); }, searchList(action) { if (action === 'reset') { debounceSearch.cancel(); this.searchText = ''; this.searchInner(); } else { debounceSearch(); } } } }); }()); const customNumberFormat = { precision: 6, negative: true, }; const customNumberPercentFormat = { precision: 6, negative: true, append: '%' }; var groupVue = new Vue({ el: '#modalGroupTradeSave', data: { viewState: pageVue.viewState, ...consVueTrade.data(), trade: ylotc.trade, options: ylotc.options, structureTypes: pageObj.structureTypes, PropertyMap: pageObj.PropertyMap, }, computed: { ...consVueTrade.computed }, methods: { ...consVueTrade.methods, closeModal: function () { $('#modalGroupTradeSave').modal('hide'); $(".tag-context .tag-item").remove(); }, saveGroupTrade: function () { if (!_trades) return; _trades.forEach(x => { x.AssetId = this.trade.AssetId; x.AssetBookName = this.trade.AssetBookName; x.TraderId = this.trade.TraderId; x.TraderName = this.trade.TraderName; x.TradeNumber = this.trade.TradeNumber; x.SalesCommission = this.trade.salesCommission; x.ClientId = this.trade.ClientId; x.ClientName = this.trade.ClientName; if (x.TradePremium) { x.MetaDic["交易溢价"] = x.TradePremium; } x.MetaDic["交易场所"] = this.trade.TradingPlace; x.MetaDic["清算机构"] = this.trade.ClearingAgency; x.MetaDic["主协议编号"] = this.trade.MainProtocolCode; x.MetaDic["补充协议编号"] = this.trade.SupProtocolCode; x.MetaDic["中央对手方清算"] = $("#selIsCentralClearing").val(); x.MetaDic["中央清算平台"] = $("#selCentralClearingPaltform").val(); x.MetaDic["ExchangeRate"] = $("#selExchangeRate").val(); x.MetaDic["交易平台"] = $("#selTradingPaltform").val(); x.TradeType === '现金流交易' && tradeUtils.resetCashFlow(x); }); this.trade.Tags = getSelectTags(); if (this.trade.StructureType == "气囊结构") { this.trade.trade_airbag.KIParticipationRate = 1; } this.setExtendInfo(); main.post("/pricing/AjaxSaveGroupTrade", { trade: this.trade, subTrades: _trades }).done(function (resp) { if (pageVue.IsImport) { let url = "#/trade/tradeview?abstract=1&enid=" + resp.obj[0].EncryptId; layer.closeMe(url);//必须以#开头 } else { floatVue.hide(); $('#modalTradeSave').modal('hide'); _.each(_tradeVues, x => x.remove(true)); } $(".tag-context .tag-item").remove(); }); }, addNewProperty: function () { this.PropertyMap[this.trade.StructureType].push({ isNew: true, ColumnName: "", ColumnDefaultValue: "", ColumnType: 0 });//0:文本 }, deleteProperty: function (index) { this.PropertyMap[this.trade.StructureType].splice(index, 1); }, setExtendInfo: function () { var propertyList = []; this.PropertyMap[this.trade.StructureType].forEach((item, index) => { var note = { name: item.name || item.ColumnName, value: PercentColumnText.displayText(item) }; if (note.name) { propertyList.push(note); } }); this.trade.ExtendInfo = this.trade.StructureType == "气囊结构" ? null : JSON.stringify(propertyList); return this.trade.ExtendInfo; }, changeStrucTureType: function () { if (groupVue.trade.TradeType == "气囊结构") { groupVue.trade.trade_airbag.KIParticipationRate = 1; } else { groupVue.trade.OptionType = null; groupVue.trade.Strike = null; } }, changeBuySell: function () { groupVue.trade.TradePrice *= -1; groupVue.trade.TradeSinglePrice *= -1; groupVue.trade.PremiumRate *= -1; }, changeIsUsePremiumRate: function () { if (groupVue.trade.IsUsePremiumRate) { groupVue.changeStockEqvNotional(); } else { groupVue.changeTradeAmount(); } }, changeStockEqvNotional: function () { var notional = Math.abs(groupVue.trade.StockEqvNotional / groupVue.trade.SpotPrice); groupVue.trade.Notional = pricingFormat.notional(notional); groupVue.trade.TradeAmount = pricingFormat.notional(notional / groupVue.viewState.variety.CountRatio); groupVue.trade.TradeSinglePrice = pricingFormat.tradeSinglePrice(groupVue.trade.TradePrice / groupVue.trade.Notional); groupVue.trade.PremiumRate = pricingFormat.premiumRate(groupVue.trade.TradePrice / groupVue.trade.StockEqvNotional); }, changeTradeAmount: function () { var notional = groupVue.trade.TradeAmount * groupVue.viewState.variety.CountRatio; groupVue.trade.Notional = pricingFormat.notional(notional); groupVue.trade.StockEqvNotional = pricingFormat.stockEqvNotional(Math.abs(notional * groupVue.trade.SpotPrice)); groupVue.trade.TradeSinglePrice = pricingFormat.tradeSinglePrice(groupVue.trade.TradePrice / groupVue.trade.Notional); groupVue.trade.PremiumRate = pricingFormat.premiumRate(groupVue.trade.TradePrice / groupVue.trade.StockEqvNotional); }, init: function () { _setAutocomplete('GroupAssetId', ylotc.assetunits, null, function (data) { groupVue.trade.AssetId = data.id; groupVue.trade.AssetBookName = data.Name; }); var traders = $.grep(ylotc.traders, function (e) { return e.Name == pageVue.Trade.TraderName; }); let trader = pageVue.Trade.TraderId > 0 ? ylotc.traders.find(x => x.id === pageVue.Trade.TraderId) : null; if (!trader) { trader = { Name: "", id: 0 } } _setAutocomplete('GroupTraderId', ylotc.traders, { Name: trader.Name, id: trader.id }, function (data) { groupVue.trade.TraderId = data.id; groupVue.trade.TraderName = data.Name; }); var groupClientInitData = null; if (this.trade.ClientId > 0) { groupClientInitData = { id: this.trade.ClientId, Name: "" }; var client = ylotc.clients.find(y => y.id === this.trade.ClientId); groupClientInitData.Name = client.Name; $("#selIsCentralClearing").val(client.IsCentralClearing); $("#selCentralClearingPaltform").val(client.CentralClearingPaltform); $("#selTradingPaltform").val(client.TradingPaltform); } _setAutocomplete('GroupClientId', ylotc.clients, groupClientInitData, function (data) { pageVue.SecuritiesEnvironment ? _getMainProtocolCode : null; groupVue.trade.ClientId = data.id; groupVue.trade.ClientName = data.Name; }); }, changeOption: function () { this.PropertyMap[this.trade.StructureType].forEach(d => { if (d.ColumnName != undefined) { d.name = d.ColumnName; } if (d.ColumnDefaultValue != undefined) { d.value = d.ColumnDefaultValue; } }); } }, components: { 'vue-niceselect': FastVue.vueNiceSelect(), 'vue-client': vueClient(), 'vue-variety': vueVariety(), 'vue-margintemplatename': vueMarginTemplateName(), 'vue-tradetype': vueTradeType(), 'vue-underlying': vueUnderlying(), 'vue-datepicker': FastVue.vueDatePicker(), 'vue-number-input': FastVue.vueNumberInput(), 'vue-daycount': vueDayCount(), }, }); var extendVue = new Vue({ el: "#tradeSave_ExtendInfo", data: { ExtendMap: pageObj.ExtendMap, ExtendInfos: "", }, methods: { addNewProperty: function () { var map = this.ExtendMap[this.ExtendInfos]; map.push({ isNew: true, ColumnName: "", ColumnDefaultValue: "", ColumnType: 0 });//0:文本 }, deleteProperty: function (index) { var map = this.ExtendMap[this.ExtendInfos]; map.splice(index, 1); }, changeOption: function (index) { var map = this.ExtendMap[this.ExtendInfos]; map.forEach(d => { if (d.ColumnName != undefined) { d.name = d.ColumnName; } if (d.ColumnDefaultValue != undefined) { d.value = d.ColumnDefaultValue; } }); }, setExtendInfo: function (trade) { var propertyList = []; var key = this.ExtendInfos; if (key) { var map = this.ExtendMap; if (map[key]) { map[key].forEach((item, index) => { var note = { name: item.name || item.ColumnName, value: PercentColumnText.displayText(item) }; if (note.name) { propertyList.push(note); } }); } } trade.ExtendInfo = propertyList.length === 0 ? null : JSON.stringify(propertyList); if (trade.ExtendInfo) { trade.MetaDic["自定义要素模板"] = key; } else { trade.MetaDic["自定义要素模板"] = ""; } return trade.ExtendInfo; }, }, components: { 'vue-datepicker': FastVue.vueDatePicker(), 'vue-number-input': FastVue.vueNumberInput(), } }); var extendVue2 = new Vue({ el: "#tradeSave_ExtendInfo2", data: { ExtendMap: pageObj.ExtendMap, ExtendInfos: "", }, methods: { addNewProperty: function () { var map = this.ExtendMap[this.ExtendInfos]; map.push({ isNew: true, ColumnName: "", ColumnDefaultValue: "", ColumnType: 0 });//0:文本 }, deleteProperty: function (index) { var map = this.ExtendMap[this.ExtendInfos]; map.splice(index, 1); }, changeOption: function (index) { var map = this.ExtendMap[this.ExtendInfos]; map.forEach(d => { if (d.ColumnName != undefined) { d.name = d.ColumnName; } if (d.ColumnDefaultValue != undefined) { d.value = d.ColumnDefaultValue; } }); }, setExtendInfo: function (trade) { var propertyList = []; var key = this.ExtendInfos; if (key) { var map = this.ExtendMap; if (map[key]) { map[key].forEach((item, index) => { var note = { name: item.name || item.ColumnName, value: PercentColumnText.displayText(item) }; if (note.name) { propertyList.push(note); } }); } } trade.ExtendInfo = propertyList.length === 0 ? null : JSON.stringify(propertyList); if (trade.ExtendInfo) { trade.MetaDic["自定义要素模板"] = key; } else { trade.MetaDic["自定义要素模板"] = ""; } return trade.ExtendInfo; }, }, components: { 'vue-datepicker': FastVue.vueDatePicker(), 'vue-number-input': FastVue.vueNumberInput(), } });