/, '').replace(/<\/div>$/, '');
// 返回格式化的JSON结构,但保持在外层的字符串容器中
// 使用block显示,确保完全展开
return '
' +
'"' +
'' +
nestedHTML +
'
' +
'"' +
' ';
}
} catch (e) {
// 解析失败,按普通字符串处理
}
}
}
return '
' + formatStringValue(JSON.stringify(this.value)) + '
';
}
case 'number':
// 确保大数字不使用科学计数法
let numStr = typeof this.value === 'number' && this.value.toString().includes('e')
? this.value.toLocaleString('fullwide', {useGrouping: false})
: this.value;
return '
' +
numStr +
'
';
case 'bigint':
// 对BigInt类型特殊处理,只显示数字,不添加n后缀
return '
' +
getBigNumberDisplayString(this.value) +
'
';
case 'boolean':
return '
' +
this.value +
'
';
case 'null':
return '
null
';
case 'object':
return this.getObjectHTML();
case 'array':
return this.getArrayHTML();
default:
return '';
}
},
getObjectHTML: function() {
if (!this.value || Object.keys(this.value).length === 0) {
return '
{}
';
}
let html = '
' +
'
' +
'
{' +
'
' +
'
';
let keys = Object.keys(this.value);
keys.forEach((key, index) => {
let prop = this.value[key];
let childNode = createNode(prop);
// 判断子节点是否为对象或数组,决定是否加item-block
let itemClass = (childNode.type === 'object' || childNode.type === 'array') ? 'item item-block' : 'item';
html += '
';
// 如果值是对象或数组,在key前面添加展开按钮
if (childNode.type === 'object' || childNode.type === 'array') {
html += '
';
}
html += '
"' +
'
' + htmlspecialchars(key) + '' +
'
"' +
'
: ';
// 添加值
if (childNode.type === 'object' || childNode.type === 'array') {
html += childNode.getInlineHTMLWithoutExpand();
} else {
html += childNode.getHTML().replace(/^
/, '').replace(/<\/div>$/, '');
}
// 如果不是最后一个属性,添加逗号
if (index < keys.length - 1) {
html += ',';
}
html += '
';
});
html += '
}';
return html;
},
getArrayHTML: function() {
if (!this.value || this.value.length === 0) {
return '
[]
';
}
let html = '
' +
'
' +
'
[' +
'
' +
'
';
this.value.forEach((item, index) => {
let childNode = createNode(item);
html += '
';
// 如果数组元素是对象或数组,在前面添加展开按钮
if (childNode.type === 'object' || childNode.type === 'array') {
html += '
';
html += childNode.getInlineHTMLWithoutExpand();
} else {
html += childNode.getHTML().replace(/^
/, '').replace(/<\/div>$/, '');
}
// 如果不是最后一个元素,添加逗号
if (index < this.value.length - 1) {
html += ',';
}
html += '
';
});
html += '
]';
return html;
},
// 新增内联HTML方法,用于在同一行显示开始大括号/方括号
getInlineHTML: function() {
switch(this.type) {
case 'object':
return this.getInlineObjectHTML();
case 'array':
return this.getInlineArrayHTML();
default:
return this.getHTML();
}
},
// 新增不包含展开按钮的内联HTML方法
getInlineHTMLWithoutExpand: function() {
switch(this.type) {
case 'object':
return this.getInlineObjectHTMLWithoutExpand();
case 'array':
return this.getInlineArrayHTMLWithoutExpand();
default:
return this.getHTML();
}
},
getInlineObjectHTML: function() {
if (!this.value || Object.keys(this.value).length === 0) {
return '
{}';
}
let html = '
{' +
'
' +
'
' +
'
';
let keys = Object.keys(this.value);
keys.forEach((key, index) => {
let prop = this.value[key];
let childNode = createNode(prop);
// 判断子节点是否为对象或数组,决定是否加item-block
let itemClass = (childNode.type === 'object' || childNode.type === 'array') ? 'item item-block' : 'item';
html += '
';
if (childNode.type === 'object' || childNode.type === 'array') {
html += '
';
}
html += '
"' +
'
' + htmlspecialchars(key) + '' +
'
"' +
'
: ';
if (childNode.type === 'object' || childNode.type === 'array') {
html += childNode.getInlineHTMLWithoutExpand();
} else {
html += childNode.getHTML().replace(/^
/, '').replace(/<\/div>$/, '');
}
if (index < keys.length - 1) {
html += ',';
}
html += '
';
});
html += '
}';
return html;
},
getInlineArrayHTML: function() {
if (!this.value || this.value.length === 0) {
return '
[]';
}
let html = '
[' +
'
' +
'
' +
'
';
this.value.forEach((item, index) => {
let childNode = createNode(item);
html += '
';
// 如果数组元素是对象或数组,在前面添加展开按钮
if (childNode.type === 'object' || childNode.type === 'array') {
html += '
';
html += childNode.getInlineHTMLWithoutExpand();
} else {
html += childNode.getHTML().replace(/^
/, '').replace(/<\/div>$/, '');
}
// 如果不是最后一个元素,添加逗号
if (index < this.value.length - 1) {
html += ',';
}
html += '
';
});
html += '
]';
return html;
},
getInlineObjectHTMLWithoutExpand: function() {
if (!this.value || Object.keys(this.value).length === 0) {
return '
{}';
}
let html = '
{' +
'
' +
'
';
let keys = Object.keys(this.value);
keys.forEach((key, index) => {
let prop = this.value[key];
let childNode = createNode(prop);
// 判断子节点是否为对象或数组,决定是否加item-block
let itemClass = (childNode.type === 'object' || childNode.type === 'array') ? 'item item-block' : 'item';
html += '
';
if (childNode.type === 'object' || childNode.type === 'array') {
html += '
';
}
html += '
"' +
'
' + htmlspecialchars(key) + '' +
'
"' +
'
: ';
if (childNode.type === 'object' || childNode.type === 'array') {
html += childNode.getInlineHTMLWithoutExpand();
} else {
html += childNode.getHTML().replace(/^
/, '').replace(/<\/div>$/, '');
}
if (index < keys.length - 1) {
html += ',';
}
html += '
';
});
html += '
}';
return html;
},
getInlineArrayHTMLWithoutExpand: function() {
if (!this.value || this.value.length === 0) {
return '
[]';
}
let html = '
[' +
'
' +
'
';
this.value.forEach((item, index) => {
let childNode = createNode(item);
html += '
';
// 确保所有类型的数组元素都能正确处理
if (childNode.type === 'object' || childNode.type === 'array') {
html += '
';
html += childNode.getInlineHTMLWithoutExpand();
} else {
html += childNode.getHTML().replace(/^
/, '').replace(/<\/div>$/, '');
}
// 如果不是最后一个元素,添加逗号
if (index < this.value.length - 1) {
html += ',';
}
html += '
';
});
html += '
]';
return html;
}
};
return node;
}
// 获取值类型
function getType(value) {
if (value === null) return 'null';
if (value === undefined) return 'undefined';
let type = typeof value;
// 特别处理BigInt类型
if (type === 'bigint') return 'bigint';
if (type === 'object') {
if (isBigNumberLike(value)) {
return 'bigint'; // 将 BigNumber 对象也当作 bigint 处理
}
if (Array.isArray(value)) return 'array';
}
return type;
}
function isUrl(str) {
const urlRegex = /^(https?:\/\/|ftp:\/\/)[^\s<>"'\\]+$/i;
return urlRegex.test(str);
}
function isBigNumberLike(value) {
return value && typeof value === 'object' &&
typeof value.s === 'number' &&
typeof value.e === 'number' &&
Array.isArray(value.c);
}
function getBigNumberDisplayString(value) {
if (typeof value === 'bigint') {
return value.toString();
}
if (!isBigNumberLike(value)) {
return String(value);
}
const direct = tryConvertBigNumberToString(value);
if (direct) {
return direct;
}
return rebuildBigNumberFromParts(value);
}
function tryConvertBigNumberToString(value) {
const nativeToString = value && value.toString;
if (typeof nativeToString === 'function' && nativeToString !== Object.prototype.toString) {
try {
const result = nativeToString.call(value);
if (typeof result === 'string' && result !== '[object Object]') {
return result;
}
} catch (e) {}
}
const ctor = getAvailableBigNumberCtor();
if (ctor && typeof Object.setPrototypeOf === 'function') {
try {
if (!(value instanceof ctor)) {
Object.setPrototypeOf(value, ctor.prototype);
}
if (typeof value.toString === 'function' && value.toString !== Object.prototype.toString) {
const result = value.toString();
if (typeof result === 'string' && result !== '[object Object]') {
return result;
}
}
} catch (e) {}
}
return null;
}
function rebuildBigNumberFromParts(value) {
const sign = value.s < 0 ? '-' : '';
const CHUNK_SIZE = 14;
let digits = '';
for (let i = 0; i < value.c.length; i++) {
let chunkStr = Math.abs(value.c[i]).toString();
if (i > 0) {
chunkStr = chunkStr.padStart(CHUNK_SIZE, '0');
}
digits += chunkStr;
}
digits = digits.replace(/^0+/, '') || '0';
const decimalIndex = value.e + 1;
if (decimalIndex <= 0) {
const zeros = '0'.repeat(Math.abs(decimalIndex));
let fraction = zeros + digits;
fraction = fraction.replace(/0+$/, '');
if (!fraction) {
return sign + '0';
}
return sign + '0.' + fraction;
}
if (decimalIndex >= digits.length) {
return sign + digits + '0'.repeat(decimalIndex - digits.length);
}
const intPart = digits.slice(0, decimalIndex);
let fracPart = digits.slice(decimalIndex).replace(/0+$/, '');
if (!fracPart) {
return sign + intPart;
}
return sign + intPart + '.' + fracPart;
}
function getAvailableBigNumberCtor() {
if (typeof JSON !== 'undefined' && typeof JSON.BigNumber === 'function') {
return JSON.BigNumber;
}
if (typeof BigNumber === 'function') {
return BigNumber;
}
return null;
}