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