rapid-spreadjs 1.0.184 → 1.0.186

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -1237,16 +1237,20 @@ const BusinessUtils = {
1237
1237
  });
1238
1238
  return itemExp;
1239
1239
  };
1240
- //将1~20这些数字替换为具体的设置条件
1240
+ //将1~100这些数字替换为具体的设置条件
1241
1241
  const replaceNum = (itemExp, conJsonArr) => {
1242
1242
  const nums = [];
1243
- for (let iNum = 1; iNum <= 20; iNum++) {
1243
+ for (let iNum = 1; iNum <= 100; iNum++) {
1244
1244
  nums.push(iNum);
1245
1245
  }
1246
1246
  nums.forEach((num) => {
1247
1247
  if (itemExp.indexOf(num) > -1 && num <= conJsonArr.length) {
1248
1248
  //将条件公式【1 || (2 && 3)】中的数组替换为#1#的形式
1249
- itemExp = itemExp.replaceAll(num, `#${num}#`);
1249
+ /**
1250
+ * 如下正则替换的原理为:将字符串中独立的数字66替换为Y
1251
+ * '78ab5c66d5566e4566f66g'.replace(new RegExp(`(?<!\\d)${66}(?!\\d)`, 'g'), 'Y') → '78ab5cYd5566e4566fYg'
1252
+ */
1253
+ itemExp = itemExp.replace(new RegExp(`(?<!\\d)${num}(?!\\d)`, 'g'), `#${num}#`);
1250
1254
  }
1251
1255
  });
1252
1256
  nums.forEach((num) => {
@@ -1299,6 +1303,8 @@ const BusinessUtils = {
1299
1303
  //记录是否所有前置公式对应的条件都没有超差
1300
1304
  let isAllNotCc = true;
1301
1305
  for (let j = 0; j < qzGsJsonArr.length; j++) {
1306
+ // if (j == 11) debugger;
1307
+ // debugger;
1302
1308
  const itemQzgs = qzGsJsonArr[j];
1303
1309
  //当前公式中的前置条件
1304
1310
  let curGsQz = itemQzgs.qzFor.replaceAll('jd(', '精度开始').replaceAll(')jd', '精度结束').replaceAll('abs', '[###]');
@@ -1345,7 +1351,7 @@ const BusinessUtils = {
1345
1351
  }
1346
1352
  }
1347
1353
  }
1348
- break;
1354
+ // break;
1349
1355
  }
1350
1356
  }
1351
1357
  catch (error) {
@@ -5329,117 +5335,132 @@ const EChartsUtilsAll = {
5329
5335
  return option;
5330
5336
  },
5331
5337
  /**
5332
- * 筛分
5338
+ * 筛分(动态多折线版)
5339
+ * 与 chart50 主体逻辑一致(x轴 0.45 次方变换、按x排序、空值过滤、markLine 模拟x轴标签等),
5340
+ * 区别在于折线数量不再固定为 3 条,而是根据 chartLinesJson 中的折线配置数量动态生成 N 条线:
5341
+ * - 每条线的图例名取 lineData[i].legend
5342
+ * - 每条线的颜色取 lineData[i].lineColor
5343
+ * - 每条线的 Y 数据取 yDataArr[i]
5344
+ * - 符号与线型按索引循环取预设值(首线保持实心方块+实线,与 chart50 一致)
5333
5345
  * @param config 折线配置
5334
- * @param xDataArr x轴原始数据(二维数组)
5335
- * @param yDataArr y轴原始数据(二维数组)
5346
+ * @param xDataArr x轴原始数据(二维数组,取 xDataArr[0] 作为共享x轴)
5347
+ * @param yDataArr y轴原始数据(二维数组,yDataArr[i] 对应第 i 条线)
5336
5348
  * @returns 返回ECharts配置项
5337
5349
  */
5338
5350
  chart50: (config, xDataArr, yDataArr) => {
5339
5351
  let lineData = JSON.parse(config.chartLinesJson);
5340
- let title = '', //config.chartTitle,
5341
- xName = config.chartXName, yName = config.chartYName;
5342
- // x轴原始数据、y轴原始数据、y轴原始数据(上限)、y轴原始数据(下限)
5343
- const xDataSourceOld = xDataArr[0], yDataSourceOld = yDataArr[0], yDataSourceSxOld = yDataArr[1], yDataSourceXxOld = yDataArr[2];
5352
+ let title = '', xName = config.chartXName, yName = config.chartYName;
5353
+ // 折线数量:以 chartLinesJson 中配置的折线条数为准
5354
+ const lineCount = Array.isArray(lineData) ? lineData.length : 0;
5355
+ // x轴原始数据(共享一份)
5356
+ const xDataSourceOld = xDataArr[0];
5344
5357
  const allData = [];
5345
5358
  xDataSourceOld.forEach((item, index) => {
5346
- allData.push({
5347
- x: item,
5348
- y: yDataSourceOld[index],
5349
- ySx: yDataSourceSxOld[index],
5350
- yXx: yDataSourceXxOld[index],
5351
- });
5359
+ const point = { x: item };
5360
+ // 将每条线的 y 值都收进同一个点对象,key 为 y0/y1/y2...
5361
+ for (let i = 0; i < lineCount; i++) {
5362
+ point['y' + i] = (yDataArr[i] || [])[index];
5363
+ }
5364
+ allData.push(point);
5352
5365
  });
5353
5366
  allData.sort(function (a, b) {
5354
5367
  return a.x - b.x;
5355
5368
  });
5356
- const xDataSource = [], yDataSource = [], yDataSourceSx = [], yDataSourceXx = [];
5357
- // 记录上限或下限中值为null的个数
5358
- let sxValNullCount = 0;
5359
- yDataSourceSxOld.forEach((item, index) => {
5360
- if (item == null || item == '/') {
5361
- sxValNullCount++;
5362
- }
5363
- });
5364
- // 如果上限或下限值中的所有值都为null,则只展示筛分曲线的折线
5365
- if (sxValNullCount == yDataSourceSxOld.length) {
5366
- allData.forEach((item, index) => {
5367
- xDataSource.push(item.x);
5368
- yDataSource.push(item.y);
5369
- yDataSourceSx.push(item.ySx);
5370
- yDataSourceXx.push(item.yXx);
5371
- });
5372
- }
5373
- else {
5374
- // 只获取上限或下限中值不为null的点
5375
- allData.forEach((item, index) => {
5376
- if (item.ySx != null && item.ySx != '/' && item.yXx != null && item.yXx != '/') {
5377
- xDataSource.push(item.x);
5378
- yDataSource.push(item.y);
5379
- yDataSourceSx.push(item.ySx);
5380
- yDataSourceXx.push(item.yXx);
5369
+ // 每条线的数据数组
5370
+ const yDataSources = [];
5371
+ for (let i = 0; i < lineCount; i++) {
5372
+ yDataSources.push([]);
5373
+ }
5374
+ // 统计各条线中值为 null 或 "/" 的个数(用于后续空值过滤逻辑,保持与 chart50 一致的行为)
5375
+ const nullCounts = [];
5376
+ for (let i = 0; i < lineCount; i++) {
5377
+ let cnt = 0;
5378
+ (yDataArr[i] || []).forEach((item) => {
5379
+ if (item == null || item == '/') {
5380
+ cnt++;
5381
5381
  }
5382
5382
  });
5383
+ nullCounts.push(cnt);
5383
5384
  }
5384
- // x轴需要的数据(x轴原始数据的0.45次方,并修约0.01)、x轴需要的上限数据(x轴原始数据的0.45次方,并修约0.01)、x轴需要的下限数据(x轴原始数据的0.45次方,并修约0.01)、标记线需要的数据
5385
- let xData = [], xDataSx = [], xDataXx = [], markLineData = [];
5385
+ // 若任意一条线存在非空值,则按“所有线均非空”过滤出有效点;否则保留全部点(与 chart50 上限/下限过滤逻辑保持语义一致)
5386
+ const hasAnyValid = nullCounts.some((cnt, i) => cnt < (yDataArr[i] || []).length);
5387
+ allData.forEach((item) => {
5388
+ if (!hasAnyValid) {
5389
+ for (let i = 0; i < lineCount; i++) {
5390
+ yDataSources[i].push(item['y' + i]);
5391
+ }
5392
+ return;
5393
+ }
5394
+ // 存在有效值时,仅当所有线该点均非空才保留
5395
+ let allValid = true;
5396
+ for (let i = 0; i < lineCount; i++) {
5397
+ const v = item['y' + i];
5398
+ if (v == null || v == '/') {
5399
+ allValid = false;
5400
+ break;
5401
+ }
5402
+ }
5403
+ if (allValid) {
5404
+ for (let i = 0; i < lineCount; i++) {
5405
+ yDataSources[i].push(item['y' + i]);
5406
+ }
5407
+ }
5408
+ });
5409
+ // x轴数据:x轴原始数据的0.45次方,并修约0.001
5410
+ let xData = [];
5411
+ let markLineData = [];
5386
5412
  // x和y轴的字体大小
5387
5413
  const xyFontSize = 10;
5388
- // 组装数据
5389
- xDataSource.forEach((item, index) => {
5390
- // 得到x轴原始数据的0.45次方值,并修约0.001
5414
+ // 组装 x 轴与 markLine(所有线共用同一套 x 值)
5415
+ xDataSourceOld.forEach((item, index) => {
5391
5416
  const val045 = Number(EChartsUtilsComm.getRound(item ** 0.45, 0.001));
5392
- xData.push([val045, yDataSource[index]]);
5393
5417
  markLineData.push({
5394
5418
  name: item + '',
5395
5419
  xAxis: val045,
5396
5420
  label: {
5397
- show: xDataSource.length >= 6 && index % 2 != 0 && index < 6 ? false : true, // 控制x轴的名称某些点是否显示,避免重叠的情况
5421
+ show: xDataSourceOld.length >= 6 && index % 2 != 0 && index < 6 ? false : true,
5398
5422
  fontSize: xyFontSize,
5399
5423
  },
5400
5424
  });
5401
- xDataSx.push([val045, yDataSourceSx[index]]);
5402
- xDataXx.push([val045, yDataSourceXx[index]]);
5425
+ xData.push(val045);
5403
5426
  });
5427
+ // 符号与线型预设值(循环取用)
5428
+ const symbolPresets = ['rect', 'triangle', 'circle', 'diamond', 'roundRect', 'arrow'];
5429
+ const lineTypePresets = ['solid', 'dotted', [10, 5], 'dashed', [2, 2], [6, 3, 2, 3]];
5404
5430
  /**
5405
- * 获取series需要的3条线配置
5406
- * @param type 线类型(1:筛分曲线、2:上限、3:下限)
5407
- * @param data 对应的坐标点数据
5431
+ * 获取 series 需要的单条线配置(动态版)
5432
+ * @param index 第几条线
5433
+ * @param data 对应的坐标点数据([x, y])
5408
5434
  */
5409
- const getLineObj = (type, data) => {
5410
- const name = type == 1 ? '筛分曲线' : type == 2 ? '上限' : '下限';
5411
- const symbol = type == 1 ? 'rect' : type == 2 ? 'triangle' : 'circle';
5412
- const lineType = type == 1 ? 'solid' : type == 2 ? 'dotted' : [10, 5];
5413
- const color = type == 1 ? lineData[0].lineColor : type == 2 ? lineData[1].lineColor : lineData[2].lineColor; //type == 1 ? '#F56C6C' : type == 2 ? '#409EFF' : '#000';
5435
+ const getLineObj = (index, data) => {
5436
+ const lineCfg = lineData[index] || {};
5437
+ // 图例名:优先取 lineData[index].legend,其次用序号兜底
5438
+ const name = lineCfg.legend != null && lineCfg.legend !== '' ? lineCfg.legend : '折线' + (index + 1);
5439
+ // 颜色:优先取 lineData[index].lineColor,其次循环取预设色
5440
+ const color = lineCfg.lineColor != null && lineCfg.lineColor !== '' ? lineCfg.lineColor : null;
5441
+ const symbol = symbolPresets[index % symbolPresets.length];
5442
+ const lineType = lineTypePresets[index % lineTypePresets.length];
5414
5443
  let obj = {
5415
5444
  name: name,
5416
5445
  type: 'line',
5417
- smooth: true, // 平滑的线条
5418
- // 设置数据点形状(实心),参考文档:https://echarts.apache.org/zh/option.html#series-line.symbol
5446
+ smooth: true,
5419
5447
  symbol: symbol,
5420
5448
  symbolSize: 5,
5421
- z: 10, // 控制曲线的浮动层级,避免在markLine下方被遮住
5422
- // 线条的颜色
5449
+ z: 10,
5423
5450
  lineStyle: {
5424
5451
  color: color,
5425
- // 线条类型(solid:实线、dashed:粗虚线、dotted:细虚线)
5426
5452
  type: lineType,
5427
5453
  },
5428
- // 线条上数据点的颜色
5429
5454
  itemStyle: {
5430
5455
  color: color,
5431
5456
  },
5432
5457
  data: data,
5433
- connectNulls: true, // 是否连接空数据
5458
+ connectNulls: true,
5434
5459
  markLine: {
5435
- symbol: '', // 取消箭头
5436
- silent: true, // 取消鼠标hover事件
5460
+ symbol: '',
5461
+ silent: true,
5437
5462
  label: {
5438
- // 标线的文本,模拟x轴显示的内容
5439
- position: 'start', // 改变label位置
5440
- //rotate: 45, // 设置文字旋转度数(注意:ECharts官网文档居然没有rotate这个属性的说明)
5441
- // backgroundColor:'#fff'
5442
- // color:'#f00',// 文字颜色
5463
+ position: 'start',
5443
5464
  formatter: (data) => {
5444
5465
  return data.name;
5445
5466
  },
@@ -5455,40 +5476,48 @@ const EChartsUtilsAll = {
5455
5476
  if (xData.length == 0) {
5456
5477
  yValIsAllNull = true;
5457
5478
  }
5458
- let nullCount = 0;
5459
- xData.forEach((item) => {
5460
- if (item[1] == null || item[1] == undefined || item[1] == '/') {
5461
- nullCount++;
5479
+ // 组装每条线的 [x, y] 坐标点数据
5480
+ const seriesDataList = [];
5481
+ for (let i = 0; i < lineCount; i++) {
5482
+ const linePoints = [];
5483
+ for (let j = 0; j < xData.length; j++) {
5484
+ linePoints.push([xData[j], yDataSources[i][j]]);
5462
5485
  }
5463
- });
5464
- if (nullCount == xData.length) {
5465
- yValIsAllNull = true;
5486
+ seriesDataList.push(linePoints);
5466
5487
  }
5467
- if (yDataSourceSxOld.some((item) => item != null && item != undefined && item != '/') ||
5468
- yDataSourceXxOld.some((item) => item != null && item != undefined && item != '/')) {
5469
- yValIsAllNull = false;
5470
- }
5471
- if (xData.filter((x) => x[1] == 0).length == xData.length &&
5472
- xDataSx.filter((x) => x[1] == 0).length == xDataSx.length &&
5473
- xDataXx.filter((x) => x[1] == 0).length == xDataXx.length) {
5488
+ let nullCount = 0;
5489
+ seriesDataList.forEach((linePoints) => {
5490
+ linePoints.forEach((item) => {
5491
+ if (item[1] == null || item[1] == undefined || item[1] == '/') {
5492
+ nullCount++;
5493
+ }
5494
+ });
5495
+ });
5496
+ if (nullCount == xData.length * lineCount) {
5474
5497
  yValIsAllNull = true;
5475
5498
  }
5476
- if (!yDataArr[0].some((x) => x != '' && x != '/' && x != null && x != undefined) &&
5477
- !yDataArr[1].some((x) => x != '' && x != '/' && x != null && x != undefined) &&
5478
- !yDataArr[2].some((x) => x != '' && x != '/' && x != null && x != undefined)) {
5499
+ if (yDataArr.every((arr) => !arr.some((x) => x != '' && x != '/' && x != null && x != undefined))) {
5479
5500
  yValIsAllNull = true;
5480
5501
  }
5502
+ // 图例名称与选中状态(动态)
5503
+ const legendNames = [];
5504
+ const legendSelected = {};
5505
+ for (let i = 0; i < lineCount; i++) {
5506
+ const lineCfg = lineData[i] || {};
5507
+ const name = lineCfg.legend != null && lineCfg.legend !== '' ? lineCfg.legend : '折线' + (i + 1);
5508
+ legendNames.push(name);
5509
+ legendSelected[name] = true;
5510
+ }
5511
+ // series 动态生成
5512
+ const series = seriesDataList.map((linePoints, i) => getLineObj(i, !yValIsAllNull ? linePoints : []));
5481
5513
  let option = {
5482
5514
  grid: {
5483
- // show: true,// 是否显示外边框线
5484
- // borderColor: '#f00',// 外边框线颜色
5485
5515
  top: 20,
5486
5516
  left: 30,
5487
5517
  right: 10,
5488
5518
  bottom: 35,
5489
5519
  containLabel: true,
5490
5520
  },
5491
- // 提示框组件,参考文档:https://echarts.apache.org/zh/option.html#tooltip
5492
5521
  tooltip: {
5493
5522
  trigger: 'axis',
5494
5523
  formatter: function (datas, ticket) {
@@ -5501,7 +5530,6 @@ const EChartsUtilsAll = {
5501
5530
  }
5502
5531
  },
5503
5532
  },
5504
- // 顶部的标题,参考文档:https://echarts.apache.org/zh/option.html#title
5505
5533
  title: [
5506
5534
  {
5507
5535
  show: true,
@@ -5524,29 +5552,22 @@ const EChartsUtilsAll = {
5524
5552
  },
5525
5553
  },
5526
5554
  ],
5527
- // 图例,参考文档:https://echarts.apache.org/zh/option.html#legend
5528
5555
  legend: {
5529
- // show: !yValIsAllNull,
5530
5556
  top: '0px',
5531
5557
  left: 'center',
5532
- data: ['筛分曲线', '上限', '下限'],
5533
- selected: {
5534
- 筛分曲线: true, // 显示
5535
- 上限: true, // 显示
5536
- 下限: true, // 显示
5537
- },
5538
- selectedMode: 'multiple', // 用于控制图例的选择模式(single:单选、multiple:多选、false:禁止选择)
5558
+ data: legendNames,
5559
+ selected: legendSelected,
5560
+ selectedMode: 'multiple',
5539
5561
  },
5540
5562
  xAxis: {
5541
5563
  type: 'value',
5542
- axisTick: { show: false }, // 隐藏刻度线
5543
- axisLabel: { show: false }, // 隐藏刻度值
5544
- // 网格线,参考文档:https://echarts.apache.org/zh/option.html#xAxis.splitLine
5564
+ axisTick: { show: false },
5565
+ axisLabel: { show: false },
5545
5566
  splitLine: {
5546
- show: false, // 隐藏分割线
5567
+ show: false,
5547
5568
  },
5548
- min: xData.length > 0 ? (xData[0][0] > 0.2 ? xData[0][0] - 0.2 : 0) : null, //控制x轴的最小值
5549
- max: xData.length > 0 ? xData[xData.length - 1][0] + 0.1 : null,
5569
+ min: xData.length > 0 ? (xData[0] > 0.2 ? xData[0] - 0.2 : 0) : null,
5570
+ max: xData.length > 0 ? xData[xData.length - 1] + 0.1 : null,
5550
5571
  },
5551
5572
  yAxis: [
5552
5573
  {
@@ -5558,23 +5579,19 @@ const EChartsUtilsAll = {
5558
5579
  splitLine: {
5559
5580
  show: true,
5560
5581
  lineStyle: {
5561
- color: '#e0e6f1', // '#e0e6f1',
5582
+ color: '#e0e6f1',
5562
5583
  type: 'solid',
5563
5584
  },
5564
5585
  },
5565
5586
  min: 0,
5566
5587
  max: 100,
5567
- splitNumber: 10, // 设置y轴分隔的段数,如0~100之间默认情况可能会按照0、20、40、60……的间隔显示,设置相应的数字后就会根据实际情况显示的更细,如0、10、20、30……
5588
+ splitNumber: 10,
5568
5589
  axisLabel: {
5569
5590
  fontSize: xyFontSize,
5570
5591
  },
5571
5592
  },
5572
5593
  ],
5573
- series: [
5574
- getLineObj(1, !yValIsAllNull ? xData : []),
5575
- getLineObj(2, !yValIsAllNull ? xDataSx : []),
5576
- getLineObj(3, !yValIsAllNull ? xDataXx : []),
5577
- ],
5594
+ series: series,
5578
5595
  };
5579
5596
  return option;
5580
5597
  },