diff --git a/YLErpWeb/Views/Pricing/Structure_DZ.cshtml b/YLErpWeb/Views/Pricing/Structure_DZ.cshtml index 18c7d47e..af6dcf67 100644 --- a/YLErpWeb/Views/Pricing/Structure_DZ.cshtml +++ b/YLErpWeb/Views/Pricing/Structure_DZ.cshtml @@ -85,6 +85,7 @@ + + + + @if (PS.Config.Is润和) { diff --git a/YLErpWeb/fe-tests/jest.config.js b/YLErpWeb/fe-tests/jest.config.js index f6877998..4723646b 100644 --- a/YLErpWeb/fe-tests/jest.config.js +++ b/YLErpWeb/fe-tests/jest.config.js @@ -30,6 +30,7 @@ module.exports = { '../wwwroot/Scripts/app/swaptrade/swapCalc.js', '../wwwroot/Scripts/app/swaptrade/unwindBondCalc.js', '../wwwroot/Scripts/app/swaptrade/swapPricePrecisionHelper.js', + '../wwwroot/Scripts/app/trade/percentColumnText.js', '../wwwroot/Scripts/fast/fastVue.base.js', // 逐步加入更多文件 ], diff --git a/YLErpWeb/fe-tests/percentColumnText.test.js b/YLErpWeb/fe-tests/percentColumnText.test.js new file mode 100644 index 00000000..91df8c72 --- /dev/null +++ b/YLErpWeb/fe-tests/percentColumnText.test.js @@ -0,0 +1,48 @@ +/** + * percentColumnText.js 特征测试(characterization)——冻结散落 6 处的逐字相同一行式: + * value: item.ColumnType !== 4 || (item.value || item.ColumnDefaultValue + "").indexOf("%") > 0 + * ? ((item.value || item.ColumnDefaultValue) + "") + * : (((item.value || item.ColumnDefaultValue) * 100) + "%") + * 【业务约定显式化】ColumnType==4 是"百分比列":值以小数形式存(0.05),展示时 ×100 加 %; + * 若值文本已含 %(手输/后端已格式化)则原样展示,不做二次换算。 + */ +const PercentColumnText = require('../wwwroot/Scripts/app/trade/percentColumnText.js'); + +describe('PercentColumnText.displayText 百分比列展示文本', () => { + test('非百分比列(ColumnType!=4)原样字符串化', () => { + expect(PercentColumnText.displayText({ value: '0.05', ColumnDefaultValue: '0.1', ColumnType: 0 })).toBe('0.05'); + expect(PercentColumnText.displayText({ value: 'abc', ColumnDefaultValue: 'x', ColumnType: 1 })).toBe('abc'); + }); + + test('百分比列小数值×100加%', () => { + expect(PercentColumnText.displayText({ value: '0.05', ColumnDefaultValue: '', ColumnType: 4 })).toBe('5%'); + expect(PercentColumnText.displayText({ value: '0.125', ColumnDefaultValue: '', ColumnType: 4 })).toBe('12.5%'); + expect(PercentColumnText.displayText({ value: '5', ColumnDefaultValue: '', ColumnType: 4 })).toBe('500%'); + }); + + test('百分比列值已含%则原样(不做二次换算)', () => { + expect(PercentColumnText.displayText({ value: '5%', ColumnDefaultValue: '', ColumnType: 4 })).toBe('5%'); + expect(PercentColumnText.displayText({ value: '0.30%', ColumnDefaultValue: '', ColumnType: 4 })).toBe('0.30%'); + }); + + test('value为空回退ColumnDefaultValue', () => { + expect(PercentColumnText.displayText({ value: '', ColumnDefaultValue: '0.2', ColumnType: 4 })).toBe('20%'); + expect(PercentColumnText.displayText({ value: '', ColumnDefaultValue: '2%', ColumnType: 4 })).toBe('2%'); + expect(PercentColumnText.displayText({ value: null, ColumnDefaultValue: '0.2', ColumnType: 0 })).toBe('0.2'); + }); + + test('quirk冻结: 回退源也无值时得到NaN%(undefined*100)', () => { + // 原一行式同款行为:raw=undefined → undefined*100+'%' = 'NaN%' + expect(PercentColumnText.displayText({ value: '', ColumnDefaultValue: undefined, ColumnType: 4 })).toBe('NaN%'); + }); + + test('quirk冻结: %恰在首位(indexOf=0不>0)仍走×100路径', () => { + // 原式用 >0 而非 >=0:'%'→'NaN%'。真实值从不以%开头,此测试仅钉住边界语义 + expect(PercentColumnText.displayText({ value: '%', ColumnDefaultValue: '', ColumnType: 4 })).toBe('NaN%'); + }); + + test('输入契约: value为非空数字时与原式同样抛TypeError(调用方须传字符串或空值)', () => { + // 原式 (item.value||...).indexOf 对数字直接TypeError——提取版保持一致,不做静默兜底 + expect(() => PercentColumnText.displayText({ value: 0.05, ColumnDefaultValue: '', ColumnType: 4 })).toThrow(TypeError); + }); +}); diff --git a/YLErpWeb/wwwroot/Scripts/app/pricing/structure.js b/YLErpWeb/wwwroot/Scripts/app/pricing/structure.js index f70b77bd..63a8e75c 100644 --- a/YLErpWeb/wwwroot/Scripts/app/pricing/structure.js +++ b/YLErpWeb/wwwroot/Scripts/app/pricing/structure.js @@ -2883,7 +2883,7 @@ var groupVue = new Vue({ setExtendInfo: function () { var propertyList = []; this.PropertyMap[this.trade.StructureType].forEach((item, index) => { - var note = { name: item.name || item.ColumnName, value: item.ColumnType !== 4 || (item.value || item.ColumnDefaultValue + "").indexOf("%") > 0 ? ((item.value || item.ColumnDefaultValue) + "") : (((item.value || item.ColumnDefaultValue) * 100) + "%") }; + var note = { name: item.name || item.ColumnName, value: PercentColumnText.displayText(item) }; if (note.name) { propertyList.push(note); } @@ -3014,7 +3014,7 @@ var extendVue = new Vue({ var map = this.ExtendMap; if (map[key]) { map[key].forEach((item, index) => { - var note = { name: item.name || item.ColumnName, value: item.ColumnType !== 4 || (item.value || item.ColumnDefaultValue + "").indexOf("%") > 0 ? ((item.value || item.ColumnDefaultValue) + "") : (((item.value || item.ColumnDefaultValue) * 100) + "%") }; + var note = { name: item.name || item.ColumnName, value: PercentColumnText.displayText(item) }; if (note.name) { propertyList.push(note); } @@ -3069,7 +3069,7 @@ var extendVue2 = new Vue({ var map = this.ExtendMap; if (map[key]) { map[key].forEach((item, index) => { - var note = { name: item.name || item.ColumnName, value: item.ColumnType !== 4 || (item.value || item.ColumnDefaultValue + "").indexOf("%") > 0 ? ((item.value || item.ColumnDefaultValue) + "") : (((item.value || item.ColumnDefaultValue) * 100) + "%") }; + var note = { name: item.name || item.ColumnName, value: PercentColumnText.displayText(item) }; if (note.name) { propertyList.push(note); } diff --git a/YLErpWeb/wwwroot/Scripts/app/pricing/structure_dz.js b/YLErpWeb/wwwroot/Scripts/app/pricing/structure_dz.js index e5636152..757f2a16 100644 --- a/YLErpWeb/wwwroot/Scripts/app/pricing/structure_dz.js +++ b/YLErpWeb/wwwroot/Scripts/app/pricing/structure_dz.js @@ -2548,7 +2548,7 @@ var groupVue = new Vue({ setExtendInfo: function () { var propertyList = []; this.PropertyMap[this.trade.StructureType].forEach((item, index) => { - var note = { name: item.name || item.ColumnName, value: item.ColumnType !== 4 || (item.value || item.ColumnDefaultValue + "").indexOf("%") > 0 ? ((item.value || item.ColumnDefaultValue) + "") : (((item.value || item.ColumnDefaultValue) * 100) + "%") }; + var note = { name: item.name || item.ColumnName, value: PercentColumnText.displayText(item) }; if (note.name) { propertyList.push(note); } diff --git a/YLErpWeb/wwwroot/Scripts/app/trade/percentColumnText.js b/YLErpWeb/wwwroot/Scripts/app/trade/percentColumnText.js new file mode 100644 index 00000000..bb7194e6 --- /dev/null +++ b/YLErpWeb/wwwroot/Scripts/app/trade/percentColumnText.js @@ -0,0 +1,33 @@ +/** + * percentColumnText.js — 交易要素列的百分比展示文本(纯函数) + * ============================================================================ + * 把散落在 structure.js ×3 / structure_dz.js / tradeEditV2.js / tradeEditGroup.js + * 的六处逐字相同一行式显式化为命名函数。 + * 【约定】ColumnType==4 = 百分比列:值以小数形式存储(如 0.05),展示时 ×100 追加 %; + * 若值文本已含 %(人工录入或后端已格式化)则原样展示,不做二次换算; + * 非百分比列一律原样字符串化。 + * + * 表达式与原一行式逐字符等价(含 >0 而非 >=0、空值回退 ColumnDefaultValue、 + * 回退源也无值时 NaN% 等历史行为)——特征测试见 fe-tests/percentColumnText.test.js。 + * 输入契约:value 须为字符串或空值(数字会与原式同样抛 TypeError)。 + * + * 加载:浏览器 script 标签(先于 structure/tradeEditV2/tradeEditGroup 页面脚本); + * Node:module.exports 供 jest。 + */ +var PercentColumnText = (function () { + 'use strict'; + + function displayText(item) { + var raw = item.value || item.ColumnDefaultValue; + if (item.ColumnType !== 4 || (item.value || item.ColumnDefaultValue + "").indexOf("%") > 0) { + return raw + ""; + } + return (raw * 100) + "%"; + } + + return Object.freeze({ + displayText: displayText + }); +}()); + +if (typeof module === 'object' && module.exports) module.exports = PercentColumnText; diff --git a/YLErpWeb/wwwroot/Scripts/app/trade/tradeEditGroup.js b/YLErpWeb/wwwroot/Scripts/app/trade/tradeEditGroup.js index d27f0d47..8e134338 100644 --- a/YLErpWeb/wwwroot/Scripts/app/trade/tradeEditGroup.js +++ b/YLErpWeb/wwwroot/Scripts/app/trade/tradeEditGroup.js @@ -94,7 +94,7 @@ var groupVue = new Vue({ setExtendInfo: function () { var propertyList = []; this.PropertyMap[this.trade.StructureType].forEach((item, index) => { - var note = { name: item.name || item.ColumnName, value: item.ColumnType !== 4 || (item.value || item.ColumnDefaultValue + "").indexOf("%") > 0 ? ((item.value || item.ColumnDefaultValue) + "") : (((item.value || item.ColumnDefaultValue) * 100) + "%") }; + var note = { name: item.name || item.ColumnName, value: PercentColumnText.displayText(item) }; if (note.name) { propertyList.push(note); } diff --git a/YLErpWeb/wwwroot/Scripts/app/trade/tradeEditV2.js b/YLErpWeb/wwwroot/Scripts/app/trade/tradeEditV2.js index 19d2ab0b..53401509 100644 --- a/YLErpWeb/wwwroot/Scripts/app/trade/tradeEditV2.js +++ b/YLErpWeb/wwwroot/Scripts/app/trade/tradeEditV2.js @@ -675,7 +675,7 @@ const vue = new Vue({ var map = this.trade.TradeType === "自定义交易" ? this.PropertyMap : this.ExtendMap; if (map[key]) { map[key].forEach((item, index) => { - var note = { name: item.name || item.ColumnName, value: item.ColumnType !== 4 || (item.value || item.ColumnDefaultValue + "").indexOf("%") > 0 ? ((item.value || item.ColumnDefaultValue) + "") : (((item.value || item.ColumnDefaultValue) * 100) + "%") }; + var note = { name: item.name || item.ColumnName, value: PercentColumnText.displayText(item) }; if (note.name) { propertyList.push(note); }