cnhis-design-vue 2.1.118 → 2.1.119
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/CHANGELOG.md +17 -0
- package/es/age/index.js +2 -2
- package/es/big-table/index.js +63 -52
- package/es/big-table/style.css +1 -1
- package/es/button/index.js +2 -2
- package/es/captcha/index.js +3 -3
- package/es/card-reader-sdk/index.js +1 -1
- package/es/checkbox/index.js +1 -1
- package/es/color-picker/index.js +1 -1
- package/es/drag-layout/index.js +3 -3
- package/es/editor/index.js +1 -1
- package/es/ellipsis/index.js +1 -1
- package/es/fabric-chart/index.js +573 -75
- package/es/fabric-chart/style.css +1 -1
- package/es/form-table/index.js +20 -20
- package/es/full-calendar/index.js +436 -513
- package/es/full-calendar/style.css +1 -1
- package/es/index/index.js +1200 -754
- package/es/index/style.css +1 -1
- package/es/input/index.js +1 -1
- package/es/map/index.js +1 -1
- package/es/multi-chat/index.js +25 -25
- package/es/multi-chat-client/index.js +19 -19
- package/es/multi-chat-history/index.js +4 -4
- package/es/multi-chat-record/index.js +4 -4
- package/es/multi-chat-setting/index.js +20 -20
- package/es/multi-chat-sip/index.js +1 -1
- package/es/radio/index.js +1 -1
- package/es/scale-container/index.js +1 -1
- package/es/scale-view/index.js +27 -27
- package/es/select/index.js +4 -4
- package/es/select-label/index.js +3 -3
- package/es/select-person/index.js +2 -2
- package/es/select-tag/index.js +4 -4
- package/es/shortcut-setter/index.js +2 -2
- package/es/slider-tree/index.js +1 -1
- package/es/table-filter/index.js +30 -30
- package/es/tag/index.js +1 -1
- package/es/verification-code/index.js +2 -2
- package/lib/cui.common.js +1316 -865
- package/lib/cui.umd.js +1316 -865
- package/lib/cui.umd.min.js +65 -65
- package/package.json +1 -1
- package/packages/big-table/src/BigTable.vue +5 -1
- package/packages/big-table/src/utils/headerFilter.js +6 -3
- package/packages/fabric-chart/src/FabricChart.vue +1 -1
- package/packages/fabric-chart/src/fabric-chart/FabricLines.vue +6 -6
- package/packages/fabric-chart/src/fabric-chart/FabricPolylines.vue +6 -6
- package/packages/fabric-chart/src/fabric-chart/FabricTextGroup.vue +14 -10
- package/packages/fabric-chart/src/mixins/draw.js +97 -1
- package/packages/fabric-chart/src/mixins/drawExtracorporealCirculation.js +196 -0
- package/packages/fabric-chart/src/mixins/fabricCommon.js +1 -1
- package/packages/fabric-chart/src/utils/index.js +81 -0
- package/packages/full-calendar/src/FullCalendar.vue +96 -60
- package/packages/full-calendar/src/components/Tag.vue +3 -3
- package/packages/full-calendar/src/components/TagDetail.vue +3 -3
- package/packages/full-calendar/src/utils/index.js +14 -0
- package/packages/fabric-chart/src/mixins/type.js +0 -6
package/package.json
CHANGED
|
@@ -1913,7 +1913,11 @@ export default create({
|
|
|
1913
1913
|
}
|
|
1914
1914
|
|
|
1915
1915
|
if (['MONEY', 'NUMBER'].includes(attrType) || (own.extraField && own.fieldType === 'NUMBER')) {
|
|
1916
|
-
|
|
1916
|
+
let value = row[own.columnName];
|
|
1917
|
+
// 数字可能设置了颜色
|
|
1918
|
+
if(typeof value === 'string' && this.checkHtml(value)){
|
|
1919
|
+
return this.getField(row, own, rowIndex, true);
|
|
1920
|
+
}
|
|
1917
1921
|
return parseNumberField(value, own);
|
|
1918
1922
|
}
|
|
1919
1923
|
|
|
@@ -77,11 +77,13 @@ export default {
|
|
|
77
77
|
scaleNum = 1;
|
|
78
78
|
FILTER_BOX_TOP_OFFSET = 0;
|
|
79
79
|
const { resTop = 0, resLeft = 0, resWidth = 0, resHeight = 0 } = this.showFilterHandleLocationNew(target, tempWrapId);
|
|
80
|
+
// 表格可能滚动了
|
|
81
|
+
let bigTableScrollLeft = this.$refs.xGrid?.getScroll?.()?.scrollLeft || 0;
|
|
80
82
|
btnRectTop = resTop + resHeight + 8;
|
|
81
83
|
btnWidth = resWidth;
|
|
82
|
-
btnRectLeft = resLeft;
|
|
84
|
+
btnRectLeft = resLeft - bigTableScrollLeft;
|
|
83
85
|
btnRectRight = resWidth + btnRectLeft;
|
|
84
|
-
right = document.getElementById(tempWrapId).offsetWidth - btnWidth -
|
|
86
|
+
right = document.getElementById(tempWrapId).offsetWidth - btnWidth - btnRectLeft;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
field.left = 'initial';
|
|
@@ -434,7 +436,8 @@ export default {
|
|
|
434
436
|
this.$set(el, 'QUOTE', []);
|
|
435
437
|
return;
|
|
436
438
|
} else if (showSetting?.length > 0) {
|
|
437
|
-
this
|
|
439
|
+
let con = this.isApiTable ? 'EQ' : 'CONVERT';
|
|
440
|
+
this.$set(el, 'con', con);
|
|
438
441
|
showSetting.forEach(set => {
|
|
439
442
|
this.$set(set, 'label', set.change_text);
|
|
440
443
|
this.$set(set, 'value', JSON.stringify(set.filter));
|
|
@@ -31,7 +31,7 @@ import FabricGrid from './FabricGrid';
|
|
|
31
31
|
import FabricTextGroup from './fabric-chart/FabricTextGroup';
|
|
32
32
|
import FabricScaleValue from './fabric-chart/FabricScaleValue';
|
|
33
33
|
import FabricLines from './fabric-chart/FabricLines';
|
|
34
|
-
import { isObject } from './
|
|
34
|
+
import { isObject } from './utils';
|
|
35
35
|
|
|
36
36
|
export default create({
|
|
37
37
|
name: 'fabric-chart',
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import MouseRightClick from '../components/MouseRightClick';
|
|
10
10
|
import FabricCommon from '../mixins/fabricCommon';
|
|
11
11
|
import draw from '../mixins/draw';
|
|
12
|
-
import { isObject } from '../
|
|
12
|
+
import { isObject } from '../utils';
|
|
13
13
|
import DropPopup from '../components/DropPopup';
|
|
14
14
|
import eventCommon from '../mixins/eventCommon';
|
|
15
15
|
import vexutils from '@/utils/vexutils';
|
|
@@ -172,8 +172,8 @@ export default {
|
|
|
172
172
|
if (!item[0] || isObject(item[0])) return;
|
|
173
173
|
const startMinute = new Date(item[0]).getTime();
|
|
174
174
|
const endMinute = item[1] ? new Date(item[1]).getTime() : '';
|
|
175
|
-
let x1 = this.
|
|
176
|
-
let x2 = this.
|
|
175
|
+
let x1 = this.computedX(item[0]);
|
|
176
|
+
let x2 = this.computedX(item[1]);
|
|
177
177
|
// 数字文字
|
|
178
178
|
const textObj = item[3] || {};
|
|
179
179
|
const { content: textContent, continue: isContinue } = textObj;
|
|
@@ -250,13 +250,13 @@ export default {
|
|
|
250
250
|
if (preItem1) {
|
|
251
251
|
const preEndMinute = new Date(preItem1).getTime();
|
|
252
252
|
if (preEndMinute >= minMinute && preEndMinute < maxMinute) {
|
|
253
|
-
leftLimit.x1 = this.
|
|
253
|
+
leftLimit.x1 = this.computedX(preItem1);
|
|
254
254
|
if (!x2) rightLimit.x1 = leftLimit.x1;
|
|
255
255
|
}
|
|
256
256
|
} else {
|
|
257
257
|
const preStartMinute = new Date(preItem0).getTime();
|
|
258
258
|
if (preStartMinute >= minMinute && preStartMinute < maxMinute) {
|
|
259
|
-
leftLimit.x1 = this.
|
|
259
|
+
leftLimit.x1 = this.computedX(preItem0);
|
|
260
260
|
if (!x2) rightLimit.x1 = leftLimit.x1;
|
|
261
261
|
}
|
|
262
262
|
}
|
|
@@ -265,7 +265,7 @@ export default {
|
|
|
265
265
|
const [preItem0] = lineList[j + 1];
|
|
266
266
|
if (preItem0) {
|
|
267
267
|
const preStartMinute = new Date(preItem0).getTime();
|
|
268
|
-
if (preStartMinute > minMinute && preStartMinute <= maxMinute) rightLimit.x2 = this.
|
|
268
|
+
if (preStartMinute > minMinute && preStartMinute <= maxMinute) rightLimit.x2 = this.computedX(preItem0);
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
|
|
@@ -345,7 +345,7 @@ export default {
|
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
347
|
const point = targetList.find(k => isEffectiveNode(k) && new Date(k.time).getTime() >= minTime && new Date(k.time).getTime() <= maxTime);
|
|
348
|
-
const firstPointLeft = point ? this.
|
|
348
|
+
const firstPointLeft = point ? this.computedX(point.time) : 0;
|
|
349
349
|
const rightLimit = point ? firstPointLeft - this.spaceWidth : '';
|
|
350
350
|
// 配置是否可拖动标题图标批量增加-
|
|
351
351
|
const isAdd = (firstPointLeft || endX) - this.spaceWidth >= originX;
|
|
@@ -571,7 +571,7 @@ export default {
|
|
|
571
571
|
const lines = [];
|
|
572
572
|
|
|
573
573
|
const drawLine = ({ value, lineStyle }) => {
|
|
574
|
-
const top = this.
|
|
574
|
+
const top = this.computedY(polylineType, +value);
|
|
575
575
|
return this.drawLine([originX, top, endX, top], { polylineIndex, lineIndex: 0, polylineTypeId, ...(lineStyle || defaultVaule.criticalStyle) });
|
|
576
576
|
};
|
|
577
577
|
const drawText = ({ name, nameStyle }, top) => {
|
|
@@ -619,8 +619,8 @@ export default {
|
|
|
619
619
|
let isInit = false;
|
|
620
620
|
let points = null;
|
|
621
621
|
if (isEffectiveNode(point) && _this.isLimit(point.time)) {
|
|
622
|
-
const x = _this.
|
|
623
|
-
const y = _this.
|
|
622
|
+
const x = _this.computedX(point.time);
|
|
623
|
+
const y = _this.computedY(polylineType, point.value);
|
|
624
624
|
isInit = y < originY || y > endY;
|
|
625
625
|
points = [x, y < originY ? originY : y > endY ? endY : y];
|
|
626
626
|
}
|
|
@@ -648,7 +648,7 @@ export default {
|
|
|
648
648
|
let line;
|
|
649
649
|
let point;
|
|
650
650
|
let previousLine;
|
|
651
|
-
line = points && nextPoint ? this.drawLine([...points, ...nextPoint], { polylineIndex, polylineTypeId, lineIndex: index, ...lineAttr }) : null;
|
|
651
|
+
line = points && nextPoint && !linePoints.data?.breakpoint ? this.drawLine([...points, ...nextPoint], { polylineIndex, polylineTypeId, lineIndex: index, ...lineAttr }) : null;
|
|
652
652
|
previousLine = lineList[index - 1];
|
|
653
653
|
const pointOthers = { polylineTypeId, polylineIndex, pointIndex: index, ...pointAttr, lineAttr };
|
|
654
654
|
if (points) {
|
|
@@ -726,7 +726,7 @@ export default {
|
|
|
726
726
|
this.createAttrVaule({ ...params, attr: 'diffValue' });
|
|
727
727
|
},
|
|
728
728
|
// 计算y轴坐标
|
|
729
|
-
|
|
729
|
+
computedY(polylineType, linePointY) {
|
|
730
730
|
const { position = 'left', list = [] } = polylineType;
|
|
731
731
|
const key = position === 'left' ? 'Left' : 'Right';
|
|
732
732
|
const yScaleCell = this.propItems[`yScaleCell${key}`];
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
<script>
|
|
9
9
|
import fabricCommon from '../mixins/fabricCommon';
|
|
10
10
|
import draw from '../mixins/draw';
|
|
11
|
+
import drawExtracorporealCirculation from '../mixins/drawExtracorporealCirculation';
|
|
11
12
|
import defaultVaule from '../const/defaultVaule';
|
|
12
13
|
import DropPopup from '../components/DropPopup';
|
|
13
14
|
import MouseRightClick from '../components/MouseRightClick';
|
|
@@ -37,7 +38,7 @@ export default {
|
|
|
37
38
|
DropPopup,
|
|
38
39
|
MouseRightClick
|
|
39
40
|
},
|
|
40
|
-
mixins: [fabricCommon, draw, eventCommon],
|
|
41
|
+
mixins: [fabricCommon, draw, eventCommon, drawExtracorporealCirculation],
|
|
41
42
|
props: {
|
|
42
43
|
templateData: {
|
|
43
44
|
type: Object,
|
|
@@ -98,7 +99,10 @@ export default {
|
|
|
98
99
|
this.eventStyle.evented && this.createEvent();
|
|
99
100
|
this.drawBorder();
|
|
100
101
|
// this.canvas.renderAll();
|
|
101
|
-
|
|
102
|
+
if (this.templateData.bottom) {
|
|
103
|
+
this.drawExtracorporealCirculation(this.extracorporealCirculation);
|
|
104
|
+
this.drawBottomTextDataGroup(this.templateData.bottom);
|
|
105
|
+
}
|
|
102
106
|
},
|
|
103
107
|
drawBorder() {
|
|
104
108
|
const { endX, canvasWidth, canvasHeight, topTotal } = this.propItems;
|
|
@@ -233,7 +237,7 @@ export default {
|
|
|
233
237
|
const baseTop = originY + (item.marginTop || 10);
|
|
234
238
|
if (this.isLimit(item.scalevalue)) {
|
|
235
239
|
const textItemPoints = [];
|
|
236
|
-
const left = this.
|
|
240
|
+
const left = this.computedX(item.scalevalue);
|
|
237
241
|
item.dataList.forEach((v, i) => {
|
|
238
242
|
const top = baseTop + i * (item.lineHeight || 15);
|
|
239
243
|
const text = new this.fabric.Text(String(v.value), {
|
|
@@ -316,7 +320,7 @@ export default {
|
|
|
316
320
|
objectCaching: false,
|
|
317
321
|
origin: v
|
|
318
322
|
};
|
|
319
|
-
const left = this.
|
|
323
|
+
const left = this.computedX(v.time);
|
|
320
324
|
title.dataList.push(left);
|
|
321
325
|
const icon = await this.createPoint(_icon.type, {
|
|
322
326
|
originX: 'center',
|
|
@@ -507,7 +511,7 @@ export default {
|
|
|
507
511
|
limitIndex: -1, // 标志点是否往上排列的标志,大于-1则表示需要往上排列
|
|
508
512
|
y: baseY
|
|
509
513
|
};
|
|
510
|
-
const x = this.
|
|
514
|
+
const x = this.computedX(item[0]);
|
|
511
515
|
if (this.isLimit(item[0])) {
|
|
512
516
|
const pointList = [];
|
|
513
517
|
item[1].forEach(async (v, i) => {
|
|
@@ -631,7 +635,7 @@ export default {
|
|
|
631
635
|
const isStart = v[1].some(k => k.other?.isStart);
|
|
632
636
|
return !isStart && new Date(v[0]).getTime() >= new Date(point.time).getTime();
|
|
633
637
|
});
|
|
634
|
-
const limitRight = obj ? this.
|
|
638
|
+
const limitRight = obj ? this.computedX(obj[0]) : endX;
|
|
635
639
|
if (point.left > limitRight) {
|
|
636
640
|
point.set('left', limitRight);
|
|
637
641
|
}
|
|
@@ -646,11 +650,11 @@ export default {
|
|
|
646
650
|
const limitRightTime = rightId ? bottom.list.find(v => v[1].some(k => k.data?.id && k.data?.id === rightId))[0] : null;
|
|
647
651
|
const limitLeft =
|
|
648
652
|
(limitLeftTime && !startList) || (limitLeftTime && startList && new Date(limitLeftTime).getTime() >= new Date(startList[0]).getTime())
|
|
649
|
-
? this.
|
|
653
|
+
? this.computedX(limitLeftTime)
|
|
650
654
|
: (!limitLeftTime && startList) || (limitLeftTime && startList && new Date(limitLeftTime).getTime() < new Date(startList[0]).getTime())
|
|
651
|
-
? this.
|
|
655
|
+
? this.computedX(startList[0])
|
|
652
656
|
: originX;
|
|
653
|
-
const limitRight = limitRightTime ? this.
|
|
657
|
+
const limitRight = limitRightTime ? this.computedX(limitRightTime) : endX;
|
|
654
658
|
if (point.left > limitRight) {
|
|
655
659
|
point.set('left', limitRight);
|
|
656
660
|
}
|
|
@@ -674,7 +678,7 @@ export default {
|
|
|
674
678
|
};
|
|
675
679
|
const x = arguments.length > 1 && point.other?.viewTime ? point.other.viewTime : this.getXValue(point.realLeft || point.left);
|
|
676
680
|
this.dropVal = {
|
|
677
|
-
title: point.name || '',
|
|
681
|
+
title: point.name || point.origin?.data?.value || '',
|
|
678
682
|
list: [{ id: '1', name: '时间', value: x }]
|
|
679
683
|
};
|
|
680
684
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isNumber, isObject } from '
|
|
1
|
+
import { isNumber, isObject, getTangent, getIntersectionPoint, sortPoints, isInPolygon, uniquePoints } from '../utils';
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
4
|
name: 'draw',
|
|
@@ -340,6 +340,102 @@ export default {
|
|
|
340
340
|
...data
|
|
341
341
|
});
|
|
342
342
|
}
|
|
343
|
+
},
|
|
344
|
+
drawShadow(coordinates, angle = 45, space = 10, style = {}) {
|
|
345
|
+
const result = [];
|
|
346
|
+
const that = this;
|
|
347
|
+
// 去除无用角度
|
|
348
|
+
angle = normalizeAngle(angle);
|
|
349
|
+
// if (angle === 0) return result;
|
|
350
|
+
|
|
351
|
+
const minX = Math.min(...coordinates.map(([x]) => x));
|
|
352
|
+
const maxX = Math.max(...coordinates.map(([x]) => x));
|
|
353
|
+
const minY = Math.min(...coordinates.map(([, y]) => y));
|
|
354
|
+
const maxY = Math.max(...coordinates.map(([, y]) => y));
|
|
355
|
+
|
|
356
|
+
if (angle === 0) {
|
|
357
|
+
// 绘制水平线
|
|
358
|
+
let start = minY,
|
|
359
|
+
end = maxY;
|
|
360
|
+
while (start < end - 1) {
|
|
361
|
+
start += space;
|
|
362
|
+
result.push(createLine([minX, start], [maxX, start]));
|
|
363
|
+
}
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const offsetX = (maxY - minY) / getTangent(angle);
|
|
368
|
+
|
|
369
|
+
const isLeanRight = (angle > 0 && angle < 90) || (angle > 180 && angle < 270);
|
|
370
|
+
|
|
371
|
+
let start = minX;
|
|
372
|
+
let end = maxX;
|
|
373
|
+
|
|
374
|
+
if (isLeanRight) {
|
|
375
|
+
end += offsetX;
|
|
376
|
+
} else {
|
|
377
|
+
start += offsetX;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
getLinePoints(start, end).forEach(linePoint => {
|
|
381
|
+
let intersectionPoints = [];
|
|
382
|
+
getShapeLinePoints(coordinates).forEach(shapeLinePoint => {
|
|
383
|
+
const intersectionPoint = getIntersectionPoint(linePoint[0], linePoint[1], shapeLinePoint[0], shapeLinePoint[1]);
|
|
384
|
+
intersectionPoint && intersectionPoints.push(intersectionPoint);
|
|
385
|
+
});
|
|
386
|
+
intersectionPoints = sortPoints(uniquePoints(intersectionPoints));
|
|
387
|
+
if (intersectionPoints.length >= 2) {
|
|
388
|
+
for (let i = 0; i < intersectionPoints.length; i++) {
|
|
389
|
+
if (intersectionPoints[i + 1] && isInnerLine(intersectionPoints[i], intersectionPoints[i + 1])) {
|
|
390
|
+
result.push(createLine(intersectionPoints[i], intersectionPoints[i + 1]));
|
|
391
|
+
}
|
|
392
|
+
// i++;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
return result;
|
|
397
|
+
|
|
398
|
+
// 是否是外侧阴影
|
|
399
|
+
function isInnerLine(point1, point2) {
|
|
400
|
+
return isInPolygon([(point1[0] + point2[0]) / 2, (point1[1] + point2[1]) / 2], coordinates);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function normalizeAngle(angle) {
|
|
404
|
+
// 去除无用角度
|
|
405
|
+
angle = angle % 360;
|
|
406
|
+
// 负角度
|
|
407
|
+
angle = angle < 0 ? 180 - angle : angle;
|
|
408
|
+
// 大角度
|
|
409
|
+
angle = angle >= 180 ? angle - 180 : angle;
|
|
410
|
+
return angle;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function getLinePoints(start, end) {
|
|
414
|
+
const result = [completePoint([start, minY])];
|
|
415
|
+
|
|
416
|
+
while (start < end) {
|
|
417
|
+
start += space;
|
|
418
|
+
result.push(completePoint([start, minY]));
|
|
419
|
+
}
|
|
420
|
+
return result;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function completePoint(point) {
|
|
424
|
+
const otherPoint = [point[0] - offsetX, maxY];
|
|
425
|
+
return [point, otherPoint];
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function getShapeLinePoints(coordinates) {
|
|
429
|
+
return coordinates.reduce((res, c, idx) => {
|
|
430
|
+
const next = coordinates[idx + 1] || coordinates[0];
|
|
431
|
+
res.push([c, next]);
|
|
432
|
+
return res;
|
|
433
|
+
}, []);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function createLine(startPoint, endPoint) {
|
|
437
|
+
return new that.fabric.Line([startPoint[0], startPoint[1], endPoint[0], endPoint[1]], { ...that.defaultLineStyle, ...style });
|
|
438
|
+
}
|
|
343
439
|
}
|
|
344
440
|
}
|
|
345
441
|
};
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import cloneDeep from 'lodash/cloneDeep';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
name: 'drawExtracorporealCirculation',
|
|
5
|
+
data() {
|
|
6
|
+
this.extracorporealCirculation = cloneDeep(this.templateData.bottom?.extracorporealCirculation);
|
|
7
|
+
this.extracorporealCirculationObjs = [];
|
|
8
|
+
return {};
|
|
9
|
+
},
|
|
10
|
+
components: {},
|
|
11
|
+
methods: {
|
|
12
|
+
drawExtracorporealCirculation(extracorporealCirculation) {
|
|
13
|
+
const { endX, originX, endY, markHeight, canvasWidth } = this.propItems;
|
|
14
|
+
if (!markHeight || !extracorporealCirculation || !extracorporealCirculation.list?.length) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (this.extracorporealCirculationObjs.length) {
|
|
18
|
+
[...this.extracorporealCirculationObjs].forEach(obj => this.canvas.remove(obj));
|
|
19
|
+
this.extracorporealCirculationObjs = [];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { height = 20, extracorporealCirculationStyle, ascendAortaStyle, list = [] } = extracorporealCirculation;
|
|
23
|
+
const y2 = endY + height;
|
|
24
|
+
|
|
25
|
+
let prevEndX;
|
|
26
|
+
let prevLine;
|
|
27
|
+
|
|
28
|
+
list.forEach((item, index) => {
|
|
29
|
+
const xList = this.getExtracorporealCirculationX(item);
|
|
30
|
+
const idx = xList.findIndex(x => x > 0 && x < canvasWidth);
|
|
31
|
+
if (idx === -1) return;
|
|
32
|
+
|
|
33
|
+
let prevShadowBox;
|
|
34
|
+
xList.forEach((x, i) => {
|
|
35
|
+
const nextX = xList[i + 1];
|
|
36
|
+
const prevX = xList[i - 1];
|
|
37
|
+
if (isValid(x) || isValid(nextX)) {
|
|
38
|
+
const x1 = isValid(x) ? x : originX;
|
|
39
|
+
const x2 = isValid(nextX) ? nextX : endX;
|
|
40
|
+
const prevX1 = isValid(prevX) ? prevX : originX;
|
|
41
|
+
const shadowBox = {};
|
|
42
|
+
if (i < xList.length - 1) {
|
|
43
|
+
shadowBox.params = [x1, x2, y2, [0, 2].includes(i) ? extracorporealCirculationStyle : ascendAortaStyle];
|
|
44
|
+
shadowBox.shadowObjs = this.drawShadowBox(...shadowBox.params);
|
|
45
|
+
}
|
|
46
|
+
if (isValid(x)) {
|
|
47
|
+
const key = getKey(i);
|
|
48
|
+
const optLine = this.drawOptLine([x, endY, x, y2], {
|
|
49
|
+
origin: {
|
|
50
|
+
index,
|
|
51
|
+
key,
|
|
52
|
+
data: item[key]
|
|
53
|
+
},
|
|
54
|
+
limitX: {
|
|
55
|
+
x1: i === 0 ? prevEndX ?? originX : prevX1,
|
|
56
|
+
x2
|
|
57
|
+
},
|
|
58
|
+
...([1, 2, 3].includes(i) ? { leftShadowBox: prevShadowBox } : {}),
|
|
59
|
+
...([0, 1, 2].includes(i) ? { rightShadowBox: shadowBox } : {})
|
|
60
|
+
});
|
|
61
|
+
if (i === xList.length - 1) {
|
|
62
|
+
prevEndX = x;
|
|
63
|
+
prevLine = optLine;
|
|
64
|
+
}
|
|
65
|
+
if (i === 0 && prevLine) {
|
|
66
|
+
prevLine.limitX.x2 = shadowBox.params[0];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
prevShadowBox = shadowBox;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
function isValid(x) {
|
|
75
|
+
return x && x > 0 && x < canvasWidth;
|
|
76
|
+
}
|
|
77
|
+
function getKey(i) {
|
|
78
|
+
switch (i) {
|
|
79
|
+
case 0:
|
|
80
|
+
return 'extracorporealCirculationStart';
|
|
81
|
+
case 1:
|
|
82
|
+
return 'closeAscendAorta';
|
|
83
|
+
case 2:
|
|
84
|
+
return 'openAscendAorta';
|
|
85
|
+
case 3:
|
|
86
|
+
return 'extracorporealCirculationEnd';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
drawOptLine(coordinate, props) {
|
|
91
|
+
const optLine = new this.fabric.Line(coordinate, {
|
|
92
|
+
...props,
|
|
93
|
+
stroke: 'transparent',
|
|
94
|
+
strokeWidth: 5,
|
|
95
|
+
hasControls: false,
|
|
96
|
+
hasBorders: false,
|
|
97
|
+
hoverCursor: 'e-resize',
|
|
98
|
+
lockMovementY: true,
|
|
99
|
+
originX: 'center'
|
|
100
|
+
});
|
|
101
|
+
this.setExtracorporealCirculationEvent(optLine);
|
|
102
|
+
this.canvas.add(optLine);
|
|
103
|
+
this.extracorporealCirculationObjs.push(optLine);
|
|
104
|
+
return optLine;
|
|
105
|
+
},
|
|
106
|
+
setExtracorporealCirculationEvent(optLine) {
|
|
107
|
+
this.setPopup(optLine);
|
|
108
|
+
if (this.eventStyle.evented) {
|
|
109
|
+
optLine.on('moving', () => {
|
|
110
|
+
const { left, limitX } = optLine;
|
|
111
|
+
if (left < limitX.x1) {
|
|
112
|
+
optLine.setCoords().set({ x1: limitX.x1, x2: limitX.x1 });
|
|
113
|
+
}
|
|
114
|
+
if (left > limitX.x2) {
|
|
115
|
+
optLine.setCoords().set({ x1: limitX.x2, x2: limitX.x2 });
|
|
116
|
+
}
|
|
117
|
+
this.updateShadowBox(optLine, 'left');
|
|
118
|
+
this.updateShadowBox(optLine, 'right');
|
|
119
|
+
this.showDrapPopup(optLine);
|
|
120
|
+
});
|
|
121
|
+
optLine.on('moved', () => {
|
|
122
|
+
this.isDropVisible = false;
|
|
123
|
+
const params = optLine.origin;
|
|
124
|
+
params.data.time = this.getXValue(optLine.left);
|
|
125
|
+
this.$emit('extracorporealCirculationChange', params);
|
|
126
|
+
const { index, key, data } = params;
|
|
127
|
+
this.extracorporealCirculation.list[index][key] = data;
|
|
128
|
+
this.drawExtracorporealCirculation(this.extracorporealCirculation);
|
|
129
|
+
this.canvas.discardActiveObject();
|
|
130
|
+
this.canvas.forEachObject(obj => {
|
|
131
|
+
if (obj.type && obj.type === 'mark') {
|
|
132
|
+
obj.bringForward();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
updateShadowBox(optLine, direction) {
|
|
139
|
+
const { shadowObjs, params } = optLine[`${direction}ShadowBox`] || {};
|
|
140
|
+
if (!shadowObjs || !params) return;
|
|
141
|
+
shadowObjs.forEach(obj => this.canvas.remove(obj));
|
|
142
|
+
const idx = direction === 'left' ? 1 : 0;
|
|
143
|
+
params[idx] = optLine.left;
|
|
144
|
+
const _shadowObjs = this.drawShadowBox(...params);
|
|
145
|
+
optLine[`${direction}ShadowBox`] = {
|
|
146
|
+
shadowObjs: _shadowObjs,
|
|
147
|
+
params
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
drawShadowBox(x1, x2, y2, { mode, style }) {
|
|
151
|
+
const { endY } = this.propItems;
|
|
152
|
+
const _style = { ...style };
|
|
153
|
+
if (_style.angle) delete _style.angle;
|
|
154
|
+
const points = [
|
|
155
|
+
[x1, endY],
|
|
156
|
+
[x2, endY],
|
|
157
|
+
[x2, y2],
|
|
158
|
+
[x1, y2]
|
|
159
|
+
];
|
|
160
|
+
const polygon = new this.fabric.Polygon(
|
|
161
|
+
points.map(v => ({ x: v[0], y: v[1] })),
|
|
162
|
+
{
|
|
163
|
+
...this.defaultLineStyle,
|
|
164
|
+
..._style,
|
|
165
|
+
stroke: 'transparent',
|
|
166
|
+
...(['slash'].includes(mode) ? { fill: 'transparent' } : {})
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
const shadowLines = [];
|
|
170
|
+
if (['slash'].includes(mode)) {
|
|
171
|
+
// 斜线阴影模式
|
|
172
|
+
shadowLines.push(...this.drawShadow(points, style.angle, _style.space, _style));
|
|
173
|
+
}
|
|
174
|
+
this.canvas.add(polygon, ...shadowLines);
|
|
175
|
+
this.extracorporealCirculationObjs.push(...[polygon, ...shadowLines]);
|
|
176
|
+
return [polygon, ...shadowLines];
|
|
177
|
+
},
|
|
178
|
+
getExtracorporealCirculationX(item) {
|
|
179
|
+
const { extracorporealCirculationStart, closeAscendAorta, openAscendAorta, extracorporealCirculationEnd } = item;
|
|
180
|
+
let x1, x2, x3, x4;
|
|
181
|
+
if (extracorporealCirculationStart) {
|
|
182
|
+
x1 = this.computedX(extracorporealCirculationStart.time);
|
|
183
|
+
}
|
|
184
|
+
if (closeAscendAorta) {
|
|
185
|
+
x2 = this.computedX(closeAscendAorta.time);
|
|
186
|
+
}
|
|
187
|
+
if (openAscendAorta) {
|
|
188
|
+
x3 = this.computedX(openAscendAorta.time);
|
|
189
|
+
}
|
|
190
|
+
if (extracorporealCirculationEnd) {
|
|
191
|
+
x4 = this.computedX(extracorporealCirculationEnd.time);
|
|
192
|
+
}
|
|
193
|
+
return [x1, x2, x3, x4];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export const isNumber = num => {
|
|
2
|
+
return typeof num === 'number' && Number.isFinite(num);
|
|
3
|
+
};
|
|
4
|
+
export const isObject = obj => {
|
|
5
|
+
return Object.prototype.toString.call(obj) === '[object Object]';
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function getTangent(angle) {
|
|
9
|
+
return +Math.tan((angle * Math.PI) / 180);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function nearlyEqual(v1, v2) {
|
|
13
|
+
return Math.abs(v1 - v2) <= 0.0001;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function sortPoints(points) {
|
|
17
|
+
return points.sort((a, b) => a[1] - b[1]);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function uniquePoints(points) {
|
|
21
|
+
return points.reduce((fin, point) => {
|
|
22
|
+
if (!hasPoint(fin, point)) fin.push(point);
|
|
23
|
+
return fin;
|
|
24
|
+
}, []);
|
|
25
|
+
|
|
26
|
+
function hasPoint(points, point) {
|
|
27
|
+
return points.some(p => nearlyEqual(p[0], point[0]) && nearlyEqual(p[1], point[1]));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isInPolygon(checkPoint, polygonPoints) {
|
|
32
|
+
let counter = 0;
|
|
33
|
+
let xinters;
|
|
34
|
+
let p1, p2;
|
|
35
|
+
const pointCount = polygonPoints.length;
|
|
36
|
+
p1 = polygonPoints[0];
|
|
37
|
+
|
|
38
|
+
for (let i = 1; i <= pointCount; i++) {
|
|
39
|
+
p2 = polygonPoints[i % pointCount];
|
|
40
|
+
if (checkPoint[0] > Math.min(p1[0], p2[0]) && checkPoint[0] <= Math.max(p1[0], p2[0])) {
|
|
41
|
+
if (checkPoint[1] <= Math.max(p1[1], p2[1])) {
|
|
42
|
+
if (p1[0] != p2[0]) {
|
|
43
|
+
xinters = ((checkPoint[0] - p1[0]) * (p2[1] - p1[1])) / (p2[0] - p1[0]) + p1[1];
|
|
44
|
+
if (p1[1] == p2[1] || checkPoint[1] <= xinters) {
|
|
45
|
+
counter++;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
p1 = p2;
|
|
51
|
+
}
|
|
52
|
+
return counter % 2 !== 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getIntersectionPoint(a, b, c, d) {
|
|
56
|
+
/** 1 解线性方程组, 求线段交点. **/
|
|
57
|
+
// 如果分母为0 则平行或共线, 不相交
|
|
58
|
+
const denominator = (b[1] - a[1]) * (d[0] - c[0]) - (a[0] - b[0]) * (c[1] - d[1]);
|
|
59
|
+
if (denominator === 0) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 线段所在直线的交点坐标 (x , y)
|
|
64
|
+
const x = ((b[0] - a[0]) * (d[0] - c[0]) * (c[1] - a[1]) + (b[1] - a[1]) * (d[0] - c[0]) * a[0] - (d[1] - c[1]) * (b[0] - a[0]) * c[0]) / denominator;
|
|
65
|
+
const y = -((b[1] - a[1]) * (d[1] - c[1]) * (c[0] - a[0]) + (b[0] - a[0]) * (d[1] - c[1]) * a[1] - (d[0] - c[0]) * (b[1] - a[1]) * c[1]) / denominator;
|
|
66
|
+
|
|
67
|
+
/** 2 判断交点是否在两条线段上 **/
|
|
68
|
+
if (
|
|
69
|
+
// 交点在线段1上
|
|
70
|
+
((x - a[0]) * (x - b[0]) < 0 || nearlyEqual(x, a[0]) || nearlyEqual(x, b[0])) &&
|
|
71
|
+
((y - a[1]) * (y - b[1]) < 0 || nearlyEqual(y, a[1]) || nearlyEqual(y, b[1])) &&
|
|
72
|
+
// 且交点也在线段2上
|
|
73
|
+
((x - c[0]) * (x - d[0]) < 0 || nearlyEqual(x, c[0]) || nearlyEqual(x, d[0])) &&
|
|
74
|
+
((y - c[1]) * (y - d[1]) < 0 || nearlyEqual(y, c[1]) || nearlyEqual(y, d[1]))
|
|
75
|
+
) {
|
|
76
|
+
// 返回交点p
|
|
77
|
+
return [x, y];
|
|
78
|
+
}
|
|
79
|
+
// 否则不相交
|
|
80
|
+
return false;
|
|
81
|
+
}
|