- 添加 swapPricePrecisionHelper.js 工具类处理价格精度格式化 - 新增 swappriceprecision.js 配置文件定义各类金融产品的精度规则 - 在 EodPositionRisks.cshtml 和 SwapIncome.cshtml 中引入新的价格格式化脚本 - 替换原有的价格格式化函数为基于产品类型的动态精度控制 - 移除旧的价格验证和标准化逻辑,改用新的精度控制机制 - 添加 vue-swap-price-input 组件用于精确的价格输入控制 - 更新 Controller 中的价格处理逻辑以支持新精度格式化方式
221 lines
6.9 KiB
JavaScript
221 lines
6.9 KiB
JavaScript
//!!!通过/front/otcformat加载
|
||
//用于: 系统数据格式化
|
||
//依赖: lodash.js,main.numberFormat,/front/FormatOptions
|
||
//使用: otcformat.trading.price(number),otcformat.trading.openPrice(number)
|
||
|
||
var main = main || {};
|
||
|
||
(function (global) {
|
||
|
||
function getDefaultOption() {
|
||
return {
|
||
"trading": {
|
||
"umprice": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
},
|
||
"umpriceP": {
|
||
"percent": true,
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true
|
||
},
|
||
"umpricePR": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
},
|
||
"tradeSinglePrice": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
},
|
||
"premiumRateP": {
|
||
"percent": true,
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true
|
||
},
|
||
"premiumRate": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
},
|
||
"tradePrice": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
},
|
||
"StockEqvNotional": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
},
|
||
"notional": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
},
|
||
"notionalP": {
|
||
"percent": true,
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true
|
||
},
|
||
"volatility": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
},
|
||
"volatilityP": {
|
||
"percent": true,
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true
|
||
},
|
||
"greek": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
},
|
||
"marginRateP": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": true
|
||
},
|
||
"marginRate": {
|
||
"precision": 9,
|
||
"grouping": false,
|
||
"rounded": true,
|
||
"percent": false
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
var _fmtOptions = getDefaultOption();
|
||
|
||
if (main.formatOptions) {
|
||
for (const [k, v] of Object.entries(_fmtOptions)) {
|
||
_fmtOptions[k] = $.extend(v, main.formatOptions[k]);
|
||
}
|
||
}
|
||
|
||
(function () {
|
||
|
||
//对期权费率的百分比格式单独处理
|
||
let opt = _fmtOptions.trading.premiumRateP;
|
||
let precisionP = (typeof opt === 'object' ? opt.precision : opt);
|
||
if (!precisionP || precisionP < 0) {
|
||
precisionP = 0;
|
||
}
|
||
//百分数左半部分格式,例:0.12% => 0.12(precisionP=2)
|
||
_fmtOptions.trading.premiumRatePLeft = precisionP;
|
||
}());
|
||
|
||
//懒加载格式化函数
|
||
function getFormat(fmtOption) {
|
||
if (typeof fmtOption !== 'object') {
|
||
fmtOption = { precision: fmtOption };
|
||
}
|
||
let fn = function (number) {
|
||
if (!fmtOption._format) {
|
||
if (global.otcformat.options.disableGrouping) {
|
||
fmtOption.grouping = false;
|
||
}
|
||
fmtOption._format = main.numberFormat(fmtOption);
|
||
}
|
||
return fmtOption._format(number);
|
||
};
|
||
fn.precision = fmtOption.precision;
|
||
return fn;
|
||
}
|
||
|
||
const _format = {};
|
||
|
||
_.each(["trading"], grpName => {
|
||
let fmtGrp = {};
|
||
let optGrp = _fmtOptions[grpName];
|
||
_.forOwn(optGrp, (val, key) => {
|
||
let fn = getFormat(val);
|
||
fmtGrp[_.upperFirst(key)] = fn;
|
||
fmtGrp[_.lowerFirst(key)] = fn;
|
||
});
|
||
_format[grpName] = fmtGrp;
|
||
fmtGrp.mixin = function () {
|
||
return { filters: _.omit(fmtGrp, 'mixin') };
|
||
};
|
||
});
|
||
|
||
_format.fixed2 = main.numberFormat(2);
|
||
_format.fixed4 = main.numberFormat(4);
|
||
_format.fixed6 = main.numberFormat(6);
|
||
|
||
_format.fixed2P = main.numberFormat(2, { percent: true });
|
||
_format.fixed4P = main.numberFormat(4, { percent: true });
|
||
_format.fixed6P = main.numberFormat(6, { percent: true });
|
||
|
||
_format.options = {
|
||
disableGrouping: false //是否禁用千分位分组
|
||
};
|
||
|
||
_format.date = function (val) {
|
||
if (val) {
|
||
if (typeof val === 'string') {
|
||
return val.length > 10 ? val.substring(0, 10) : val;
|
||
}
|
||
if (_.isDate(val)) {
|
||
return val.getFullYear() + "-" + val.getMonth().toString().padStart(2, '0') + "-" + d.getDate().toString().padStart(2, '0');
|
||
}
|
||
return val.toString();
|
||
}
|
||
return '';
|
||
};
|
||
|
||
_format.flex = function (val, minDecimals, maxDecimals = 6
|
||
, percent = false, grouping = false, rounded = true) {
|
||
if (!val) return "";
|
||
if (typeof val !== "number") {
|
||
val = parseFloat(val);
|
||
if (!val) return val;
|
||
}
|
||
if (maxDecimals < minDecimals) {
|
||
maxDecimals = minDecimals;
|
||
}
|
||
//数值格式化
|
||
if (rounded !== false) {
|
||
let negative = val < 0;
|
||
val = _.round(negative ? -val : val, percent ? maxDecimals + 2 : maxDecimals);
|
||
negative && (val = -val);
|
||
} else {
|
||
val = _.floor(val, percent ? maxDecimals + 2 : maxDecimals);
|
||
}
|
||
if (isNaN(val)) return "NaN";
|
||
if (Math.abs(val) < 1e-6) return "0";
|
||
let fmt = new Intl.NumberFormat('en', {
|
||
useGrouping: grouping,
|
||
minimumFractionDigits: minDecimals,
|
||
maximumFractionDigits: maxDecimals,
|
||
style: percent ? 'percent' : 'decimal'
|
||
});
|
||
return fmt.format(val);
|
||
};
|
||
|
||
Object.freeze(_format);
|
||
Object.freeze(_format.trading);
|
||
|
||
global.otcformat = _format;
|
||
|
||
}(window));
|