Compare commits
157 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
34a20d3475 | ||
|
d8af8fb70a | ||
|
85de91411e | ||
|
c1356549ec | ||
|
f34617b7db | ||
|
71628dcdd2 | ||
|
2ef2d01fc0 | ||
|
bc9757f7b9 | ||
|
3341a29421 | ||
|
5dc7de9ded | ||
|
00359591b5 | ||
|
624b06fe85 | ||
|
4921b43e1b | ||
|
7b9bb93103 | ||
|
932b2e1d79 | ||
|
9b01aada15 | ||
|
da059a3c9c | ||
|
acefe20fc0 | ||
|
efac958ea0 | ||
|
ae686de0ab | ||
|
dc855fa6ef | ||
|
97f606a314 | ||
|
2e45db73e5 | ||
|
1a017ceed0 | ||
|
a686b8939e | ||
|
e03b492c1d | ||
|
c3587b4411 | ||
|
b3fbfbb3ad | ||
|
83a0e74a88 | ||
|
467d3e48cd | ||
|
45f9b1d9e2 | ||
|
da024251de | ||
|
00887b7409 | ||
|
1985b51f98 | ||
|
fce6f58eb0 | ||
|
18a51e7c26 | ||
|
5f62a24f08 | ||
|
1375fc4fbc | ||
|
3739fcc4ac | ||
|
2c69d7e145 | ||
|
173643eb37 | ||
|
6c2b475213 | ||
|
14ecacf811 | ||
|
c9ec52a7c9 | ||
|
5c19aab68c | ||
|
f78fa04842 | ||
|
aab9cb8bed | ||
|
b5582126ba | ||
|
4d37cc9267 | ||
|
760c683e3e | ||
|
1be38bdb76 | ||
|
a253ec5de5 | ||
|
bfaf8ea7d8 | ||
|
001a963b04 | ||
|
e5249cf4b3 | ||
|
04a0560339 | ||
|
6eb2ca001c | ||
|
1677cfc318 | ||
|
a7b5057f9e | ||
|
35d4ab4cfc | ||
|
4c3a511551 | ||
|
bd70771cf5 | ||
|
73d21dbca9 | ||
|
67f62970d7 | ||
|
54eef21574 | ||
|
bbba502ba7 | ||
|
9ceeb48562 | ||
|
8ad81f244f | ||
|
cfed96504b | ||
|
1fb3c04c37 | ||
|
edb841c38c | ||
|
9a7d6a007b | ||
|
e58d229abc | ||
|
f84d221857 | ||
|
26ed24d339 | ||
|
73caf6074b | ||
|
89f7d38a77 | ||
|
d1281b0346 | ||
|
53008131c6 | ||
|
c9b5c908a0 | ||
|
dcefdfab33 | ||
|
4357eec04f | ||
|
9d8ccd5a67 | ||
|
d24f91afc1 | ||
|
84d8a396f0 | ||
|
9917926a43 | ||
|
b7d2f79462 | ||
|
27bcdc52a0 | ||
|
50cb5b1ece | ||
|
eda8b8b42c | ||
|
62eb86e5ec | ||
|
d7ac074608 | ||
|
c123a04fd7 | ||
|
156a63ea02 | ||
|
97c4aaf20c | ||
|
fc2e4137f5 | ||
|
7ed95d2701 | ||
|
8e13a2190b | ||
|
e1a75e68a1 | ||
|
3240ca7760 | ||
|
31cc8f75c5 | ||
|
74d82f5872 | ||
|
cad7ff2129 | ||
|
1639866515 | ||
|
c735f4dd50 | ||
|
2508d084d0 | ||
|
1bf4583525 | ||
|
e6f7d8a207 | ||
|
4322001225 | ||
|
ae050fdc5b | ||
|
16fcf932ff | ||
|
b8ef4c33da | ||
|
e3900b6f9e | ||
|
5870a3814c | ||
|
333fe16661 | ||
|
3026eed365 | ||
|
f16c7e0b11 | ||
|
eb429506f5 | ||
|
870852b97a | ||
|
ca4c840da4 | ||
|
bf1818da69 | ||
|
0c87981d43 | ||
|
cb9aa77312 | ||
|
e2ffe1ca72 | ||
|
832513c750 | ||
|
6ebbdec414 | ||
|
2dbd0d7764 | ||
|
0a0ff63fec | ||
|
28242e5a2c | ||
|
67c5425b67 | ||
|
a56598888d | ||
|
abbc3b96d2 | ||
|
60cc0d06cb | ||
|
71367cf330 | ||
|
cc6f67dcc0 | ||
|
82f432136e | ||
|
143d6a67cc | ||
|
91fd06b695 | ||
|
8ae7ff5a8c | ||
|
62cd098bdd | ||
|
6a72265a7b | ||
|
3be099bdf8 | ||
|
134ccdaded | ||
|
d9a8baeb93 | ||
|
0381242401 | ||
|
7e66128000 | ||
|
15c1463f5a | ||
|
56aebd69e7 | ||
|
72fadaa866 | ||
|
9277754f5e | ||
|
e15e5703b4 | ||
|
ad7b55704e | ||
|
68a01f94f2 | ||
|
5150fe4651 | ||
|
df44298137 | ||
|
742d89f08a | ||
|
6b16e3d488 |
BIN
src/assets/iscs_picture/bg-door-stand-A.png
Normal file
BIN
src/assets/iscs_picture/bg-door-stand-A.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/iscs_picture/bg-door-station-A.png
Normal file
BIN
src/assets/iscs_picture/bg-door-station-A.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@ -78,6 +78,8 @@ import bgStationC from '@/assets/iscs_picture/bg-station-C.png'
|
||||
import bgStationD from '@/assets/iscs_picture/bg-station-D.png'
|
||||
import bgStationE from '@/assets/iscs_picture/bg-station-E.png'
|
||||
import bgStationF from '@/assets/iscs_picture/bg-station-F.png'
|
||||
import bgDoorStationA from '@/assets/iscs_picture/bg-door-station-A.png';
|
||||
import bgDoorStandA from '@/assets/iscs_picture/bg-door-stand-A.png';
|
||||
|
||||
const pictureObj = {
|
||||
'psdLeft': psdLeft,
|
||||
@ -155,7 +157,9 @@ const pictureObj = {
|
||||
bgStationC,
|
||||
bgStationD,
|
||||
bgStationE,
|
||||
bgStationF
|
||||
bgStationF,
|
||||
bgDoorStationA,
|
||||
bgDoorStandA
|
||||
};
|
||||
export default class Picture extends Group {
|
||||
constructor(device) {
|
||||
|
118
src/iscs_new/animateHandle.js
Normal file
118
src/iscs_new/animateHandle.js
Normal file
@ -0,0 +1,118 @@
|
||||
import Group from 'zrender/src/container/Group';
|
||||
|
||||
function traverse(group, map) {
|
||||
group.eachChild(el => {
|
||||
if (el instanceof Group) {
|
||||
traverse(el, map);
|
||||
} else {
|
||||
map[el.name] = el;
|
||||
}
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
class Animate {
|
||||
constructor(state) {
|
||||
this._state = {...state};
|
||||
this._sum = 0;
|
||||
this._count = 0;
|
||||
this._first = true;
|
||||
this._dispose = false;
|
||||
}
|
||||
|
||||
run(interval) {
|
||||
this._sum = this._sum + interval;
|
||||
const total = this._state.time + (this._first ? this._state.delay : 0);
|
||||
if (this._sum > total) {
|
||||
this.animate(this);
|
||||
this._count = this._count + 1;
|
||||
this._sum = 0;
|
||||
this._first = false;
|
||||
}
|
||||
}
|
||||
|
||||
isLoop() {
|
||||
return this._state.loop || this._count < this._state.frameList.length;
|
||||
}
|
||||
|
||||
isNeedDefault() {
|
||||
return this._state.needDefault;
|
||||
}
|
||||
|
||||
isDispose() {
|
||||
return this._dispose;
|
||||
}
|
||||
|
||||
isEqual(code) {
|
||||
return this._state.code == code;
|
||||
}
|
||||
|
||||
getIndex(index = 0) {
|
||||
return index || this._count % this._state.frameList.length;
|
||||
}
|
||||
|
||||
getFrame(index = 0) {
|
||||
return this._state.frameList[index];
|
||||
}
|
||||
|
||||
animate() {
|
||||
const shape = this._state.shape;
|
||||
const mapShape = this._state.mapShape;
|
||||
const index = this.getIndex();
|
||||
const frame = this.getFrame(index);
|
||||
if (shape && mapShape && frame) {
|
||||
const mapView = traverse(shape, {});
|
||||
if (this.isNeedDefault()) {
|
||||
Object.keys(mapShape).forEach(name => {
|
||||
const state = mapShape[name];
|
||||
const view = mapView[name];
|
||||
if (view) {
|
||||
shape.setInvisible(shape.model.base.hide);
|
||||
view.attr({shape: state.default.shape, style: state.default.style});
|
||||
view.dirty();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Object.keys(frame).forEach(name => {
|
||||
const view = mapView[name];
|
||||
const model = frame[name];
|
||||
if (view && model) {
|
||||
shape.setInvisible(model.hide);
|
||||
view.attr({shape: model.shape, style: model.style});
|
||||
view.dirty();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._dispose = true;
|
||||
}
|
||||
}
|
||||
|
||||
class AnimateHandle {
|
||||
constructor(painter) {
|
||||
this._animates = [];
|
||||
}
|
||||
|
||||
onframe(delay) {
|
||||
const animate = this._animates.shift();
|
||||
if (animate) {
|
||||
animate.run(delay);
|
||||
if (!animate.isDispose() && animate.isLoop()) {
|
||||
this._animates.push(animate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
animate(state) {
|
||||
const animate = this._animates.find(el => el.isEqual(state.code));
|
||||
if (animate) {
|
||||
animate.dispose();
|
||||
}
|
||||
this._animates.push(new Animate(state));
|
||||
}
|
||||
}
|
||||
|
||||
export default AnimateHandle;
|
3
src/iscs_new/config/defaultState.js
Normal file
3
src/iscs_new/config/defaultState.js
Normal file
@ -0,0 +1,3 @@
|
||||
export default {
|
||||
|
||||
}
|
30
src/iscs_new/config/defaultStyle.js
Normal file
30
src/iscs_new/config/defaultStyle.js
Normal file
@ -0,0 +1,30 @@
|
||||
const defaultStyle = {
|
||||
/** 透明填充 颜色*/
|
||||
transparentColor : 'transparent',
|
||||
|
||||
/** 默认背景 颜色*/
|
||||
backgroundColor : '#000000',
|
||||
|
||||
/** 默认字体 族类*/
|
||||
fontFamily : 'SimSun,Times New Roman',
|
||||
|
||||
/** 默认字体 大小*/
|
||||
fontSize : 12,
|
||||
|
||||
/** 选中透明度*/
|
||||
opacity : 0.5,
|
||||
|
||||
/** 提亮度*/
|
||||
liftLevel : 0.8,
|
||||
|
||||
/** 边框宽度*/
|
||||
borderWidth : 1,
|
||||
|
||||
/** 边框颜色*/
|
||||
borderColor : '#000',
|
||||
|
||||
/** 边框Dash*/
|
||||
borderDash: [4, 4]
|
||||
}
|
||||
|
||||
export default defaultStyle;
|
6
src/iscs_new/constant/shapeEvent.js
Normal file
6
src/iscs_new/constant/shapeEvent.js
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
ShowBorder: 'showBorder',
|
||||
HideBorder: 'hideBorder',
|
||||
ShowTips: 'showTips',
|
||||
HideTips: 'hideTips'
|
||||
}
|
5
src/iscs_new/constant/shapeLayer.js
Normal file
5
src/iscs_new/constant/shapeLayer.js
Normal file
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
HightLight: `__hightLight__`,
|
||||
Selecting: `___selecting__`,
|
||||
Tips: `__tips__`,
|
||||
}
|
8
src/iscs_new/constant/shapeRender.js
Normal file
8
src/iscs_new/constant/shapeRender.js
Normal file
@ -0,0 +1,8 @@
|
||||
export default {
|
||||
zlevel: 1,
|
||||
z: 9,
|
||||
scale: [1, 1],
|
||||
position: [0, 0],
|
||||
rotation: 0,
|
||||
origin: [0, 0]
|
||||
}
|
6
src/iscs_new/constant/shapeType.js
Normal file
6
src/iscs_new/constant/shapeType.js
Normal file
@ -0,0 +1,6 @@
|
||||
const shapeType = {
|
||||
Compose: 'Compose',
|
||||
Element: 'Element'
|
||||
};
|
||||
|
||||
export default shapeType;
|
351
src/iscs_new/controller.js
Normal file
351
src/iscs_new/controller.js
Normal file
@ -0,0 +1,351 @@
|
||||
import * as eventTool from 'zrender/src/core/event';
|
||||
import Storage from './utils/storage';
|
||||
import Eventful from 'zrender/src/mixin/Eventful';
|
||||
import DragHandle from './dragHandle';
|
||||
import SelectingHandle from './selectingHandle';
|
||||
import SelectHandle from './selectHandle';
|
||||
import KeyBoardHandle from './keyboardHandle';
|
||||
import events from './utils/events';
|
||||
|
||||
class MouseEvent {
|
||||
constructor(controller, e) {
|
||||
const shapeFactory = controller.$map.getShapeFactory();
|
||||
const shape = e.target;
|
||||
this.clientX = e.event.clientX;
|
||||
this.clientY = e.event.clientY;
|
||||
|
||||
if (shape && !['@ignore', '@selecting', '@border', '@drag'].includes(shape.subType)) {
|
||||
if (shape.code) {
|
||||
let composeCode = shape.composeCode;
|
||||
let compose = null;
|
||||
|
||||
while(composeCode) {
|
||||
compose = shapeFactory.getShapeByCode(composeCode);
|
||||
composeCode = compose.model.composeCode;
|
||||
}
|
||||
|
||||
this.code = compose? compose.code: shape.code;
|
||||
this.type = compose? compose.type: shape.type;
|
||||
}
|
||||
|
||||
if (shape.subType) {
|
||||
this.subType = shape.subType;
|
||||
}
|
||||
|
||||
if (shape.val) {
|
||||
this.val = shape.val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default class Controller extends Eventful {
|
||||
constructor(map) {
|
||||
super();
|
||||
this.$map = map;
|
||||
this.option = map.getOption();
|
||||
this.events = map.getEvents();
|
||||
this._pan =false;
|
||||
this._isNotLeftMouse = false;
|
||||
this._shortcuts = '';
|
||||
this._distance = 0;
|
||||
this._target = null;
|
||||
this.initModule(map);
|
||||
this.initHandler(map);
|
||||
}
|
||||
|
||||
initModule(map) {
|
||||
this.dragHandle = new DragHandle(map, this);
|
||||
this.selectingHandle = new SelectingHandle(map, this);
|
||||
this.selectHandle = new SelectHandle(map, this);
|
||||
this.keyBoardHandle = new KeyBoardHandle(map, this);
|
||||
this._storage = new Storage();
|
||||
}
|
||||
|
||||
initHandler(map) {
|
||||
const that = this;
|
||||
const zr = map.getZr();
|
||||
const keyupHandle = this.keyup.bind(this);
|
||||
const keydownHandle = this.keydown.bind(this);
|
||||
|
||||
const dragStartHandle = this.dragHandle.onDragStart;
|
||||
const draggingHandle = this.dragHandle.onDragging;
|
||||
const dragEndHandle = this.dragHandle.onDragEnd;
|
||||
const selectStartHandle = this.selectingHandle.onSelectStart;
|
||||
const selectingHandle = this.selectingHandle.onSelecting;
|
||||
const selectEndHandle = this.selectingHandle.onSelectEnd;
|
||||
const selectedHandle = this.selectHandle.onSelected;
|
||||
const boardKeyupHandle = this.keyBoardHandle.onKeyup;
|
||||
const boardKeydownHandle = this.keyBoardHandle.onKeydown;
|
||||
|
||||
this.on(this.events.__DragStart, dragStartHandle, this.dragHandle); // 单个元素拖拽
|
||||
this.on(this.events.__Dragging, draggingHandle, this.dragHandle);
|
||||
this.on(this.events.__DragEnd, dragEndHandle, this.dragHandle);
|
||||
this.on(this.events.__SelectStart, selectStartHandle, this.selectingHandle);
|
||||
this.on(this.events.__Selecting, selectingHandle, this.selectingHandle);
|
||||
this.on(this.events.__SelectEnd, selectEndHandle, this.selectingHandle);
|
||||
this.on(this.events.__Selected, selectedHandle, this.selectHandle);
|
||||
|
||||
zr.on('click', this.click, this);
|
||||
zr.on('contextmenu', this.contextmenu, this);
|
||||
|
||||
this.enable = function (opts={}) {
|
||||
that._panEnable = opts.panEnable || that._panEnable || false;
|
||||
that._zoomEnable = opts.zoomEnable || that._zoomEnable || false;
|
||||
that._keyEnable = opts.keyEnable || that._keyEnable || false;
|
||||
that._dragEnable = opts.draggle || that._dragEnable || false;
|
||||
that._areaSelectEnable = opts.selecting || that._areaSelectEnable || false;
|
||||
that._selectEnable = opts.selectable || that._selectEnable || false;
|
||||
that._reflectEnable = opts.reflect || that._reflectEnable || false;
|
||||
that._preventDefaultMouseMove = opts.preventDefaultMouseMove || that._preventDefaultMouseMove|| true;
|
||||
that.disable();
|
||||
|
||||
zr.on('mousedown', that.mousedown, that);
|
||||
zr.on('mousemove', that.mousemove, that);
|
||||
zr.on('mouseup', that.mouseup, that);
|
||||
zr.on('globalout', that.mouseup, that);
|
||||
zr.on('mousewheel', that.mousewheel, that);
|
||||
|
||||
zr.dom.addEventListener('keyup', keyupHandle, false);
|
||||
zr.dom.addEventListener('keydown', keydownHandle, false);
|
||||
zr.dom.focus();
|
||||
|
||||
that.on(that.events.__Keyup, boardKeyupHandle, that.keyBoardHandle);
|
||||
that.on(that.events.__Keydown, boardKeydownHandle, that.keyBoardHandle);
|
||||
};
|
||||
|
||||
this.disable = function () {
|
||||
zr.off('mousedown', that.mousedown);
|
||||
zr.off('mousemove', that.mousemove);
|
||||
zr.off('mouseup', that.mouseup);
|
||||
zr.off('globalout', that.mouseup);
|
||||
zr.off('mousewheel', that.mousewheel);
|
||||
|
||||
zr.dom.removeEventListener('keyup', keyupHandle, false);
|
||||
zr.dom.removeEventListener('keydown', keydownHandle, false);
|
||||
|
||||
that.off(that.events.__Keyup, boardKeyupHandle);
|
||||
that.off(that.events.__Keydown, boardKeydownHandle);
|
||||
};
|
||||
|
||||
this.dispose = function () {
|
||||
zr.off('click', that.click);
|
||||
zr.off('contextmenu', that.contextmenu);
|
||||
that.off(that.events.__DragStart, dragStartHandle);
|
||||
that.off(that.events.__Dragging, draggingHandle);
|
||||
that.off(that.events.__DragEnd, dragEndHandle);
|
||||
that.off(that.events.__SelectStart, selectStartHandle);
|
||||
that.off(that.events.__Selecting, selectingHandle);
|
||||
that.off(that.events.__SelectEnd, selectEndHandle);
|
||||
that.off(that.events.__Selected, selectedHandle);
|
||||
that.disable();
|
||||
};
|
||||
}
|
||||
|
||||
isSpecialSubType(e) {
|
||||
return ['@ignore', '@selecting', '@drag', '@border'].includes(e.subType);
|
||||
}
|
||||
|
||||
isSelected(code) {
|
||||
return this._storage.has(code)
|
||||
}
|
||||
|
||||
setTarget(target) {
|
||||
this._target = target;
|
||||
}
|
||||
|
||||
setCursorStyle(cursorStyle) {
|
||||
this.$map.setCursorStyle(cursorStyle);
|
||||
}
|
||||
|
||||
limitDrag(e) {
|
||||
const dx2 = Math.pow(e.dx, 2);
|
||||
const dy2 = Math.pow(e.dy, 2);
|
||||
const scale = this.option.getScaleRate();
|
||||
const diff = Math.ceil(Math.sqrt(dx2+dy2));
|
||||
return (scale > 1) || (diff > 2/scale);
|
||||
}
|
||||
|
||||
mousedown(e) {
|
||||
const event = new MouseEvent(this, e);
|
||||
const zr = this.$map.getZr();
|
||||
|
||||
this._x = e.offsetX;
|
||||
this._y = e.offsetY;
|
||||
this._pan = false;
|
||||
this._target = this.$map.getShapeByCode(event.code);
|
||||
|
||||
zr.dom.focus();
|
||||
this._isNotLeftMouse = eventTool.isMiddleOrRightButtonOnMouseUpDown(e);
|
||||
this.trigger(events.Click, this._target);
|
||||
this.selectingHandle.clear();
|
||||
|
||||
if (this._isNotLeftMouse) {
|
||||
this.setCursorStyle('grab');
|
||||
} else {
|
||||
if (this.isSpecialSubType(event)) { return; }
|
||||
if (this._dragEnable) {
|
||||
this.trigger(this.events.__DragStart, { x: e.offsetX, y: e.offsetY, code: event.code });
|
||||
}
|
||||
|
||||
if (this._areaSelectEnable) {
|
||||
this.trigger(this.events.__SelectStart, { x: e.offsetX, y: e.offsetY});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mousemove(e) {
|
||||
const oldX = this._x;
|
||||
const oldY = this._y;
|
||||
const target = this._target||{}
|
||||
const dx = Math.round(e.offsetX - this._x);
|
||||
const dy = Math.round(e.offsetY - this._y);
|
||||
|
||||
this._x = e.offsetX;
|
||||
this._y = e.offsetY;
|
||||
this._preventDefaultMouseMove && eventTool.stop(e.event);
|
||||
|
||||
if (this._isNotLeftMouse) {
|
||||
if (this._panEnable) {
|
||||
if (dx**2 + dy**2 > 8) {
|
||||
this._pan = true;
|
||||
}
|
||||
this.trigger(this.events.__Pan, { dx, dy, oldX, oldY, newX: this._x, newY: this._y });
|
||||
this.setCursorStyle('grabbing');
|
||||
}
|
||||
} else {
|
||||
if (this._dragEnable && this.dragHandle.isDragging()) {
|
||||
this.selectingHandle.clear();
|
||||
if (this.limitDrag({dx, dy})) {
|
||||
this.trigger(this.events.__Dragging, { dx, dy });
|
||||
if (this._reflectEnable) {
|
||||
this.trigger(events.Reflect, {dx, dy, code: target.code});
|
||||
}
|
||||
} else {
|
||||
this._x = oldX;
|
||||
this._y = oldY;
|
||||
}
|
||||
} else if (this._areaSelectEnable && this.selectingHandle.isSelecting()) {
|
||||
this.trigger(this.events.__Selecting, { x: e.offsetX, y: e.offsetY });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mouseup(e) {
|
||||
const target = this._target;
|
||||
if (this._isNotLeftMouse) {
|
||||
this._isNotLeftMouse = false;
|
||||
this.setCursorStyle('auto');
|
||||
} else {
|
||||
if (this._selectEnable && target) {
|
||||
this.trigger(this.events.__Selected, { target });
|
||||
}
|
||||
|
||||
if (this._dragEnable && this.dragHandle.isDragging()) {
|
||||
this.selectingHandle.clear();
|
||||
this.trigger(this.events.__DragEnd, {x: e.offsetX, y: e.offsetY});
|
||||
} else if (this._areaSelectEnable && this.selectingHandle.isSelecting()) {
|
||||
this.trigger(this.events.__SelectEnd, { x: e.offsetX, y: e.offsetY });
|
||||
}
|
||||
}
|
||||
this._target = null;
|
||||
}
|
||||
|
||||
mousewheel(e) {
|
||||
const zoomEnable = this._zoomEnable;
|
||||
const wheelDelta = e.wheelDelta;
|
||||
const originX = Math.ceil(e.offsetX);
|
||||
const originY = Math.ceil(e.offsetY);
|
||||
|
||||
if (wheelDelta === 0 || !zoomEnable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (zoomEnable) {
|
||||
eventTool.stop(e.event);
|
||||
|
||||
let scale = 1;
|
||||
if (wheelDelta > 0) {
|
||||
scale = 1;
|
||||
this.setCursorStyle('zoom-in');
|
||||
} else if (wheelDelta < 0) {
|
||||
scale = -1;
|
||||
this.setCursorStyle('zoom-out');
|
||||
}
|
||||
|
||||
this.trigger(this.events.__Zoom, {type: this.events.__Zoom, scale, originX, originY });
|
||||
}
|
||||
}
|
||||
|
||||
click(e) {
|
||||
const event = new MouseEvent(this, e);
|
||||
if (!event.code) {
|
||||
this.selectHandle.clear();
|
||||
this.selectingHandle.clear();
|
||||
this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
contextmenu(e) {
|
||||
eventTool.stop(e.event);
|
||||
|
||||
const event = new MouseEvent(this, e);
|
||||
if (!this._pan) {
|
||||
this.trigger(events.ContextMenu, event);
|
||||
}
|
||||
|
||||
this._pan = false;
|
||||
}
|
||||
|
||||
keydown(e) {
|
||||
let shortcuts = e.key;
|
||||
|
||||
if (e.altKey && e.key != 'Alt') {
|
||||
shortcuts = `Alt_${shortcuts}`;
|
||||
}
|
||||
|
||||
if (e.shiftKey && e.key != 'Shift') {
|
||||
shortcuts = `Shift_${shortcuts}`;
|
||||
}
|
||||
|
||||
if (e.ctrlKey && e.key != 'Control') {
|
||||
shortcuts = `Control_${shortcuts}`;
|
||||
}
|
||||
|
||||
this._shortcuts = shortcuts;
|
||||
this.trigger(this.events.__Keydown, {key: shortcuts});
|
||||
this.trigger(events.Keydown, {key: shortcuts});
|
||||
}
|
||||
|
||||
keyup(e) {
|
||||
this.trigger(this.events.__Keyup, {key: this._shortcuts});
|
||||
this.trigger(events.Keyup, {key: this._shortcuts})
|
||||
this._shortcuts = '';
|
||||
}
|
||||
|
||||
clear() {
|
||||
const shapeFactory = this.$map.getShapeFactory();
|
||||
this._storage.values().forEach(shape => shapeFactory.hideHightLight(shape));
|
||||
this._storage.clear();
|
||||
this._storage.clearClipboard();
|
||||
this._target = null;
|
||||
this._pan = false;
|
||||
}
|
||||
|
||||
getStorage() {
|
||||
return this._storage;
|
||||
}
|
||||
|
||||
getKeyStr() {
|
||||
return this._shortcuts;
|
||||
}
|
||||
|
||||
getTarget() {
|
||||
return this._target;
|
||||
}
|
||||
|
||||
destroy () {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
100
src/iscs_new/core/abstractShape.js
Normal file
100
src/iscs_new/core/abstractShape.js
Normal file
@ -0,0 +1,100 @@
|
||||
import * as graphic from '../core/graphic';
|
||||
import * as utils from '../utils/utils';
|
||||
import * as color from 'zrender/src/tool/color';
|
||||
import Group from 'zrender/src/container/Group';
|
||||
import shapeRender from '../constant/shapeRender';
|
||||
import defaultStyle from '../config/defaultStyle';
|
||||
|
||||
function shapeStyleBuilder({subType, model}) {
|
||||
return {
|
||||
subType: subType,
|
||||
...shapeRender,
|
||||
code: model.code,
|
||||
type: model.type,
|
||||
z: 9998,
|
||||
cursor: 'pointer',
|
||||
shape: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0
|
||||
},
|
||||
style: {
|
||||
lineWidth: defaultStyle.borderWidth,
|
||||
stroke: color.lift(defaultStyle.borderColor, defaultStyle.liftLevel),
|
||||
fill: `rgba(200,200,200,0.5)`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 图形抽象层
|
||||
// 继承Group是为了直接获取的到包围框不需要进行坐标变化。
|
||||
class AbstractShape extends Group {
|
||||
constructor({model, shapeType, shapeFactory}) {
|
||||
super({...shapeRender, code: model.code, type: model.type});
|
||||
this.model = model;
|
||||
this.shapeType = shapeType;
|
||||
this.shapeFactory = shapeFactory;
|
||||
this.instanceHightLight = new graphic.Rect(shapeStyleBuilder({subType: '@align', model: this.model}));
|
||||
}
|
||||
|
||||
// 设置高亮
|
||||
active() {}
|
||||
|
||||
// 取消高亮
|
||||
inactive() {}
|
||||
|
||||
// 设置获取焦点
|
||||
focus() {}
|
||||
|
||||
// 设置取消焦点
|
||||
blur() {}
|
||||
|
||||
// 绑定数据
|
||||
combine() {}
|
||||
|
||||
// 解除绑定
|
||||
uncouple() {}
|
||||
|
||||
// 获取依赖图形
|
||||
getDepShapes() {}
|
||||
|
||||
// 设置状态
|
||||
setState(state) {}
|
||||
|
||||
// 拖动
|
||||
drift({dx, dy}) {
|
||||
this.model.base.position[0] = this.model.base.position[0] + dx;
|
||||
this.model.base.position[1] = this.model.base.position[1] + dy;
|
||||
this.instance.scale = this.model.base.scale;
|
||||
this.instance.position = this.model.base.position;
|
||||
this.instance.rotation = this.model.base.rotation*Math.PI/180;
|
||||
this.instance.origin = utils.createOrigin(this.instance);
|
||||
this.instance.transform = utils.createTransform({scale: this.model.base.scale, position: this.model.base.position, rotation: this.model.base.rotation*Math.PI/180});
|
||||
this.setInvisible(this.model.base.hide)
|
||||
}
|
||||
|
||||
// 修改状态
|
||||
attr(attrs) {
|
||||
this.instance? this.instance.attr(attrs): super.attr(attrs);
|
||||
}
|
||||
|
||||
// 设置显隐
|
||||
setInvisible(hide) {
|
||||
hide ? super.hide() : super.show();
|
||||
super.dirty();
|
||||
}
|
||||
|
||||
// 遍历执行
|
||||
traverse(cb) {
|
||||
this.eachChild(el => {
|
||||
if (el.traverse) {
|
||||
el.traverse(cb, el);
|
||||
} else {
|
||||
cb.call(el);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default AbstractShape;
|
859
src/iscs_new/core/form/elementConst.js
Normal file
859
src/iscs_new/core/form/elementConst.js
Normal file
@ -0,0 +1,859 @@
|
||||
|
||||
import * as graphic from '../../core/graphic';
|
||||
import form2ShapeStyle from './form2ShapeStyle';
|
||||
import form2TextStyle from './form2TextStyle';
|
||||
import types from './types';
|
||||
const graphicType = Object.fromEntries(Object.keys(graphic).map(type => [type, type]));
|
||||
|
||||
const elementConst = {
|
||||
[graphicType.Line]: {
|
||||
type: graphicType.Line,
|
||||
name:'线段',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'x1',
|
||||
label: '起始点横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入起始点横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'y1',
|
||||
label: '起始点纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入起始点纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 100,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'x2',
|
||||
label: '终止点横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入终止点横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 100,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'y2',
|
||||
label: '终止点纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入终止点纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: ''}
|
||||
// opts.shape.percent number 1 已显示的百分比,用于绘制动画。
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Text]: {
|
||||
type: graphicType.Text,
|
||||
name:'文字',
|
||||
formList: {
|
||||
style: [
|
||||
...form2TextStyle
|
||||
],
|
||||
shape: [
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Rect]: {
|
||||
type: graphicType.Rect,
|
||||
name:'矩形',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle,
|
||||
{
|
||||
prop: 'fill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: '填充样式。'
|
||||
}
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'x',
|
||||
label: '左上角横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入左上角横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'y',
|
||||
label: '左上角纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入左上角纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'width',
|
||||
label: '宽度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入宽度', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'height',
|
||||
label: '高度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入高度', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'r',
|
||||
label: '圆角矩形半径',
|
||||
type: types.NumberArray,
|
||||
precision: 0,
|
||||
step:1,
|
||||
length:4,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆角矩形半径', trigger: 'blur' }
|
||||
],
|
||||
value: [0, 0, 0, 0],
|
||||
description: '用于创建圆角矩形。左上、右上、右下、左下角的半径依次为 r1、 r2、 r3、 r4。[1, 1, 1, 1]'
|
||||
}]
|
||||
}
|
||||
},
|
||||
[graphicType.Circle]: {
|
||||
type: graphicType.Circle,
|
||||
name:'圆形',
|
||||
formList:{
|
||||
style: [
|
||||
...form2ShapeStyle,
|
||||
{
|
||||
prop: 'fill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: '填充样式。'
|
||||
}
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'cx',
|
||||
label: '圆心横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心横坐标'},
|
||||
{
|
||||
prop: 'cy',
|
||||
label: '圆心纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心纵坐标'
|
||||
},
|
||||
{
|
||||
prop: 'r',
|
||||
label: '半径',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入半径', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: '半径'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Polygon]: {
|
||||
type: graphicType.Polygon,
|
||||
name:'多边形',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle,
|
||||
{
|
||||
prop: 'fill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: '填充样式。'
|
||||
}
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'points',
|
||||
label: '坐标集合',
|
||||
type: types.Points,
|
||||
precision: 0, step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入坐标集合', trigger: 'blur' }
|
||||
],
|
||||
value: [[0, 0], [100, 100], [100, 200]],
|
||||
description: '每个元素是一个横纵坐标的数组'
|
||||
},
|
||||
{
|
||||
prop: 'smooth',
|
||||
label: '圆滑程度',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.05,
|
||||
precision: 2,
|
||||
rules:[
|
||||
{ required: true, message:'请输入坐标集合', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '取值范围为 0 到 1 之间的数字,0 表示不圆滑'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
// [graphicType.Arrow]: {
|
||||
// type: graphicType.Arrow,
|
||||
// name:'箭头',
|
||||
// formList: {
|
||||
// style: [
|
||||
|
||||
// ],
|
||||
// shape: [
|
||||
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
[graphicType.Polyline]: {
|
||||
type: graphicType.Polyline,
|
||||
name:'多边形折线段',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'points',
|
||||
label: '坐标集合',
|
||||
type: types.Points,
|
||||
precision: 0, step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入坐标集合', trigger: 'blur' }
|
||||
],
|
||||
value: [[0, 0], [100, 100], [100, 200]],
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'smooth',
|
||||
label: '圆滑程度',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.05,
|
||||
precision: 2,
|
||||
rules:[
|
||||
{ required: true, message:'请输入坐标集合', trigger: 'blur' }
|
||||
],
|
||||
value: 10,
|
||||
description: '取值范围为 0 到 1 之间的数字,0 表示不圆滑'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Isogon]: {
|
||||
type: graphicType.Isogon,
|
||||
name:'正多边形',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle,
|
||||
{
|
||||
prop: 'fill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: '填充样式。'
|
||||
}
|
||||
],
|
||||
shape:[
|
||||
{
|
||||
prop: 'x',
|
||||
label: '圆心横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心横坐标'
|
||||
},
|
||||
{
|
||||
prop: 'y',
|
||||
label: '圆心纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心纵坐标'
|
||||
},
|
||||
{
|
||||
prop: 'r',
|
||||
label: '半径',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入半径', trigger: 'blur' }
|
||||
],
|
||||
value: 40,
|
||||
description: '半径'
|
||||
},
|
||||
{
|
||||
prop: 'n',
|
||||
label: '边数',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入边数', trigger: 'blur' }
|
||||
],
|
||||
value: 5,
|
||||
description: '边数'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Ellipse]: {
|
||||
type: graphicType.Ellipse,
|
||||
name:'椭圆',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle,
|
||||
{
|
||||
prop: 'fill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: '填充样式。'
|
||||
}
|
||||
],
|
||||
shape:[
|
||||
{
|
||||
prop: 'cx',
|
||||
label: '圆心横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心横坐标'
|
||||
},
|
||||
{
|
||||
prop: 'cy',
|
||||
label: '圆心纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心纵坐标'
|
||||
},
|
||||
{
|
||||
prop: 'rx',
|
||||
label: '横向半径',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入横向半径', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: '横向半径'
|
||||
},
|
||||
{
|
||||
prop: 'ry',
|
||||
label: '纵向半径',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入纵向半径', trigger: 'blur' }
|
||||
],
|
||||
value: 30,
|
||||
description: '纵向半径'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Arc]: {
|
||||
type: graphicType.Arc,
|
||||
name:'圆弧',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'cx',
|
||||
label: '圆心横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心横坐标'
|
||||
},
|
||||
{
|
||||
prop: 'cy',
|
||||
label: '圆心纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心纵坐标'
|
||||
},
|
||||
{
|
||||
prop: 'r',
|
||||
label: '半径',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入半径', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: '半径'
|
||||
},
|
||||
{
|
||||
prop: 'startAngle',
|
||||
label: '起始弧度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
min: 0,
|
||||
max: 360,
|
||||
rules:[
|
||||
{ required: true, message:'请输入起始弧度', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '起始弧度'
|
||||
},
|
||||
{
|
||||
prop: 'endAngle',
|
||||
label: '终止弧度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
min: 0,
|
||||
max: 360,
|
||||
rules:[
|
||||
{ required: true, message:'请输入终止弧度', trigger: 'blur' }
|
||||
],
|
||||
value: 180,
|
||||
description: '终止弧度'
|
||||
},
|
||||
{
|
||||
prop: 'clockwise',
|
||||
label: '顺时针方向',
|
||||
type: types.Boolean,
|
||||
rules:[
|
||||
{ required: true, message:'请选择图形是否不可见', trigger: 'change' }
|
||||
],
|
||||
value: true,
|
||||
description: '顺时针方向。'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Sector]: {
|
||||
type: graphicType.Sector,
|
||||
name:'扇形',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle,
|
||||
{
|
||||
prop: 'fill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: '填充样式。'
|
||||
}
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'cx',
|
||||
label: '圆心横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心横坐标'
|
||||
},
|
||||
{
|
||||
prop: 'cy',
|
||||
label: '圆心纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心纵坐标'
|
||||
},
|
||||
{
|
||||
prop: 'r',
|
||||
label: '半径',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入半径', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: '半径'
|
||||
},
|
||||
{
|
||||
prop: 'r0',
|
||||
label: '内半径',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入内半径', trigger: 'blur' }
|
||||
],
|
||||
value: 30,
|
||||
description: '内半径'
|
||||
},
|
||||
{
|
||||
prop: 'startAngle',
|
||||
label: '起始弧度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
min: 0,
|
||||
max: 360,
|
||||
rules:[
|
||||
{ required: true, message:'请输入起始弧度', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '起始弧度'
|
||||
},
|
||||
{
|
||||
prop: 'endAngle',
|
||||
label: '终止弧度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
min: 0,
|
||||
max: 360,
|
||||
rules:[
|
||||
{ required: true, message:'请输入终止弧度', trigger: 'blur' }
|
||||
],
|
||||
value: 180,
|
||||
description: '终止弧度'
|
||||
},
|
||||
{
|
||||
prop: 'clockwise',
|
||||
label: '顺时针方向',
|
||||
type: types.Boolean,
|
||||
rules:[
|
||||
{ required: true, message:'请选择图形是否不可见', trigger: 'change' }
|
||||
],
|
||||
value: true,
|
||||
description: '顺时针方向。'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Heart]: {
|
||||
type: graphicType.Heart,
|
||||
name:'心形',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle,
|
||||
{
|
||||
prop: 'fill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: '填充样式。'
|
||||
}
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'cx',
|
||||
label: '圆心横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心横坐标'
|
||||
},
|
||||
{
|
||||
prop: 'cy',
|
||||
label: '圆心纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心纵坐标'
|
||||
},
|
||||
{
|
||||
prop: 'width',
|
||||
label: '宽度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入宽度', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: '宽度'
|
||||
},
|
||||
{
|
||||
prop: 'height',
|
||||
label: '高度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入高度', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: '高度'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Droplet]: {
|
||||
type: graphicType.Droplet,
|
||||
name:'水滴',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle,
|
||||
{
|
||||
prop: 'fill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: '填充样式。'
|
||||
}
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'cx',
|
||||
label: '圆心横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心横坐标'},
|
||||
{
|
||||
prop: 'cy',
|
||||
label: '圆心纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '圆心纵坐标'
|
||||
},
|
||||
{
|
||||
prop: 'width',
|
||||
label: '宽度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入宽度', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: '宽度'
|
||||
},
|
||||
{
|
||||
prop: 'height',
|
||||
label: '高度',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入高度', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: '高度'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
[graphicType.Star]: {
|
||||
type: graphicType.Star,
|
||||
name:'星形',
|
||||
formList: {
|
||||
style: [
|
||||
...form2ShapeStyle,
|
||||
{
|
||||
prop: 'fill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: '填充样式。'
|
||||
}
|
||||
],
|
||||
shape: [
|
||||
{
|
||||
prop: 'cx',
|
||||
label: '圆心横坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心横坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'cy',
|
||||
label: '圆心纵坐标',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入圆心纵坐标', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'n',
|
||||
label: '瓣数',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入瓣数', trigger: 'blur' }
|
||||
],
|
||||
value: 5,
|
||||
description: '如瓣数等于 5 时,是我们熟悉的五角星。'
|
||||
},
|
||||
{
|
||||
prop: 'r',
|
||||
label: '半径',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入半径', trigger: 'blur' }
|
||||
],
|
||||
value: 10,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'r0',
|
||||
label: '内半径',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入内半径', trigger: 'blur' }
|
||||
],
|
||||
value: 5,
|
||||
description: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
export default elementConst;
|
86
src/iscs_new/core/form/form2Base.js
Normal file
86
src/iscs_new/core/form/form2Base.js
Normal file
@ -0,0 +1,86 @@
|
||||
import types from './types';
|
||||
|
||||
export default [
|
||||
{
|
||||
prop: 'z1',
|
||||
label: '层级z1',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
min:0,
|
||||
max:20,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入层级z', trigger: 'blur' }
|
||||
],
|
||||
value: 10,
|
||||
description: '控制图形的前后顺序。'
|
||||
},
|
||||
{
|
||||
prop: 'z2',
|
||||
label: '层级z2',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入层级z2', trigger: 'blur' }
|
||||
],
|
||||
value: 50,
|
||||
description: '控制图形的前后顺序。z2 值小的图形会被 z2 值大的图形覆盖。z2 相比 z1 优先级更低。'
|
||||
},
|
||||
{
|
||||
prop: 'hide',
|
||||
label: '是否隐藏',
|
||||
type: types.Boolean,
|
||||
rules:[
|
||||
{ required: true, message:'请选择图形是否不可见', trigger: 'blur' }
|
||||
],
|
||||
value: false,
|
||||
description: '图形是否不可见,选中时不绘制图形。'
|
||||
},
|
||||
{
|
||||
prop: 'position',
|
||||
label: '位置',
|
||||
type: types.NumberArray,
|
||||
length:2,
|
||||
precision: 0,
|
||||
min:0,
|
||||
max:20000,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入位置', trigger: 'blur' }
|
||||
],
|
||||
value: [0, 0],
|
||||
description: '控制图形的位置。'
|
||||
},
|
||||
{
|
||||
prop: 'scale',
|
||||
label: '缩放',
|
||||
type: types.NumberArray,
|
||||
length:2,
|
||||
precision: 0,
|
||||
min:0.1,
|
||||
max:1,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入缩放', trigger: 'blur' }
|
||||
],
|
||||
value: [1, 1],
|
||||
description: '控制图形的缩放。'
|
||||
},
|
||||
{
|
||||
prop: 'rotation',
|
||||
label: '旋转',
|
||||
type: types.Number,
|
||||
precision: 0,
|
||||
min:0,
|
||||
max:360,
|
||||
step:1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入旋转', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '控制图形的旋转。'
|
||||
}
|
||||
];
|
120
src/iscs_new/core/form/form2ShapeStyle.js
Normal file
120
src/iscs_new/core/form/form2ShapeStyle.js
Normal file
@ -0,0 +1,120 @@
|
||||
import types from './types';
|
||||
|
||||
export default [
|
||||
{
|
||||
prop: 'lineWidth',
|
||||
label: '线宽',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
precision: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入线宽', trigger: 'blur' }
|
||||
],
|
||||
value: 1,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'opacity',
|
||||
label: '不透明度',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.05,
|
||||
precision: 2,
|
||||
rules:[
|
||||
{ required: true, message:'请输入不透明度', trigger: 'blur' }
|
||||
],
|
||||
value: 1,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'stroke',
|
||||
label: '描边样式',
|
||||
type: types.Color,
|
||||
value: '#000',
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'lineDash',
|
||||
label: '描边虚线',
|
||||
type: types.NumberArray,
|
||||
length:2,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
precision: 0,
|
||||
value: [0, 0],
|
||||
description: '描边虚线样式,参考 SVG stroke-dasharray。'
|
||||
},
|
||||
{
|
||||
prop: 'lineDashOffset',
|
||||
label: '描边虚线偏移',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
precision: 0,
|
||||
value: [0, 0],
|
||||
description: '描边虚线偏移,参考 SVG stroke-dashoffset。'
|
||||
},
|
||||
{
|
||||
prop: 'shadowColor',
|
||||
label: '阴影颜色',
|
||||
type: types.Color,
|
||||
value: 'rgba(0,0,0,0)',
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'shadowOffsetX',
|
||||
label: '阴影横向偏移',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
precision: 0,
|
||||
value: 0,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'shadowOffsetY',
|
||||
label: '阴影纵向偏移',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
precision: 0,
|
||||
value: 0,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'shadowBlur',
|
||||
label: '阴影模糊大小',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
precision: 0,
|
||||
value: 0,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'strokeNoScale',
|
||||
label: '描边不缩放',
|
||||
type: types.Boolean,
|
||||
value: false,
|
||||
description: '不选中时则会根据缩放同比例缩放描边粗细。'
|
||||
// 描边粗细不随缩放而改变,
|
||||
}
|
||||
// {
|
||||
// prop: 'blend',
|
||||
// label: '混合模式',
|
||||
// type: types.String,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入混合模式', trigger: 'blur' }
|
||||
// ],
|
||||
// value: '',
|
||||
// description: '混合模式,同 Canvas globalCompositeOperation。'
|
||||
// }
|
||||
];
|
416
src/iscs_new/core/form/form2TextStyle.js
Normal file
416
src/iscs_new/core/form/form2TextStyle.js
Normal file
@ -0,0 +1,416 @@
|
||||
import types from './types';
|
||||
|
||||
export default [
|
||||
{
|
||||
prop: 'text',
|
||||
label: '内容',
|
||||
type: types.String,
|
||||
rules:[
|
||||
{ required: true, message:'请输入内容', trigger: 'blur' }
|
||||
],
|
||||
value: '内容',
|
||||
maxlength:1000,
|
||||
description: ''
|
||||
},
|
||||
// {
|
||||
// prop: 'font',
|
||||
// label: '文字样式',
|
||||
// type: types.String,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字样式', trigger: 'blur' }
|
||||
// ],
|
||||
// value: '',
|
||||
// description: '文字样式,由 fontSize、 fontFamily、 fontStyle、 fontWeight 组成,建议分别设置这几项而非直接设置 font。'
|
||||
// },
|
||||
// {
|
||||
// prop: 'fontStyle',
|
||||
// label: '',
|
||||
// type: types.String,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字样式', trigger: 'blur' }
|
||||
// ],
|
||||
// value: 'normal',
|
||||
// description: '同 CSS font-style。'
|
||||
// },
|
||||
{
|
||||
prop: 'fontWeight',
|
||||
label: '粗细',
|
||||
type: types.Number,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字粗细', trigger: 'blur' }
|
||||
],
|
||||
min: 300,
|
||||
max: 800,
|
||||
step: 100,
|
||||
precisionFlag: 0,
|
||||
value: 300,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'fontSize',
|
||||
label: '大小',
|
||||
type: types.Number,
|
||||
min: 8,
|
||||
max: 30,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字大小', trigger: 'blur' }
|
||||
],
|
||||
value: 16,
|
||||
description: ''
|
||||
},
|
||||
// {
|
||||
// prop: 'fontFamily',
|
||||
// label: '文字族',
|
||||
// type: types.String,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字族', trigger: 'blur' }
|
||||
// ],
|
||||
// value: '文字样式',
|
||||
// description: '同 CSS font-family。'
|
||||
// },
|
||||
{
|
||||
prop: 'textFill',
|
||||
label: '填充样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字填充样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#000',
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'textStroke',
|
||||
label: '描边样式',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字描边样式', trigger: 'blur' }
|
||||
],
|
||||
value: '#fff',
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'textStrokeWidth',
|
||||
label: '描边宽度',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字描边宽度', trigger: 'blur' }
|
||||
],
|
||||
value: 2,
|
||||
description: ''
|
||||
},
|
||||
// {
|
||||
// prop: 'textWidth',
|
||||
// label: '文字宽度',
|
||||
// type: types.Number,
|
||||
// min: 0,
|
||||
// max: 10000,
|
||||
// step: 1,
|
||||
// precisionFlag: 0,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字宽度', trigger: 'blur' }
|
||||
// ],
|
||||
// value: 0,
|
||||
// description: '文字宽度。'
|
||||
// },
|
||||
// {
|
||||
// prop: 'textHeight',
|
||||
// label: '文字高度',
|
||||
// type: types.Number,
|
||||
// min: 0,
|
||||
// max: 10000,
|
||||
// step: 1,
|
||||
// precisionFlag: 0,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字高度', trigger: 'blur' }
|
||||
// ],
|
||||
// value: 0,
|
||||
// description: '文字高度,仅用于设置背景色时需要设置。'
|
||||
// },
|
||||
// {
|
||||
// prop: 'textLineHeight',
|
||||
// label: '文字行高',
|
||||
// type: types.Number,
|
||||
// min: 0,
|
||||
// max: 10000,
|
||||
// step: 1,
|
||||
// precisionFlag: 0,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字行高', trigger: 'blur' }
|
||||
// ],
|
||||
// value: 0,
|
||||
// description: '文字行高。'
|
||||
// },
|
||||
// {
|
||||
// prop: 'textPosition',
|
||||
// label: '文字位置',
|
||||
// type: types.Select,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字位置', trigger: 'blur' }
|
||||
// ],
|
||||
// value: '',
|
||||
// description: "文字位置,可以为 'inside'、 'left'、 'right'、 'top'、 'bottom',或一个二维数组 [x, y] 表示相对形状的位置。"
|
||||
// },
|
||||
// {
|
||||
// prop: 'textOffset',
|
||||
// label: '文字行高',
|
||||
// type: types.Point,
|
||||
// min: 0,
|
||||
// max: 10000,
|
||||
// step: 1,
|
||||
// precisionFlag: 0,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字位置偏移', trigger: 'blur' }
|
||||
// ],
|
||||
// value: 0,
|
||||
// description: '文字位置偏移,包括 x、 y。'
|
||||
// },
|
||||
{
|
||||
prop: 'textAlign',
|
||||
label: '水平对齐方式',
|
||||
type: types.Select,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字水平对齐方式', trigger: 'blur' }
|
||||
],
|
||||
value: 'left',
|
||||
optionList:[{value:'left', label:'左对齐'}, {value:'center', label:'居中对齐'}, {value:'right', label:'右对齐'}],
|
||||
// 文字水平对齐方式,可取值:'left'、 'center'、 'right',默认根据 textPosition 计算。
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'textVerticalAlign',
|
||||
label: '垂直对齐方式',
|
||||
type: types.Select,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字垂直对齐方式', trigger: 'blur' }
|
||||
],
|
||||
value: 'top',
|
||||
optionList:[{value:'top', label:'顶对齐'}, {value:'middle', label:'居中对齐'}, {value:'bottom', label:'底对齐'}],
|
||||
// 文字垂直对齐方式,可取值:'top'、 'middle'、 'bottom',默认根据 textPosition 计算。
|
||||
description: ''
|
||||
},
|
||||
// {
|
||||
// prop: 'textDistance',
|
||||
// label: '文字与其对齐的边缘的距离',
|
||||
// type: types.Number,
|
||||
// min: 0,
|
||||
// max: 10000,
|
||||
// step: 1,
|
||||
// precisionFlag: 0,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字与其对齐的边缘的距离', trigger: 'blur' }
|
||||
// ],
|
||||
// value: 0,
|
||||
// description: '文字与其对齐的边缘的距离,如 textPosition 为 top 时,textDistance 表示与形状上方的距离。'
|
||||
// },
|
||||
{
|
||||
prop: 'textShadowColor',
|
||||
label: '阴影颜色',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字阴影颜色', trigger: 'blur' }
|
||||
],
|
||||
value: 'rgba(0,0,0,0)',
|
||||
description: '文字阴影颜色。'
|
||||
},
|
||||
{
|
||||
prop: 'textShadowBlur',
|
||||
label: '阴影模糊大小',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 10000,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字阴影模糊大小', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '文字阴影模糊大小。'
|
||||
},
|
||||
{
|
||||
prop: 'textShadowOffsetX',
|
||||
label: '阴影水平偏移',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字阴影水平偏移', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '文字阴影水平偏移。'
|
||||
},
|
||||
{
|
||||
prop: 'textShadowOffsetY',
|
||||
label: '阴影垂直偏移',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字阴影垂直偏移', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '文字阴影垂直偏移。'
|
||||
},
|
||||
{
|
||||
prop: 'textBoxShadowColor',
|
||||
label: '包围盒阴影颜色',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字包围盒阴影颜色', trigger: 'blur' }
|
||||
],
|
||||
value: 'rgba(0,0,0,0)',
|
||||
description: '文字包围盒阴影颜色。'
|
||||
},
|
||||
{
|
||||
prop: 'textBoxShadowBlur',
|
||||
label: '包围盒阴影模糊大小',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字包围盒阴影模糊大小', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '文字包围盒阴影模糊大小。'
|
||||
},
|
||||
{
|
||||
prop: 'textBoxShadowOffsetX',
|
||||
label: '包围盒阴影水平偏移',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字包围盒阴影水平偏移', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '文字包围盒阴影水平偏移。'
|
||||
},
|
||||
{
|
||||
prop: 'textBoxShadowOffsetY',
|
||||
label: '包围盒阴影垂直偏移',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字包围盒阴影垂直偏移。', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '文字包围盒阴影垂直偏移。'
|
||||
},
|
||||
// {
|
||||
// prop: 'transformText',
|
||||
// label: '文字是否跟随变换效果',
|
||||
// type: types.Boolean,
|
||||
// rules:[
|
||||
// { required: true, message:'请选择文字是否跟随变换效果', trigger: 'blur' }
|
||||
// ],
|
||||
// value: false,
|
||||
// description: '文字是否跟随变换效果,仅对 Path 或 Image 元素有效'
|
||||
// },
|
||||
// {
|
||||
// prop: 'textRotation',
|
||||
// label: '文字旋转角度',
|
||||
// type: types.Number,
|
||||
// min: 0,
|
||||
// max: 360,
|
||||
// step: 1,
|
||||
// precisionFlag: 0,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字旋转角度', trigger: 'blur' }
|
||||
// ],
|
||||
// value: 0,
|
||||
// description: '文字旋转角度,仅对 Path 或 Image 元素有效,并且 transformText 应设置为 false。'
|
||||
// },
|
||||
// {
|
||||
// prop: 'textOrigin',
|
||||
// label: '文字变换中心',
|
||||
// type: types.Point,
|
||||
// min: 0,
|
||||
// max: 10000,
|
||||
// step: 1,
|
||||
// precisionFlag: 0,
|
||||
// rules:[
|
||||
// { required: true, message:'请输入文字变换中心', trigger: 'blur' }
|
||||
// ],
|
||||
// value: 0,
|
||||
// description: "文字变换中心,可以是 'center' 或一个二维数组 [x, y] 表示相对形状的位置,默认值是 textPosition。"
|
||||
// },
|
||||
{
|
||||
prop: 'textBackgroundColor',
|
||||
label: '包围盒颜色',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字包围盒颜色', trigger: 'blur' }
|
||||
],
|
||||
value: 'rgba(0,0,0,0)',
|
||||
description: '文字包围盒颜色。'
|
||||
},
|
||||
{
|
||||
prop: 'textBorderColor',
|
||||
label: '文字包围盒描边颜色',
|
||||
type: types.Color,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字包围盒描边颜色', trigger: 'blur' }
|
||||
],
|
||||
value: 'rgba(0,0,0,0)',
|
||||
description: '文字包围盒描边颜色。'
|
||||
},
|
||||
{
|
||||
prop: 'textBorderWidth',
|
||||
label: '包围盒描边宽度',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字包围盒描边宽度', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '文字包围盒描边宽度。'
|
||||
},
|
||||
{
|
||||
prop: 'textBorderRadius',
|
||||
label: '圆角大小',
|
||||
type: types.Number,
|
||||
min: 0,
|
||||
max: 360,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字圆角大小', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: ''
|
||||
},
|
||||
{
|
||||
prop: 'textPadding',
|
||||
label: '文字内边距',
|
||||
type: types.NumberArray,
|
||||
length:4,
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: 1,
|
||||
precisionFlag: 0,
|
||||
rules:[
|
||||
{ required: true, message:'请输入文字内边距', trigger: 'blur' }
|
||||
],
|
||||
value: [0, 0, 0, 0],
|
||||
description: '文字内边距,[2, 3, 4, 5] 的形式,单位是像素。'
|
||||
}
|
||||
];
|
49
src/iscs_new/core/form/form2TruncateStyle.js
Normal file
49
src/iscs_new/core/form/form2TruncateStyle.js
Normal file
@ -0,0 +1,49 @@
|
||||
export default [
|
||||
{
|
||||
prop: 'outerWidth',
|
||||
label: '外部宽度',
|
||||
type: types.Number,
|
||||
min: 2,
|
||||
max: 100,
|
||||
step: 1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入外部宽度', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '包含了 textPadding 的宽度,超出这个范围就裁剪。'
|
||||
},
|
||||
{
|
||||
prop: 'outerHeight',
|
||||
label: '外部高度',
|
||||
type: types.Number,
|
||||
min: 2,
|
||||
max: 100,
|
||||
step: 1,
|
||||
rules:[
|
||||
{ required: true, message:'请输入外部高度', trigger: 'blur' }
|
||||
],
|
||||
value: 0,
|
||||
description: '包含了 textPadding 的高度,超出这个范围就裁剪。'
|
||||
},
|
||||
{
|
||||
prop: 'ellipsis',
|
||||
label: '截断超出部分',
|
||||
type: types.String,
|
||||
rules:[
|
||||
{ required: true, message:'请输入截断超出部分', trigger: 'blur' }
|
||||
],
|
||||
value: '',
|
||||
description: '默认用省略号表示超出部分,也可以对其进行自定义。'
|
||||
|
||||
},
|
||||
{
|
||||
prop: 'placeholder',
|
||||
label: '截断文字',
|
||||
type: types.String,
|
||||
rules:[
|
||||
{ required: true, message:'请输入截断文字', trigger: 'blur' }
|
||||
],
|
||||
value: '',
|
||||
description: '如果空间过小,导致省略号也显示不下,但是又不想空着,可能得有个什么标记表示这里是有字符的,就用个 “点”,就是在这个 placeholder 里设置。'
|
||||
}
|
||||
]
|
40
src/iscs_new/core/form/formBuilder.js
Normal file
40
src/iscs_new/core/form/formBuilder.js
Normal file
@ -0,0 +1,40 @@
|
||||
import elementConst from './elementConst';
|
||||
import form2Base from './form2Base';
|
||||
|
||||
const formBuilder = {
|
||||
buildForm(el) {
|
||||
const form = {};
|
||||
form.type = el.type;
|
||||
form.name = el.name;
|
||||
form.formGroup = [];
|
||||
form.model = {};
|
||||
|
||||
// 添加通用配置
|
||||
form.model['base'] = {};
|
||||
form2Base.forEach(each=>{
|
||||
form.model['base'][each.prop] = each.value;
|
||||
});
|
||||
form.formGroup.push({name:'通用配置', type:'base', styleList:form2Base});
|
||||
|
||||
const list = [{name:'绘图配置', type:'shape'}, {name:'样式配置', type:'style'}];
|
||||
list.forEach(eachType=>{
|
||||
form.model[eachType.type] = {};
|
||||
const eachList = el.formList[eachType.type];
|
||||
eachList.forEach(each=>{
|
||||
form.model[eachType.type][each.prop] = each.value;
|
||||
});
|
||||
form.formGroup.push({name:eachType.name, type: eachType.type, styleList:eachList});
|
||||
});
|
||||
return form;
|
||||
},
|
||||
buildFormList() {
|
||||
const formList = [];
|
||||
const elementList = Object.values(elementConst);
|
||||
elementList.forEach(el=>{
|
||||
formList.push(this.buildForm(el));
|
||||
});
|
||||
return formList;
|
||||
}
|
||||
};
|
||||
|
||||
export default formBuilder;
|
10
src/iscs_new/core/form/types.js
Normal file
10
src/iscs_new/core/form/types.js
Normal file
@ -0,0 +1,10 @@
|
||||
export default {
|
||||
String: 'String',
|
||||
Number: 'Number',
|
||||
Select: 'Select',
|
||||
Boolean: 'Boolean',
|
||||
Color: 'Color',
|
||||
Point: 'Point',
|
||||
Points: 'Points',
|
||||
NumberArray: 'NumberArray'
|
||||
};
|
20
src/iscs_new/core/graphic.js
Normal file
20
src/iscs_new/core/graphic.js
Normal file
@ -0,0 +1,20 @@
|
||||
export {default as Group} from 'zrender/src/container/Group';
|
||||
export {default as Image} from 'zrender/src/graphic/Image';
|
||||
export {default as Text} from 'zrender/src/graphic/Text';
|
||||
export {default as Arc} from './shape/ArcShape';
|
||||
export {default as BezierCurve} from 'zrender/src/graphic/shape/BezierCurve';
|
||||
export {default as Circle} from 'zrender/src/graphic/shape/Circle';
|
||||
export {default as Droplet} from 'zrender/src/graphic/shape/Droplet';
|
||||
export {default as Ellipse} from 'zrender/src/graphic/shape/Ellipse';
|
||||
export {default as Heart} from 'zrender/src/graphic/shape/Heart';
|
||||
export {default as Isogon} from 'zrender/src/graphic/shape/Isogon';
|
||||
export {default as Line} from 'zrender/src/graphic/shape/Line';
|
||||
export {default as Polygon} from 'zrender/src/graphic/shape/Polygon';
|
||||
export {default as Polyline} from 'zrender/src/graphic/shape/Polyline';
|
||||
export {default as Rect} from 'zrender/src/graphic/shape/Rect';
|
||||
export {default as Ring} from 'zrender/src/graphic/shape/Ring';
|
||||
export {default as Rose} from 'zrender/src/graphic/shape/Rose';
|
||||
export {default as Sector} from './shape/SectorShape';
|
||||
export {default as Star} from 'zrender/src/graphic/shape/Star';
|
||||
export {default as Trochoid} from 'zrender/src/graphic/shape/Trochoid';
|
||||
export {default as Svg} from './shape/Svg';
|
17
src/iscs_new/core/shape/ArcShape.js
Normal file
17
src/iscs_new/core/shape/ArcShape.js
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
import Arc from 'zrender/src/graphic/shape/Arc';
|
||||
export default class ArcShape extends Arc {
|
||||
constructor(opts) {
|
||||
opts.shape.startAngle = Math.PI / 180 * opts.shape.startAngle;
|
||||
opts.shape.endAngle = Math.PI / 180 * opts.shape.endAngle;
|
||||
super(opts);
|
||||
}
|
||||
|
||||
setStyle(style) {
|
||||
super.setStyle(style);
|
||||
}
|
||||
|
||||
attr(key, value) {
|
||||
super.attr(key, value);
|
||||
}
|
||||
}
|
17
src/iscs_new/core/shape/SectorShape.js
Normal file
17
src/iscs_new/core/shape/SectorShape.js
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
import Sector from 'zrender/src/graphic/shape/Sector';
|
||||
export default class ArcShape extends Sector {
|
||||
constructor(opts) {
|
||||
opts.shape.startAngle = Math.PI / 180 * opts.shape.startAngle;
|
||||
opts.shape.endAngle = Math.PI / 180 * opts.shape.endAngle;
|
||||
super(opts);
|
||||
}
|
||||
|
||||
setStyle(style) {
|
||||
super.setStyle(style);
|
||||
}
|
||||
|
||||
attr(key, value) {
|
||||
super.attr(key, value);
|
||||
}
|
||||
}
|
26
src/iscs_new/core/shape/Svg.js
Normal file
26
src/iscs_new/core/shape/Svg.js
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
import Path from 'zrender/src/graphic/Path';
|
||||
import * as pathTool from 'zrender/src/tool/path';
|
||||
export default class Svg extends Path {
|
||||
constructor(opts) {
|
||||
super(pathTool.createFromString(opts.shape.path, {
|
||||
...opts,
|
||||
type: 'Svg'
|
||||
}));
|
||||
|
||||
super.attr('position', [opts.shape.x, opts.shape.y]);
|
||||
}
|
||||
|
||||
setShape(shape) {
|
||||
super.setShape(shape);
|
||||
this.attr('position', [shape.x, shape.y]);
|
||||
}
|
||||
|
||||
setStyle(style) {
|
||||
super.setStyle(style);
|
||||
}
|
||||
|
||||
attr(key, value) {
|
||||
super.attr(key, value);
|
||||
}
|
||||
}
|
45
src/iscs_new/dragHandle.js
Normal file
45
src/iscs_new/dragHandle.js
Normal file
@ -0,0 +1,45 @@
|
||||
import shapeLayer from './constant/shapeLayer';
|
||||
export default class DragHandle {
|
||||
constructor(map, controller) {
|
||||
this.$zr = map.getZr();
|
||||
this.$controller = controller;
|
||||
this.$option = map.getOption();
|
||||
this.$painter = map.getPainter();
|
||||
this._dragging = false;
|
||||
}
|
||||
|
||||
isDragging() {
|
||||
return this._dragging;
|
||||
}
|
||||
|
||||
onDragStart(e) {
|
||||
const storage = this.$controller.getStorage();
|
||||
if (e.code && storage.has(e.code)) {
|
||||
this._dragging = true;
|
||||
}
|
||||
}
|
||||
|
||||
onDragging(e) {
|
||||
const dx = e.dx;
|
||||
const dy = e.dy;
|
||||
const scaleRate = this.$option.getScaleRate();
|
||||
const storage = this.$controller.getStorage();
|
||||
|
||||
e.dx = dx / scaleRate;
|
||||
e.dy = dy / scaleRate;
|
||||
|
||||
if (this._dragging) {
|
||||
storage.values().forEach(target => {
|
||||
if (target) {
|
||||
target.shapeFactory.hideHightLight(target);;
|
||||
target.drift(e);
|
||||
target.shapeFactory.showHightLight(target);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onDragEnd(e) {
|
||||
this._dragging = false;
|
||||
}
|
||||
}
|
114
src/iscs_new/factory/compose.js
Normal file
114
src/iscs_new/factory/compose.js
Normal file
@ -0,0 +1,114 @@
|
||||
import * as utils from '../utils/utils';
|
||||
import Group from 'zrender/src/container/Group';
|
||||
import AbstractShape from '../core/abstractShape';
|
||||
import shapeRender from '../constant/shapeRender';
|
||||
import shapeEvent from '../constant/shapeEvent';
|
||||
|
||||
class Compose extends AbstractShape {
|
||||
constructor(args) {
|
||||
super(args);
|
||||
this.create();
|
||||
}
|
||||
|
||||
create() {
|
||||
const that = this;
|
||||
// mouse进入事件
|
||||
function onmouseover(e) {
|
||||
that.shapeFactory.trigger(shapeEvent.ShowTips, e, 'text for test');
|
||||
}
|
||||
|
||||
// mouse移动事件
|
||||
function onmousemove(e) {
|
||||
onmouseover(e);
|
||||
}
|
||||
|
||||
// mouse离开事件
|
||||
function onmouseout(e) {
|
||||
that.shapeFactory.trigger(shapeEvent.HideTips, e);
|
||||
}
|
||||
|
||||
this.instance = new Group({
|
||||
...shapeRender,
|
||||
...this.model.base,
|
||||
code: this.model.code,
|
||||
type: this.model.type,
|
||||
onmouseover,
|
||||
onmousemove,
|
||||
onmouseout
|
||||
});
|
||||
|
||||
this.model.elementCodes.forEach(code => {
|
||||
const el = this.shapeFactory.getShapeByCode(code);
|
||||
if (el) {
|
||||
this.shapeFactory.removeFromLayer(el.type, el);
|
||||
this.instance.add(el);
|
||||
}
|
||||
})
|
||||
this.instance.scale = this.model.base.scale;
|
||||
this.instance.position = this.model.base.position;
|
||||
this.instance.rotation = this.model.base.rotation*Math.PI/180;
|
||||
this.instance.origin = utils.createOrigin(this.instance);
|
||||
this.instance.transform = utils.createTransform({scale: this.model.base.scale, position: this.model.base.position, rotation: this.model.base.rotation*Math.PI/180});
|
||||
this.add(this.instance);
|
||||
this.setInvisible(this.model.base.hide)
|
||||
}
|
||||
|
||||
// 设置高亮
|
||||
active() {
|
||||
}
|
||||
|
||||
// 取消高亮
|
||||
inactive() {
|
||||
}
|
||||
|
||||
// 设置获取焦点
|
||||
focus() {
|
||||
}
|
||||
|
||||
// 设置取消焦点
|
||||
blur() {
|
||||
}
|
||||
|
||||
// 绑定数据
|
||||
combine() {
|
||||
this.inactive();
|
||||
this.shapeFactory.hideHightLight(this);
|
||||
this.model.elementCodes.forEach(code => {
|
||||
const el = this.shapeFactory.getShapeByCode(code);
|
||||
if (el && el.model) {
|
||||
this.shapeFactory.hideHightLight(el);
|
||||
this.shapeFactory.removeFromLayer(el.type, el);
|
||||
this.instance.add(el);
|
||||
el.model.composeCode = this.code;
|
||||
el.attr(el.model);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 解除绑定
|
||||
uncouple() {
|
||||
this.inactive();
|
||||
this.shapeFactory.hideHightLight(this);
|
||||
this.model.elementCodes.forEach(code => {
|
||||
const el = this.shapeFactory.getShapeByCode(code);
|
||||
if (el && el.model) {
|
||||
this.shapeFactory.hideHightLight(el);
|
||||
this.instance.remove(el);
|
||||
this.shapeFactory.addToLayer(el.type, el);
|
||||
el.model.composeCode = '';
|
||||
el.attr(el.model);
|
||||
}
|
||||
})
|
||||
this.model.elementCodes = [];
|
||||
}
|
||||
|
||||
// 获取依赖图形
|
||||
getDepShapes() {
|
||||
return this.model.elementCodes.reduce((shapes, code) => shapes.concat(this.shapeFactory.getShapeByCode(code).getDepShapes()), [this]);
|
||||
}
|
||||
|
||||
// 设置状态
|
||||
setState(state) {}
|
||||
}
|
||||
|
||||
export default Compose;
|
118
src/iscs_new/factory/element.js
Normal file
118
src/iscs_new/factory/element.js
Normal file
@ -0,0 +1,118 @@
|
||||
import * as graphic from '../core/graphic';
|
||||
import * as utils from '../utils/utils';
|
||||
import AbstractShape from '../core/abstractShape';
|
||||
import shapeEvent from '../constant/shapeEvent';
|
||||
import shapeRender from '../constant/shapeRender';
|
||||
import shapeLayer from '../constant/shapeLayer';
|
||||
|
||||
class Element extends AbstractShape {
|
||||
constructor(args) {
|
||||
super(args);
|
||||
this.create();
|
||||
}
|
||||
|
||||
create() {
|
||||
const that = this;
|
||||
const elementBuilder = graphic[this.type];
|
||||
if (elementBuilder) {
|
||||
// mouse进入事件
|
||||
function onmouseover(e) {
|
||||
that.shapeFactory.trigger(shapeEvent.ShowTips, e, 'text for test');
|
||||
}
|
||||
|
||||
// mouse移动事件
|
||||
function onmousemove(e) {
|
||||
onmouseover(e);
|
||||
}
|
||||
|
||||
// mouse离开事件
|
||||
function onmouseout(e) {
|
||||
that.shapeFactory.trigger(shapeEvent.HideTips, e);
|
||||
}
|
||||
|
||||
this.instance = new elementBuilder({
|
||||
...shapeRender,
|
||||
...this.model.base,
|
||||
code: this.model.code,
|
||||
type: this.model.type,
|
||||
shape: {...this.model.shape},
|
||||
style: {...this.model.style},
|
||||
onmouseover,
|
||||
onmousemove,
|
||||
onmouseout
|
||||
});
|
||||
|
||||
this.instance.scale = this.model.base.scale;
|
||||
this.instance.position = this.model.base.position;
|
||||
this.instance.rotation = this.model.base.rotation*Math.PI/180;
|
||||
this.instance.origin = utils.createOrigin(this.instance);
|
||||
this.instance.transform = utils.createTransform({scale: this.model.base.scale, position: this.model.base.position, rotation: this.model.base.rotation*Math.PI/180});
|
||||
this.add(this.instance);
|
||||
this.setInvisible(this.model.base.hide);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置高亮
|
||||
active() {
|
||||
}
|
||||
|
||||
// 取消高亮
|
||||
inactive() {
|
||||
}
|
||||
|
||||
// 设置获取焦点
|
||||
focus() {
|
||||
}
|
||||
|
||||
// 设置取消焦点
|
||||
blur() {
|
||||
}
|
||||
|
||||
// 绑定数据
|
||||
combine() {
|
||||
this.inactive();
|
||||
this.shapeFactory.hideHightLight(this);
|
||||
const compose = this.shapeFactory.getShapeByCode(this.model.composeCode);
|
||||
if (compose &&
|
||||
compose.model &&
|
||||
compose.model.elementCodes) {
|
||||
this.shapeFactory.hideHightLight(compose);
|
||||
const index = compose.model.elementCodes.findIndex(this.code);
|
||||
if (index < 0) {
|
||||
compose.model.elementCodes.push(this.code);
|
||||
this.shapeFactory.removeFormLayer(this.type, this);
|
||||
compose.instance.add(this);
|
||||
compose.attr(compose.model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 解除绑定
|
||||
uncouple() {
|
||||
this.inactive();
|
||||
this.shapeFactory.hideHightLight(this);
|
||||
const compose = this.shapeFactory.getShapeByCode(this.model.composeCode);
|
||||
if (compose &&
|
||||
compose.model &&
|
||||
compose.model.elementCodes) {
|
||||
this.shapeFactory.hideHightLight(compose);
|
||||
const index = compose.model.elementCodes.findIndex(this.code);
|
||||
if (index >= 0) {
|
||||
compose.model.elementCodes.splice(index, 1);
|
||||
compose.instance.remove(this);
|
||||
compose.attr(compose.model);
|
||||
this.shapeFactory.addToLayer(this.type, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取依赖图形
|
||||
getDepShapes() {
|
||||
return [this];
|
||||
}
|
||||
|
||||
// 设置状态
|
||||
setState(state) {}
|
||||
}
|
||||
|
||||
export default Element;
|
267
src/iscs_new/factory/index.js
Normal file
267
src/iscs_new/factory/index.js
Normal file
@ -0,0 +1,267 @@
|
||||
import * as zrUtil from 'zrender/src/core/util';
|
||||
import * as graphic from '../core/graphic';
|
||||
import Eventful from 'zrender/src/mixin/Eventful';
|
||||
import TipsHandle from './tipsHandle';
|
||||
import Compose from './compose';
|
||||
import Element from './element';
|
||||
import shapeType from '../constant/shapeType';
|
||||
import shapeRender from '../constant/shapeRender';
|
||||
import shapeEvent from '../constant/shapeEvent';
|
||||
import orders from '../utils/orders';
|
||||
import shapeLayer from '../constant/shapeLayer';
|
||||
import templateParser from './templateParser';
|
||||
import defaultStyle from '../config/defaultStyle';
|
||||
|
||||
const None = e => null;
|
||||
const shapeBuilderMap = {
|
||||
[shapeType.Element]: Element,
|
||||
[shapeType.Compose]: Compose
|
||||
}
|
||||
const shapeSensitizeStyle = {
|
||||
border: {
|
||||
borderStyle: {
|
||||
lineDash: [4, 4],
|
||||
lineWidth: 1,
|
||||
stroke: '#000',
|
||||
fill: 'transparent'
|
||||
}
|
||||
}
|
||||
}
|
||||
class Perspective extends graphic.Group {
|
||||
constructor(args) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
_createBorder(rect) {
|
||||
this._border = new graphic.Rect({
|
||||
...shapeRender,
|
||||
subType: '@border',
|
||||
z: 9999,
|
||||
silent: true,
|
||||
shape: {
|
||||
...rect
|
||||
},
|
||||
style: {
|
||||
...shapeSensitizeStyle.border.borderStyle
|
||||
}
|
||||
})
|
||||
this.add(this._border);
|
||||
}
|
||||
|
||||
_createAngles() {
|
||||
|
||||
}
|
||||
|
||||
render(rect) {
|
||||
this.removeAll();
|
||||
this._createBorder(rect);
|
||||
this._createAngles();
|
||||
}
|
||||
|
||||
setShape(rect) {
|
||||
this.render(rect);
|
||||
}
|
||||
}
|
||||
class ShapeFactory extends Eventful {
|
||||
constructor(map) {
|
||||
super();
|
||||
this.$map = map;
|
||||
this.$painter = map.getPainter();
|
||||
this.$controller = map.getController();
|
||||
|
||||
this.sensitize = new Perspective({subType: '@ignore'});
|
||||
|
||||
this.tipsHandle = new TipsHandle(map);
|
||||
|
||||
this.source = {};
|
||||
this.mapTemplate = {};
|
||||
this.mapShape = {};
|
||||
|
||||
this.initEventHandle();
|
||||
}
|
||||
|
||||
initEventHandle() {
|
||||
const that = this;
|
||||
const showBorderHandle = this.showBorder;
|
||||
const hideBorderHandle = this.hideBorder;
|
||||
const showTipsHandle = this.tipsHandle.onShow;
|
||||
const hideTipsHandle = this.tipsHandle.onHide;
|
||||
|
||||
this.on(shapeEvent.ShowBorder, showBorderHandle, this);
|
||||
this.on(shapeEvent.HideBorder, hideBorderHandle, this);
|
||||
this.on(shapeEvent.ShowTips, showTipsHandle, this.tipsHandle);
|
||||
this.on(shapeEvent.HideTips, hideTipsHandle, this.tipsHandle);
|
||||
|
||||
this.dispose = function() {
|
||||
that.off(shapeEvent.ShowBorder, showBorderHandle);
|
||||
that.off(shapeEvent.HideBorder, showBorderHandle);
|
||||
that.off(shapeEvent.ShowTips, showTipsHandle);
|
||||
that.off(shapeEvent.HideTips, hideTipsHandle);
|
||||
}
|
||||
}
|
||||
|
||||
parseTemplates(list=[]) {
|
||||
list.forEach(el => {
|
||||
this.mapTemplate[el.type] = templateParser.parse(el);
|
||||
})
|
||||
}
|
||||
|
||||
parse(source={}, take=None) {
|
||||
try {
|
||||
this.source = source;
|
||||
zrUtil.each(source.elementList ||[], model => {
|
||||
take(this.addShape(this.createShape(model, shapeType.Element)));
|
||||
}, this);
|
||||
|
||||
zrUtil.each(source.composeList ||[], model => {
|
||||
take(this.addShape(this.createShape(model, shapeType.Compose)));
|
||||
}, this);
|
||||
} catch (error) {
|
||||
console.error('[ERROR] ', error);
|
||||
}
|
||||
}
|
||||
|
||||
createShape(model={}, shapeType) {
|
||||
let shape = null;
|
||||
const shapeBuilder = shapeBuilderMap[shapeType];
|
||||
if (shapeBuilder) {
|
||||
shape = new shapeBuilder({model, shapeType, shapeFactory: this});
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
addShape(shape) {
|
||||
if (shape && shape.code) {
|
||||
this.mapShape[shape.code] = shape;
|
||||
shape.combine();
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
removeShape(shape) {
|
||||
if (shape && shape.code) {
|
||||
shape.uncouple();
|
||||
delete this.mapShape[shape.code];
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
updateSource(model={}, action={}) {
|
||||
switch (action.shapeType) {
|
||||
case shapeType.Compose: return update2List(this.source, model, action, 'composeList');
|
||||
case shapeType.Element: return update2List(this.source, model, action, 'elementList');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
showHightLight(shape) {
|
||||
const target = this.$controller.getTarget();
|
||||
|
||||
if (shape.instanceHightLight) {
|
||||
shape.instanceHightLight.setShape(shape.getBoundingRect())
|
||||
this.$painter.addToLayer(shapeLayer.HightLight, shape.instanceHightLight);
|
||||
}
|
||||
|
||||
if (target == shape) {
|
||||
this.showBorder(shape);
|
||||
}
|
||||
|
||||
shape.traverse(el => {
|
||||
el.attr({ z: shapeRender.z + 9 })
|
||||
});
|
||||
|
||||
shape.active();
|
||||
}
|
||||
|
||||
hideHightLight(shape) {
|
||||
const target = this.$controller.getTarget();
|
||||
|
||||
if (shape.instanceHightLight) {
|
||||
this.$painter.removeFromLayer(shapeLayer.HightLight, shape.instanceHightLight);
|
||||
}
|
||||
|
||||
if (target != shape) {
|
||||
this.hideBorder(shape);
|
||||
}
|
||||
|
||||
shape.traverse(el => {
|
||||
el.attr({ z: shapeRender.z })
|
||||
});
|
||||
|
||||
shape.inactive();
|
||||
}
|
||||
|
||||
showBorder(shape) {
|
||||
this.sensitize.setShape(shape.getBoundingRect());
|
||||
this.$painter.addToLayer(shapeLayer.HightLight, this.sensitize);
|
||||
}
|
||||
|
||||
hideBorder(shape) {
|
||||
this.$painter.removeFromLayer(shapeLayer.HightLight, this.sensitize);
|
||||
}
|
||||
|
||||
addToLayer(level, shape) {
|
||||
return this.$painter.addToLayer(level, shape);
|
||||
}
|
||||
|
||||
removeFromLayer(level, shape) {
|
||||
return this.$painter.removeFromLayer(level, shape);
|
||||
}
|
||||
|
||||
isDrawing() {
|
||||
this.$map.isDrawing();
|
||||
}
|
||||
|
||||
getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
getMapTemplate() {
|
||||
return this.mapTemplate;
|
||||
}
|
||||
|
||||
getMapShape() {
|
||||
return this.mapShape;
|
||||
}
|
||||
|
||||
getShapeByCode(code) {
|
||||
return this.mapShape[code];
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.source = {};
|
||||
this.mapTemplate = {};
|
||||
this.mapShape = {};
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.clear();
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
function update2List(source, model, action, name='') {
|
||||
const list = source[name];
|
||||
|
||||
if (!list) { source[name] = []; }
|
||||
|
||||
let updateModel = model;
|
||||
const i = list.findIndex(elem => { return elem.code == model.code; })
|
||||
switch(action.order) {
|
||||
case orders.Binding:
|
||||
case orders.Add:
|
||||
i < 0 && list.push(model);
|
||||
break;
|
||||
case orders.Unbinding:
|
||||
case orders.Delete:
|
||||
i >= 0 && list.splice(i, 1);
|
||||
break;
|
||||
case orders.Update:
|
||||
updateModel = Object.assign(list[i]||{}, model)
|
||||
break;
|
||||
}
|
||||
|
||||
return updateModel;
|
||||
}
|
||||
|
||||
export default ShapeFactory;
|
45
src/iscs_new/factory/templateParser.js
Normal file
45
src/iscs_new/factory/templateParser.js
Normal file
@ -0,0 +1,45 @@
|
||||
import * as utils from '../utils/utils';
|
||||
|
||||
class TemplateParser {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
parse(template) {
|
||||
return {
|
||||
type: template.type,
|
||||
name: template.name,
|
||||
isActive: template.isActive,
|
||||
isFocus: template.isFocus,
|
||||
mapShape: this.parseShape(template.shapeList),
|
||||
mapState: this.parseState(template.stateList),
|
||||
mapEvent: this.parseEvent(template.eventList),
|
||||
}
|
||||
}
|
||||
|
||||
parseShape(list=[], map={}) {
|
||||
list.forEach(el => {
|
||||
const mapShape = map[el.name] = {};
|
||||
mapShape[utils.defStatus] = { status: utils.defStatus, style: el.style, shape: el.shape };
|
||||
(el.stateList||[]).forEach(it => {
|
||||
mapShape[it.status] = it;
|
||||
})
|
||||
})
|
||||
return map;
|
||||
}
|
||||
|
||||
parseState(list=[], map={}) {
|
||||
list.forEach(el => {
|
||||
map[el.status] = el;
|
||||
})
|
||||
return map;
|
||||
}
|
||||
|
||||
parseEvent(list=[], map={}) {
|
||||
list.forEach(el => {
|
||||
map[el.status] = el;
|
||||
})
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
export default new TemplateParser();
|
55
src/iscs_new/factory/tipsHandle.js
Normal file
55
src/iscs_new/factory/tipsHandle.js
Normal file
@ -0,0 +1,55 @@
|
||||
import * as graphic from '../core/graphic';
|
||||
import shapeLayer from '../constant/shapeLayer';
|
||||
import shapeRender from '../constant/shapeRender';
|
||||
|
||||
function shapeStyleBuilder() {
|
||||
return {
|
||||
...shapeRender,
|
||||
z: 10000,
|
||||
silent: true,
|
||||
style: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
fontSize: 16,
|
||||
fontWeight: 'normal',
|
||||
textBackgroundColor: '#feffc8',
|
||||
text: '',
|
||||
textFill: '#000',
|
||||
textPadding: [7, 14],
|
||||
textAlign: 'left',
|
||||
textVerticalAlign: 'bottom',
|
||||
textBorderColor: '#666666',
|
||||
textBorderWidth: 0,
|
||||
textBorderRadius: 4,
|
||||
textLineHeight: 22,
|
||||
textBoxShadowColor: 'rgba(0,0,0,.3)',
|
||||
textBoxShadowOffsetX: 0,
|
||||
textBoxShadowOffsetY: 1,
|
||||
textBoxShadowBlur: 3,
|
||||
opacity: 0.8
|
||||
}
|
||||
}
|
||||
}
|
||||
export default class TipsHandle {
|
||||
constructor(map) {
|
||||
this.$map = map;
|
||||
this.message = new graphic.Text(shapeStyleBuilder());
|
||||
}
|
||||
|
||||
onShow(e, text) {
|
||||
const {offsetX, offsetY} = e;
|
||||
const painter = this.$map.getPainter();
|
||||
const option = this.$map.getOption();
|
||||
const x = (offsetX + option.offsetX) / option.scaleRate;
|
||||
const y = (offsetY + option.offsetY) / option.scaleRate;
|
||||
this.message.setStyle({ x, y, text });
|
||||
painter.addToLayer(shapeLayer.Tips, this.message);
|
||||
}
|
||||
|
||||
onHide(e) {
|
||||
const painter = this.$map.getPainter();
|
||||
|
||||
painter.removeFromLayer(shapeLayer.Tips, this.message);
|
||||
this.message.setStyle('text', '');
|
||||
}
|
||||
}
|
32
src/iscs_new/keyboardHandle.js
Normal file
32
src/iscs_new/keyboardHandle.js
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
export default class KeyBoardHandle {
|
||||
constructor(map, controller) {
|
||||
this.$map = map;
|
||||
this.$controller = controller;
|
||||
}
|
||||
|
||||
execFunc(moduleName, funcName, args) {
|
||||
const module = this.$controller[moduleName]||{};
|
||||
const func = module[funcName];
|
||||
if (func instanceof Function) {
|
||||
func.apply(module, args);
|
||||
}
|
||||
}
|
||||
|
||||
onKeydown(e) {
|
||||
switch (e.key) {
|
||||
case 'v':
|
||||
this.execFunc('selectHandle', 'setDraggable', ['vertical']);
|
||||
break;
|
||||
case 'h':
|
||||
this.execFunc('selectHandle', 'setDraggable', ['horizontal']);
|
||||
break;
|
||||
case 'Escape':
|
||||
this.execFunc('selectHandle', 'setDraggable', [true]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
onKeyup(e) {
|
||||
}
|
||||
}
|
414
src/iscs_new/map.js
Normal file
414
src/iscs_new/map.js
Normal file
@ -0,0 +1,414 @@
|
||||
import _ from 'lodash';
|
||||
import * as utils from './utils/utils';
|
||||
import zrender from 'zrender';
|
||||
import events from './utils/events';
|
||||
import Eventful from 'zrender/src/mixin/Eventful';
|
||||
import Painter from './painter';
|
||||
import Option from './option';
|
||||
import Controller from './controller';
|
||||
import StateHandle from './stateHandle';
|
||||
import ShapeFactory from './factory';
|
||||
import orders from './utils/orders';
|
||||
import shapeType from './constant/shapeType';
|
||||
|
||||
const renderer = 'canvas';
|
||||
const devicePixelRatio = 1;
|
||||
class JMap {
|
||||
constructor(opts) {
|
||||
// 内部鼠标事件
|
||||
this.events = {
|
||||
__Pan: '__pan__',
|
||||
__Zoom: '__zoom__',
|
||||
__DragStart: '__dragStart__',
|
||||
__Dragging: '__dragging__',
|
||||
__DragEnd: '__dragEnd__',
|
||||
__SelectStart: '__selectStart__',
|
||||
__Selecting: '__selecting__',
|
||||
__SelectEnd: '__selectEnd__',
|
||||
__Selected: '__selected__',
|
||||
__Keyup: '__keyup__',
|
||||
__Keydown: '__keydown__'
|
||||
};
|
||||
|
||||
// 初始化Map实例
|
||||
this.initMapInstance(opts);
|
||||
}
|
||||
|
||||
// 初始化属性有鼠标事件 缩放等
|
||||
initMapInstance(opts) {
|
||||
const width = opts.dom.clientWidth;
|
||||
const height = opts.dom.clientHeight;
|
||||
const optionHandler = this.setOption.bind(this);
|
||||
|
||||
this.draw = opts.draw;
|
||||
// 实例化zr
|
||||
this.$zr = zrender.init(opts.dom, { renderer, devicePixelRatio, width, height, ...utils.deepClone(opts.config || {})});
|
||||
this.$zr.dom.setAttribute('tabIndex', -1);
|
||||
this.$zr.dom.style.cursor = 'auto';
|
||||
|
||||
// 实例化缩放偏移缩放参数
|
||||
this.$option = new Option({ scaleRate: 1, offsetX: 0, offsetY: 0, ...utils.deepClone(opts.option || {})}, (dataZoom) => { this.$controller.trigger(events.DataZoom, dataZoom); }); // 缩放
|
||||
|
||||
// 实例化绘图模块
|
||||
this.$painter = new Painter(this);
|
||||
this.$painter.updateZrSize({width: this.$zr.getWidth(), height: this.$zr.getHeight()});
|
||||
this.$painter.updateTransform(this.$option);
|
||||
|
||||
// 实例化事件分发模块
|
||||
this.$controller = new Controller(this);
|
||||
this.$controller.enable();
|
||||
this.$controller.on(this.events.__Pan, optionHandler);
|
||||
this.$controller.on(this.events.__Zoom, optionHandler);
|
||||
|
||||
// 名声周期发射器
|
||||
this.$eventEmitter = new Eventful({});
|
||||
|
||||
// 数据容器工厂
|
||||
this.$shapeFactory = new ShapeFactory(this);
|
||||
|
||||
// 状态处理器
|
||||
this.$stateHandle = new StateHandle(this);
|
||||
|
||||
this.disable = function() {
|
||||
this.off(this.events.Pan, optionHandler);
|
||||
this.off(this.events.Zoom, optionHandler);
|
||||
};
|
||||
|
||||
// 加载插件
|
||||
this.plugins = opts.plugins || [];
|
||||
this.plugins.forEach(el => { this.use(el); });
|
||||
}
|
||||
|
||||
setMap(templates = [], source = {}, eventOpts = {}) {
|
||||
// 清楚数据
|
||||
this.$shapeFactory.clear();
|
||||
this.$painter.clear();
|
||||
|
||||
// 绑定事件
|
||||
this.$controller.enable(eventOpts);
|
||||
|
||||
// 更新视图位置
|
||||
this.$painter.updateTransform(this.$option);
|
||||
|
||||
// 解析模板
|
||||
this.$shapeFactory.parseTemplates(templates);
|
||||
|
||||
// 数据加载完成 回调
|
||||
this.$eventEmitter.trigger(events.DataLoaded);
|
||||
|
||||
// 初次渲染视图
|
||||
this.repaint(source);
|
||||
|
||||
// 设置默认状态
|
||||
this.setDefaultState();
|
||||
|
||||
// 视图加载完成 回调
|
||||
this.$eventEmitter.trigger(events.ViewLoaded);
|
||||
|
||||
// 返回视图缩放偏移
|
||||
this.$option.notice(this.$option);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
setDefaultState() {
|
||||
this.$eventEmitter.trigger(events.StateLoaded);
|
||||
return this;
|
||||
}
|
||||
|
||||
setOption(opts = {}) {
|
||||
this.$option.update(opts.type == this.events.__Zoom ? pullBack(this.$zr, this.$option, opts) : opts);
|
||||
this.$painter.updateTransform(this.$option);
|
||||
|
||||
this.$controller.disable();
|
||||
this.$controller.enable();
|
||||
|
||||
this.$eventEmitter.trigger(events.OptionUpdate);
|
||||
return this;
|
||||
}
|
||||
|
||||
setCenter(code) {
|
||||
const shape = this.$shapeFactory.getShapeByCode(code);
|
||||
if (shape && shape) {
|
||||
var rect = utils.createBoundingRect(shape);
|
||||
var center = utils.calculateDCenter(rect, { width: this.$zr.getWidth(), height: this.$zr.getHeight() });
|
||||
this.setOption(center);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
setBackgroundColor(color) {
|
||||
this.$zr.setBackgroundColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
setCursorStyle(cursorStyle = 'auto') {
|
||||
this.$zr.setCursorStyle(cursorStyle);
|
||||
return this;
|
||||
}
|
||||
|
||||
repaint(source = {}) {
|
||||
this.$shapeFactory.parse(source, shape => {
|
||||
if (shape) {
|
||||
this.$painter.add(shape);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
render(list = []) {
|
||||
list.forEach(({model, action}) => {
|
||||
let updateModel = this.isDrawing() ? this.$shapeFactory.updateSource(model, action) : model;
|
||||
let curShape = this.$shapeFactory.getShapeByCode(updateModel.code);
|
||||
let deps = null;
|
||||
let oldShape = null;
|
||||
let newShape = null;
|
||||
|
||||
if (updateModel) {
|
||||
this.$controller.clear();
|
||||
switch (action.order) {
|
||||
case orders.Binding:
|
||||
case orders.Add:
|
||||
newShape = this.$shapeFactory.createShape(updateModel, action.shapeType);
|
||||
this.$shapeFactory.addShape(newShape);
|
||||
this.$painter.add(newShape);
|
||||
break;
|
||||
case orders.Delete:
|
||||
deps = curShape.getDepShapes();
|
||||
deps.forEach(el => {
|
||||
updateModel = this.isDrawing() ? this.$shapeFactory.updateSource(el, {...action, shapeType: el.shapeType}) : el;
|
||||
if (updateModel) {
|
||||
curShape = this.$shapeFactory.getShapeByCode(updateModel.code);
|
||||
oldShape = this.$shapeFactory.removeShape(curShape);
|
||||
this.$painter.remove(oldShape);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case orders.Update:
|
||||
oldShape = this.$shapeFactory.removeShape(curShape);
|
||||
this.$painter.remove(oldShape);
|
||||
newShape = this.$shapeFactory.createShape(updateModel, action.shapeType);
|
||||
this.$shapeFactory.addShape(newShape);
|
||||
this.$painter.add(newShape);
|
||||
break;
|
||||
case orders.Unbinding:
|
||||
oldShape = this.$shapeFactory.removeShape(curShape);
|
||||
this.$painter.remove(oldShape);
|
||||
this.$shapeFactory.addShape(oldShape);
|
||||
this.$painter.add(oldShape);
|
||||
break;
|
||||
// case orders.changeStatus:
|
||||
// // model
|
||||
// this.$painter.update(this.$stateHandle.update(this.$shapeFactory, []));
|
||||
// debugger;
|
||||
// break;
|
||||
// case orders.ResetStatus:
|
||||
// debugger;
|
||||
// break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.$eventEmitter.trigger(events.ViewUpdate, list);
|
||||
return this;
|
||||
}
|
||||
|
||||
update(list = []) {
|
||||
this.$painter.update(this.$stateHandle.update(this.$shapeFactory, list));
|
||||
this.$eventEmitter.trigger(events.StateUpdate, list);
|
||||
return this;
|
||||
}
|
||||
|
||||
getEvents() {
|
||||
return this.events;
|
||||
}
|
||||
|
||||
getZr() {
|
||||
return this.$zr;
|
||||
}
|
||||
|
||||
getOption() {
|
||||
return this.$option;
|
||||
}
|
||||
|
||||
getPainter() {
|
||||
return this.$painter;
|
||||
}
|
||||
|
||||
getController() {
|
||||
return this.$controller;
|
||||
}
|
||||
|
||||
getStorage() {
|
||||
return this.$controller.getStorage();
|
||||
}
|
||||
|
||||
getShapeFactory() {
|
||||
return this.$shapeFactory;
|
||||
}
|
||||
|
||||
getShapeByCode(code) {
|
||||
return this.$shapeFactory.getShapeByCode(code);
|
||||
}
|
||||
|
||||
getSource() {
|
||||
return this.$shapeFactory.getSource();
|
||||
}
|
||||
|
||||
getMapShape() {
|
||||
return this.$shapeFactory.getMapShape();
|
||||
}
|
||||
|
||||
getMapTemplate() {
|
||||
return this.$shapeFactory.getMapTemplate();
|
||||
}
|
||||
|
||||
resize(opt) {
|
||||
this.$zr.resize(opt);
|
||||
this.$painter.updateZrSize(opt);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.$painter.refresh();
|
||||
}
|
||||
|
||||
isDrawing() {
|
||||
return this.draw;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.$shapeFactory.clear();
|
||||
this.$controller.clear();
|
||||
this.$painter.clear();
|
||||
this.$zr.refresh();
|
||||
}
|
||||
|
||||
use(el) {
|
||||
this.plugins.includes(el) || this.plugins.push(el);
|
||||
el.install(this);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.disable();
|
||||
this.clear();
|
||||
this.$shapeFactory.destroy();
|
||||
this.$controller.destroy();
|
||||
this.$painter.destroy();
|
||||
this.$zr && this.$zr.dispose();
|
||||
this.plugins.forEach(el => {
|
||||
el.uninstall(this);
|
||||
});
|
||||
this.plugins = [];
|
||||
}
|
||||
|
||||
on(name, cb, context) {
|
||||
const idx = Object.values(events).indexOf(name);
|
||||
if (idx >= 0) {
|
||||
switch (name) {
|
||||
case events.DataLoaded:
|
||||
this.$eventEmitter.on(events.DataLoaded, cb, context);
|
||||
break;
|
||||
case events.ViewLoaded:
|
||||
this.$eventEmitter.on(events.ViewLoaded, cb, context);
|
||||
break;
|
||||
case events.StateLoaded:
|
||||
this.$eventEmitter.on(events.StateLoaded, cb, context);
|
||||
break;
|
||||
case events.ViewUpdate:
|
||||
this.$eventEmitter.on(events.ViewUpdate, cb, context);
|
||||
break;
|
||||
case events.StateUpdate:
|
||||
this.$eventEmitter.on(events.StateUpdate, cb, context);
|
||||
break;
|
||||
case events.OptionUpdate:
|
||||
this.$eventEmitter.on(events.OptionUpdate, cb, context);
|
||||
break;
|
||||
|
||||
case events.Click:
|
||||
this.$controller.on(events.Click, cb, context);
|
||||
break;
|
||||
case events.ContextMenu:
|
||||
this.$controller.on(events.ContextMenu, cb, context);
|
||||
break;
|
||||
case events.Reflect:
|
||||
this.$controller.on(events.Reflect, _.throttle(cb, 200), context);
|
||||
break;
|
||||
case events.DataZoom:
|
||||
this.$controller.on(events.DataZoom, cb, context);
|
||||
break;
|
||||
case events.Keydown:
|
||||
this.$controller.on(events.Keydown, cb, context);
|
||||
break;
|
||||
case events.Keypress:
|
||||
this.$controller.on(events.Keypress, cb, context);
|
||||
break;
|
||||
case events.Keyup:
|
||||
this.$controller.on(events.Keyup, cb, context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
off(name, cb) {
|
||||
const idx = Object.values(events).indexOf(name);
|
||||
if (idx >= 0) {
|
||||
switch (name) {
|
||||
case events.DataLoaded:
|
||||
this.$eventEmitter.off(events.DataLoaded, cb, context);
|
||||
break;
|
||||
case events.ViewLoaded:
|
||||
this.$eventEmitter.off(events.ViewLoaded, cb, context);
|
||||
break;
|
||||
case events.StateLoaded:
|
||||
this.$eventEmitter.off(events.StateLoaded, cb, context);
|
||||
break;
|
||||
case events.ViewUpdate:
|
||||
this.$eventEmitter.off(events.ViewUpdate, cb, context);
|
||||
break;
|
||||
case events.StateUpdate:
|
||||
this.$eventEmitter.off(events.StateUpdate, cb, context);
|
||||
break;
|
||||
case events.OptionUpdate:
|
||||
this.$eventEmitter.off(events.OptionUpdate, cb, context);
|
||||
break;
|
||||
|
||||
case events.Click:
|
||||
this.$controller.off(events.Click, cb);
|
||||
break;
|
||||
case events.ContextMenu:
|
||||
this.$controller.off(events.ContextMenu, cb);
|
||||
break;
|
||||
case events.Reflect:
|
||||
this.$controller.off(events.Reflect, _.throttle(cb, 200));
|
||||
break;
|
||||
case events.DataZoom:
|
||||
this.$controller.off(events.DataZoom, cb);
|
||||
break;
|
||||
case events.Keydown:
|
||||
this.$controller.off(events.Keydown, cb);
|
||||
break;
|
||||
case events.Keypress:
|
||||
this.$controller.off(events.Keypress, cb);
|
||||
break;
|
||||
case events.Keyup:
|
||||
this.$controller.off(events.Keyup, cb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pullBack(zr, option = {}, payload = {}) {
|
||||
const zrWidth = zr.getWidth();
|
||||
const zrHeight = zr.getHeight();
|
||||
const originX = payload.originX || zrWidth / 2;
|
||||
const originY = payload.originY || zrHeight / 2;
|
||||
const x = (option.offsetX + originX) / option.scaleRate;
|
||||
const y = (option.offsetY + originY) / option.scaleRate;
|
||||
const newScaleRate = option.getScaleRate(payload.scale);
|
||||
const dx = originX - (x * newScaleRate - option.offsetX);
|
||||
const dy = originY - (y * newScaleRate - option.offsetY);
|
||||
return {...payload, dx, dy};
|
||||
}
|
||||
|
||||
export default JMap;
|
84
src/iscs_new/maps.js
Normal file
84
src/iscs_new/maps.js
Normal file
@ -0,0 +1,84 @@
|
||||
import * as utils from './utils/utils';
|
||||
import * as Dom from './utils/dom';
|
||||
import JMap from './map';
|
||||
|
||||
const DOM_ATTRIBUTE_KEY = '_maps_instance_';
|
||||
class JMaps {
|
||||
constructor() {
|
||||
this._version = '1.0.0';
|
||||
this.instances = {};
|
||||
}
|
||||
|
||||
init(opts) {
|
||||
if (!opts) {
|
||||
throw new Error('Initialize failed: invalid params.');
|
||||
}
|
||||
|
||||
if (!opts.dom && opts.el) {
|
||||
opts['dom'] = document.getElementById(opts.el);
|
||||
}
|
||||
|
||||
if (!opts.dom) {
|
||||
throw new Error('Initialize failed: invalid dom and el.');
|
||||
}
|
||||
|
||||
const existInstance = this.getInstanceByDom(opts.dom);
|
||||
if (existInstance) {
|
||||
console.warn('There is a chart instance already initialized on the dom.');
|
||||
return existInstance;
|
||||
}
|
||||
|
||||
if (Dom.isDom(opts.dom) && opts.dom.nodeName.toUpperCase() !== 'CANVAS' &&
|
||||
(
|
||||
(!opts.dom.clientWidth && (!opts || opts.width == null)) ||
|
||||
(!opts.dom.clientHeight && (!opts || opts.height == null))
|
||||
)
|
||||
) {
|
||||
console.warn('Can\'t get DOM width or height. Please check ' +
|
||||
'dom.clientWidth and dom.clientHeight. They should not be 0.' +
|
||||
'For example, you may need to call this in the callback ' +
|
||||
'of window.onload.');
|
||||
}
|
||||
|
||||
const map = new JMap(opts);
|
||||
|
||||
this.instances[opts.el] = map;
|
||||
|
||||
Dom.setAttribute(opts.dom, DOM_ATTRIBUTE_KEY, opts.el);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
getVersion() {
|
||||
return this._version;
|
||||
}
|
||||
|
||||
getInstanceByDom(dom) {
|
||||
return this.instances[Dom.getAttribute(dom, DOM_ATTRIBUTE_KEY)];
|
||||
}
|
||||
|
||||
getInstanceById(el) {
|
||||
return this.instances[el];
|
||||
}
|
||||
|
||||
dispose(map) {
|
||||
if (utils.isString(map)) {
|
||||
map = this.instances[map];
|
||||
} else if (!utils.isInstanceOf(map, map)) {
|
||||
map = this.getInstanceByDom(map.getDom());
|
||||
}
|
||||
|
||||
if (map) {
|
||||
map.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
Object.values(this.instances).forEach(map => {
|
||||
this.dispose(map);
|
||||
})
|
||||
this.instances = []
|
||||
}
|
||||
}
|
||||
|
||||
export default JMaps;
|
62
src/iscs_new/option.js
Normal file
62
src/iscs_new/option.js
Normal file
@ -0,0 +1,62 @@
|
||||
class Option {
|
||||
constructor(opts, notice) {
|
||||
this.ratio = 100;
|
||||
|
||||
this.step = 0.1;
|
||||
|
||||
this.scaleMin = 0.3;
|
||||
|
||||
this.scaleMax = 10;
|
||||
|
||||
this.scaleRate = opts.scaleRate || 1; // 缩放
|
||||
|
||||
this.offsetX = opts.offsetX || 0; // x偏移
|
||||
|
||||
this.offsetY = opts.offsetY || 0; // y偏移
|
||||
|
||||
this.rotation = opts.rotation || 0; // 旋转弧度
|
||||
|
||||
this.throttle = opts.throttle || 100; // 刷新频率
|
||||
|
||||
this.preventDefaultMouseMove = true;
|
||||
|
||||
this.notice = notice;
|
||||
}
|
||||
|
||||
update(payload) {
|
||||
if (Number.isFinite(payload.dx)) {
|
||||
this.offsetX -= payload.dx;
|
||||
}
|
||||
if (Number.isFinite(payload.dy)) {
|
||||
this.offsetY -= payload.dy;
|
||||
}
|
||||
|
||||
if (Number.isFinite(payload.offsetX)) {
|
||||
this.offsetX = payload.offsetX;
|
||||
}
|
||||
if (Number.isFinite(payload.offsetY)) {
|
||||
this.offsetY = payload.offsetY;
|
||||
}
|
||||
|
||||
if (Number.isFinite(payload.scale)) {
|
||||
this.scaleRate = this.getScaleRate(payload.scale);
|
||||
}
|
||||
|
||||
if (Number.isFinite(payload.scaleRate)) {
|
||||
this.scaleRate = payload.scaleRate;
|
||||
}
|
||||
|
||||
if (this.notice instanceof Function) { this.notice(this); }
|
||||
}
|
||||
|
||||
getScaleRate(scale) {
|
||||
if (Number.isFinite(scale)) {
|
||||
const sumScaleNum = parseInt((this.scaleRate - this.scaleMin + scale * this.step) * this.ratio);
|
||||
const maxScaleNum = this.scaleMax * this.ratio;
|
||||
return sumScaleNum > 0? ((sumScaleNum%maxScaleNum) / this.ratio + this.scaleMin).toFixed(1): this.scaleRate;
|
||||
}
|
||||
return this.scaleRate;
|
||||
}
|
||||
}
|
||||
|
||||
export default Option;
|
117
src/iscs_new/painter.js
Normal file
117
src/iscs_new/painter.js
Normal file
@ -0,0 +1,117 @@
|
||||
import * as graphic from './core/graphic';
|
||||
import shapeLayer from './constant/shapeLayer';
|
||||
import Group from 'zrender/src/container/Group';
|
||||
import TransformHandle from './transformHandle';
|
||||
import AnimateHandle from './animateHandle';
|
||||
|
||||
class Painter extends Group {
|
||||
constructor(map) {
|
||||
super({name: `__Container__` });
|
||||
// 添加父级图层
|
||||
const zr = map.getZr();
|
||||
zr.add(this);
|
||||
|
||||
// 初始图层
|
||||
this.initLevels(map);
|
||||
|
||||
// 视图控制器
|
||||
this.$transformHandle = new TransformHandle(this);
|
||||
|
||||
// 动画处理器
|
||||
this.$animateHandle = new AnimateHandle(this);
|
||||
|
||||
// 重写onFrame加入钩子
|
||||
this.onframe(zr);
|
||||
}
|
||||
|
||||
onframe(zr) {
|
||||
const onframe = zr.animation.onframe;
|
||||
const animateHandle = this.$animateHandle;
|
||||
zr.animation.onframe = interval => {
|
||||
onframe.call(zr.animation, interval);
|
||||
animateHandle.onframe(interval);
|
||||
}
|
||||
}
|
||||
|
||||
initLevels(map) {
|
||||
// 初始化图层对象
|
||||
this.mapShapeLayer = {};
|
||||
|
||||
// 创建select图层
|
||||
this.mapShapeLayer[shapeLayer.Selecting] = new Group({ name: shapeLayer.Selecting });
|
||||
|
||||
// 创建hover图层
|
||||
this.mapShapeLayer[shapeLayer.HightLight] = new Group({ name: shapeLayer.HightLight });
|
||||
|
||||
// 创建tips图层
|
||||
this.mapShapeLayer[shapeLayer.Tips] = new Group({name: shapeLayer.Tips });
|
||||
|
||||
// 创建元素图层
|
||||
Object.keys(graphic).forEach(key => {
|
||||
this.mapShapeLayer[key] = new Group({
|
||||
name: `__${key}__`
|
||||
});
|
||||
})
|
||||
|
||||
// 添加图层
|
||||
Object.values(this.mapShapeLayer).forEach(el => {
|
||||
super.add(el);
|
||||
})
|
||||
}
|
||||
|
||||
add(shape) {
|
||||
shape && this.removeFromLayer(shapeLayer.HightLight, shape.instanceHightLight);
|
||||
shape && this.addToLayer(shape.type, shape);
|
||||
}
|
||||
|
||||
remove(shape) {
|
||||
shape && this.removeFromLayer(shapeLayer.HightLight, shape.instanceHightLight);
|
||||
shape && this.removeFromLayer(shape.type, shape);
|
||||
}
|
||||
|
||||
update(stateList=[]) {
|
||||
stateList
|
||||
.sort((a,b) => a.weight - b.weight)
|
||||
.forEach(state => {
|
||||
this.$animateHandle.animate(state);
|
||||
})
|
||||
}
|
||||
|
||||
updateTransform(opt) {
|
||||
this.$transformHandle.updateTransform(opt);
|
||||
}
|
||||
|
||||
updateZrSize(opt) {
|
||||
this.$transformHandle.updateZrSize(opt);
|
||||
}
|
||||
|
||||
addToLayer(name, shape) {
|
||||
name = Object.keys(graphic).includes(name)? name: `Group`;
|
||||
this.mapShapeLayer[name].add(shape);
|
||||
return shape;
|
||||
}
|
||||
|
||||
removeFromLayer(name, shape) {
|
||||
name = Object.keys(graphic).includes(name)? name: `Group`;
|
||||
this.mapShapeLayer[name].remove(shape);
|
||||
return shape;
|
||||
}
|
||||
|
||||
getLevelByName(name) {
|
||||
return this.mapShapeLayer[name];
|
||||
}
|
||||
|
||||
clear() {
|
||||
Object.values(this.mapShapeLayer).forEach(el => {
|
||||
el.removeAll();
|
||||
})
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.clear();
|
||||
this.mapShapeLayer = {};
|
||||
this.mapAnimate = {};
|
||||
}
|
||||
}
|
||||
|
||||
export default Painter;
|
111
src/iscs_new/plugins/shapeBuilder/entry.vue
Normal file
111
src/iscs_new/plugins/shapeBuilder/entry.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div class="builder" v-show="visible">
|
||||
<div class="container">
|
||||
<el-button-group>
|
||||
<el-button v-for="(type,i) in graphicType" :key="i" @click="doBuilder(type)">
|
||||
{{type}}
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as graphic from '../../core/graphic';
|
||||
import * as utils from '@/iscs_new/utils/utils';
|
||||
import shapeType from '@/iscs_new/constant/shapeType.js';
|
||||
import orders from '@/iscs_new/utils/orders';
|
||||
import elementConst from '@/iscs_new/core/form/elementConst';
|
||||
import formBuilder from '@/iscs_new/core/form/formBuilder';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
|
||||
const exec = (fm, name, ...args) => fm && fm[name] && fm[name](...args);
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
visible: true,
|
||||
enum: 'Compose',
|
||||
graphicType: [],
|
||||
strategyMap: {
|
||||
'Compose': {
|
||||
init: () => {
|
||||
this.graphicType = Object.fromEntries(Object.keys(graphic).filter(type => !['Group'].includes(type)).map(type => [type, type]))
|
||||
},
|
||||
doBuilder: (type) => {
|
||||
const form = formBuilder.buildForm(elementConst[type]);
|
||||
const model = utils.deepClone(form.model);
|
||||
model.code = utils.getUID(type);
|
||||
model.type = type;
|
||||
model.name = '<名称>';
|
||||
model.base.position = [300, 100];
|
||||
model.stateList = [];
|
||||
this.$iscs && this.$iscs.render([{model, action: {shapeType: shapeType.Element, order: orders.Add}}]);
|
||||
EventBus.$emit('getComposeElemList');
|
||||
}
|
||||
},
|
||||
'Map': {
|
||||
init: () =>{
|
||||
|
||||
},
|
||||
doBuilder: (type) => {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
exec(this.strategyMap[this.enum], 'init')
|
||||
},
|
||||
doBuilder(type) {
|
||||
exec(this.strategyMap[this.enum], 'doBuilder', type)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.builder {
|
||||
background: #f1f1f1;
|
||||
height: 100%;
|
||||
width: 130px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
/*滚动条整体样式*/
|
||||
width : 5px;
|
||||
/*高宽分别对应横竖滚动条的尺寸*/
|
||||
height: 1px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
/*滚动条里面小方块*/
|
||||
border-radius : 10px;
|
||||
background-color: lightskyblue;
|
||||
background-image: -webkit-linear-gradient(
|
||||
45deg,
|
||||
rgba(255, 255, 255, 0.2) 25%,
|
||||
transparent 25%,
|
||||
transparent 50%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
rgba(255, 255, 255, 0.2) 75%,
|
||||
transparent 75%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
/*滚动条里面轨道*/
|
||||
box-shadow : inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
background : #ededed;
|
||||
border-radius: 7px;
|
||||
}
|
||||
}
|
||||
</style>
|
67
src/iscs_new/plugins/shapeBuilder/index.js
Normal file
67
src/iscs_new/plugins/shapeBuilder/index.js
Normal file
@ -0,0 +1,67 @@
|
||||
import Vue from 'vue';
|
||||
import events from '@/iscs_new/utils/events';
|
||||
import entry from './entry.vue';
|
||||
|
||||
const VuePage = Vue.extend(entry);
|
||||
|
||||
const handle = {
|
||||
onClick(e) {
|
||||
if (!e) {
|
||||
this.page.type = '';
|
||||
}
|
||||
},
|
||||
onContextMenu(e) {
|
||||
if (!e) {
|
||||
this.page.type = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
class ShapeBuilder {
|
||||
constructor(map) {
|
||||
this.zr = map.getZr();
|
||||
this.map = map;
|
||||
this.page = this.initUI();
|
||||
}
|
||||
|
||||
initUI() {
|
||||
const el = this.zr.dom;
|
||||
const page = new VuePage({
|
||||
el: document.createElement('div'),
|
||||
data () {}
|
||||
});
|
||||
|
||||
el.page = page;
|
||||
el.dom = page.$el;
|
||||
el.grSelectStyle = {};
|
||||
el.appendChild(el.dom);
|
||||
return page;
|
||||
}
|
||||
|
||||
addEventListener() {
|
||||
if (this.map) {
|
||||
this.map.on(events.Click, handle.onClick, this);
|
||||
this.map.on(events.ContextMenu, handle.onContextMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListener() {
|
||||
if (this.map) {
|
||||
this.map.off(events.Click, handle.onClick, this);
|
||||
this.map.off(events.ContextMenu, handle.onContextMenu, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
el: null,
|
||||
install(map) {
|
||||
this.el = new ShapeBuilder(map);
|
||||
this.el.addEventListener();
|
||||
},
|
||||
uninstall(map) {
|
||||
if (this.el) {
|
||||
this.el.removeEventListener();
|
||||
this.el = null;
|
||||
}
|
||||
}
|
||||
}
|
208
src/iscs_new/plugins/shapeContextMenu/entry.vue
Normal file
208
src/iscs_new/plugins/shapeContextMenu/entry.vue
Normal file
@ -0,0 +1,208 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div v-if="visible" class="menus" :style="{ left: position.x+'px', top: position.y+'px' }">
|
||||
<menu-item v-for="(el, i) in menus" :key="i" :option="el" @close="doClose" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MenuItem from './menu-item';
|
||||
import shapeType from '@/iscs_new/constant/shapeType.js';
|
||||
import orders from '@/iscs_new/utils/orders';
|
||||
import * as utils from '@/iscs_new/utils/utils';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MenuItem
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
visible: true,
|
||||
selected: null,
|
||||
breforePosition: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
clipboardList: [],
|
||||
menus: [],
|
||||
menusMap: {
|
||||
Normal: [
|
||||
{
|
||||
label: '组合',
|
||||
handler: this.doBinding,
|
||||
disabledCb: e => {
|
||||
const storage = this.$iscs.getController().getStorage();
|
||||
return storage.values().length <= 1;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '解组',
|
||||
handler: this.doUnBinding,
|
||||
disabledCb: e => {
|
||||
return this.selected.shapeType != shapeType.Compose;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '复制',
|
||||
handler: this.doCopy,
|
||||
disabledCb: e => {
|
||||
const storage = this.$iscs.getController().getStorage();
|
||||
return !storage.values().length;
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
handler: this.doDelete,
|
||||
disabledCb: e => {
|
||||
const storage = this.$iscs.getController().getStorage();
|
||||
return !storage.values().length;
|
||||
}
|
||||
}
|
||||
],
|
||||
None: [
|
||||
{
|
||||
label: '粘贴',
|
||||
handler: this.doPaste,
|
||||
disabledCb: e => {
|
||||
return !this.clipboardList.length;
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
doShow(point, code) {
|
||||
const list = code ? this.menusMap.Normal: this.menusMap.None;
|
||||
this.selected= this.$iscs.getShapeByCode(code);
|
||||
this.menus = list.map(el => { el.disabled = el.disabledCb({}); return el} );
|
||||
if (this.menus &&
|
||||
this.menus.length) {
|
||||
this.position = {...point},
|
||||
this.visible = true;
|
||||
}
|
||||
},
|
||||
doClose() {
|
||||
this.selected = null;
|
||||
this.visible = false;
|
||||
},
|
||||
doBinding(el) {
|
||||
const controller = this.$iscs.getController();
|
||||
const storage = controller.getStorage()
|
||||
const values = storage.values();
|
||||
if (values.length > 1) {
|
||||
const elem = {
|
||||
model: {
|
||||
code: utils.getUID('compose'),
|
||||
type: 'Device',
|
||||
elementCodes: values.map(el => el.model.code),
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [0, 0],
|
||||
rotation: 0,
|
||||
hide: false,
|
||||
},
|
||||
composeCode: '',
|
||||
},
|
||||
action: { order: orders.Binding, shapeType: shapeType.Compose }
|
||||
}
|
||||
this.$iscs.render([elem]);
|
||||
} else {
|
||||
this.$message.info('请选择两个及其以上数目元素');
|
||||
}
|
||||
},
|
||||
doUnBinding(el) {
|
||||
if (this.selected) {
|
||||
this.$iscs.render([
|
||||
{
|
||||
model: this.selected.model,
|
||||
action: { order: orders.Unbinding, shapeType: shapeType.Compose }
|
||||
}
|
||||
]);
|
||||
}
|
||||
},
|
||||
doCopy(el) {
|
||||
const option = this.$iscs.getOption();
|
||||
const storage = this.$iscs.getController().getStorage();
|
||||
this.clipboardList = [...storage.values()];
|
||||
this.breforePosition = {
|
||||
x: this.position.x + option.offsetX,
|
||||
y: this.position.y + option.offsetY
|
||||
}
|
||||
},
|
||||
doPaste(el) {
|
||||
const option = this.$iscs.getOption();
|
||||
const renderList = [];
|
||||
const clipboardList = [...this.clipboardList];
|
||||
const diffPosition = [
|
||||
(this.position.x + option.offsetX - this.breforePosition.x)/option.scaleRate,
|
||||
(this.position.y + option.offsetY - this.breforePosition.y)/option.scaleRate
|
||||
]
|
||||
|
||||
clipboardList.forEach(el => {
|
||||
this.clone(el, utils.getUID(el.type), '', el => {
|
||||
const shapeType = el.shapeType;
|
||||
const model = el.model;
|
||||
const position = model.base.position||[0, 0];
|
||||
model.base.position = model.composeCode? position: position.map((el,i) => el+diffPosition[i]);
|
||||
renderList.push({ model, action: { order: orders.Add, shapeType } });
|
||||
});
|
||||
})
|
||||
|
||||
this.$iscs.render(renderList);
|
||||
},
|
||||
doDelete(el) {
|
||||
const storage = this.$iscs.getController().getStorage();
|
||||
const renderList = storage.values().map(el => {
|
||||
return {
|
||||
model: el.model,
|
||||
action: { order: orders.Delete, shapeType: el.shapeType }
|
||||
}
|
||||
});
|
||||
this.$iscs.render(renderList);
|
||||
},
|
||||
clone(el, code='', composeCode='', cb) {
|
||||
const model = utils.deepClone(el.model);
|
||||
model.code = code;
|
||||
model.composeCode = composeCode;
|
||||
if (el.shapeType == shapeType.Compose) {
|
||||
model.elementCodes = model.elementCodes.map(code => {
|
||||
const shape = this.$iscs.getShapeByCode(code);
|
||||
const newCode = utils.getUID(shape.type)
|
||||
this.clone(shape, newCode, code, cb);
|
||||
return newCode;
|
||||
})
|
||||
}
|
||||
cb({...el, model});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 2000;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
.menus {
|
||||
position: absolute;
|
||||
pointer-events: all;
|
||||
background: #f1f1f1;
|
||||
box-shadow: 0 2px 12px rgba(0,0,0,0.3);
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
67
src/iscs_new/plugins/shapeContextMenu/index.js
Normal file
67
src/iscs_new/plugins/shapeContextMenu/index.js
Normal file
@ -0,0 +1,67 @@
|
||||
import Vue from 'vue';
|
||||
import events from '@/iscs_new/utils/events';
|
||||
import entry from './entry.vue';
|
||||
|
||||
const elPage = Vue.extend(entry);
|
||||
|
||||
const handle = {
|
||||
onClick(e) {
|
||||
if (this.page) {
|
||||
this.page.doClose()
|
||||
}
|
||||
},
|
||||
onContextMenu(e) {
|
||||
if (this.page) {
|
||||
this.page.doShow({x: e.clientX, y: e.clientY}, e.code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ShapeBuilder {
|
||||
constructor(map) {
|
||||
this.zr = map.getZr();
|
||||
this.map = map;
|
||||
this.page = this.initUI();
|
||||
}
|
||||
|
||||
initUI() {
|
||||
const el = this.zr.dom;
|
||||
const page = new elPage({
|
||||
el: document.createElement('div'),
|
||||
data () {}
|
||||
});
|
||||
el.page = page;
|
||||
el.dom = page.$el;
|
||||
el.grSelectStyle = {};
|
||||
el.appendChild(el.dom);
|
||||
return page;
|
||||
}
|
||||
|
||||
addEventListener() {
|
||||
if (this.map) {
|
||||
this.map.on(events.Click, handle.onClick, this);
|
||||
this.map.on(events.ContextMenu, handle.onContextMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListener() {
|
||||
if (this.map) {
|
||||
this.map.off(events.Click, handle.onClick, this);
|
||||
this.map.off(events.ContextMenu, handle.onContextMenu, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
el: null,
|
||||
install(map) {
|
||||
this.el = new ShapeBuilder(map);
|
||||
this.el.addEventListener();
|
||||
},
|
||||
uninstall(map) {
|
||||
if (this.el) {
|
||||
this.el.removeEventListener();
|
||||
this.el = null;
|
||||
}
|
||||
}
|
||||
}
|
202
src/iscs_new/plugins/shapeContextMenu/menu-item.vue
Normal file
202
src/iscs_new/plugins/shapeContextMenu/menu-item.vue
Normal file
@ -0,0 +1,202 @@
|
||||
<template>
|
||||
<li v-if="option.children && option.children.length" class="menu-item" @mouseenter="enter($vnode.key)" @mouseleave="leave">
|
||||
<div ref="flexBox" class="flex-box">
|
||||
<el-button type="text" class="item" :disabled="checkDisabled(option)">
|
||||
<el-link v-if="option.tipsType" :type="option.tipsType" :underline="false">{{ option.label }}</el-link>
|
||||
<span v-else :style="{color: textColor(option) }">{{ option.label }}</span>
|
||||
</el-button>
|
||||
<i class="el-icon-arrow-right" />
|
||||
</div>
|
||||
<ul v-if="isPopup" ref="popup" class="menu" :style="{display: isShow? 'block': 'table', marginLeft: marginLeft+'px'}">
|
||||
<div class="menu-pop pop-menu">
|
||||
<div v-show="isShow" class="arrow el-icon-arrow-down" />
|
||||
<pop-menu-item v-for="(el, i) in option.children" :key="i" :option="el" :allowedColor="allowedColor" :disabledColor="disabledColor" @close="close" />
|
||||
<div v-show="isShow" class="arrow el-icon-arrow-up" />
|
||||
</div>
|
||||
</ul>
|
||||
</li>
|
||||
<li v-else-if="checkVisible(option)" class="menu-item" >
|
||||
<div v-if="option.type === 'separator'" class="separator"> </div>
|
||||
<el-button v-else-if="option.type ==='file'" type="text" class="uploadDemo item" :disabled="checkDisabled(option)">
|
||||
<input :ref="option.label" type="file" class="file_box" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" @change="doHandle(option, true)">
|
||||
<el-link v-if="option.tipsType" :type="option.tipsType" :underline="false">{{ option.label }} </el-link>
|
||||
<span v-else :style="{color: textColor(option) }">{{ option.label }}</span>
|
||||
</el-button>
|
||||
<el-button v-else type="text" class="item" :disabled="checkDisabled(option)" @click="doHandle(option, false)">
|
||||
<el-link v-if="option.tipsType" :type="option.tipsType" :underline="false">{{ option.label }}</el-link>
|
||||
<span v-else :style="{color: textColor(option) }">{{ option.label }}</span>
|
||||
</el-button>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'PopMenuItem',
|
||||
props: {
|
||||
option: {
|
||||
type: Object,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabledColor: {
|
||||
type: String,
|
||||
default: '#ccc',
|
||||
},
|
||||
allowedColor: {
|
||||
type: String,
|
||||
default: '#000'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
active: -1
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isPopup() {
|
||||
return this.active == this.$vnode.key;
|
||||
},
|
||||
isShow() {
|
||||
return this.option.children.length > 12;
|
||||
},
|
||||
marginLeft() {
|
||||
return this.$refs.flexBox.offsetWidth;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkDisabled(option) {
|
||||
return option.disabled || this.disabled;
|
||||
},
|
||||
checkVisible(option) {
|
||||
if (typeof (option.show) === 'undefined') {
|
||||
return true;
|
||||
} else {
|
||||
return option.show;
|
||||
}
|
||||
},
|
||||
textColor(option) {
|
||||
return this.checkDisabled(option) ? this.disabledColor : this.allowedColor;
|
||||
},
|
||||
doHandle(option, isFile) {
|
||||
if (option.handler && !this.checkDisabled(option)) {
|
||||
if (isFile) {
|
||||
const obj = this.$refs[option.label][0];
|
||||
if (obj.files) {
|
||||
const file = obj.files[0];
|
||||
option.handler(file);
|
||||
obj.value = '';
|
||||
}
|
||||
} else {
|
||||
option.handler(option);
|
||||
}
|
||||
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.$emit('close');
|
||||
},
|
||||
enter(active) {
|
||||
this.active = active;
|
||||
},
|
||||
leave(e) {
|
||||
this.active = -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
$bg: #FFFFFF;
|
||||
$item-hover: #CFE8FC;
|
||||
$item-text: #606266;
|
||||
$item-separator: #666;
|
||||
$item-border: #909399;
|
||||
$item-disabled: #cccccc;
|
||||
$item-height: 30px;
|
||||
|
||||
/deep/ {
|
||||
.el-button--text {
|
||||
padding: 6px 15px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
margin-top: -$item-height - 1;
|
||||
max-height: 360px;
|
||||
overflow: auto;
|
||||
|
||||
&-pop {
|
||||
display:table;
|
||||
border: 1px solid $item-border;
|
||||
.arrow {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background: $bg;
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
.flex-box{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
list-style: none;
|
||||
min-width: 110px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.menu-item:hover {
|
||||
background: $item-hover;
|
||||
}
|
||||
|
||||
.separator {
|
||||
background: $item-separator;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.item {
|
||||
color: $item-text;
|
||||
height: $item-height;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.uploadDemo {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
color: $item-text;
|
||||
|
||||
input {
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
36
src/iscs_new/plugins/shapeProperty/entry.vue
Normal file
36
src/iscs_new/plugins/shapeProperty/entry.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
class="property"
|
||||
title="我是标题"
|
||||
:modal="false"
|
||||
:visible.sync="visible"
|
||||
:with-header="false">
|
||||
<div class="container">
|
||||
<span>我来啦!</span>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
visible: true
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.property {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
.container {
|
||||
padding: 30px;
|
||||
}
|
||||
}
|
||||
</style>
|
77
src/iscs_new/plugins/shapeProperty/index.js
Normal file
77
src/iscs_new/plugins/shapeProperty/index.js
Normal file
@ -0,0 +1,77 @@
|
||||
import Vue from 'vue';
|
||||
import events from '@/iscs_new/utils/events';
|
||||
import entry from './entry.vue';
|
||||
|
||||
const elPage = Vue.extend(entry);
|
||||
|
||||
const toggling = (page, e) => {
|
||||
if (!!e) {
|
||||
Vue.nextTick(() => {
|
||||
page.visible = true;
|
||||
});
|
||||
} else {
|
||||
page.visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handle = {
|
||||
onClick(e) {
|
||||
toggling(this.page, e);
|
||||
},
|
||||
onContextMenu(e) {
|
||||
},
|
||||
onModify(e) {
|
||||
},
|
||||
onDelete(e) {
|
||||
}
|
||||
}
|
||||
|
||||
class ShapeBuilder {
|
||||
constructor(map) {
|
||||
this.zr = map.getZr();
|
||||
this.map = map;
|
||||
this.page = this.initUI();
|
||||
}
|
||||
|
||||
initUI() {
|
||||
const el = this.zr.dom;
|
||||
const page = new elPage({
|
||||
el: document.createElement('div'),
|
||||
data () {}
|
||||
});
|
||||
el.page = page;
|
||||
el.dom = page.$el;
|
||||
el.grSelectStyle = {};
|
||||
el.appendChild(el.dom);
|
||||
return page;
|
||||
}
|
||||
|
||||
addEventListener() {
|
||||
if (this.map) {
|
||||
this.map.on(events.Click, handle.onClick, this);
|
||||
this.map.on(events.ContextMenu, handle.onContextMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListener() {
|
||||
if (this.map) {
|
||||
this.map.off(events.Click, handle.onClick, this);
|
||||
this.map.off(events.ContextMenu, handle.onContextMenu, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
el: null,
|
||||
install(map) {
|
||||
this.el = new ShapeBuilder(map);
|
||||
this.el.addEventListener();
|
||||
},
|
||||
uninstall(map) {
|
||||
if (this.el) {
|
||||
this.el.removeEventListener();
|
||||
this.el = null;
|
||||
}
|
||||
}
|
||||
}
|
79
src/iscs_new/plugins/shapeState/entry.vue
Normal file
79
src/iscs_new/plugins/shapeState/entry.vue
Normal file
@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div class="builder" v-show="visible">
|
||||
<div class="container">
|
||||
////
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as graphic from '../../core/graphic';
|
||||
import * as utils from '@/iscs_new/utils/utils';
|
||||
import shapeType from '@/iscs_new/constant/shapeType.js';
|
||||
import orders from '@/iscs_new/utils/orders';
|
||||
import elementConst from '@/iscs_new/core/form/elementConst';
|
||||
import formBuilder from '@/iscs_new/core/form/formBuilder';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
visible: true,
|
||||
graphicType: Object.fromEntries(Object.keys(graphic).filter(type => !['Group'].includes(type)).map(type => [type, type]))
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
doBuilder(type) {
|
||||
const form = formBuilder.buildForm(elementConst[type]);
|
||||
const model = utils.deepClone(form.model);
|
||||
model.code = utils.getUID(type);
|
||||
model.type = type;
|
||||
model.name = '<名称>';
|
||||
model.base.position = [300, 100];
|
||||
model.stateList = [];
|
||||
this.$iscs && this.$iscs.render([{model, action: {shapeType: shapeType.Element, order: orders.Add}}]);
|
||||
EventBus.$emit('getComposeElemList');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.builder {
|
||||
background: #f1f1f1;
|
||||
height: 100%;
|
||||
width: 130px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
/*滚动条整体样式*/
|
||||
width : 5px;
|
||||
/*高宽分别对应横竖滚动条的尺寸*/
|
||||
height: 1px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
/*滚动条里面小方块*/
|
||||
border-radius : 10px;
|
||||
background-color: lightskyblue;
|
||||
background-image: -webkit-linear-gradient(
|
||||
45deg,
|
||||
rgba(255, 255, 255, 0.2) 25%,
|
||||
transparent 25%,
|
||||
transparent 50%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
rgba(255, 255, 255, 0.2) 75%,
|
||||
transparent 75%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
/*滚动条里面轨道*/
|
||||
box-shadow : inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
background : #ededed;
|
||||
border-radius: 7px;
|
||||
}
|
||||
}
|
||||
</style>
|
67
src/iscs_new/plugins/shapeState/index.js
Normal file
67
src/iscs_new/plugins/shapeState/index.js
Normal file
@ -0,0 +1,67 @@
|
||||
import Vue from 'vue';
|
||||
import events from '@/iscs_new/utils/events';
|
||||
import entry from './entry.vue';
|
||||
|
||||
const VuePage = Vue.extend(entry);
|
||||
|
||||
const handle = {
|
||||
onClick(e) {
|
||||
if (!e) {
|
||||
this.page.type = '';
|
||||
}
|
||||
},
|
||||
onContextMenu(e) {
|
||||
if (!e) {
|
||||
this.page.type = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
class ShapeBuilder {
|
||||
constructor(map) {
|
||||
this.zr = map.getZr();
|
||||
this.map = map;
|
||||
this.page = this.initUI();
|
||||
}
|
||||
|
||||
initUI() {
|
||||
const el = this.zr.dom;
|
||||
const page = new VuePage({
|
||||
el: document.createElement('div'),
|
||||
data () {}
|
||||
});
|
||||
|
||||
el.page = page;
|
||||
el.dom = page.$el;
|
||||
el.grSelectStyle = {};
|
||||
el.appendChild(el.dom);
|
||||
return page;
|
||||
}
|
||||
|
||||
addEventListener() {
|
||||
if (this.map) {
|
||||
this.map.on(events.Click, handle.onClick, this);
|
||||
this.map.on(events.ContextMenu, handle.onContextMenu, this);
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListener() {
|
||||
if (this.map) {
|
||||
this.map.off(events.Click, handle.onClick, this);
|
||||
this.map.off(events.ContextMenu, handle.onContextMenu, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
el: null,
|
||||
install(map) {
|
||||
this.el = new ShapeBuilder(map);
|
||||
this.el.addEventListener();
|
||||
},
|
||||
uninstall(map) {
|
||||
if (this.el) {
|
||||
this.el.removeEventListener();
|
||||
this.el = null;
|
||||
}
|
||||
}
|
||||
}
|
58
src/iscs_new/selectHandle.js
Normal file
58
src/iscs_new/selectHandle.js
Normal file
@ -0,0 +1,58 @@
|
||||
import shapeLayer from './constant/shapeLayer';
|
||||
export default class SelectHandle {
|
||||
constructor(map, controller) {
|
||||
this.$map = map;
|
||||
this.$zr = map.getZr();
|
||||
this.$controller = controller;
|
||||
this.$painter = map.getPainter();
|
||||
|
||||
this.e = {};
|
||||
}
|
||||
|
||||
onSelected(e) {
|
||||
if (e.target) {
|
||||
const storage = this.$controller.getStorage();
|
||||
this.e = {...e};
|
||||
if ([`Control`].includes(this.$controller.getKeyStr())) {
|
||||
if (this.$controller.isSelected(e.target.code)) {
|
||||
this.$controller.setTarget(null);
|
||||
this.delSelected(e.target);
|
||||
} else {
|
||||
this.addSelected(e.target);
|
||||
}
|
||||
} else if (!storage.has(e.target.code)){
|
||||
this.clear();
|
||||
this.addSelected(e.target);
|
||||
} else {
|
||||
this.addSelected(e.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addSelected(target) {
|
||||
const storage = this.$controller.getStorage();
|
||||
storage.set(target.code, target);
|
||||
target.shapeFactory.showHightLight(target);
|
||||
}
|
||||
|
||||
delSelected(target) {
|
||||
const storage = this.$controller.getStorage();
|
||||
target.shapeFactory.hideHightLight(target);;
|
||||
storage.delete(target.code);
|
||||
}
|
||||
|
||||
clear() {
|
||||
const storage = this.$controller.getStorage();
|
||||
storage.values().forEach(target => {
|
||||
this.delSelected(target);
|
||||
});
|
||||
}
|
||||
|
||||
setDraggable(draggable) {
|
||||
const target = this.e.target;
|
||||
if (target &&
|
||||
target.highLightInstance) {
|
||||
target.highLightInstance.setDraggable(draggable);
|
||||
}
|
||||
}
|
||||
}
|
293
src/iscs_new/selectingHandle.js
Normal file
293
src/iscs_new/selectingHandle.js
Normal file
@ -0,0 +1,293 @@
|
||||
import * as graphic from './core/graphic.js';
|
||||
import shapeRender from './constant/shapeRender';
|
||||
import shapeLayer from './constant/shapeLayer';
|
||||
import events from './utils/events.js';
|
||||
import defaultStyle from './config/defaultStyle';
|
||||
|
||||
const vernierStyle = {
|
||||
area: {
|
||||
areaStyle: {
|
||||
fill: `rgba(200,200,200,0.3)`
|
||||
}
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
strokeNoScale: true,
|
||||
lineWidth: 30,
|
||||
stroke: 'rgba(255,255,255,0.6)'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
distance: 18,
|
||||
length: 5,
|
||||
lineStyle: {
|
||||
strokeNoScale: true,
|
||||
lineWidth: 2,
|
||||
stroke: '#000000'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
distance: 5,
|
||||
textStyle: {
|
||||
strokeNoScale: true,
|
||||
textStroke: '#000',
|
||||
textAlign: 'center',
|
||||
textVerticalAlign: 'center'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class Vernier extends graphic.Group {
|
||||
constructor(args) {
|
||||
super(args);
|
||||
this._scaleRate = 1;
|
||||
this._area = null;
|
||||
this._axisLineX = null;
|
||||
this._axisLineY = null;
|
||||
}
|
||||
|
||||
_createArea(rect) {
|
||||
this._area = new graphic.Rect({
|
||||
subType: '@ignore',
|
||||
...shapeRender,
|
||||
z: 9999,
|
||||
silent: true,
|
||||
shape: {
|
||||
...rect
|
||||
},
|
||||
style: {
|
||||
...vernierStyle.area.areaStyle
|
||||
}
|
||||
})
|
||||
this.add(this._area);
|
||||
}
|
||||
|
||||
_createLineAxisX(rect) {
|
||||
const minX = rect.x;
|
||||
const minY = rect.y;
|
||||
const maxX = rect.x + rect.width;
|
||||
const maxY = rect.y + rect.height;
|
||||
const directionX = (Math.abs(rect.width)/rect.width);
|
||||
const directionY = (Math.abs(rect.height)/rect.height);
|
||||
const axisLineWidthHalf = vernierStyle.axisLine.lineStyle.lineWidth/this._scaleRate/2;
|
||||
|
||||
this._axisLineX = new graphic.Line({
|
||||
...shapeRender,
|
||||
z: 9999,
|
||||
silent: true,
|
||||
position: [0, -axisLineWidthHalf*directionY],
|
||||
shape: {
|
||||
x1: minX,
|
||||
y1: minY,
|
||||
x2: maxX,
|
||||
y2: minY
|
||||
},
|
||||
style: {
|
||||
...vernierStyle.axisLine.lineStyle
|
||||
}
|
||||
})
|
||||
|
||||
const step = vernierStyle.axisTick.lineStyle.lineWidth*2/this._scaleRate;
|
||||
const count = parseInt(Math.abs(rect.width/step));
|
||||
|
||||
for(var i = 0; i in new Array(count+1).fill(0); i++) {
|
||||
const offset = step * i * directionX;
|
||||
const tick = i % vernierStyle.axisTick.length == 0
|
||||
const len = tick? vernierStyle.axisTick.distance*0.7: vernierStyle.axisTick.distance*0.4;
|
||||
if (tick) {
|
||||
this.add(new graphic.Line({
|
||||
...shapeRender,
|
||||
z: 10000,
|
||||
silent: true,
|
||||
shape: {
|
||||
x1: minX + offset,
|
||||
y1: minY,
|
||||
x2: minX + offset,
|
||||
y2: minY - len * directionY / this._scaleRate
|
||||
},
|
||||
style: {
|
||||
...vernierStyle.axisTick.lineStyle,
|
||||
...vernierStyle.axisLabel.textStyle,
|
||||
text: i%2? '': i/vernierStyle.axisTick.length/2,
|
||||
textPosition: directionY > 0? 'top': 'bottom'
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
this.add(new graphic.Line({
|
||||
...shapeRender,
|
||||
z: 10000,
|
||||
silent: true,
|
||||
shape: {
|
||||
x1: minX + offset,
|
||||
y1: minY,
|
||||
x2: minX + offset,
|
||||
y2: minY - len * directionY / this._scaleRate
|
||||
},
|
||||
style: {
|
||||
...vernierStyle.axisTick.lineStyle
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
this.add(this._axisLineX);
|
||||
}
|
||||
|
||||
_createLineAxisY(rect) {
|
||||
const minX = rect.x;
|
||||
const minY = rect.y;
|
||||
const maxX = rect.x + rect.width;
|
||||
const maxY = rect.y + rect.height;
|
||||
const directionX = (Math.abs(rect.width)/rect.width);
|
||||
const directionY = (Math.abs(rect.height)/rect.height);
|
||||
const axisLineWidthHalf = vernierStyle.axisLine.lineStyle.lineWidth/this._scaleRate/2;
|
||||
|
||||
this._axisLineY = new graphic.Line({
|
||||
...shapeRender,
|
||||
z: 9999,
|
||||
silent: true,
|
||||
position: [-axisLineWidthHalf*directionX, 0],
|
||||
shape: {
|
||||
x1: minX,
|
||||
y1: minY,
|
||||
x2: minX,
|
||||
y2: maxY
|
||||
},
|
||||
style: {
|
||||
...vernierStyle.axisLine.lineStyle
|
||||
}
|
||||
})
|
||||
this.add(this._axisLineY);
|
||||
|
||||
|
||||
const step = vernierStyle.axisTick.lineStyle.lineWidth*2 /this._scaleRate;
|
||||
const count = parseInt(Math.abs(rect.height/step));
|
||||
|
||||
for(var i = 0; i in new Array(count+1).fill(0); i++) {
|
||||
const offset = step * i * directionY;
|
||||
const tick = i % vernierStyle.axisTick.length == 0;
|
||||
const len = tick? vernierStyle.axisTick.distance*0.7: vernierStyle.axisTick.distance*0.4;
|
||||
if (tick) {
|
||||
this.add(new graphic.Line({
|
||||
...shapeRender,
|
||||
z: 10000,
|
||||
silent: true,
|
||||
shape: {
|
||||
x1: minX,
|
||||
y1: minY + offset,
|
||||
x2: minX - len * directionX / this._scaleRate,
|
||||
y2: minY + offset
|
||||
},
|
||||
style: {
|
||||
...vernierStyle.axisTick.lineStyle,
|
||||
...vernierStyle.axisLabel.textStyle,
|
||||
text: i%2? '': i/vernierStyle.axisTick.length/2,
|
||||
textPosition: directionX > 0? 'left': 'right'
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
this.add(new graphic.Line({
|
||||
...shapeRender,
|
||||
z: 10000,
|
||||
silent: true,
|
||||
shape: {
|
||||
x1: minX,
|
||||
y1: minY + offset,
|
||||
x2: minX - len * directionX / this._scaleRate,
|
||||
y2: minY + offset
|
||||
},
|
||||
style: {
|
||||
...vernierStyle.axisTick.lineStyle
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render(rect) {
|
||||
this.removeAll();
|
||||
this._scaleRate = this.parent? this.parent.transform[0]: 1;
|
||||
this._createArea(rect);
|
||||
this._createLineAxisX(rect);
|
||||
this._createLineAxisY(rect);
|
||||
}
|
||||
|
||||
setShape(rect) {
|
||||
this.render(rect);
|
||||
}
|
||||
}
|
||||
export default class SelectingHandle {
|
||||
constructor(map, controller) {
|
||||
this.$map = map;
|
||||
this.$zr = map.getZr();
|
||||
this.$controller = controller;
|
||||
this.$painter = map.getPainter();
|
||||
|
||||
this.begPoint = null;
|
||||
this.endPoint = null;
|
||||
this.selecting = new Vernier({subType: '@selecting'});
|
||||
}
|
||||
|
||||
isSelecting() {
|
||||
return this.begPoint;
|
||||
}
|
||||
|
||||
onSelectStart(e) {
|
||||
this.selecting.setShape({ x: e.x, y: e.y, width: 0, height: 0 });
|
||||
this.$painter.addToLayer(shapeLayer.Selecting, this.selecting);
|
||||
this.begPoint = { x: e.x, y: e.y };
|
||||
this.endPoint = null;
|
||||
}
|
||||
|
||||
onSelecting(e) {
|
||||
this.endPoint = { x: e.x, y: e.y };
|
||||
this.selecting.setShape(this.normalizedArea(this.begPoint, this.endPoint));
|
||||
this.$painter.addToLayer(shapeLayer.Selecting, this.selecting);
|
||||
}
|
||||
|
||||
onSelectEnd(e) {
|
||||
this.endPoint = { x: e.x, y: e.y };
|
||||
this.selecting.setShape(this.normalizedArea(this.begPoint, this.endPoint));
|
||||
this.$painter.addToLayer(shapeLayer.Selecting, this.selecting);
|
||||
|
||||
const selectingRect = this.selecting.getBoundingRect();
|
||||
Object.values(this.$map.getMapShape()).forEach(el => {
|
||||
if (el.model && !el.model.composeCode && this.checkSelectingRectContainShape(selectingRect, el)) {
|
||||
this.setSelected(el);
|
||||
}
|
||||
});
|
||||
|
||||
this.clear();
|
||||
}
|
||||
|
||||
setSelected(target) {
|
||||
const storage = this.$controller.getStorage();
|
||||
storage.set(target.code, target);
|
||||
target.shapeFactory.showHightLight(target);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.$painter.removeFromLayer(shapeLayer.Selecting, this.selecting);
|
||||
this.selecting.setShape({ x: 0, y: 0, width: 0, height: 0 });
|
||||
this.begPoint = this.endPoint = null;
|
||||
}
|
||||
|
||||
checkSelectingRectContainShape(rect, shape) {
|
||||
const shapeRect = shape.getBoundingRect();
|
||||
if (shapeRect) {
|
||||
return rect.contain(shapeRect.x, shapeRect.y) && rect.contain(shapeRect.x+shapeRect.width, shapeRect.y+shapeRect.height);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
normalizedArea(begin, end) {
|
||||
const options = this.$map.getOption();
|
||||
const x = (begin.x + options.offsetX) / options.scaleRate;
|
||||
const y = (begin.y + options.offsetY) / options.scaleRate;
|
||||
const width = (end.x - begin.x) / options.scaleRate;
|
||||
const height = (end.y - begin.y) / options.scaleRate;
|
||||
return {x, y, width, height};
|
||||
}
|
||||
}
|
63
src/iscs_new/stateHandle.js
Normal file
63
src/iscs_new/stateHandle.js
Normal file
@ -0,0 +1,63 @@
|
||||
import * as utils from './utils/utils';
|
||||
|
||||
export default class StateHandle {
|
||||
constructor(map) {
|
||||
this.$map = map;
|
||||
}
|
||||
|
||||
parse(shapeFactory, state) {
|
||||
const mapTemplate = shapeFactory.getMapTemplate();
|
||||
const template = mapTemplate[state.type];
|
||||
const templateState = template.mapState[state.status] || {};
|
||||
// const frameList = templateState.frameList||[];
|
||||
const frameList = Object.values(templateState.covertStatusList) || [];
|
||||
|
||||
// 增加第一帧初始数据
|
||||
// if (templateState &&
|
||||
// templateState.needDefault) {
|
||||
// templateState.frameList.unshift(
|
||||
// Object.entries(template.mapShape).map(el => {
|
||||
// return { name: el[0], ...el[1][utils.defStatus]};
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
|
||||
return {
|
||||
...state,
|
||||
...templateState,
|
||||
mapShape: template.mapShape,
|
||||
shape: shapeFactory.getShapeByCode(state.code),
|
||||
frameList: frameList.map(frame => {
|
||||
// return Object.fromEntries(frame.map(el => {
|
||||
return Object.fromEntries(frame.frameList.map((el, index) => {
|
||||
const mapState = template.mapShape[el.name] || {};
|
||||
const state = mapState[el.status] || {};
|
||||
return [el.name || index, {
|
||||
loop:frame.loop,
|
||||
...el,
|
||||
...state
|
||||
}];
|
||||
}));
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
update(shapeFactory, states = []) {
|
||||
return states.reduce((list, state) => {
|
||||
return [
|
||||
...list,
|
||||
this.parse(shapeFactory, state) // 测试只有自身
|
||||
// this.updateState(this.parse(shapeFactory, state)), // 处理自身
|
||||
// this.updateState(this.parse(shapeFactory, state)) // 处理依赖
|
||||
];
|
||||
}, []);
|
||||
}
|
||||
|
||||
updateState(state = {}) {
|
||||
return {};
|
||||
}
|
||||
|
||||
updateDepState(state = {}) {
|
||||
return {};
|
||||
}
|
||||
}
|
64
src/iscs_new/transformHandle.js
Normal file
64
src/iscs_new/transformHandle.js
Normal file
@ -0,0 +1,64 @@
|
||||
import * as utils from './utils/utils';
|
||||
|
||||
export default class TransformHandle {
|
||||
constructor(painter) {
|
||||
this.$painter = painter;
|
||||
|
||||
this.rect = { x: 0, y: 0, width: 0, height: 0 };
|
||||
|
||||
this.transform = utils.createTransform({scale:[1,1], position:[0,0], rotation:0 });
|
||||
}
|
||||
|
||||
getTransform() {
|
||||
return this.transform;
|
||||
}
|
||||
|
||||
// 检查显隐
|
||||
checkVisible(shape) {
|
||||
return (!shape.model || !shape.model.base.hide || !shape.model.composeCode) && utils.createBoundingRectCheckVisible(shape, this.transform).intersect(this.rect);
|
||||
}
|
||||
|
||||
// 重新计算显隐
|
||||
visibleView(shape) {
|
||||
this.checkVisible(shape)
|
||||
? shape.show()
|
||||
: shape.hide();
|
||||
shape.dirty();
|
||||
}
|
||||
|
||||
// 缩放/平移图层
|
||||
transformAll() {
|
||||
this.traverse(this.visibleView, this);
|
||||
}
|
||||
|
||||
// 更新偏移量
|
||||
updateTransform(opt) {
|
||||
this.transform = utils.createTransform({scale: [opt.scaleRate, opt.scaleRate], position: [-opt.offsetX/opt.scaleRate, -opt.offsetY/opt.scaleRate], rotation: 0});
|
||||
this.transformAll();
|
||||
}
|
||||
|
||||
// 更新画布尺寸
|
||||
updateZrSize(opt) {
|
||||
this.rect = { x: 0, y: 0, width: opt.width, height: opt.height };
|
||||
this.transformAll();
|
||||
}
|
||||
|
||||
// 遍历view执行回调
|
||||
traverse(cb, context) {
|
||||
debugger
|
||||
this.traverseLayer(layer => {
|
||||
layer.eachChild(shape => {
|
||||
cb.call(context, shape);
|
||||
})
|
||||
}, context)
|
||||
}
|
||||
|
||||
// 遍历图层执行回调
|
||||
traverseLayer(cb, context) {
|
||||
this.$painter.eachChild(layer => {
|
||||
layer.transform = this.transform;
|
||||
cb.call(context, layer);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
17
src/iscs_new/utils/dom.js
Normal file
17
src/iscs_new/utils/dom.js
Normal file
@ -0,0 +1,17 @@
|
||||
export function isDom(dom) {
|
||||
return typeof dom === 'object' &&
|
||||
typeof dom.nodeType === 'number' &&
|
||||
typeof dom.ownerDocument === 'object';
|
||||
}
|
||||
|
||||
export function setAttribute(dom, key, value) {
|
||||
dom.setAttribute
|
||||
? dom.setAttribute(key, value)
|
||||
: (dom[key] = value);
|
||||
}
|
||||
|
||||
export function getAttribute(dom, key) {
|
||||
return dom.getAttribute
|
||||
? dom.getAttribute(key)
|
||||
: dom[key];
|
||||
}
|
15
src/iscs_new/utils/events.js
Normal file
15
src/iscs_new/utils/events.js
Normal file
@ -0,0 +1,15 @@
|
||||
export default {
|
||||
Reflect: 'reflect',
|
||||
Click: 'click',
|
||||
ContextMenu: 'contextmenu',
|
||||
DataZoom: 'dataZoom',
|
||||
Keydown: 'keydown',
|
||||
Keyup: 'keyup',
|
||||
Keypress: 'keypress',
|
||||
DataLoaded: 'dataLoaded',
|
||||
ViewLoaded: 'viewLoaded',
|
||||
StateLoaded: 'stateLoaded',
|
||||
ViewUpdate: 'viewUpdate',
|
||||
StateUpdate: 'stateUpdate',
|
||||
OptionUpdate: 'optionUpdate'
|
||||
}
|
9
src/iscs_new/utils/orders.js
Normal file
9
src/iscs_new/utils/orders.js
Normal file
@ -0,0 +1,9 @@
|
||||
export default {
|
||||
Add: '&Add',
|
||||
Delete: '&DEL',
|
||||
Update: '&UPT',
|
||||
Binding: '&Binding',
|
||||
Unbinding: '&Unbinding',
|
||||
ChangeStatus:'&ChangeStatus',
|
||||
ResetStatus:'&ResetStatus'
|
||||
};
|
63
src/iscs_new/utils/storage.js
Normal file
63
src/iscs_new/utils/storage.js
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
export default class Storage {
|
||||
constructor() {
|
||||
this.map = new Map();
|
||||
this.lst = new Set();
|
||||
this.clipboard = [];
|
||||
}
|
||||
|
||||
has(code) {
|
||||
return code ? this.map.has(code) : false;
|
||||
}
|
||||
|
||||
set(code, target) {
|
||||
if (!this.has(code)) {
|
||||
this.lst.add(code);
|
||||
this.map.set(code, target);
|
||||
}
|
||||
}
|
||||
|
||||
get(code) {
|
||||
return this.map.get(code);
|
||||
}
|
||||
|
||||
delete(code) {
|
||||
if (this.has(code)) {
|
||||
this.map.delete(code);
|
||||
this.lst.delete(code);
|
||||
}
|
||||
}
|
||||
|
||||
values() {
|
||||
return Array.from(this.lst).map(code => { return this.get(code); });
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.lst.clear();
|
||||
this.map.clear();
|
||||
}
|
||||
|
||||
isSelectExist(code) {
|
||||
return this.has(code);
|
||||
}
|
||||
|
||||
forEach() {
|
||||
return this.map.forEach;
|
||||
}
|
||||
|
||||
setClipboard(lst) {
|
||||
this.clipboard = Array.from(lst);
|
||||
}
|
||||
|
||||
clearClipboard() {
|
||||
this.clipboard = [];
|
||||
}
|
||||
|
||||
getClipboard() {
|
||||
return this.clipboard;
|
||||
}
|
||||
|
||||
getClipboardSize() {
|
||||
return this.clipboard.length;
|
||||
}
|
||||
}
|
111
src/iscs_new/utils/utils.js
Normal file
111
src/iscs_new/utils/utils.js
Normal file
@ -0,0 +1,111 @@
|
||||
import BoundingRect from 'zrender/src/core/BoundingRect';
|
||||
import * as matrix from 'zrender/src/core/matrix';
|
||||
|
||||
// 默认状态标识
|
||||
export const defStatus = 'default';
|
||||
|
||||
// 获取一个UID
|
||||
export const getUID =(function(base=0) {
|
||||
return function(type) { return [(type || ''), base++, Math.random().toFixed(5)].join('_');}
|
||||
})();
|
||||
|
||||
// 克隆一个对象
|
||||
export function deepClone(obj) {
|
||||
return JSON.parse(JSON.stringify(obj))
|
||||
}
|
||||
|
||||
// 克隆一个对象到另一个对象
|
||||
export function deepAssign(tag, obj) {
|
||||
return JSON.parse(JSON.stringify({...tag, ...obj}));
|
||||
}
|
||||
|
||||
// 拷贝对象指定层次的引用
|
||||
export function assignByDepth(source, target, depth) {
|
||||
Object.keys(target).forEach(key => {
|
||||
if (depth) {
|
||||
Object.keys(target).forEach(key => {
|
||||
source[key] = assignByDepth(source[key]||{}, target[key]||{}, depth-1);
|
||||
});
|
||||
} else {
|
||||
source[key] = target[key];
|
||||
}
|
||||
});
|
||||
return source;
|
||||
}
|
||||
|
||||
// 创建一个transform
|
||||
export function createTransform({scale=[1,1], position=[0,0], rotation=0}) {
|
||||
let transform = matrix.create();
|
||||
transform = matrix.translate(matrix.create(), transform, position);
|
||||
transform = matrix.rotate(matrix.create(), transform, rotation);
|
||||
transform = matrix.scale(matrix.create(), transform, scale);
|
||||
return transform;
|
||||
}
|
||||
|
||||
// 计算自身缩放和偏移后的包围框
|
||||
export function createBoundingRect(shape) {
|
||||
const rect = shape.getBoundingRect().clone();
|
||||
const scaleX = shape.scale[0];
|
||||
const scaleY = shape.scale[1];
|
||||
const offsetX = shape.position[0];
|
||||
const offsetY = shape.position[1];
|
||||
|
||||
rect.x = rect.x * scaleX + offsetX;
|
||||
rect.y = rect.y * scaleY + offsetY;
|
||||
rect.width = rect.width * scaleX;
|
||||
rect.height = rect.height * scaleY;
|
||||
return rect;
|
||||
}
|
||||
|
||||
// 计算变化计算包围框
|
||||
export function createBoundingRectCheckVisible(shape, transform) {
|
||||
const rect = shape.getBoundingRect();
|
||||
const scaleX = transform[0];
|
||||
const scaleY = transform[3];
|
||||
const offsetX = transform[4];
|
||||
const offsetY = transform[5];
|
||||
|
||||
rect.x = rect.x * scaleX + offsetX;
|
||||
rect.y = rect.y * scaleY + offsetY;
|
||||
rect.width = rect.width * scaleX;
|
||||
rect.height = rect.height * scaleY;
|
||||
return rect;
|
||||
}
|
||||
|
||||
// 计算图形的旋转中心
|
||||
export function createOrigin(shape) {
|
||||
const rect = shape.getBoundingRect();
|
||||
return [rect.x + rect.width/2, rect.y + rect.height/2];
|
||||
}
|
||||
|
||||
// 计算视图中心
|
||||
export function calculateDCenter(viewRect, bound) {
|
||||
var dx = (bound.width - viewRect.width) / 2 - viewRect.x;
|
||||
var dy = (bound.height - viewRect.height) / 2 - viewRect.y;
|
||||
return { dx, dy };
|
||||
}
|
||||
|
||||
// 矩形碰撞检测
|
||||
export function checkRectCollision(rect1, rect2) {
|
||||
const center1 = { x: rect1.x + rect1.width / 2, y: rect1.y + rect1.height / 2 };
|
||||
const center2 = { x: rect2.x + rect2.width / 2, y: rect2.y + rect2.height / 2 };
|
||||
return Math.abs(center1.x - center2.x) < rect1.width / 2 + rect2.width / 2 && Math.abs(center1.y - center2.y) < rect1.height / 2 + rect2.height / 2
|
||||
}
|
||||
|
||||
// 通过两点计算弧度
|
||||
export function getRadian(point1, point2) {
|
||||
return Math.atan2(point2.y-point1.y, point2.x-point1.x);
|
||||
}
|
||||
|
||||
// 类型检测
|
||||
const checkJsType = (type) => { return (obj) => { return Object.prototype.toString.call(obj) === `[object ${type.name}]`; }; };
|
||||
|
||||
export function isFunction() { return checkJsType(Function); }
|
||||
|
||||
export function isArray() { return checkJsType(Array); }
|
||||
|
||||
export function isString() { return checkJsType(String); }
|
||||
|
||||
export function isInstanceOf(obj, target) {
|
||||
return obj instanceof target;
|
||||
}
|
@ -27,7 +27,7 @@ class Signal extends Group {
|
||||
this._code = model.code;
|
||||
this._type = model._type;
|
||||
this.model = model;
|
||||
this.mapDevice = mapDevice;
|
||||
this.mapDevice = mapDevice;
|
||||
this.style = style;
|
||||
this.count = parseInt(model.lampPositionType);
|
||||
this.lamps = new Array(this.count);
|
||||
@ -322,12 +322,12 @@ class Signal extends Group {
|
||||
const drict = this.model.right ? 1 : -1; // 朝向 左:右
|
||||
const posit = this.model.positionType == '01' ? -1 : 1; // 位置 上:下
|
||||
// 信号机名称
|
||||
const actual = this.mapDevice[model.linkSignalCode];
|
||||
const actual = this.mapDevice[model.linkSignalCode];
|
||||
const sigNameX = model.position.x + model.positionPoint.x + drict * 0.433 * style.Signal.transmission.sideLength + model.namePosition.x;
|
||||
const sigNameY = model.position.y + model.positionPoint.y + posit * (style.Signal.distance + style.Section.line.width + style.Signal.lamp.radiusR * 2 + model.namePosition.y + style.Signal.text.distance);
|
||||
const textAlign = style.Signal.text.isAlignCenter ? 'middle' : this.model.right ? 'left' : 'right';
|
||||
const textVerticalAlign = posit == 1 ? 'top' : 'bottom';
|
||||
const fillColor = actual.virtual? style.Signal.transmission.fillColorVirtual: style.Signal.transmission.fillColor;
|
||||
const fillColor = actual.virtual ? style.Signal.transmission.fillColorVirtual : style.Signal.transmission.fillColor;
|
||||
this.sigName = new ESigName({
|
||||
zlevel: this.zlevel,
|
||||
z: this.z,
|
||||
@ -511,12 +511,12 @@ class Signal extends Group {
|
||||
}
|
||||
|
||||
if (this.style.Signal.lamp.guidName !== 'singleRY') {
|
||||
if (this.lamps.length == 1) {
|
||||
if (this.lamps.length == 1) {
|
||||
this.lamps[0] && this.lamps[0].setColor(this.style.Signal.lamp.redColor);
|
||||
} else {
|
||||
} else {
|
||||
this.lamps[0] && this.lamps[0].setColor(this.style.Signal.lamp.redColor);
|
||||
this.lamps[1] && this.lamps[1].setColor(this.style.Signal.lamp.yellowColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -859,8 +859,8 @@ class Signal extends Group {
|
||||
default:
|
||||
var drict = this.model.right ? 1 : -1; // 朝向 右:左
|
||||
var offsetY = this.model.positionType == '01' ? this.style.Signal.text.fontSize : 0; // 位置 上:下
|
||||
var shape = this.model.type == 'TRANSMISSION'? this.transmission: this.sigPost;
|
||||
rect = shape.getBoundingRect().clone();
|
||||
var shape = this.model.type == 'TRANSMISSION' ? this.transmission : this.sigPost;
|
||||
rect = shape.getBoundingRect().clone();
|
||||
rect.x = rect.x + drict * this.style.Signal.post.standardVerticalWidth;
|
||||
rect.y = rect.y - offsetY;
|
||||
break;
|
||||
|
@ -30,6 +30,7 @@ const Jlmap3dOtherVR = () => import('@/views/jlmap3d/maintainer/jl3dothervr');
|
||||
// const Jl3dMaintainer = () => import('@/views/jlmap3d/maintainer/jl3dmaintainer');
|
||||
|
||||
const DisplayNew = () => import('@/views/newMap/displayNew/index');
|
||||
const DisplayCity = () => import('@/views/newMap/displayCity/index');
|
||||
const DesignDisplayNew = () => import('@/views/newMap/displayNew/scriptDisplay/scriptPreview/index');
|
||||
const PracticeDisplay = () => import('@/views/newMap/displayNew/practiceDisplay');
|
||||
const BigLPFStrategy = () => import('@/views/newMap/displayNew/bigLPFStrategy');
|
||||
@ -59,6 +60,11 @@ const IscsDesign = () => import('@/views/iscs/iscsDesign/index');
|
||||
const IscsConfig = () => import('@/views/iscs/iscsSystem/config/index');
|
||||
const IscsStationConfig = () => import('@/views/iscs/iscsSystem/stationConfig/index');
|
||||
|
||||
const IscsNewDesign = () => import('@/views/iscs_new/iscsDesign/index');
|
||||
const IscsNewDraw = () => import('@/views/iscs_new/iscsDraw/index');
|
||||
const IscsNewPreview = () => import('@/views/iscs_new/iscsPreview/index');
|
||||
|
||||
|
||||
const NewMapDraft = () => import('@/views/newMap/newMapdraft/index');
|
||||
const NewDesignPlatformUser = () => import('@/views/newMap/newDesignUser/index');
|
||||
|
||||
@ -162,6 +168,7 @@ const RunPlanViewWindow = () => import('@/views/newMap/displayNew/demon/runPlanV
|
||||
const SecondaryHome = () => import('@/views/trainingPlatform/secondaryHome');
|
||||
const Demo = () => import('@/views/demo');
|
||||
const DemoTraining = () => import('@/views/newMap/displayNew/demoTraining');
|
||||
const Test = () => import('@/views/test');
|
||||
|
||||
// import { GenerateRouteProjectList } from '@/scripts/ProjectConfig';
|
||||
// import { getSessionStorage } from '@/utils/auth';
|
||||
@ -207,6 +214,38 @@ export const userTrainingPlatform = '016'; // 实训系统
|
||||
// export const refereePlatform = '017'; // 裁判系统
|
||||
|
||||
export const constantRoutes = [
|
||||
{
|
||||
path: '/test',
|
||||
component: Test,
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path:'/iscs_new/design/compose/edit',
|
||||
hidden: true,
|
||||
component: IscsNewDraw,
|
||||
meta: {
|
||||
i18n: 'router.iscsDraw',
|
||||
roles: [admin]
|
||||
}
|
||||
},
|
||||
{
|
||||
path:'/iscs_new/design/compose/preview',
|
||||
hidden: true,
|
||||
component: IscsNewPreview,
|
||||
meta: {
|
||||
i18n: 'router.iscsDraw',
|
||||
roles: [admin]
|
||||
}
|
||||
},
|
||||
{
|
||||
path:'/iscs_new/design/map/edit',
|
||||
hidden: true,
|
||||
component: IscsNewDesign,
|
||||
meta: {
|
||||
i18n: 'router.iscsDraw',
|
||||
roles: [admin]
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/demo',
|
||||
component: Demo,
|
||||
@ -362,6 +401,11 @@ export const publicAsyncRoute = [
|
||||
component: DisplayNew,
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/displayCity/:mode',
|
||||
component: DisplayCity,
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/design/displayNew/:mode',
|
||||
component: DesignDisplayNew,
|
||||
|
@ -1,8 +1,8 @@
|
||||
export function getBaseUrl() {
|
||||
let BASE_API;
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
BASE_API = 'https://joylink.club/jlcloud';
|
||||
// BASE_API = 'https://test.joylink.club/jlcloud';
|
||||
// BASE_API = 'https://joylink.club/jlcloud';
|
||||
BASE_API = 'https://test.joylink.club/jlcloud';
|
||||
// BASE_API = 'http://192.168.8.107:9000'; // 袁琪
|
||||
// BASE_API = 'http://192.168.8.129:9000'; // 旭强
|
||||
// BASE_API = 'http://192.168.8.119:9000'; // 张赛
|
||||
|
@ -1,10 +1,10 @@
|
||||
import Vue from 'vue';
|
||||
import { getBaseUrl } from '@/utils/baseUrl'
|
||||
import { getBaseUrl } from '@/utils/baseUrl';
|
||||
|
||||
// 创建或者打开数据库
|
||||
export function openIndexedDB() {
|
||||
const baseUrl = getBaseUrl();
|
||||
const indexedDBName = baseUrl.replace(/http.?:\/\/(.*)[\/|:].*/, "$1");
|
||||
const baseUrl = getBaseUrl();
|
||||
const indexedDBName = baseUrl.replace(/http.?:\/\/(.*)[\/|:].*/, '$1');
|
||||
const request = window.indexedDB.open(indexedDBName, 1);
|
||||
request.onerror = function (event) {
|
||||
console.log('数据库打开报错');
|
||||
@ -18,6 +18,7 @@ export function openIndexedDB() {
|
||||
Vue.prototype.$db = event.target.result;
|
||||
Vue.prototype.$db.createObjectStore('mapData', { keyPath: 'id' });
|
||||
Vue.prototype.$db.createObjectStore('runPlan', { keyPath: 'templateId' });
|
||||
Vue.prototype.$db.createObjectStore('composeTemplateList', { keyPath: 'id' });
|
||||
};
|
||||
}
|
||||
// 新增数据
|
||||
|
@ -132,6 +132,8 @@ export default {
|
||||
{ name: '站厅D', value: 'bgStationD' },
|
||||
{ name: '站厅E', value: 'bgStationE' },
|
||||
{ name: '站厅F', value: 'bgStationF' },
|
||||
{ name: '门禁站厅A', value: 'bgDoorStationA' },
|
||||
{ name: '门禁站台A', value: 'bgDoorStandA' }
|
||||
],
|
||||
|
||||
rules: {
|
||||
|
@ -233,10 +233,8 @@ export default {
|
||||
},
|
||||
// 点击选择事件
|
||||
onSelected(em) {
|
||||
console.log(em);
|
||||
},
|
||||
onDblclick(em) {
|
||||
console.log(em);
|
||||
},
|
||||
// 右键点击事件
|
||||
onContextMenu(em) {
|
||||
|
192
src/views/iscs_new/components/dataForm.vue
Normal file
192
src/views/iscs_new/components/dataForm.vue
Normal file
@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<el-form ref="form" :model="formModel" class="composeForm" label-width="110px">
|
||||
<!-- name -->
|
||||
<el-form-item prop="name" label="元素名称" class="formName" :rules="[ { required: true, message:'请输入名称', trigger: 'blur' }]">
|
||||
<el-input
|
||||
v-model="formModel.name"
|
||||
size="small"
|
||||
type="text"
|
||||
style="width:200px"
|
||||
:maxlength="200"
|
||||
/>
|
||||
</el-form-item>
|
||||
<template v-for="(styleGroup,index) in form.formGroup">
|
||||
<div v-if="styleGroup.styleList.length>0" :key="index" class="styleGroup">
|
||||
<div class="styleGroupName">
|
||||
{{ styleGroup.name }}
|
||||
</div>
|
||||
<template v-for="item in styleGroup.styleList">
|
||||
<el-form-item :key="item.prop" :prop="styleGroup.type+'.'+item.prop" :label="item.label" class="formName" :rules="item.rules?item.rules:[]">
|
||||
<!-- {{ tempModel=styleGroup.type?formModel[styleGroup.type]:formModel }} -->
|
||||
<el-tooltip
|
||||
v-if="item.description"
|
||||
:id="item.prop"
|
||||
effect="dark"
|
||||
:content="item.description"
|
||||
:popper-options="{removeOnDestroy:true}"
|
||||
placement="bottom-start"
|
||||
popper-class="composeItemTooltip"
|
||||
>
|
||||
<span class="el-icon-info itemTips" />
|
||||
</el-tooltip>
|
||||
<template v-if="checkFieldType(item, 'Number')">
|
||||
<el-input-number
|
||||
v-if="item.precision!=undefined"
|
||||
v-model="formModel[styleGroup.type][item.prop]"
|
||||
size="small"
|
||||
:min="isNaN(item.min) ? -Infinity : item.min"
|
||||
:max="isNaN(item.max)? Infinity : item.max"
|
||||
:step="isNaN(item.step) ? -Infinity : item.step"
|
||||
:precision="item.precision"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else
|
||||
v-model="formModel[styleGroup.type][item.prop]"
|
||||
size="small"
|
||||
:min="isNaN(item.min) ? -Infinity : item.min"
|
||||
:max="isNaN(item.max)? Infinity : item.max"
|
||||
:step="isNaN(item.step) ? -Infinity : item.step"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'Boolean')">
|
||||
<el-switch
|
||||
v-model="formModel[styleGroup.type][item.prop]"
|
||||
style="vertical-align: top;"
|
||||
size="small"
|
||||
:active-color="item.activeColor || '#409eff'"
|
||||
:inactive-color="item.inactiveColor || '#dcdfe6'"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'Color')">
|
||||
<el-color-picker
|
||||
v-model="formModel[styleGroup.type][item.prop]"
|
||||
show-alpha
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'NumberArray')">
|
||||
<el-input-number
|
||||
v-for="count in item.length"
|
||||
:key="count"
|
||||
v-model="formModel[styleGroup.type][item.prop][count-1]"
|
||||
style="margin:6px 0px 0px 5px"
|
||||
size="small"
|
||||
:min="isNaN(item.min) ? -Infinity : item.min"
|
||||
:max="isNaN(item.max)? Infinity : item.max"
|
||||
:step="isNaN(item.step) ? -Infinity : item.step"
|
||||
:precision="item.precision"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'Points')">
|
||||
<div class="point-section">
|
||||
<template v-for="(point, j) in formModel[styleGroup.type][item.prop]">
|
||||
<div :key="j" style="overflow: hidden;">
|
||||
<el-input-number v-model="point[0]" size="mini" @blur="changeNumber(0,j,formModel[styleGroup.type],item.prop)" />
|
||||
<span class="pointSplice">, </span>
|
||||
<el-input-number v-model="point[1]" size="mini" @blur="changeNumber(1,j,formModel[styleGroup.type],item.prop)" />
|
||||
<el-button
|
||||
icon="el-icon-plus"
|
||||
circle
|
||||
class="point-button"
|
||||
@click="addPoint(j,formModel[styleGroup.type],item.prop)"
|
||||
/>
|
||||
<el-button
|
||||
icon="el-icon-minus"
|
||||
:disabled="j <3"
|
||||
circle
|
||||
class="point-button"
|
||||
style="margin-left: 4px;"
|
||||
@click="delPoint(j,formModel[styleGroup.type],item.prop)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'Select')">
|
||||
<el-select
|
||||
:ref="'select_'+item.prop"
|
||||
v-model="formModel[styleGroup.type][item.prop]"
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in item.optionList"
|
||||
:key="option['value']"
|
||||
:label="option['label']"
|
||||
:value="option['value']"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'String')">
|
||||
<el-input
|
||||
v-model="formModel[styleGroup.type][item.prop]"
|
||||
size="small"
|
||||
type="text"
|
||||
style="width:200px"
|
||||
:maxlength="item.maxlength"
|
||||
/>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:'DataForm',
|
||||
props: {
|
||||
form: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
formModel: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
checkFieldType(field, type) {
|
||||
return field.type === type;
|
||||
},
|
||||
init() {
|
||||
this.$refs.form.resetFields();
|
||||
},
|
||||
changeNumber(type, index, form, prop) {
|
||||
if (form[prop][index][type] == undefined || parseFloat(form[prop][index][type])) {
|
||||
const newForm = Object.assign([], form[prop]);
|
||||
newForm[index][type] = parseFloat(form[prop][index][type]) || 0;
|
||||
this.$set(form, prop, newForm);
|
||||
}
|
||||
},
|
||||
addPoint(index, form, prop) {
|
||||
const data = [0, 0];
|
||||
form[prop].splice(index + 1, 0, data);
|
||||
},
|
||||
delPoint(index, form, prop) {
|
||||
form[prop].splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.composeForm{padding: 10px 15px;}
|
||||
.styleGroup{border: 1px #ccc solid;padding:25px 20px 20px 20px;position: relative;margin-bottom: 30px;}
|
||||
.formName .el-form-item__label {font-size:14px;}
|
||||
.formName.el-form-item {margin-bottom:25px}
|
||||
.point-section {float:left;display: inline-block;margin-top:8px}
|
||||
.pointSplice{display: inline-block;margin-left: 4px;margin-right:4px;line-height: 28px;font-size:14px}
|
||||
.styleGroupName{font-size: 14px;position: absolute;max-width: 100px;height: 20px;background: #fff;left: 10px;top: -9px;text-align: center;padding: 0px 10px;}
|
||||
.point-button {width:28px;height:28px;display:inline-block;margin-left:5px;text-align:center;padding:0px;}
|
||||
.itemTips{display: inline-block;font-size: 18px;vertical-align: top;margin-left: -8px;margin-right: 5px;cursor: pointer;color: #dde0e3;}
|
||||
// align-items: center;justify-content: center;
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.composeForm .el-form-item__label{line-height:20px;margin-top: 20px;transform: translateY(-50%);}
|
||||
.composeForm .el-form-item__content{font-size: 0px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align: center;-ms-flex-align: center;align-items: center;min-height: 40px;flex-wrap: wrap;justify-content: flex-start;}
|
||||
.composeItemTooltip{max-width:300px}
|
||||
</style>
|
163
src/views/iscs_new/components/eachFormItem.vue
Normal file
163
src/views/iscs_new/components/eachFormItem.vue
Normal file
@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<el-form-item :label="item.label" class="formName" :rules="item.rules?item.rules:[]" :prop="parentProp+'.'+item.prop">
|
||||
<!-- :prop="styleGroup.type+'.'+item.prop" -->
|
||||
<template v-if="checkFieldType(item, 'Number')">
|
||||
<el-input-number
|
||||
v-if="item.precision!=undefined"
|
||||
v-model="data[item.prop]"
|
||||
size="small"
|
||||
:min="isNaN(item.min) ? -Infinity : item.min"
|
||||
:max="isNaN(item.max)? Infinity : item.max"
|
||||
:step="isNaN(item.step) ? -Infinity : item.step"
|
||||
:precision="item.precision"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else
|
||||
v-model="data[item.prop]"
|
||||
size="small"
|
||||
:min="isNaN(item.min) ? -Infinity : item.min"
|
||||
:max="isNaN(item.max)? Infinity : item.max"
|
||||
:step="isNaN(item.step) ? -Infinity : item.step"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'Boolean')">
|
||||
<el-switch
|
||||
v-model="data[item.prop]"
|
||||
style="vertical-align: top;"
|
||||
size="small"
|
||||
:active-color="item.activeColor || '#409eff'"
|
||||
:inactive-color="item.inactiveColor || '#dcdfe6'"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'Color')">
|
||||
<el-color-picker
|
||||
v-model="data[item.prop]"
|
||||
show-alpha
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'NumberArray')">
|
||||
<el-input-number
|
||||
v-for="count in item.length"
|
||||
:key="parentProp+'.'+item.prop+''+count"
|
||||
v-model="data[item.prop][count-1]"
|
||||
style="margin:6px 0px 0px 5px"
|
||||
size="small"
|
||||
:min="isNaN(item.min) ? -Infinity : item.min"
|
||||
:max="isNaN(item.max)? Infinity : item.max"
|
||||
:step="isNaN(item.step) ? -Infinity : item.step"
|
||||
:precision="item.precision"
|
||||
/>
|
||||
</template>
|
||||
<!-- <template v-else-if="checkFieldType(item, 'Points')">
|
||||
<div class="point-section">
|
||||
<template v-for="(point, j) in formModel[styleGroup.type][item.prop]">
|
||||
<div :key="j" style="overflow: hidden;">
|
||||
<el-input-number v-model="point[0]" size="mini" @blur="changeNumber(0,j,formModel[styleGroup.type],item.prop)" />
|
||||
<span class="pointSplice">, </span>
|
||||
<el-input-number v-model="point[1]" size="mini" @blur="changeNumber(1,j,formModel[styleGroup.type],item.prop)" />
|
||||
<el-button
|
||||
icon="el-icon-plus"
|
||||
circle
|
||||
class="point-button"
|
||||
@click="addPoint(j,formModel[styleGroup.type],item.prop)"
|
||||
/>
|
||||
<el-button
|
||||
icon="el-icon-minus"
|
||||
:disabled="j <3"
|
||||
circle
|
||||
class="point-button"
|
||||
style="margin-left: 4px;"
|
||||
@click="delPoint(j,formModel[styleGroup.type],item.prop)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template> -->
|
||||
<template v-else-if="checkFieldType(item, 'Select')">
|
||||
<el-select
|
||||
:ref="'select_'+item.prop"
|
||||
v-model="data[item.prop]"
|
||||
size="small"
|
||||
>
|
||||
<el-option
|
||||
v-for="option in item.optionList"
|
||||
:key="option['value']"
|
||||
:label="option['label']"
|
||||
:value="option['value']"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else-if="checkFieldType(item, 'String')">
|
||||
<el-input
|
||||
v-model="data[item.prop]"
|
||||
size="small"
|
||||
type="text"
|
||||
style="width:200px"
|
||||
:maxlength="item.maxlength"
|
||||
/>
|
||||
</template>
|
||||
<span class="el-icon-error deleteCurrent" @click="deleteCurrent(item.prop)" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<script>
|
||||
import elementConst from '@/iscs_new/core/form/elementConst';
|
||||
export default {
|
||||
name:'EachFormItem',
|
||||
props: {
|
||||
prop: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
type:{
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
styleType: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
parentProp:{
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
item:{label:'', type:'' }
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const list = elementConst[this.type]['formList'][this.styleType];
|
||||
const data = list.find(each=>{ return each.prop == this.prop; });
|
||||
if (data) {
|
||||
this.item = data;
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
checkFieldType(field, type) {
|
||||
return field.type === type;
|
||||
},
|
||||
deleteCurrent(prop) {
|
||||
this.$emit('deleteShape', {styleType:this.styleType, data:this.data, prop:prop});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.deleteCurrent{
|
||||
font-size: 20px;
|
||||
color: #f00;
|
||||
margin-left: 15px;
|
||||
vertical-align: top;
|
||||
display: inline-flex;
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
margin-top: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
225
src/views/iscs_new/components/tableForm.vue
Normal file
225
src/views/iscs_new/components/tableForm.vue
Normal file
@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button type="primary" size="small" class="addStatus" @click="addStatus">添加</el-button>
|
||||
<el-form ref="form" class="tableForm" :model="formModel">
|
||||
<!-- label-width="110px" -->
|
||||
<el-table
|
||||
:data="formModel.stateList"
|
||||
stripe
|
||||
class="eachStatusTable"
|
||||
size="mini"
|
||||
row-key="id"
|
||||
:expand-row-keys="expandKeys"
|
||||
@expand-change="expandChange"
|
||||
>
|
||||
<el-table-column type="expand">
|
||||
<template slot-scope="props">
|
||||
<div class="styleList">
|
||||
<div class="styleListName">样式</div>
|
||||
<div class="addStyleForm">
|
||||
<el-select v-model="props.row.defaultStyleSelect" size="mini">
|
||||
<el-option v-for="(eachStyle) in styleSelectList" :key="eachStyle.value" :label="eachStyle.label" :value="eachStyle.value" />
|
||||
</el-select>
|
||||
<el-button type="primary" size="mini" class="addStyle" @click="addStyle(props.$index,'style')">添加</el-button>
|
||||
</div>
|
||||
<div v-if="props.row.style" class="styleInList">
|
||||
<div v-for="(eachStyleInfo,index) in Object.keys(props.row.style)" :key="index" class="eachStyleInfo">
|
||||
<each-form-item
|
||||
:prop="eachStyleInfo"
|
||||
:data="formModel.stateList[props.$index].style"
|
||||
:type="formModel.type"
|
||||
style-type="style"
|
||||
:parent-prop="'stateList.'+props.$index+'.style'"
|
||||
@deleteShape="deleteShape"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shapeList">
|
||||
<div class="shapeListName">绘图</div>
|
||||
<div class="addStyleForm">
|
||||
<el-select v-model="props.row.defaultShapeSelect" size="mini">
|
||||
<el-option v-for="(eachShape) in shapeSelectList" :key="eachShape.value" :label="eachShape.label" :value="eachShape.value" />
|
||||
</el-select>
|
||||
<el-button type="primary" size="mini" class="addStyle" @click="addStyle(props.$index,'shape')">添加</el-button>
|
||||
</div>
|
||||
<div v-if="props.row.shape" class="styleInList">
|
||||
<div v-for="(eachShapeInfo,index) in Object.keys(props.row.shape)" :key="index" class="eachStyleInfo">
|
||||
<each-form-item
|
||||
:prop="eachShapeInfo"
|
||||
:data="formModel.stateList[props.$index].shape"
|
||||
:type="formModel.type"
|
||||
style-type="shape"
|
||||
:parent-prop="'stateList.'+props.$index+'.shape'"
|
||||
@deleteShape="deleteShape"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="178">
|
||||
<!-- align="center" -->
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'stateList.'+scope.$index+'.status'"
|
||||
:rules="[{required: true, message:'请输入状态', trigger: 'blur'}]"
|
||||
>
|
||||
<el-input v-model="scope.row.status" size="mini" type="text" style="width:158px" :maxlength="100" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="描述" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'stateList.'+scope.$index+'.description'"
|
||||
:rules="[{required: true, message:'请输入描述', trigger: 'blur'}]"
|
||||
>
|
||||
<el-input v-model="scope.row.description" size="mini" type="text" style="width:170px" :maxlength="100" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="danger" size="mini" @click="deleteStatus(scope.$index,scope.row)">删除</el-button>
|
||||
<!-- <el-button type="success" size="mini" @click="previewStatus(scope.$index,scope.row)">预览</el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- :model="formModel" -->
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import elementConst from '@/iscs_new/core/form/elementConst';
|
||||
import EachFormItem from './eachFormItem';
|
||||
import * as utils from '@/iscs_new/utils/utils';
|
||||
|
||||
export default {
|
||||
name:'TableForm',
|
||||
components:{
|
||||
EachFormItem
|
||||
},
|
||||
props: {
|
||||
composeElem: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formModel:this.composeElem,
|
||||
// {stateList:this.composeElem.stateList, style:this.composeElem.style, type:this.composeElem.type, shape:this.composeElem.shape}
|
||||
styleSelectList:[],
|
||||
shapeSelectList:[],
|
||||
expandKeys:[]
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const styleNameList = Object.keys(this.formModel.style);
|
||||
const style = elementConst[this.formModel.type]['formList']['style'];
|
||||
styleNameList.forEach(eachStyleName=>{
|
||||
const eachStyle = style.find(each=>{ return each.prop == eachStyleName; });
|
||||
this.styleSelectList.push({value:eachStyleName, label:eachStyle.label});
|
||||
});
|
||||
|
||||
const shapeNameList = Object.keys(this.formModel.shape);
|
||||
const shape = elementConst[this.formModel.type]['formList']['shape'];
|
||||
shapeNameList.forEach(eachShapeName=>{
|
||||
const eachShape = shape.find(each=>{ return each.prop == eachShapeName; });
|
||||
this.shapeSelectList.push({value:eachShapeName, label:eachShape.label});
|
||||
});
|
||||
this.formModel.stateList.forEach(each=>{
|
||||
each.defaultStyleSelect = this.styleSelectList[0].value;
|
||||
each.defaultShapeSelect = this.shapeSelectList[0].value;
|
||||
});
|
||||
|
||||
},
|
||||
methods:{
|
||||
addStatus() {
|
||||
const length = this.formModel.stateList.length;
|
||||
this.formModel.stateList.push({id:length + 1, status:'', description:'', defaultStyleSelect:this.styleSelectList[0].value,
|
||||
defaultShapeSelect:this.shapeSelectList[0].value});
|
||||
this.expandKeys.push(length + 1);
|
||||
},
|
||||
deleteStatus(index, row) {
|
||||
this.formModel.stateList.splice(index, 1);
|
||||
const key = this.expandKeys.findIndex(each=>{ return each == row.id; });
|
||||
if (key > 0) { this.expandKeys.splice(key, 1); }
|
||||
},
|
||||
// previewStatus(index, row) {
|
||||
// const styleLength = Object.keys(row.style || {}).length;
|
||||
// const shapeLength = Object.keys(row.shape || {}).length;
|
||||
// if (styleLength > 0 || shapeLength > 0 ) {
|
||||
// const data = {style:row.style || {}, shape:row.shape || {}};
|
||||
// debugger;
|
||||
// // this.$iscs
|
||||
// }
|
||||
// },
|
||||
addStyle(index, type) {
|
||||
const style = this.formModel.stateList[index][type];
|
||||
if (!style) {
|
||||
this.$set(this.formModel.stateList[index], type, {});
|
||||
}
|
||||
const data = this.formModel.stateList[index];
|
||||
const dataName = 'default' + type.replace(type[0], type[0].toUpperCase()) + 'Select';
|
||||
if (!data[type][data[dataName]] && data[dataName]) {
|
||||
const other = utils.deepClone(this.formModel[type][data[dataName]]);
|
||||
this.$set(this.formModel.stateList[index][type], data[dataName], other);
|
||||
}
|
||||
},
|
||||
expandChange(row, expandedRows) {
|
||||
this.expandKeys = [];
|
||||
expandedRows.forEach(each=>{
|
||||
this.expandKeys.push(each.id);
|
||||
});
|
||||
},
|
||||
deleteShape({styleType, data, prop}) {
|
||||
this.$delete(data, prop);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.eachStatusTable{
|
||||
width: 530px;
|
||||
margin-left: 10px;
|
||||
margin-top: 10px;
|
||||
border: 1px #dedede solid;
|
||||
}
|
||||
.addStatus{
|
||||
float: right;
|
||||
display: inline-block;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.styleList,.shapeList{
|
||||
padding: 15px 10px;
|
||||
border: 1px #ccc solid;
|
||||
position: relative;
|
||||
margin-bottom:20px;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
.styleListName,.shapeListName{
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
left: 6px;
|
||||
top: -8px;
|
||||
width: 40px;
|
||||
background: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
.addStyle,.addShape{
|
||||
float: right;
|
||||
display: inline-block;
|
||||
}
|
||||
.styleInList{
|
||||
margin-top: 15px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
// .eachStyleInfo .el-form-item{border-bottom: 1px #dedede solid;}
|
||||
</style>
|
||||
<style lang="sass">
|
||||
.eachStatusTable .el-table__expanded-cell{padding: 20px;}
|
||||
</style>
|
323
src/views/iscs_new/iscsDesign/index.vue
Normal file
323
src/views/iscs_new/iscsDesign/index.vue
Normal file
@ -0,0 +1,323 @@
|
||||
<template>
|
||||
<transition name="el-zoom-in-center">
|
||||
<div class="mapPaint">
|
||||
<div class="map-view">
|
||||
<iscs-canvas ref="iscsCanvas" @selected="onSelected" />
|
||||
</div>
|
||||
<div class="right-card" :class="{'hide': draftShow}">
|
||||
<div class="btn_draft_box" @click="draftShow = !draftShow"><i :class="draftShow?'el-icon-arrow-right':'el-icon-arrow-left'" /></div>
|
||||
<el-card type="border-card" class="heightClass">
|
||||
<div slot="header" class="clearfix">
|
||||
<el-button
|
||||
type="text"
|
||||
style="float: right; padding: 3px 0; margin-right: 5px;"
|
||||
@click="onSave"
|
||||
>保存</el-button>
|
||||
</div>
|
||||
<el-tabs id="cardTab" v-model="cardTab" class="card" type="border-card" @tab-click="onSelectCardTab">
|
||||
<el-tab-pane label="元素绘制" name="first">
|
||||
<el-tabs v-model="enabledTab" class="card" type="card" @tab-click="onSelectTab">
|
||||
<el-tab-pane v-for="(element,index) in elementList" :key="index" :label="element.name" :name="element.type" :lazy="true">
|
||||
<data-form :ref="'dataform'+element.type" :form="element" :form-model="element.model" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class="bottomBtnGroup">
|
||||
<el-button v-show="!selected" type="primary" size="small" @click="onSubmit">添加</el-button>
|
||||
<el-button v-show="selected" type="warning" size="small" @click="onModify">修改</el-button>
|
||||
<el-button v-show="selected" type="danger" size="small" @click="onDelete">删除</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="状态编辑" name="second">
|
||||
<el-tabs v-model="statusTab" class="card" type="card" @tab-click="onSelectTab">
|
||||
<el-tab-pane v-for="(composeElem,index) in composeElemList" :key="index" :label="composeElem.name" :name="composeElem.code" :lazy="true">
|
||||
<table-form :ref="'tableform'+composeElem.code" :state-list="composeElem.stateList" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
<script>
|
||||
import localStore from 'storejs';
|
||||
import iscsCanvas from './iscsCanvas';
|
||||
import formBuilder from '@/iscs_new/core/form/formBuilder';
|
||||
import DataForm from '../components/dataForm';
|
||||
import TableForm from '../components/tableForm';
|
||||
import orders from '@/iscs_new/utils/orders';
|
||||
import * as utils from '@/iscs_new/utils/utils';
|
||||
import Idb from '../utils/indexedDb.js';
|
||||
import shapeType from '@/iscs_new/constant/shapeType.js';
|
||||
|
||||
export default {
|
||||
name: 'IscsView',
|
||||
components: {
|
||||
iscsCanvas,
|
||||
DataForm,
|
||||
TableForm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
size: {
|
||||
width: this.$store.state.app.width - 521,
|
||||
height: this.$store.state.app.height - 60
|
||||
},
|
||||
widthLeft: Number(localStore.get('LeftWidth')) || 450,
|
||||
draftShow: false,
|
||||
selected: null,
|
||||
enabledTab:'',
|
||||
cardTab:'first',
|
||||
statusTab:'',
|
||||
showDeleteButton:false,
|
||||
elementList:[],
|
||||
composeElemList:[]
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
iscsMode() {
|
||||
return this.$route.query.mode;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route(val) {
|
||||
this.onIscsChange(this.$route.query.mode, this.$route.query.system, this.$route.query.part);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composeName = this.$route.query.composeName;
|
||||
this.elementList = formBuilder.buildFormList();
|
||||
this.enabledTab = this.elementList[0].type;
|
||||
this.getComposeElemList();
|
||||
},
|
||||
methods: {
|
||||
onIscsChange(mode, system, part) {
|
||||
// this.$refs.iscsPlate.show(mode, system, part);
|
||||
// this.$refs.iscsPlate.drawIscsInit();
|
||||
},
|
||||
onSave() {
|
||||
const id = this.$route.query.id;
|
||||
const name = this.$route.query.name||"<模型名称>";
|
||||
const type = this.$route.query.type||"<模型类型>";
|
||||
const source = this.$iscs.getSource();
|
||||
if (id && source) {
|
||||
const elementList = source.elementList.map(el => {
|
||||
return this.$iscs.getShapeByCode(el.code).model;
|
||||
});
|
||||
const composeList = source.composeList.map(el => {
|
||||
return this.$iscs.getShapeByCode(el.code).model;
|
||||
});
|
||||
const rect = elementList.reduce((temp,el) => {
|
||||
const shape = this.$iscs.getShapeByCode(el.code);
|
||||
return shape&&temp? temp.union(shape.getBoundingRect().clone()): shape.getBoundingRect()
|
||||
}, null);
|
||||
const position = rect? [(rect.x + rect.width)/2, (rect.y + rect.height)/2]: [0,0];
|
||||
const model = { id, name, type, elementList, composeList, position };
|
||||
Idb.delete('composeList', model.id);
|
||||
Idb.write('composeList', model);
|
||||
Idb.list('composeList').then(list => {
|
||||
console.log(list)
|
||||
})
|
||||
}
|
||||
},
|
||||
onSelectTab() {
|
||||
this.selected = null;
|
||||
},
|
||||
onSelectCardTab() {
|
||||
|
||||
},
|
||||
onSelected(em) {
|
||||
if (em.model) {
|
||||
this.selected = JSON.parse(JSON.stringify(em.model));
|
||||
const elem = this.elementList.find(el => el.type == this.selected.type);
|
||||
if (elem) {
|
||||
elem.model = this.selected;
|
||||
this.enabledTab = this.selected.type;
|
||||
}
|
||||
} else {
|
||||
this.selected = null;
|
||||
this.clear(this.enabledTab);
|
||||
}
|
||||
},
|
||||
onSubmit() {
|
||||
this.$refs['dataform' + this.enabledTab][0].$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
const formModel = this.$refs['dataform' + this.enabledTab][0].formModel;
|
||||
const newModel = utils.deepClone(formModel);
|
||||
newModel.code = utils.getUID(this.enabledTab);
|
||||
newModel.type = this.enabledTab;
|
||||
newModel.name = '<名称>';
|
||||
newModel.stateList = [];
|
||||
this.$refs.iscsCanvas.doAction([{model: newModel, action: {shapeType: shapeType.Element, order: orders.Add}}]);
|
||||
this.clear(this.enabledTab);
|
||||
this.getComposeElemList();
|
||||
}
|
||||
});
|
||||
},
|
||||
onModify() {
|
||||
this.$refs['dataform' + this.enabledTab][0].$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
const model = utils.deepClone(this.$refs['dataform' + this.enabledTab][0].formModel);
|
||||
model.code = this.selected.code;
|
||||
model.type = this.selected.type;
|
||||
model.name = this.selected.name;
|
||||
this.$refs.iscsCanvas.doAction([{model, action: {shapeType: shapeType.Element, order: orders.Update}}]);
|
||||
this.clear(this.enabledTab);
|
||||
}
|
||||
});
|
||||
},
|
||||
onDelete() {
|
||||
this.$refs['dataform' + this.enabledTab][0].$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
const model = utils.deepClone(this.$refs['dataform' + this.enabledTab][0].formModel);
|
||||
model.code = this.selected.code;
|
||||
model.type = this.selected.type;
|
||||
model.name = this.selected.name;
|
||||
this.$refs.iscsCanvas.doAction([{model, action: {shapeType: shapeType.Element, order: orders.Delete}}]);
|
||||
this.clear(this.enabledTab);
|
||||
this.getComposeElemList();
|
||||
}
|
||||
});
|
||||
},
|
||||
clear(enabledTab) {
|
||||
this.$refs['dataform' + enabledTab][0].init();
|
||||
this.selected = null;
|
||||
},
|
||||
getComposeElemList() {
|
||||
const source = this.$iscs.getSource();
|
||||
if (source &&
|
||||
source.elementList &&
|
||||
source.elementList.length) {
|
||||
this.composeElemList = source.elementList;
|
||||
this.statusTab = this.composeElemList[0].code;
|
||||
} else {
|
||||
this.composeElemList = [];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
@import "src/styles/mixin.scss";
|
||||
.card{
|
||||
height: 100%;
|
||||
display:flex;width: 100%;flex-direction: column
|
||||
}
|
||||
|
||||
.card .el-tab-pane{
|
||||
flex:1;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
padding-bottom:30px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
// height: 110px;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
// box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
|
||||
border-radius: 10px;
|
||||
background-color: #FFFFFF;;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
// box-shadow: inset 0 0 6px rgba(0,0,0,.3);
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
border-radius: 5px;
|
||||
// box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
|
||||
background: rgba(0,0,0,0.4);
|
||||
}
|
||||
}
|
||||
|
||||
.map-view {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
.heightClass{height:100%;overflow:hidden;display:flex;width: 100%;flex-direction: column;}
|
||||
|
||||
.mapPaint{
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
width:100%;
|
||||
position:absolute;
|
||||
left:0;top:0;
|
||||
}
|
||||
|
||||
.right-card{
|
||||
width: 550px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
transform: translateX(550px);
|
||||
transition: all 0.5s;
|
||||
background: #fff;
|
||||
z-index: 9;
|
||||
/deep/{
|
||||
.v-modal{
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
&.hide{
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.btn_draft_box{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
padding: 8px 3px;
|
||||
background: #fff;
|
||||
z-index: 10;
|
||||
transform: translateX(-22px);
|
||||
cursor: pointer;
|
||||
border-radius: 5px 0 0 5px;
|
||||
box-shadow: -2px 0px 2px #000000;
|
||||
}
|
||||
|
||||
.btn_table_box {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(50% + 50px);
|
||||
padding: 8px 3px;
|
||||
background: #fff;
|
||||
z-index: 10;
|
||||
transform: translateX(-22px);
|
||||
cursor: pointer;
|
||||
border-radius: 5px 0 0 5px;
|
||||
box-shadow: -2px 0px 2px #000000;
|
||||
}
|
||||
}
|
||||
.bottomBtnGroup{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 43px;
|
||||
text-align: right;
|
||||
right: 0px;
|
||||
background: #fff;
|
||||
z-index: 2;
|
||||
padding-top: 5px;
|
||||
border-bottom: 1px #dedede solid;
|
||||
box-shadow: 2px -3px 5px #dedede;
|
||||
}
|
||||
.bottomBtnGroup button{
|
||||
display: inline-block;
|
||||
margin-right:10px;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.heightClass .el-card__body{
|
||||
flex:1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#cardTab .el-tabs__content{
|
||||
padding:0px;
|
||||
}
|
||||
</style>
|
183
src/views/iscs_new/iscsDesign/iscsCanvas.vue
Normal file
183
src/views/iscs_new/iscsDesign/iscsCanvas.vue
Normal file
@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :id="iscsId" v-loading="loading" :style="{ width: width +'px', height: height +'px',background:'#425a74' }" class="iscs-canvas" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import Iscs from '@/iscs_new/map';
|
||||
import Idb from '../utils/indexedDb.js';
|
||||
import ShapeBuilder from '@/iscs_new/plugins/shapeBuilder';
|
||||
import ShapeProperty from '@/iscs_new/plugins/shapeProperty';
|
||||
import ShapeContextMenu from '@/iscs_new/plugins/shapeContextMenu';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
dataZoom: {
|
||||
offsetX: '0',
|
||||
offsetY: '0',
|
||||
scaleRate: '1'
|
||||
},
|
||||
config: {
|
||||
scaleRate: '1',
|
||||
origin: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
},
|
||||
loading: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('iscs', [
|
||||
'iscs'
|
||||
]),
|
||||
iscsId() {
|
||||
return ['iscs', (Math.random().toFixed(5)) * 100000].join('_');
|
||||
},
|
||||
width() {
|
||||
return document.documentElement.clientWidth;
|
||||
},
|
||||
height() {
|
||||
return document.documentElement.clientHeight;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$store.state.config.canvasSizeCount': function (val) {
|
||||
this.resize();
|
||||
},
|
||||
'$store.state.socket.equipmentStatus': function (val) {
|
||||
if (val.length) {
|
||||
this.stateMessage(val);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.destroy();
|
||||
},
|
||||
methods: {
|
||||
// 初始化窗口
|
||||
init() {
|
||||
document.getElementById(this.iscsId).oncontextmenu = function (e) {
|
||||
return false;
|
||||
};
|
||||
|
||||
this.$iscs = new Iscs({
|
||||
dom: document.getElementById(this.iscsId),
|
||||
draw: true,
|
||||
config: {
|
||||
renderer: 'canvas',
|
||||
width: this.width,
|
||||
height: this.height
|
||||
},
|
||||
options: {
|
||||
scaleRate: 1,
|
||||
offsetX: 0,
|
||||
offsetY: 0
|
||||
},
|
||||
plugins: [
|
||||
ShapeBuilder,
|
||||
// ShapeProperty,
|
||||
ShapeContextMenu
|
||||
]
|
||||
});
|
||||
|
||||
const option = {
|
||||
panEnable: true,
|
||||
zoomEnable: true,
|
||||
keyEnable: true,
|
||||
draggle: true,
|
||||
selecting: true,
|
||||
selectable: true,
|
||||
reflect: true
|
||||
}
|
||||
if (this.$route.query.id) {
|
||||
setTimeout(_ => {
|
||||
Idb.select('composeList', this.$route.query.id).then(resp => {
|
||||
this.$iscs.setMap([], {
|
||||
elementList: resp.elementList||[],
|
||||
composeList: resp.composeList||[]
|
||||
}, option);
|
||||
}).catch(error => {
|
||||
this.$iscs.setMap([], {
|
||||
elementList: [],
|
||||
composeList: []
|
||||
}, option);
|
||||
})
|
||||
}, 1000)
|
||||
} else {
|
||||
this.$iscs.setMap([], {
|
||||
elementList: [],
|
||||
composeList: []
|
||||
}, option);
|
||||
}
|
||||
|
||||
Vue.prototype.$iscs = this.$iscs;
|
||||
this.$iscs.on('viewLoaded', this.onViewLoaded, this);
|
||||
this.$iscs.on('contextmenu', this.onContextMenu, this);
|
||||
this.$iscs.on('click', this.onClick, this);
|
||||
this.$iscs.on('reflect', this.onReflect, this);
|
||||
this.$iscs.on('keyboard', this.onKeyboard, this);
|
||||
window.document.oncontextmenu = function () {
|
||||
return false;
|
||||
};
|
||||
},
|
||||
// 视图加载完成
|
||||
onViewLoaded(e) {
|
||||
},
|
||||
// 键盘快捷键事件
|
||||
onKeyboard(hook) {
|
||||
console.log(hook);
|
||||
},
|
||||
// 点击选择事件
|
||||
onClick(em={}) {
|
||||
this.$emit('selected', em);
|
||||
},
|
||||
onReflect(em={}) {
|
||||
this.$emit('selected', this.$iscs.getShapeByCode(em.code));
|
||||
},
|
||||
// 右键点击事件
|
||||
onContextMenu(em={}) {
|
||||
this.$emit('contextMenu', em.model);
|
||||
},
|
||||
// 执行操作
|
||||
doAction(list) {
|
||||
this.$iscs && this.$iscs.render(list);
|
||||
},
|
||||
// 消息处理
|
||||
stateMessage(val) {
|
||||
this.$iscs && this.$iscs.setDeviceStatus(val);
|
||||
},
|
||||
// 充值窗口大小
|
||||
resize() {
|
||||
this.$nextTick(() => {
|
||||
this.$iscs && this.$iscs.resize({ width: this.width, height: this.height });
|
||||
});
|
||||
},
|
||||
// 销毁
|
||||
destroy() {
|
||||
if (this.$iscs) {
|
||||
this.$iscs.destroy();
|
||||
this.$iscs = null;
|
||||
Vue.prototype.$iscs = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.iscs-button{
|
||||
position: absolute;
|
||||
float: right;
|
||||
right: 20px;
|
||||
bottom: 15px;
|
||||
}
|
||||
.iscs-canvas{
|
||||
}
|
||||
</style>
|
386
src/views/iscs_new/iscsDraw/index.vue
Normal file
386
src/views/iscs_new/iscsDraw/index.vue
Normal file
@ -0,0 +1,386 @@
|
||||
<template>
|
||||
<transition name="el-zoom-in-center">
|
||||
<div class="mapPaint">
|
||||
<div class="map-view">
|
||||
<iscs-canvas ref="iscsCanvas" @selected="onSelected" @setStateList="setStateList" />
|
||||
</div>
|
||||
<div class="right-card" :class="{'hide': draftShow}">
|
||||
<div class="btn_draft_box" @click="draftShow = !draftShow"><i :class="draftShow?'el-icon-arrow-right':'el-icon-arrow-left'" /></div>
|
||||
<el-card type="border-card" class="heightClass">
|
||||
<div slot="header" class="clearfix">
|
||||
<el-button
|
||||
type="text"
|
||||
style="float: right; padding: 3px 0; margin-right: 5px;"
|
||||
@click="onSave"
|
||||
>保存</el-button>
|
||||
<el-button
|
||||
v-if=" composeElemList.length>0"
|
||||
type="text"
|
||||
style="float: right; padding: 3px 0; margin-right: 5px;"
|
||||
@click="onPreview"
|
||||
>预览</el-button>
|
||||
<el-button
|
||||
v-if=" composeElemList.length>0"
|
||||
type="text"
|
||||
style="float: right; padding: 3px 0; margin-right: 5px;"
|
||||
@click="onModifyStatus"
|
||||
>状态编辑</el-button>
|
||||
</div>
|
||||
<el-tabs id="cardTab" v-model="cardTab" class="card" type="border-card" @tab-click="onSelectCardTab">
|
||||
<el-tab-pane label="元素绘制" name="first">
|
||||
<el-tabs v-model="enabledTab" class="card" type="card" @tab-click="onSelectTab">
|
||||
<el-tab-pane v-for="(element,index) in elementList" :key="index" :label="element.name" :name="element.type" :lazy="true">
|
||||
<data-form :ref="'dataform'+element.type" :form="element" :form-model="element.model" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class="bottomBtnGroup">
|
||||
<el-button v-show="!selected" type="primary" size="small" @click="onSubmit">添加</el-button>
|
||||
<el-button v-show="selected" type="warning" size="small" @click="onModify">修改</el-button>
|
||||
<el-button v-show="selected" type="danger" size="small" @click="onDelete">删除</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="单元素状态编辑" name="second">
|
||||
<el-tabs v-model="statusTab" class="card" type="card" @tab-click="onSelectTab">
|
||||
<el-tab-pane v-for="(composeElem,index) in composeElemList" :key="index" :label="composeElem.name" :name="composeElem.code" :lazy="true">
|
||||
<table-form :ref="'tableform'+composeElem.code" :compose-elem="composeElem" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div class="bottomBtnGroup">
|
||||
<el-button type="primary" size="small" @click="onSaveStatus">保存</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="状态编辑" name="third">
|
||||
<status-combine-edit ref="editStatusForm" :state-list="stateList" @saveStateList="saveStateList" />
|
||||
<div class="bottomBtnGroup">
|
||||
<el-button type="primary" size="small" @click="onEditStatusSave">保存</el-button>
|
||||
</div>
|
||||
</el-tab-pane> -->
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</div>
|
||||
<status-list ref="statusList" @setStateList="setStateList" />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
<script>
|
||||
import localStore from 'storejs';
|
||||
import iscsCanvas from './iscsCanvas';
|
||||
import formBuilder from '@/iscs_new/core/form/formBuilder';
|
||||
import DataForm from '../components/dataForm';
|
||||
import TableForm from '../components/tableForm';
|
||||
import orders from '@/iscs_new/utils/orders';
|
||||
import * as utils from '@/iscs_new/utils/utils';
|
||||
import Idb from '../utils/indexedDb.js';
|
||||
import shapeType from '@/iscs_new/constant/shapeType.js';
|
||||
// import StatusCombineEdit from './statusCombineEdit';
|
||||
import StatusList from './statusList';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
|
||||
export default {
|
||||
name: 'IscsView',
|
||||
components: {
|
||||
iscsCanvas,
|
||||
DataForm,
|
||||
TableForm,
|
||||
StatusList
|
||||
// StatusCombineEdit
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
size: {
|
||||
width: this.$store.state.app.width - 521,
|
||||
height: this.$store.state.app.height - 60
|
||||
},
|
||||
widthLeft: Number(localStore.get('LeftWidth')) || 450,
|
||||
draftShow: false,
|
||||
selected: null,
|
||||
enabledTab:'',
|
||||
cardTab:'first',
|
||||
statusTab:'',
|
||||
showDeleteButton:false,
|
||||
elementList:[],
|
||||
composeElemList:[],
|
||||
stateList:[]
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
iscsMode() {
|
||||
return this.$route.query.mode;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route(val) {
|
||||
this.onIscsChange(this.$route.query.mode, this.$route.query.system, this.$route.query.part);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composeName = this.$route.query.composeName;
|
||||
this.elementList = formBuilder.buildFormList();
|
||||
this.enabledTab = this.elementList[0].type;
|
||||
this.getComposeElemList();
|
||||
EventBus.$on('getComposeElemList', () => {
|
||||
this.getComposeElemList();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
onIscsChange(mode, system, part) {
|
||||
// this.$refs.iscsPlate.show(mode, system, part);
|
||||
// this.$refs.iscsPlate.drawIscsInit();
|
||||
},
|
||||
onSave() {
|
||||
const id = this.$route.query.id;
|
||||
const name = this.$route.query.name || '<模型名称>';
|
||||
const type = this.$route.query.type || '<模型类型>';
|
||||
const source = this.$iscs.getSource();
|
||||
if (id && source) {
|
||||
const shapeList = source.elementList;
|
||||
shapeList.forEach(el => {
|
||||
return this.$iscs.getShapeByCode(el.code).model;
|
||||
});
|
||||
// const composeList = source.composeList.map(el => {
|
||||
// return this.$iscs.getShapeByCode(el.code).model;
|
||||
// });
|
||||
// const rect = shapeList.reduce((temp, el) => {
|
||||
// const shape = this.$iscs.getShapeByCode(el.code);
|
||||
// return shape && temp ? temp.union(shape.getBoundingRect().clone()) : shape.getBoundingRect();
|
||||
// }, null);
|
||||
// const position = rect ? [(rect.x + rect.width) / 2, (rect.y + rect.height) / 2] : [0, 0];
|
||||
const position = [0, 0];
|
||||
const stateList = this.stateList;
|
||||
const model = { id, name, type, shapeList, stateList, position };
|
||||
|
||||
Idb.delete('composeTemplateList', model.id);
|
||||
Idb.write('composeTemplateList', model);
|
||||
Idb.list('composeTemplateList').then(list => {
|
||||
console.log(list);
|
||||
});
|
||||
}
|
||||
},
|
||||
onSelectTab() {
|
||||
this.selected = null;
|
||||
},
|
||||
onSelectCardTab() {
|
||||
|
||||
},
|
||||
setStateList(stateList) {
|
||||
this.stateList = stateList;
|
||||
},
|
||||
onSelected(em) {
|
||||
if (em.model) {
|
||||
this.selected = JSON.parse(JSON.stringify(em.model));
|
||||
const elem = this.elementList.find(el => el.type == this.selected.type);
|
||||
if (elem) {
|
||||
elem.model = this.selected;
|
||||
this.enabledTab = this.selected.type;
|
||||
this.cardTab = 'first';
|
||||
}
|
||||
} else {
|
||||
this.selected = null;
|
||||
this.clear(this.enabledTab);
|
||||
}
|
||||
},
|
||||
onSubmit() {
|
||||
this.$refs['dataform' + this.enabledTab][0].$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
const formModel = this.$refs['dataform' + this.enabledTab][0].formModel;
|
||||
const newModel = utils.deepClone(formModel);
|
||||
newModel.code = utils.getUID(this.enabledTab);
|
||||
newModel.type = this.enabledTab;
|
||||
newModel.name = '<名称>';
|
||||
newModel.stateList = [];
|
||||
this.$refs.iscsCanvas.doAction([{model: newModel, action: {shapeType: shapeType.Element, order: orders.Add}}]);
|
||||
this.clear(this.enabledTab);
|
||||
this.getComposeElemList();
|
||||
}
|
||||
});
|
||||
},
|
||||
onModify() {
|
||||
this.$refs['dataform' + this.enabledTab][0].$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
const model = utils.deepClone(this.$refs['dataform' + this.enabledTab][0].formModel);
|
||||
model.code = this.selected.code;
|
||||
model.type = this.selected.type;
|
||||
model.name = this.selected.name;
|
||||
this.$refs.iscsCanvas.doAction([{model, action: {shapeType: shapeType.Element, order: orders.Update}}]);
|
||||
this.clear(this.enabledTab);
|
||||
}
|
||||
});
|
||||
},
|
||||
onDelete() {
|
||||
this.$refs['dataform' + this.enabledTab][0].$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
const model = utils.deepClone(this.$refs['dataform' + this.enabledTab][0].formModel);
|
||||
model.code = this.selected.code;
|
||||
model.type = this.selected.type;
|
||||
model.name = this.selected.name;
|
||||
this.$refs.iscsCanvas.doAction([{model, action: {shapeType: shapeType.Element, order: orders.Delete}}]);
|
||||
this.clear(this.enabledTab);
|
||||
this.getComposeElemList();
|
||||
}
|
||||
});
|
||||
},
|
||||
clear(enabledTab) {
|
||||
this.$refs['dataform' + enabledTab][0].init();
|
||||
this.selected = null;
|
||||
},
|
||||
getComposeElemList() {
|
||||
const source = this.$iscs.getSource();
|
||||
if (source &&
|
||||
source.elementList &&
|
||||
source.elementList.length) {
|
||||
this.composeElemList = source.elementList;
|
||||
this.statusTab = this.composeElemList[0].code;
|
||||
} else {
|
||||
this.composeElemList = [];
|
||||
}
|
||||
},
|
||||
onSaveStatus() {
|
||||
this.$refs['tableform' + this.statusTab][0].$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
const model = utils.deepClone(this.$refs['tableform' + this.statusTab][0].formModel);
|
||||
model.stateList.map(state=>{ delete state.defaultStyleSelect; delete state.defaultShapeSelect; });
|
||||
this.$refs.iscsCanvas.doAction([{model, action: {shapeType: shapeType.Element, order: orders.Update}}]);
|
||||
this.onSave();
|
||||
}
|
||||
});
|
||||
},
|
||||
onEditStatusSave() {
|
||||
this.$refs['editStatusForm'].$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.onSave();
|
||||
}
|
||||
});
|
||||
},
|
||||
onPreview() {
|
||||
this.$router.push({ path: `/iscs_new/design/compose/preview`, query:{id:this.$route.query.id} });
|
||||
},
|
||||
|
||||
onModifyStatus() {
|
||||
this.$refs.statusList.doShow();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
@import "src/styles/mixin.scss";
|
||||
.card{
|
||||
height: 100%;
|
||||
display:flex;width: 100%;flex-direction: column
|
||||
}
|
||||
|
||||
.card .el-tab-pane{
|
||||
flex:1;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
padding-bottom:30px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
// height: 110px;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
// box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
|
||||
border-radius: 10px;
|
||||
background-color: #FFFFFF;;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
// box-shadow: inset 0 0 6px rgba(0,0,0,.3);
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
border-radius: 5px;
|
||||
// box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
|
||||
background: rgba(0,0,0,0.4);
|
||||
}
|
||||
}
|
||||
|
||||
.map-view {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
.heightClass{height:100%;overflow:hidden;display:flex;width: 100%;flex-direction: column;}
|
||||
|
||||
.mapPaint{
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
width:100%;
|
||||
position:absolute;
|
||||
left:0;top:0;
|
||||
}
|
||||
|
||||
.right-card{
|
||||
width: 550px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
transform: translateX(550px);
|
||||
transition: all 0.5s;
|
||||
background: #fff;
|
||||
z-index: 9;
|
||||
/deep/{
|
||||
.v-modal{
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
&.hide{
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.btn_draft_box{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
padding: 8px 3px;
|
||||
background: #fff;
|
||||
z-index: 10;
|
||||
transform: translateX(-22px);
|
||||
cursor: pointer;
|
||||
border-radius: 5px 0 0 5px;
|
||||
box-shadow: -2px 0px 2px #000000;
|
||||
}
|
||||
|
||||
.btn_table_box {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(50% + 50px);
|
||||
padding: 8px 3px;
|
||||
background: #fff;
|
||||
z-index: 10;
|
||||
transform: translateX(-22px);
|
||||
cursor: pointer;
|
||||
border-radius: 5px 0 0 5px;
|
||||
box-shadow: -2px 0px 2px #000000;
|
||||
}
|
||||
}
|
||||
.bottomBtnGroup{
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 43px;
|
||||
text-align: right;
|
||||
right: 0px;
|
||||
background: #fff;
|
||||
z-index: 2;
|
||||
padding-top: 5px;
|
||||
border-bottom: 1px #dedede solid;
|
||||
box-shadow: 2px -3px 5px #dedede;
|
||||
}
|
||||
.bottomBtnGroup button{
|
||||
display: inline-block;
|
||||
margin-right:10px;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.heightClass .el-card__body{
|
||||
flex:1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#cardTab .el-tabs__content{
|
||||
padding:0px;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
186
src/views/iscs_new/iscsDraw/iscsCanvas.vue
Normal file
186
src/views/iscs_new/iscsDraw/iscsCanvas.vue
Normal file
@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :id="iscsId" v-loading="loading" :style="{ width: width +'px', height: height +'px',background:'#425a74' }" class="iscs-canvas" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import Iscs from '@/iscs_new/map';
|
||||
import Idb from '../utils/indexedDb.js';
|
||||
import ShapeBuilder from '@/iscs_new/plugins/shapeBuilder';
|
||||
import ShapeProperty from '@/iscs_new/plugins/shapeProperty';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
import ShapeContextMenu from '@/iscs_new/plugins/shapeContextMenu';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
dataZoom: {
|
||||
offsetX: '0',
|
||||
offsetY: '0',
|
||||
scaleRate: '1'
|
||||
},
|
||||
config: {
|
||||
scaleRate: '1',
|
||||
origin: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
},
|
||||
loading: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('iscs', [
|
||||
'iscs'
|
||||
]),
|
||||
iscsId() {
|
||||
return ['iscs', (Math.random().toFixed(5)) * 100000].join('_');
|
||||
},
|
||||
width() {
|
||||
return document.documentElement.clientWidth;
|
||||
},
|
||||
height() {
|
||||
return document.documentElement.clientHeight;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$store.state.config.canvasSizeCount': function (val) {
|
||||
this.resize();
|
||||
},
|
||||
'$store.state.socket.equipmentStatus': function (val) {
|
||||
if (val.length) {
|
||||
this.stateMessage(val);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.destroy();
|
||||
},
|
||||
methods: {
|
||||
// 初始化窗口
|
||||
init() {
|
||||
document.getElementById(this.iscsId).oncontextmenu = function (e) {
|
||||
return false;
|
||||
};
|
||||
|
||||
this.$iscs = new Iscs({
|
||||
dom: document.getElementById(this.iscsId),
|
||||
draw: true,
|
||||
config: {
|
||||
renderer: 'canvas',
|
||||
width: this.width,
|
||||
height: this.height
|
||||
},
|
||||
options: {
|
||||
scaleRate: 1,
|
||||
offsetX: 0,
|
||||
offsetY: 0
|
||||
},
|
||||
plugins: [
|
||||
ShapeBuilder,
|
||||
// ShapeProperty,
|
||||
ShapeContextMenu
|
||||
]
|
||||
});
|
||||
|
||||
const option = {
|
||||
panEnable: true,
|
||||
zoomEnable: true,
|
||||
keyEnable: true,
|
||||
draggle: true,
|
||||
selecting: true,
|
||||
selectable: true,
|
||||
reflect: true
|
||||
};
|
||||
if (this.$route.query.id) {
|
||||
setTimeout(_ => {
|
||||
Idb.select('composeTemplateList', this.$route.query.id).then(resp => {
|
||||
this.$iscs.setMap([], {
|
||||
elementList: resp.shapeList || [],
|
||||
composeList: resp.composeList || []
|
||||
}, option);
|
||||
EventBus.$emit('getComposeElemList');
|
||||
this.$emit('setStateList', resp.stateList);
|
||||
}).catch(error => {
|
||||
this.$iscs.setMap([], {
|
||||
elementList: [],
|
||||
composeList: []
|
||||
}, option);
|
||||
});
|
||||
}, 1000);
|
||||
} else {
|
||||
this.$iscs.setMap([], {
|
||||
elementList: [],
|
||||
composeList: []
|
||||
}, option);
|
||||
}
|
||||
|
||||
Vue.prototype.$iscs = this.$iscs;
|
||||
this.$iscs.on('viewLoaded', this.onViewLoaded, this);
|
||||
this.$iscs.on('contextmenu', this.onContextMenu, this);
|
||||
this.$iscs.on('click', this.onClick, this);
|
||||
this.$iscs.on('reflect', this.onReflect, this);
|
||||
this.$iscs.on('keyboard', this.onKeyboard, this);
|
||||
window.document.oncontextmenu = function () {
|
||||
return false;
|
||||
};
|
||||
},
|
||||
// 视图加载完成
|
||||
onViewLoaded(e) {
|
||||
},
|
||||
// 键盘快捷键事件
|
||||
onKeyboard(hook) {
|
||||
console.log(hook);
|
||||
},
|
||||
// 点击选择事件
|
||||
onClick(em = {}) {
|
||||
this.$emit('selected', em);
|
||||
},
|
||||
onReflect(em = {}) {
|
||||
this.$emit('selected', this.$iscs.getShapeByCode(em.code));
|
||||
},
|
||||
// 右键点击事件
|
||||
onContextMenu(em = {}) {
|
||||
this.$emit('contextMenu', em.model);
|
||||
},
|
||||
// 执行操作
|
||||
doAction(list) {
|
||||
this.$iscs && this.$iscs.render(list);
|
||||
},
|
||||
// 消息处理
|
||||
stateMessage(val) {
|
||||
this.$iscs && this.$iscs.setDeviceStatus(val);
|
||||
},
|
||||
// 充值窗口大小
|
||||
resize() {
|
||||
this.$nextTick(() => {
|
||||
this.$iscs && this.$iscs.resize({ width: this.width, height: this.height });
|
||||
});
|
||||
},
|
||||
// 销毁
|
||||
destroy() {
|
||||
if (this.$iscs) {
|
||||
this.$iscs.destroy();
|
||||
this.$iscs = null;
|
||||
Vue.prototype.$iscs = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.iscs-button{
|
||||
position: absolute;
|
||||
float: right;
|
||||
right: 20px;
|
||||
bottom: 15px;
|
||||
}
|
||||
.iscs-canvas{
|
||||
}
|
||||
</style>
|
153
src/views/iscs_new/iscsDraw/statusCombineEdit.vue
Normal file
153
src/views/iscs_new/iscsDraw/statusCombineEdit.vue
Normal file
@ -0,0 +1,153 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button type="primary" size="small" class="addComposeStatus" @click="addComposeStatus">添加</el-button>
|
||||
<el-form ref="form" class="composeStatusForm" :model="formModel">
|
||||
<!-- label-width="110px" -->
|
||||
<el-table
|
||||
:data="formModel.stateList"
|
||||
stripe
|
||||
class="composeStatusTable"
|
||||
size="mini"
|
||||
row-key="id"
|
||||
:expand-row-keys="expandKeys"
|
||||
@expand-change="expandChange"
|
||||
>
|
||||
<!-- covertStatusList: -->
|
||||
<el-table-column label="状态" width="98">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'stateList.'+scope.$index+'.status'"
|
||||
:rules="[{required: true, message:'请输入状态', trigger: 'blur'}]"
|
||||
>
|
||||
<el-input v-model="scope.row.status" size="mini" type="text" style="width:88px" :maxlength="100" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="描述" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'stateList.'+scope.$index+'.description'"
|
||||
:rules="[{required: true, message:'请输入描述', trigger: 'blur'}]"
|
||||
>
|
||||
<el-input v-model="scope.row.description" size="mini" type="text" style="width:90px" :maxlength="100" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="权重" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'stateList.'+scope.$index+'.weight'"
|
||||
:rules="[{required: true, message:'请输入权重', trigger: 'blur'}]"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="scope.row.weight"
|
||||
size="mini"
|
||||
style="width:110px"
|
||||
:step="1"
|
||||
:min="1"
|
||||
:max="100"
|
||||
:precision="0"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否可重置" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'stateList.'+scope.$index+'.needDefault'">
|
||||
<el-switch
|
||||
v-model="scope.row.needDefault"
|
||||
size="small"
|
||||
active-color="#409eff"
|
||||
inactive-color="#dcdfe6"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="115">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" size="mini" @click="modifyStatus(scope.$index,scope.row)">编辑状态组合</el-button>
|
||||
<el-button type="danger" size="mini" style="margin-top:5px;" @click="deleteStatus(scope.$index,scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:'StatusCombineEdit',
|
||||
props:{
|
||||
stateList: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expandKeys:[],
|
||||
formModel:{
|
||||
stateList:this.stateList
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
methods:{
|
||||
init() {
|
||||
|
||||
},
|
||||
expandChange(row, expandedRows) {
|
||||
|
||||
},
|
||||
addComposeStatus() {
|
||||
const length = this.formModel.stateList.length;
|
||||
this.formModel.stateList.push({id:length + 1, status:'', description:'', weight:1, needDefault:false,
|
||||
covertStatusList:[]});
|
||||
// defaultLoop:false
|
||||
this.expandKeys.push(length + 1);
|
||||
},
|
||||
deleteStatus(index, row) {
|
||||
this.formModel.stateList.splice(index, 1);
|
||||
const key = this.expandKeys.findIndex(each=>{ return each == row.id; });
|
||||
if (key > 0) { this.expandKeys.splice(key, 1); }
|
||||
},
|
||||
modifyStatus(index, row) {
|
||||
this.$refs.eachStatusTable.doShow(index, row);
|
||||
}
|
||||
// addCovertStatus(index) {
|
||||
// if (this.formModel.stateList[index].defaultLoop) {
|
||||
// const covertStatusList = this.formModel.stateList[index].covertStatusList;
|
||||
// const length = covertStatusList.length;
|
||||
// covertStatusList.push({id:length + 1, loop:this.formModel.stateList[index].defaultLoop,
|
||||
// delay:2, animateTime:10, frameList:[]});
|
||||
// // ,times:1,
|
||||
// // this.formModel.stateList[index].covertStatusList = covertStatusList;
|
||||
// this.$set(this.formModel.stateList[index], 'covertStatusList', covertStatusList);
|
||||
// } else {
|
||||
// this.formModel.stateList[index].covertStatusList.push({id:length + 1, loop:this.formModel.stateList[index].defaultLoop,
|
||||
// frameList:[]});
|
||||
// }
|
||||
// }
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.combineStatusListName{
|
||||
font-size: 14px;
|
||||
width: 200px;
|
||||
background: #fff;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
.addComposeStatus{
|
||||
float: right;
|
||||
display: inline-block;
|
||||
margin:10px 10px 10px 0px;
|
||||
}
|
||||
.composeStatusTable{}
|
||||
.composeStatusForm{padding:15px;}
|
||||
.composeStatusTable .eachStatusTable{margin-top:10px;}
|
||||
</style>
|
||||
<style lang="sass">
|
||||
.composeStatusTable .el-table__expanded-cell{padding: 20px;}
|
||||
</style>
|
370
src/views/iscs_new/iscsDraw/statusList.vue
Normal file
370
src/views/iscs_new/iscsDraw/statusList.vue
Normal file
@ -0,0 +1,370 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-dialogDrag
|
||||
class="composeStatusList"
|
||||
title="状态编辑"
|
||||
:visible.sync="show"
|
||||
width="800px"
|
||||
:before-close="doClose"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
>
|
||||
<el-button type="primary" size="small" class="addComposeStatus" @click="addComposeStatus">添加</el-button>
|
||||
<el-form ref="form" class="composeStatusForm" :model="formModel">
|
||||
<el-table
|
||||
:data="formModel.stateList"
|
||||
stripe
|
||||
border
|
||||
class="composeStatusTable"
|
||||
height="360"
|
||||
size="mini"
|
||||
row-key="id"
|
||||
>
|
||||
<el-table-column label="状态" width="169">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'stateList.'+scope.$index+'.status'"
|
||||
:rules="[{required: true, message:'请输入状态', trigger: 'blur'}]"
|
||||
>
|
||||
<el-input v-model="scope.row.status" size="mini" type="text" style="width:149px" :maxlength="100" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="描述" width="170">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'stateList.'+scope.$index+'.description'"
|
||||
:rules="[{required: true, message:'请输入描述', trigger: 'blur'}]"
|
||||
>
|
||||
<el-input v-model="scope.row.description" size="mini" type="text" style="width:150px" :maxlength="100" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="权重" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'stateList.'+scope.$index+'.weight'"
|
||||
:rules="[{required: true, message:'请输入权重', trigger: 'blur'}]"
|
||||
>
|
||||
<el-input-number v-model="scope.row.weight" size="mini" style="width:100px" :step="1" :min="1" :max="100" :precision="0" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否可重置" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'stateList.'+scope.$index+'.needDefault'">
|
||||
<el-switch
|
||||
v-model="scope.row.needDefault"
|
||||
size="small"
|
||||
active-color="#409eff"
|
||||
inactive-color="#dcdfe6"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" size="mini" @click="modifyStatus(scope.$index,scope.row)">编辑状态组合</el-button>
|
||||
<el-button type="danger" size="mini" style="margin-top:5px;" @click="deleteStatus(scope.$index,scope.row)">删除</el-button>
|
||||
<!-- <el-button type="primary" size="mini" style="margin-top:5px;" @click="previewStatus(scope.$index,scope.row)">预览</el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
<div class="bottomBtnGroup">
|
||||
<el-button type="primary" size="medium" @click="onEditStatusSave">保存</el-button>
|
||||
</div>
|
||||
<el-dialog
|
||||
v-dialogDrag
|
||||
class="composeStatus"
|
||||
title="状态组合"
|
||||
:visible.sync="innerShow"
|
||||
width="750px"
|
||||
:before-close="doInnerClose"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
>
|
||||
<div class="loopTitle">是否动画:</div>
|
||||
<el-select v-model="defaultLoop" size="mini">
|
||||
<el-option label="是" :value="true" />
|
||||
<el-option label="否" :value="false" />
|
||||
</el-select>
|
||||
<el-button type="primary" size="mini" class="addStyle" @click="addCovertStatus">添加</el-button>
|
||||
<el-form ref="Innerform" class="composeStatusForm" :model="statusModel">
|
||||
<el-table
|
||||
:data="statusModel.covertStatusList"
|
||||
stripe
|
||||
border
|
||||
style="margin-top:10px;"
|
||||
class="eachStatusTable"
|
||||
size="mini"
|
||||
row-key="id"
|
||||
>
|
||||
<el-table-column label="是否动画" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<!-- <el-form-item prop="loop"> -->
|
||||
<div style="">{{ scope.row.loop?'是':'否' }}</div>
|
||||
<!-- </el-form-item> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="动画时间" width="120" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item v-if="scope.row.loop" :prop="'covertStatusList.'+scope.$index+'.animateTime'" :rules="[{required: true, message:'请输入动画时间', trigger: 'blur'}]">
|
||||
<el-input-number v-model="scope.row.animateTime" size="mini" style="width:100px" :step="1" :min="1" :max="100" :precision="0" />
|
||||
</el-form-item>
|
||||
<div v-else>无</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="动画延时" width="120" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
v-if="scope.row.loop"
|
||||
:prop="'covertStatusList.'+scope.$index+'.delay'"
|
||||
:rules="[{required: true, message:'请输入动画延时', trigger: 'blur'}]"
|
||||
>
|
||||
<el-input-number v-model="scope.row.delay" size="mini" style="width:100px" :step="1" :min="1" :max="100" :precision="0" />
|
||||
</el-form-item>
|
||||
<div v-else>无</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态组合" width="319">
|
||||
<template slot-scope="scope">
|
||||
<!-- {{ scope.row.frameList }} -->
|
||||
<!-- <div v-if="scope.row.frameList.length<=0"> -->
|
||||
<!-- 元素 -->
|
||||
<!-- <div /> -->
|
||||
<div v-if="scope.row.loop" style="margin-bottom:10px">
|
||||
<!-- <div style="display:inline-block">当前动画帧:{{ scope.row.frameId }}</div> -->
|
||||
<el-button type="primary" size="mini" class="addStyle" @click="addElementFrameId(scope.$index,scope.row.frameId)">添加帧</el-button>
|
||||
<!-- <el-input-number
|
||||
v-model="scope.row.frameId"
|
||||
:min="1"
|
||||
:max="10"
|
||||
size="mini"
|
||||
:step="1"
|
||||
:precision="0"
|
||||
/> -->
|
||||
</div>
|
||||
<el-select
|
||||
v-model="scope.row.selectedElement"
|
||||
size="mini"
|
||||
style="width:115px;display:inline-block"
|
||||
placeholder="请选择元素"
|
||||
@change="changeCurrentStatus(scope.$index,scope.row.selectedElement)"
|
||||
>
|
||||
<el-option v-for="(element,index) in elementList" :key="index" :label="element.name" :value="element.name" />
|
||||
</el-select>
|
||||
<el-select v-model="scope.row.selectedElementStatus" size="mini" placeholder="请选择状态" style="width:115px;display:inline-block">
|
||||
<el-option v-for="(status,index) in scope.row.statusList" :key="index" :label="status.name" :value="status.name" />
|
||||
</el-select>
|
||||
<el-button type="primary" size="mini" class="addStyle" @click="addElementStatus(scope.$index,scope.row.loop)">添加</el-button>
|
||||
<div v-if="scope.row.loop">
|
||||
<div v-for="(frame,index) in scope.row.frameList" :key="index">
|
||||
第{{ index+1 }}帧:
|
||||
<span v-for="(frameIn,indexIn) in frame" :key="indexIn">
|
||||
元素名称:{{ frameIn.name }} 状态:{{ frameIn.status }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-for="(frame,index) in scope.row.frameList" :key="index">
|
||||
元素名称:{{ frame.name }} 状态:{{ frame.status }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="50">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="danger" icon="el-icon-delete" circle size="mini" @click="deleteCovertStatus(scope.$index,scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
<div class="bottomBtnGroup">
|
||||
<el-button type="primary" size="medium" @click="onEditComposeStatus">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import { deepAssign } from '@/utils/index';
|
||||
import Idb from '../utils/indexedDb.js';
|
||||
export default {
|
||||
name:'StatusList',
|
||||
data() {
|
||||
return {
|
||||
show:false,
|
||||
defaultLoop:false,
|
||||
// covertStatusList:[],
|
||||
innerShow:false,
|
||||
formModel:{
|
||||
stateList:[]
|
||||
},
|
||||
statusModel:{
|
||||
covertStatusList:[]
|
||||
},
|
||||
elementList:[],
|
||||
currentIndex:0,
|
||||
model:{}
|
||||
// statusList:[]
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
doClose() {
|
||||
this.show = false;
|
||||
},
|
||||
doShow() {
|
||||
this.formModel.stateList = [];
|
||||
this.show = true;
|
||||
Idb.select('composeTemplateList', this.$route.query.id).then(resp => {
|
||||
this.formModel.stateList = resp.stateList;
|
||||
this.model = resp;
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
addComposeStatus() {
|
||||
const length = this.formModel.stateList.length;
|
||||
this.formModel.stateList.push({id:length + 1, status:'', description:'', weight:1, needDefault:false,
|
||||
covertStatusList:[]});
|
||||
},
|
||||
deleteStatus(index, row) {
|
||||
this.formModel.stateList.splice(index, 1);
|
||||
},
|
||||
onEditStatusSave() {
|
||||
const that = this;
|
||||
that.$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
// that.formModel;
|
||||
// // const id = this.$route.query.id;
|
||||
this.model.stateList = that.formModel.stateList;
|
||||
Idb.delete('composeTemplateList', this.model.id);
|
||||
Idb.write('composeTemplateList', this.model);
|
||||
that.show = false;
|
||||
this.$emit('setStateList', that.formModel.stateList);
|
||||
}
|
||||
});
|
||||
},
|
||||
modifyStatus(index, row) {
|
||||
this.currentIndex = index;
|
||||
this.innerShow = true;
|
||||
this.statusModel.covertStatusList = Object.values(row.covertStatusList);
|
||||
const source = this.$iscs.getSource();
|
||||
const composeElemList = source.elementList;
|
||||
this.elementList = [];
|
||||
composeElemList.forEach(each=>{
|
||||
this.elementList.push({name:each.name, stateList:each.stateList});
|
||||
});
|
||||
},
|
||||
doInnerClose() {
|
||||
this.innerShow = false;
|
||||
},
|
||||
addCovertStatus() {
|
||||
if (this.defaultLoop) {
|
||||
this.statusModel.covertStatusList.push({loop:this.defaultLoop, delay:2, animateTime:10, frameList:[], statusList:[], selectedElement:'', selectedElementStatus:'', frameId:null });
|
||||
} else {
|
||||
this.statusModel.covertStatusList.push({loop:this.defaultLoop, frameList:[], statusList:[], selectedElementStatus:'', selectedElement:'' });
|
||||
}
|
||||
|
||||
},
|
||||
onEditComposeStatus() {
|
||||
this.innerShow = false;
|
||||
this.statusModel.covertStatusList.forEach(covert=>{
|
||||
delete covert.selectedElement;
|
||||
delete covert.selectedElementStatus;
|
||||
delete covert.statusList;
|
||||
delete covert.frameId;
|
||||
});
|
||||
this.formModel.stateList[this.currentIndex].covertStatusList = deepAssign({}, this.statusModel.covertStatusList);
|
||||
},
|
||||
deleteCovertStatus(index, row) {
|
||||
this.statusModel.covertStatusList.splice(index, 1);
|
||||
},
|
||||
addElementFrameId(index, frameId) {
|
||||
if (frameId) {
|
||||
this.statusModel.covertStatusList[index].frameId = frameId + 1;
|
||||
} else {
|
||||
this.statusModel.covertStatusList[index].frameId = 1;
|
||||
}
|
||||
this.statusModel.covertStatusList[index].frameList.push([]);
|
||||
},
|
||||
addElementStatus(index, loop) {
|
||||
const frameList = this.statusModel.covertStatusList[index].frameList || [];
|
||||
const temp = this.statusModel.covertStatusList[index];
|
||||
if (loop) {
|
||||
if (temp.selectedElement && temp.selectedElementStatus && temp.frameId) {
|
||||
const curFrame = frameList[temp.frameId];
|
||||
let curFrameIndex = -1;
|
||||
if (curFrame && curFrame.length > 0) {
|
||||
curFrameIndex = curFrame.findIndex(frame=>{
|
||||
return frame.name == this.statusModel.covertStatusList[index].selectedElement &&
|
||||
frame.status == this.statusModel.covertStatusList[index].selectedElementStatus;
|
||||
});
|
||||
}
|
||||
if (curFrameIndex < 0) {
|
||||
// this.statusModel.covertStatusList[index].frameList.push([]);
|
||||
this.statusModel.covertStatusList[index].frameList[temp.frameId - 1].push({name:this.statusModel.covertStatusList[index].selectedElement,
|
||||
status:this.statusModel.covertStatusList[index].selectedElementStatus});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (temp.selectedElement && temp.selectedElementStatus) {
|
||||
const indexFrame = frameList.findIndex(frame=>{
|
||||
return frame.name == this.statusModel.covertStatusList[index].selectedElement &&
|
||||
frame.status == this.statusModel.covertStatusList[index].selectedElementStatus;
|
||||
});
|
||||
if (indexFrame < 0) {
|
||||
this.statusModel.covertStatusList[index].frameList.push({name:this.statusModel.covertStatusList[index].selectedElement,
|
||||
status:this.statusModel.covertStatusList[index].selectedElementStatus});
|
||||
}
|
||||
}
|
||||
}
|
||||
this.statusModel.covertStatusList[index].selectedElementStatus = '';
|
||||
this.statusModel.covertStatusList[index].selectedElement = '';
|
||||
},
|
||||
changeCurrentStatus(index, selectedElement) {
|
||||
this.statusModel.covertStatusList[index].selectedElementStatus = '';
|
||||
this.statusModel.covertStatusList[index].statusList = [];
|
||||
const list = this.elementList.find(each=>{ return each.name == selectedElement; });
|
||||
if (list && list.stateList && list.stateList.length > 0) {
|
||||
const temp = list.stateList;
|
||||
temp.forEach(each=>{
|
||||
this.statusModel.covertStatusList[index].statusList.push({name:each.status});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
// previewStatus(index, row) {
|
||||
// // const that = this;
|
||||
// // if(needDefault)
|
||||
// const list = Object.values(row.covertStatusList);
|
||||
// list.forEach(each=>{
|
||||
// if (each.loop) {
|
||||
|
||||
// } else {
|
||||
// const frameList = each.frameList;
|
||||
// frameList.forEach(frame=>{
|
||||
// // frame.name;
|
||||
// // frame.status;
|
||||
// // this.$iscs.
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// // this.show = false;
|
||||
// }
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.composeStatusTable{margin-top:10px;}
|
||||
.bottomBtnGroup{
|
||||
width: 100%;
|
||||
margin-top:10px;
|
||||
text-align: center;
|
||||
display: inline-block
|
||||
}
|
||||
.loopTitle{display:inline-block;}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.composeStatusList .el-dialog__body,.composeStatus .el-dialog__body{padding: 15px 20px;}
|
||||
</style>
|
192
src/views/iscs_new/iscsPreview/index.vue
Normal file
192
src/views/iscs_new/iscsPreview/index.vue
Normal file
@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<transition name="el-zoom-in-center">
|
||||
<div class="mapPaint">
|
||||
<div class="map-view">
|
||||
<iscs-canvas ref="iscsCanvas" @selected="onSelected" @setData="setData" />
|
||||
</div>
|
||||
<div class="right-card">
|
||||
<!-- :class="{'hide': draftShow}" -->
|
||||
<el-card type="border-card" class="heightClass">
|
||||
<div slot="header" class="clearfix">
|
||||
<!-- 组件id为{{ $route.query.id }} -->
|
||||
状态预览
|
||||
<!-- -->
|
||||
<el-button
|
||||
type="text"
|
||||
style="float: right; padding: 3px 0; margin-right: 5px;"
|
||||
@click="resetDefaultStatus"
|
||||
>重置状态</el-button>
|
||||
</div>
|
||||
<div class="stateList">
|
||||
<!-- <el-card style="margin-top:10px;height:100%"> -->
|
||||
<div v-for="(state,index) in stateList" :key="index" class="eachStatus">
|
||||
<div>状态属性:{{ state.status }}</div>
|
||||
<div>状态描述:{{ state.description }}</div>
|
||||
<div>状态权重:{{ state.weight }}</div>
|
||||
<div>状态是否可以初始化:{{ state.needDefault?'是':'否' }}</div>
|
||||
<el-button type="primary" size="mini" style="margin-top:5px;" @click="previewStatus(state)">预览</el-button>
|
||||
</div>
|
||||
<!-- </el-card> -->
|
||||
<!-- <el-tabs v-model="statusTab" class="card" type="card" @tab-click="onSelectTab"> -->
|
||||
<!-- <el-tab-pane v-for="(composeElem,index) in composeElemList" :key="index" :label="composeElem.name" :name="composeElem.code" :lazy="true"> -->
|
||||
<!-- <table-form :ref="'tableform'+composeElem.code" :compose-elem="composeElem" /> -->
|
||||
<!-- stateList -->
|
||||
<!-- </el-tab-pane> -->
|
||||
<!-- </el-tabs> -->
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
<script>
|
||||
import * as utils from '@/iscs_new/utils/utils';
|
||||
import iscsCanvas from './iscsCanvas';
|
||||
import orders from '@/iscs_new/utils/orders';
|
||||
import shapeType from '@/iscs_new/constant/shapeType.js';
|
||||
export default {
|
||||
name:'IscsPreview',
|
||||
components: {
|
||||
iscsCanvas
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
draftShow: false,
|
||||
selected: null,
|
||||
statusTab:'',
|
||||
stateList:[],
|
||||
elementList:[],
|
||||
type:''
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods:{
|
||||
onSelectTab() {
|
||||
|
||||
},
|
||||
setData(data) {
|
||||
this.stateList = data.stateList;
|
||||
this.elementList = utils.deepClone(data.shapeList);
|
||||
this.type = data.type;
|
||||
},
|
||||
previewStatus(data) {
|
||||
// this.resetDefaultStatus();
|
||||
// covertStatusList: Object
|
||||
// description: "关闭"
|
||||
// id: 1
|
||||
// needDefault: true
|
||||
// status: "close"
|
||||
// weight: 1
|
||||
this.$iscs.update([
|
||||
{ status: data.status, code: '100', type: this.type }
|
||||
]);
|
||||
// const that = this;
|
||||
// const list = Object.values(data.covertStatusList);
|
||||
// list.forEach(each=>{
|
||||
// debugger;
|
||||
// if (each.loop) {
|
||||
// // ChangeStatus
|
||||
// } else {
|
||||
// const frameList = each.frameList;
|
||||
// // <模型类型>
|
||||
// // this.$iscs.update([
|
||||
// // { status: 's1', code: '100', type: 'Device' },
|
||||
// // { status: 's2', code: '101', type: 'Device' }
|
||||
// // ]);
|
||||
// frameList.forEach(frame=>{
|
||||
// const element = that.elementList.find(ele=>{ return ele.name == frame.name; });
|
||||
// if (element) {
|
||||
// const elementStyle = element.stateList.find(state=>{ return state.status == frame.status; });
|
||||
// if (elementStyle) {
|
||||
// const model = utils.deepClone(element);
|
||||
|
||||
// // this.$iscs.update([
|
||||
// // { status: 's1', code: '100', type: 'Device' },
|
||||
// // { status: 's2', code: '101', type: 'Device' }
|
||||
// // ]);
|
||||
|
||||
// // model.frameList = [];
|
||||
// // const style = elementStyle.style || {};
|
||||
// // // model.changeStyle =
|
||||
// // if (style && JSON.stringify(style) != '{}') {
|
||||
// // const keys = Object.keys(style);
|
||||
// // keys.forEach(eachKey=>{
|
||||
// // model.style[eachKey] = style[eachKey];
|
||||
// // });
|
||||
// // }
|
||||
// // const shape = elementStyle.shape || {};
|
||||
// // if (shape && JSON.stringify(shape) != '{}') {
|
||||
// // const keys = Object.keys(shape);
|
||||
// // keys.forEach(eachShape=>{
|
||||
// // model.shape[eachShape] = style[eachShape];
|
||||
// // });
|
||||
// // }
|
||||
// // { status: 's1', code: '100', type: 'Device' },
|
||||
// // this.$refs.iscsCanvas.doAction([{model, action: {shapeType: shapeType.Element, order: orders.Update}}]);
|
||||
// this.$refs.iscsCanvas.doAction([{model, action: {shapeType: shapeType.Element, order: orders.ChangeStatus}}]);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
},
|
||||
resetDefaultStatus() {
|
||||
this.elementList.forEach(element=>{
|
||||
const model = utils.deepClone(element);
|
||||
this.$refs.iscsCanvas.doAction([{model, action: {shapeType: shapeType.Element, order: orders.Update}}]);
|
||||
// this.$refs.iscsCanvas.doAction([{model, action: {shapeType: shapeType.Element, order: orders.ResetStatus}}]);
|
||||
});
|
||||
},
|
||||
// getComposeElemList() {
|
||||
// const source = this.$iscs.getSource();
|
||||
// if (source &&
|
||||
// source.elementList &&
|
||||
// source.elementList.length) {
|
||||
// this.composeElemList = source.elementList;
|
||||
// this.statusTab = this.composeElemList[0].code;
|
||||
// } else {
|
||||
// this.composeElemList = [];
|
||||
// }
|
||||
// },
|
||||
onSelected(em) {
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mapPaint{
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
width:100%;
|
||||
position:absolute;
|
||||
left:0;top:0;
|
||||
}
|
||||
.right-card{
|
||||
width: 500px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top:0;
|
||||
transition: all 0.5s;
|
||||
background: #fff;
|
||||
z-index: 9;
|
||||
}
|
||||
.heightClass{height:100%;overflow:hidden;display:flex;width: 100%;flex-direction: column;}
|
||||
.eachStatus{
|
||||
padding: 15px 30px;
|
||||
border-bottom: 1px #ccc solid;
|
||||
line-height: 150%;
|
||||
}
|
||||
.statelist{
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.heightClass .el-card__body{
|
||||
flex:1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
185
src/views/iscs_new/iscsPreview/iscsCanvas.vue
Normal file
185
src/views/iscs_new/iscsPreview/iscsCanvas.vue
Normal file
@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :id="iscsId" v-loading="loading" :style="{ width: width +'px', height: height +'px',background:'#425a74' }" class="iscs-canvas" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import Iscs from '@/iscs_new/map';
|
||||
import Idb from '../utils/indexedDb.js';
|
||||
import ShapeBuilder from '@/iscs_new/plugins/shapeBuilder';
|
||||
import ShapeProperty from '@/iscs_new/plugins/shapeProperty';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
import ShapeContextMenu from '@/iscs_new/plugins/shapeContextMenu';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
dataZoom: {
|
||||
offsetX: '0',
|
||||
offsetY: '0',
|
||||
scaleRate: '1'
|
||||
},
|
||||
config: {
|
||||
scaleRate: '1',
|
||||
origin: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
},
|
||||
loading: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('iscs', [
|
||||
'iscs'
|
||||
]),
|
||||
iscsId() {
|
||||
return ['iscs', (Math.random().toFixed(5)) * 100000].join('_');
|
||||
},
|
||||
width() {
|
||||
return document.documentElement.clientWidth;
|
||||
},
|
||||
height() {
|
||||
return document.documentElement.clientHeight;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$store.state.config.canvasSizeCount': function (val) {
|
||||
this.resize();
|
||||
},
|
||||
'$store.state.socket.equipmentStatus': function (val) {
|
||||
if (val.length) {
|
||||
this.stateMessage(val);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.destroy();
|
||||
},
|
||||
methods: {
|
||||
// 初始化窗口
|
||||
init() {
|
||||
document.getElementById(this.iscsId).oncontextmenu = function (e) {
|
||||
return false;
|
||||
};
|
||||
|
||||
this.$iscs = new Iscs({
|
||||
dom: document.getElementById(this.iscsId),
|
||||
draw: true,
|
||||
config: {
|
||||
renderer: 'canvas',
|
||||
width: this.width,
|
||||
height: this.height
|
||||
},
|
||||
options: {
|
||||
scaleRate: 1,
|
||||
offsetX: 0,
|
||||
offsetY: 0
|
||||
},
|
||||
plugins: [
|
||||
// ShapeBuilder,
|
||||
// ShapeProperty,
|
||||
// ShapeContextMenu
|
||||
]
|
||||
});
|
||||
|
||||
const option = {
|
||||
panEnable: true,
|
||||
zoomEnable: true,
|
||||
keyEnable: true,
|
||||
draggle: false,
|
||||
selecting: false,
|
||||
selectable: false,
|
||||
reflect: true
|
||||
};
|
||||
if (this.$route.query.id) {
|
||||
setTimeout(_ => {
|
||||
Idb.select('composeTemplateList', this.$route.query.id).then(resp => {
|
||||
this.$iscs.setMap([resp], {
|
||||
elementList: resp.shapeList || [],
|
||||
composeList: resp.composeList || []
|
||||
}, option);
|
||||
this.$emit('setData', resp);
|
||||
}).catch(error => {
|
||||
this.$iscs.setMap([], {
|
||||
elementList: [],
|
||||
composeList: []
|
||||
}, option);
|
||||
});
|
||||
}, 1000);
|
||||
} else {
|
||||
this.$iscs.setMap([], {
|
||||
elementList: [],
|
||||
composeList: []
|
||||
}, option);
|
||||
}
|
||||
|
||||
Vue.prototype.$iscs = this.$iscs;
|
||||
this.$iscs.on('viewLoaded', this.onViewLoaded, this);
|
||||
this.$iscs.on('contextmenu', this.onContextMenu, this);
|
||||
// this.$iscs.on('click', this.onClick, this);
|
||||
this.$iscs.on('reflect', this.onReflect, this);
|
||||
this.$iscs.on('keyboard', this.onKeyboard, this);
|
||||
window.document.oncontextmenu = function () {
|
||||
return false;
|
||||
};
|
||||
},
|
||||
// 视图加载完成
|
||||
onViewLoaded(e) {
|
||||
},
|
||||
// 键盘快捷键事件
|
||||
onKeyboard(hook) {
|
||||
console.log(hook);
|
||||
},
|
||||
// 点击选择事件
|
||||
onClick(em = {}) {
|
||||
this.$emit('selected', em);
|
||||
},
|
||||
onReflect(em = {}) {
|
||||
this.$emit('selected', this.$iscs.getShapeByCode(em.code));
|
||||
},
|
||||
// 右键点击事件
|
||||
onContextMenu(em = {}) {
|
||||
this.$emit('contextMenu', em.model);
|
||||
},
|
||||
// 执行操作
|
||||
doAction(list) {
|
||||
this.$iscs && this.$iscs.render(list);
|
||||
},
|
||||
// 消息处理
|
||||
stateMessage(val) {
|
||||
this.$iscs && this.$iscs.setDeviceStatus(val);
|
||||
},
|
||||
// 充值窗口大小
|
||||
resize() {
|
||||
this.$nextTick(() => {
|
||||
this.$iscs && this.$iscs.resize({ width: this.width, height: this.height });
|
||||
});
|
||||
},
|
||||
// 销毁
|
||||
destroy() {
|
||||
if (this.$iscs) {
|
||||
this.$iscs.destroy();
|
||||
this.$iscs = null;
|
||||
Vue.prototype.$iscs = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.iscs-button{
|
||||
position: absolute;
|
||||
float: right;
|
||||
right: 20px;
|
||||
bottom: 15px;
|
||||
}
|
||||
.iscs-canvas{
|
||||
}
|
||||
</style>
|
140
src/views/iscs_new/utils/indexedDb.js
Normal file
140
src/views/iscs_new/utils/indexedDb.js
Normal file
@ -0,0 +1,140 @@
|
||||
|
||||
import { getBaseUrl } from '@/utils/baseUrl'
|
||||
|
||||
let db = null;
|
||||
class IndexedDb {
|
||||
constructor(nameList) {
|
||||
this.open(nameList);
|
||||
}
|
||||
|
||||
open(nameList) {
|
||||
const baseUrl = getBaseUrl();
|
||||
const indexedDBName = baseUrl.replace(/http.?:\/\/(.*)[\/|:].*/, "$1");
|
||||
const request = window.indexedDB.open(indexedDBName, 1);
|
||||
request.onerror = function (e) {
|
||||
console.log('数据库打开报错');
|
||||
};
|
||||
|
||||
request.onsuccess = function (e) {
|
||||
db = request.result;
|
||||
console.log('数据库打开成功');
|
||||
};
|
||||
|
||||
request.onupgradeneeded = function (e) {
|
||||
db = e.target.result;
|
||||
nameList.forEach(name => {
|
||||
db.createObjectStore(name, { keyPath: 'id' });
|
||||
console.log(name);
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
write(tableName, data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (db) {
|
||||
const request = db.transaction([tableName], 'readwrite').objectStore(tableName).add(data);
|
||||
request.onsuccess = function(e) {
|
||||
console.log('数据写入成功');
|
||||
resolve(request.result);
|
||||
};
|
||||
request.onerror = function(e) {
|
||||
console.log('数据写入失败');
|
||||
reject(e);
|
||||
};
|
||||
} else {
|
||||
this.open();
|
||||
reject({message: '数据库未打开!'});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
delete(tableName, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (db) {
|
||||
const request = db.transaction([tableName], 'readwrite').objectStore(tableName).delete(key);
|
||||
request.onsuccess = function(event) {
|
||||
console.log('数据删除成功');
|
||||
resolve(request.result);
|
||||
};
|
||||
request.onerror = function(event) {
|
||||
console.log('数据删除失败');
|
||||
reject(event);
|
||||
};
|
||||
} else {
|
||||
this.open();
|
||||
reject({message: '数据库未打开!'});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
modify(tableName, data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (db) {
|
||||
const request = db.transaction([tableName], 'readwrite').objectStore(tableName).put(data);
|
||||
request.onsuccess = function(e) {
|
||||
console.log('数据修改成功');
|
||||
resolve(request.result);
|
||||
};
|
||||
request.onerror = function(e) {
|
||||
console.log('数据修改失败');
|
||||
reject(e);
|
||||
};
|
||||
} else {
|
||||
this.open();
|
||||
reject({message: '数据库未打开!'});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
select(tableName, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (db) {
|
||||
const request = db.transaction([tableName]).objectStore(tableName).get(key);
|
||||
request.onsuccess = function(e) {
|
||||
console.log('数据查询成功');
|
||||
resolve(request.result);
|
||||
};
|
||||
request.onerror = function(e) {
|
||||
console.log('数据查询失败');
|
||||
reject(e);
|
||||
};
|
||||
} else {
|
||||
this.open();
|
||||
reject({message: '数据库未打开!'});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
list(tableName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (db) {
|
||||
const store = db.transaction([tableName]).objectStore(tableName);
|
||||
|
||||
var request = store.openCursor();
|
||||
var list = [];
|
||||
request.onsuccess = function(e) {
|
||||
var c = e.target.result;
|
||||
if (c) {
|
||||
list.push(c.value);
|
||||
c.continue();
|
||||
} else {
|
||||
resolve(list);
|
||||
}
|
||||
};
|
||||
request.onerror = function(e) {
|
||||
console.log('数据读取失败');
|
||||
reject(e);
|
||||
};
|
||||
} else {
|
||||
this.open();
|
||||
reject({message: '数据库未打开!'});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
}
|
||||
}
|
||||
|
||||
export default new IndexedDb(['composeList']);
|
||||
|
284
src/views/newMap/displayCity/demon/addFault.vue
Normal file
284
src/views/newMap/displayCity/demon/addFault.vue
Normal file
@ -0,0 +1,284 @@
|
||||
<template>
|
||||
<div class="addRules">
|
||||
<div class="addRulesInner">
|
||||
<div class="addRulesInnerTitle">新增故障</div>
|
||||
<div class="closeAddRulesInner" @click="addRulesClose">
|
||||
<span class="el-icon-close closeAddRulesIn" />
|
||||
</div>
|
||||
<el-form ref="form" :model="faultRule" label-width="100px" style="margin-left:15px;">
|
||||
<el-form-item label="目标设备">
|
||||
<!-- faultRule.targetDeviceCode -->
|
||||
<el-input v-model="targetDevice.name" disabled size="small" class="inputModelClass" />
|
||||
<!--<el-button :type="field === 'targetActive' ? 'danger' : 'primary'" size="small" @click="hover('targetActive')">{{ $t('map.activate') }}</el-button>-->
|
||||
</el-form-item>
|
||||
<el-form-item label="触发方式">
|
||||
<el-select v-model="triggerMode" @change="changeTriggerMode">
|
||||
<el-option
|
||||
v-for="item in triggerModeList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="故障类型">
|
||||
<el-select v-model="faultRule.faultType" placeholder="请选择" class="inputModelClass">
|
||||
<el-option
|
||||
v-for="item in faultTypeList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="triggerMode === 'DEVICE'" label="触发设备">
|
||||
<!-- faultRule.condition.triggerDeviceCode -->
|
||||
<el-input v-model="triggerDevice" size="small" disabled class="inputModelClass" />
|
||||
<el-button :type="field === 'triggerActive' ? 'danger' : 'primary'" size="small" @click="hover('triggerActive')">{{ $t('map.activate') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="triggerMode === 'DEVICE'" label="触发状态">
|
||||
<!-- <el-input v-model="faultRule.condition.triggerDeviceStatus" size="small" class="inputModelClass" /> -->
|
||||
<el-select v-model="faultRule.condition.triggerDeviceStatus" placeholder="请选择" class="inputModelClass">
|
||||
<el-option
|
||||
v-for="item in triggerStatusList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="triggerMode === 'DEVICE'" label="关联设备">
|
||||
<el-input v-model="triggerAssociatedDevice" size="small" disabled class="inputModelClass" />
|
||||
<el-button :type="field === 'triggerAssociated'? 'danger': 'primary'" size="small" @click="hover('triggerAssociated')">{{ $t('map.activate') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="triggerMode === 'TIME'" label="触发时间">
|
||||
<el-date-picker
|
||||
v-model="faultRule.condition.triggeringTime"
|
||||
type="datetime"
|
||||
placeholder="选择日期时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span class="addRulesFooter">
|
||||
<el-button size="medium" type="primary" @click="addRulesCreate">{{ $t('global.confirm') }}</el-button>
|
||||
<el-button size="medium" @click="addRulesClose">{{ $t('global.cancel') }}</el-button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { FaultStatusEnum } from '@/scripts/FaultDicNew';
|
||||
import { setFailureModeNew} from '@/api/simulation';
|
||||
import { deviceFaultType} from '@/scripts/cmdPlugin/Config';
|
||||
// 添加故障
|
||||
export default {
|
||||
name: 'AddChoose',
|
||||
props: {
|
||||
targetDevice: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
field:'',
|
||||
triggerStatusList:[],
|
||||
faultTypeList:[],
|
||||
faultRule:{
|
||||
targetDeviceCode:'',
|
||||
targetDeviceType:'',
|
||||
faultType:'',
|
||||
condition:{
|
||||
triggerDeviceCode:'',
|
||||
triggerDeviceStatus:'',
|
||||
triggerDeviceType :'',
|
||||
type:'DEVICE',
|
||||
triggeringTime: '',
|
||||
triggerAssociatedDeviceCode: ''
|
||||
}
|
||||
},
|
||||
// targetDevice:'',
|
||||
triggerDevice:'',
|
||||
triggerAssociatedDevice: '',
|
||||
triggerMode: 'DEVICE',
|
||||
triggerModeList: [
|
||||
{label: '设备触发', value: 'DEVICE'},
|
||||
{label: '时间触发', value: 'TIME'}
|
||||
]
|
||||
// rules:{
|
||||
// targetDevice:[
|
||||
// { required: true, message:'请选择目标设备', trigger: 'blur' }
|
||||
// ],
|
||||
// triggerDevice:[
|
||||
// { required: true, message:'请选择触发设备', trigger: 'blur' }
|
||||
// ],
|
||||
// faultRule:{
|
||||
// faultType:[
|
||||
// { required: true, message:'请选择故障类型', trigger: 'blur' },
|
||||
// { required: true, message:'请选择故障类型', trigger: 'change' }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
'$store.state.menuOperation.selectedCount':function(em) {
|
||||
const device = this.$store.state.menuOperation.selected;
|
||||
if (device.code) {
|
||||
this.deviceSelect(device);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods:{
|
||||
deviceSelect(em) {
|
||||
if (this.field.toUpperCase() === 'triggerAssociated'.toUpperCase()) {
|
||||
// if (em._type == 'Station') {
|
||||
// em = this.$store.getters['map/getDeviceByCode'](em.zcCode);
|
||||
// }
|
||||
// this.faultRule.targetDeviceType = this.covertType(em._type);
|
||||
// this.faultRule.targetDeviceCode = em.code;
|
||||
if (em._type.toUpperCase() === 'Section'.toUpperCase() && em.parentName) {
|
||||
this.triggerAssociatedDevice = em._type + '-' + em.parentName + '-' + em.name;
|
||||
} else {
|
||||
this.triggerAssociatedDevice = em._type + '-' + em.name;
|
||||
}
|
||||
this.faultRule.condition.triggerAssociatedDeviceCode = em.code;
|
||||
} else if (this.field.toUpperCase() === 'triggerActive'.toUpperCase()) {
|
||||
this.faultRule.condition.triggerDeviceType = this.covertType(em._type);
|
||||
this.faultRule.condition.triggerDeviceCode = em.code;
|
||||
if (em._type.toUpperCase() === 'Section'.toUpperCase() && em.parentName) {
|
||||
this.triggerDevice = em._type + '-' + em.parentName + '-' + em.name;
|
||||
} else if (em._type.toUpperCase() === 'Train'.toUpperCase()) {
|
||||
this.triggerDevice = em._type + '-' + em.code;
|
||||
} else {
|
||||
this.triggerDevice = em._type + '-' + em.name;
|
||||
}
|
||||
this.triggerStatusList = [];
|
||||
const faultStatus = FaultStatusEnum[this.faultRule.condition.triggerDeviceType];
|
||||
if (faultStatus) {
|
||||
const list = Object.keys(faultStatus);
|
||||
list.forEach(key=>{
|
||||
this.triggerStatusList.push({label:faultStatus[key], value:key});
|
||||
});
|
||||
}
|
||||
this.field = '';
|
||||
this.faultRule.condition.triggerDeviceStatus = '';
|
||||
}
|
||||
},
|
||||
covertType(type) {
|
||||
switch (type) {
|
||||
case 'Section':return 'SECTION';
|
||||
case 'Signal':return 'SIGNAL';
|
||||
case 'Switch':return 'SWITCH';
|
||||
case 'Station':return 'STATION';
|
||||
case 'ZcControl':return 'ZC';
|
||||
case 'StationStand':return 'STAND';
|
||||
case 'Train':return 'TRAIN';
|
||||
}
|
||||
},
|
||||
hover(field) {
|
||||
if (this.field == '') {
|
||||
this.field = field;
|
||||
} else {
|
||||
this.field = '';
|
||||
}
|
||||
},
|
||||
addRulesCreate() {
|
||||
if (this.triggerDevice == '') {
|
||||
this.$messageBox('请选择触发设备');
|
||||
return;
|
||||
}
|
||||
if (this.faultRule.condition.triggerDeviceStatus == '') {
|
||||
this.$messageBox('请选择触发状态');
|
||||
return;
|
||||
}
|
||||
if (this.faultRule.faultType == '') {
|
||||
this.$messageBox('请选择故障类型');
|
||||
return;
|
||||
}
|
||||
console.log(this.faultRule, '-------------');
|
||||
setFailureModeNew(this.faultRule, this.$route.query.group).then(res=>{
|
||||
this.$emit('closeAddRules');
|
||||
this.$emit('reload');
|
||||
}).catch((error)=>{
|
||||
this.$messageBox('创建故障失败: ' + error.message);
|
||||
});
|
||||
},
|
||||
addRulesClose() {
|
||||
this.resetForm();
|
||||
this.$emit('closeAddRules');
|
||||
},
|
||||
|
||||
initValue() {
|
||||
this.faultTypeList = deviceFaultType[this.targetDevice._type];
|
||||
this.faultRule.targetDeviceCode = this.targetDevice.code;
|
||||
this.faultRule.targetDeviceType = this.covertType(this.targetDevice._type);
|
||||
},
|
||||
resetForm() {
|
||||
this.triggerDevice = '';
|
||||
this.faultRule = {
|
||||
targetDeviceCode:'',
|
||||
targetDeviceType:'',
|
||||
faultType:'',
|
||||
condition:{
|
||||
triggerDeviceCode:'',
|
||||
triggerDeviceStatus:'',
|
||||
triggerDeviceType :'',
|
||||
type:'DEVICE',
|
||||
triggeringTime: '',
|
||||
triggerAssociatedDeviceCode: ''
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.addRules{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 40px;
|
||||
}
|
||||
.addRulesInner{
|
||||
position: relative;
|
||||
width: 380px;
|
||||
margin-top:6px;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
border: 1px #ccc solid;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
box-shadow: 3px 3px 3px #a0a0a0;
|
||||
z-index:2;
|
||||
}
|
||||
.queryList{
|
||||
height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
.inputModelClass{
|
||||
width:150px;
|
||||
}
|
||||
.addRulesInnerTitle{
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.closeAddRulesInner{
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 9px;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.closeAddRulesIn{
|
||||
font-size: 19px;
|
||||
}
|
||||
.addRulesFooter{
|
||||
margin-left: 116px;
|
||||
display: inline-block;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
196
src/views/newMap/displayCity/demon/equipment.vue
Normal file
196
src/views/newMap/displayCity/demon/equipment.vue
Normal file
@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-drawer
|
||||
title="设备管理"
|
||||
:visible.sync="show"
|
||||
direction="ltr"
|
||||
:before-close="doClose"
|
||||
custom-class="dialog_box"
|
||||
size="43%"
|
||||
>
|
||||
<div style="margin-bottom: 3px; overflow: hidden; padding: 0 10px;">
|
||||
<div class="plc_box">名称: {{ plcInfo.name }}</div>
|
||||
<div class="plc_box">状态: <span :style="{'color': plcInfo.status ? 'green' : 'red'}">{{ plcInfo.status ? '在线' : '不在线' }}</span></div>
|
||||
<el-button type="text" size="small" class="freshen_box" @click="getList">刷新</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData" border style="width: 100%; max-height: calc(100% - 24px); overflow: auto;">
|
||||
<el-table-column prop="code" label="设备编号" width="180" />
|
||||
<el-table-column prop="typeName" label="设备类型" width="180" />
|
||||
<el-table-column prop="vrDeviceCode" label="连接设备编码">
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.vrDeviceCode" class="flex_box">{{ scope.row.vrDeviceName }}</div>
|
||||
<div v-if="!scope.row.vrDeviceCode" class="flex_box">(空)</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button :type="scope.row.buttonShowType ? 'danger' : 'primary'" size="small" @click="handleClick(scope.row, scope.$index)">连接</el-button>
|
||||
<el-button size="small" @click="cancel(scope.row, scope.$index)">断开</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getAllSimulationList, postSimulationConnectById, putSimulationDisconnectById } from '@/api/simulation.js';
|
||||
import ConstConfig from '@/scripts/ConstConfig';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
import { getSessionStorage } from '@/utils/auth';
|
||||
|
||||
export default {
|
||||
name: 'Equipment',
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
group: '',
|
||||
tableData: [],
|
||||
typeList: ConstConfig.ConstSelect.projectDeviceTypeList,
|
||||
plcInfo: {
|
||||
name: '',
|
||||
status: ''
|
||||
},
|
||||
index: 0,
|
||||
selected: {},
|
||||
typeObj: {
|
||||
Section: '区段',
|
||||
Signal: '信号机',
|
||||
Switch: '道岔',
|
||||
Psd: '屏蔽门',
|
||||
StationStand: '站台'
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
project() {
|
||||
return getSessionStorage('project');
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
EventBus.$on('selectDevice', (data) => {
|
||||
this.selected = data;
|
||||
this.tableData[this.index]['buttonShowType'] = false;
|
||||
this.tableData.splice(this.index, 1, this.tableData[this.index]);
|
||||
this.$store.dispatch('map/selectDeviceCode', {flag: false, type: ''});
|
||||
this.connect(this.tableData[this.index]);
|
||||
});
|
||||
},
|
||||
async beforeDestroy() {
|
||||
EventBus.$off('selectDevice');
|
||||
},
|
||||
methods: {
|
||||
async doShow() {
|
||||
this.show = true;
|
||||
this.group = this.$route.query.group;
|
||||
this.getList();
|
||||
},
|
||||
async getList() {
|
||||
try {
|
||||
const res = await getAllSimulationList(this.group);
|
||||
this.tableData = [];
|
||||
res.data.forEach((item, index) => {
|
||||
if (item.type == 'PLC_GATEWAY') {
|
||||
this.plcInfo = {
|
||||
name: 'PLC网关',
|
||||
status: item.online
|
||||
};
|
||||
} else {
|
||||
item.buttonShowType = false;
|
||||
item.typeName = this.typeList.find(el => el.value == item.type).label;
|
||||
if (item.vrDeviceCode) {
|
||||
item.vrDeviceName = this.$store.getters['map/getDeviceByCode'](item.vrDeviceCode).name;
|
||||
}
|
||||
if (this.project == 'heb' || this.project == 'designheb') {
|
||||
if (item.type == 'SWITCH') {
|
||||
this.tableData.push(item);
|
||||
}
|
||||
} else {
|
||||
this.tableData.push(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
doClose() {
|
||||
this.show = false;
|
||||
},
|
||||
handleClick(row, index) {
|
||||
row.buttonShowType = !row.buttonShowType;
|
||||
this.index = index;
|
||||
this.tableData.splice(index, 1, row);
|
||||
this.$store.dispatch('map/selectDeviceCode', {flag: row.buttonShowType, type: row.type});
|
||||
},
|
||||
async connect(row) {
|
||||
this.$confirm(`您确定连接${this.typeObj[this.selected._type] || '设备'}: ${this.selected.name}, 是否继续?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
try {
|
||||
const res = await postSimulationConnectById(this.group, row.id, this.selected.code);
|
||||
if (res && res.code == 200) {
|
||||
this.$message.success('连接成功!');
|
||||
this.tableData[this.index]['vrDeviceCode'] = this.selected.code;
|
||||
this.tableData[this.index]['vrDeviceName'] = this.selected.name;
|
||||
this.tableData.splice(this.index, 1, this.tableData[this.index]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
},
|
||||
async cancel(row, index) {
|
||||
this.$confirm('您确定将次设备断开, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
if (row.vrDeviceCode) {
|
||||
row.vrDeviceCode = '';
|
||||
row.vrDeviceName = '';
|
||||
this.tableData.splice(index, 1, row);
|
||||
try {
|
||||
const res = await putSimulationDisconnectById(this.group, row.id);
|
||||
if (res && res.code == 200) {
|
||||
this.$message.success('断开成功!');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.plc_box{
|
||||
float: left;
|
||||
margin-right: 40px;
|
||||
padding: 9px;
|
||||
}
|
||||
.freshen_box{
|
||||
float: right;
|
||||
}
|
||||
.flex_box{
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
line-height: 30px;
|
||||
}
|
||||
/deep/ {
|
||||
.el-dialog__wrapper{
|
||||
width: 800px;
|
||||
}
|
||||
.dialog_box{
|
||||
height: 100%;
|
||||
}
|
||||
.el-dialog__body{
|
||||
padding-top: 6px;
|
||||
height: calc(100% - 54px);
|
||||
}
|
||||
}
|
||||
</style>
|
600
src/views/newMap/displayCity/demon/faultChoose.vue
Normal file
600
src/views/newMap/displayCity/demon/faultChoose.vue
Normal file
@ -0,0 +1,600 @@
|
||||
<template>
|
||||
<div v-if="dialogShow" id="faultChoose">
|
||||
<div class="falutChooseTitle">{{ title }}</div>
|
||||
<div class="closeFalutChoose" @click="closeFaultChoose">
|
||||
<span class="el-icon-close closeFalutChooseIn" />
|
||||
</div>
|
||||
<el-card class="triggerFaultInfo">
|
||||
<el-button type="primary" size="small" style="margin-bottom:10px;" @click="isTableShow=!isTableShow">{{ isTableShow?'隐藏列表':'显示列表' }}</el-button>
|
||||
<el-table v-if="isTableShow" :data="faultList" height="300" border style="width: 100%;font-size:13px;">
|
||||
<el-table-column prop="targetDeviceCode" label="目标设备" width="220">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ `${deviceMap[scope.row.targetDeviceType]}${formatNameByCode(scope.row.targetDeviceCode)}` }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="faultType" label="故障类型">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ covertFaultType(scope.row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="condition" label="列车" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ `${deviceMap[scope.row.condition.triggerDeviceType] || ''}${formatNameByCode(scope.row.condition.triggerDeviceCode)}` }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="condition" label="到达区段" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ `${formatNameByCode(scope.row.condition.triggerAssociatedDeviceCode)}` }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="condition.condition.triggerTime" label="触发时间" width="150" />
|
||||
<el-table-column prop="triggeringTime" label="故障状态">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.triggeringTime? '已触发': '未触发' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="!scope.row.triggeringTime" type="text" size="small" @click="handleDelete(scope.row)">取消</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
<div class="targetCard">
|
||||
<div class="targetCardHead">
|
||||
<el-button style="padding:3px 0" type="text" @click="addRulesCreate">新增</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-form ref="form" :model="faultRule" :inline="true" label-width="100px" style="margin-left:15px;">
|
||||
<el-form-item label="目标设备" class="targetFormItem">
|
||||
<el-input v-model="targetDeviceName" disabled size="small" class="inputModelClass" style="width: 300px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="故障类型" class="targetFormItem">
|
||||
<el-select v-model="faultRule.faultType" placeholder="请选择" class="inputModelClass" size="small" style="width: 300px;">
|
||||
<el-option
|
||||
v-for="item in faultTypeList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="triggerMode === 'DEVICE'" label="列车" class="targetFormItem">
|
||||
<el-input v-model="triggerDevice" size="small" disabled class="inputModelClass" style="width: 240px;" />
|
||||
<el-button :type="field === 'triggerActive' ? 'danger' : 'primary'" size="small" @click="hover('triggerActive')">{{ $t('map.activate') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="triggerMode === 'DEVICE'" label="到达区段" class="targetFormItem">
|
||||
<el-input v-model="triggerAssociatedDevice" size="small" disabled class="inputModelClass" style="width: 240px;" />
|
||||
<el-button :type="field === 'triggerAssociated'? 'danger': 'primary'" size="small" @click="hover('triggerAssociated')">{{ $t('map.activate') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="triggerMode === 'TIME'" label="触发时间" class="targetFormItem">
|
||||
<el-date-picker
|
||||
v-model="faultRule.condition.triggerTime"
|
||||
size="small"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="datetime"
|
||||
placeholder="选择日期时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSimulationFaultRules, setFailureModeNew, deleteFailureRule, cancelFailureModeNew } from '@/api/simulation';
|
||||
import ConstConfig from '@/scripts/ConstConfig';
|
||||
import { FaultStatusEnum } from '@/scripts/FaultDicNew';
|
||||
import ModelType from '@/jmapNew/constant/deviceType';
|
||||
import { deviceFaultType } from '@/scripts/cmdPlugin/Config';
|
||||
|
||||
// 故障列表
|
||||
export default {
|
||||
name: 'FaultChoose',
|
||||
props: {
|
||||
group: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
offset: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogShow: false,
|
||||
loading: false,
|
||||
isAdd:false,
|
||||
isTableShow:true,
|
||||
deviceMap: {},
|
||||
simulationFault:{},
|
||||
faultList: [],
|
||||
faultRule:{
|
||||
targetDeviceCode:'',
|
||||
targetDeviceType:'',
|
||||
faultType:'',
|
||||
condition:{
|
||||
triggerDeviceCode:'',
|
||||
triggerDeviceStatus:'',
|
||||
triggerDeviceType :'',
|
||||
type:'DEVICE',
|
||||
triggerTime: '',
|
||||
triggerAssociatedDeviceCode: ''
|
||||
}
|
||||
},
|
||||
triggerDevice:'',
|
||||
triggerAssociatedDevice: '',
|
||||
triggerMode: 'DEVICE',
|
||||
triggerModeList: [
|
||||
{label: '设备触发', value: 'DEVICE'},
|
||||
{label: '时间触发', value: 'TIME'}
|
||||
],
|
||||
field:'',
|
||||
triggerStatusList:[],
|
||||
faultTypeList:[],
|
||||
targetDeviceName: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return '自动故障设置';
|
||||
},
|
||||
lineCode() {
|
||||
return this.$route.query.lineCode;
|
||||
},
|
||||
targetDevice() {
|
||||
return this.$store.state.training.triggerFaultDevice;
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
'$store.state.socket.autoFaultTrigger':function(val) {
|
||||
this.dialogShow && this.getSimulationFaultRules();
|
||||
},
|
||||
'$store.state.menuOperation.selectedCount':function(em) {
|
||||
const device = this.$store.state.menuOperation.selected;
|
||||
if (device && device.code) {
|
||||
this.deviceSelect(device);
|
||||
}
|
||||
},
|
||||
targetDevice: function(device) {
|
||||
this.targetDeviceName = this.targetDevice.name || this.targetDevice.code;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.deviceMap = [];
|
||||
ConstConfig.ConstSelect.simulationDeviceList.forEach(elem => {
|
||||
this.deviceMap[elem.value] = elem.label;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
formatNameByCode(code) {
|
||||
let name = '';
|
||||
const device = this.$store.getters['map/getDeviceByCode'](code);
|
||||
if (device) {
|
||||
switch (device._type) {
|
||||
case ModelType.Signal:
|
||||
case ModelType.Switch:
|
||||
case ModelType.Station:
|
||||
case ModelType.Section: {
|
||||
if (device.parentName) {
|
||||
name += device.parentName + '-' + device.name;
|
||||
} else {
|
||||
name += device.name;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ModelType.Train:
|
||||
name = device.code;
|
||||
break;
|
||||
}
|
||||
if (device.stationCode) {
|
||||
const station = this.$store.getters['map/getDeviceByCode'](device.stationCode);
|
||||
if (station) {
|
||||
name += '【' + station.name + '】';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
},
|
||||
hover(field) {
|
||||
if (this.field == '') {
|
||||
this.field = field;
|
||||
} else {
|
||||
this.field = '';
|
||||
}
|
||||
},
|
||||
handleDelete(row) {
|
||||
cancelFailureModeNew(row.id, this.$route.query.group).then(resp => {
|
||||
this.getSimulationFaultRules();
|
||||
}).catch(() => {
|
||||
this.$message.error('取消故障失败!');
|
||||
});
|
||||
},
|
||||
covertType(type) {
|
||||
switch (type) {
|
||||
case 'SECTION':return 'Section';
|
||||
case 'SIGNAL':return 'Signal';
|
||||
case 'SWITCH':return 'Switch';
|
||||
case 'STATION':return 'Station';
|
||||
case 'ZC':return 'ZcControl';
|
||||
case 'STAND':return 'StationStand';
|
||||
case 'TRAIN':return 'Train';
|
||||
case 'Section':return 'SECTION';
|
||||
case 'Signal':return 'SIGNAL';
|
||||
case 'Switch':return 'SWITCH';
|
||||
case 'Station':return 'STATION';
|
||||
case 'ZcControl':return 'ZC';
|
||||
case 'StationStand':return 'STAND';
|
||||
case 'Train':return 'TRAIN';
|
||||
}
|
||||
},
|
||||
covertFaultType(row) {
|
||||
let faultType = '';
|
||||
if (row && row.id) {
|
||||
let type = this.covertType(row.targetDeviceType);
|
||||
if (type == 'Station') {
|
||||
type = 'ZcControl';
|
||||
}
|
||||
const currentList = deviceFaultType[type];
|
||||
currentList.forEach(temp=>{
|
||||
if (temp.value === row.faultType) {
|
||||
faultType = temp.label;
|
||||
}
|
||||
});
|
||||
}
|
||||
return faultType;
|
||||
},
|
||||
closeFaultChoose() {
|
||||
this.dialogShow = false;
|
||||
this.isAdd = false;
|
||||
if (this.$refs.addFault) {
|
||||
this.$refs.addFault.resetForm();
|
||||
}
|
||||
},
|
||||
closeAddRules() {
|
||||
this.isAdd = false;
|
||||
},
|
||||
getSimulationFaultRules() {
|
||||
if (this.dialogShow) {
|
||||
getSimulationFaultRules(this.$route.query.group).then(resp => {
|
||||
this.faultList = resp.data;
|
||||
}).catch(() => {
|
||||
this.$messageBox('获取数据异常');
|
||||
});
|
||||
}
|
||||
},
|
||||
changeTriggerMode(val) {
|
||||
this.resetForm();
|
||||
this.triggerMode = val;
|
||||
this.faultRule.condition.type = val;
|
||||
},
|
||||
doShow() {
|
||||
this.dialogShow = true;
|
||||
this.getSimulationFaultRules();
|
||||
this.resetForm();
|
||||
this.faultTypeList = deviceFaultType[this.targetDevice._type];
|
||||
this.faultRule.targetDeviceCode = this.targetDevice.code;
|
||||
this.faultRule.targetDeviceType = this.covertType(this.targetDevice._type);
|
||||
this.faultRule.faultType = (this.faultTypeList[0] || {}).value;
|
||||
this.$nextTick(()=>{
|
||||
this.dragEvent();
|
||||
});
|
||||
},
|
||||
resetForm() {
|
||||
this.getSimulationFaultRules();
|
||||
this.field = '';
|
||||
this.triggerDevice = '';
|
||||
this.triggerAssociatedDevice = '';
|
||||
this.faultRule = {
|
||||
targetDeviceCode:this.targetDevice.code,
|
||||
targetDeviceType:this.covertType(this.targetDevice._type),
|
||||
faultType:'',
|
||||
condition:{
|
||||
triggerDeviceCode:'',
|
||||
triggerDeviceStatus:'',
|
||||
triggerDeviceType :'',
|
||||
type:'DEVICE',
|
||||
triggerTime: '',
|
||||
triggerAssociatedDeviceCode: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
doClose() {
|
||||
this.dialogShow = false;
|
||||
},
|
||||
handleAdd() {
|
||||
this.isAdd = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.addFault.initValue();
|
||||
});
|
||||
},
|
||||
deleteFailure(index, row) {
|
||||
event.cancelBubble = true;
|
||||
this.$confirm('删除故障规则,是否继续?', '提 示', {
|
||||
confirmButtonText: '确 定',
|
||||
cancelButtonText: '取 消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
deleteFailureRule(row.id).then(resp => {
|
||||
}).catch(error => {
|
||||
this.$message.error(`删除故障规则失败: ${error.message}`);
|
||||
});
|
||||
}).catch( () => { });
|
||||
},
|
||||
settingFailure(index, row, idx) {
|
||||
const faultModel = {ruleId: row.id, auto:true};
|
||||
// row['loading' + idx] = true;
|
||||
setFailureModeNew(faultModel, this.group).then(() => {
|
||||
this.getSimulationFaultRules();
|
||||
this.$message.success('设置自动故障成功');
|
||||
}).catch(() => {
|
||||
this.$messageBox('设置自动故障失败');
|
||||
});
|
||||
},
|
||||
cancleAutoFault() {
|
||||
const faultModel = {auto:false};
|
||||
setFailureModeNew(faultModel, this.group).then(() => {
|
||||
this.getSimulationFaultRules();
|
||||
this.$message.success('取消自动故障成功');
|
||||
}).catch(() => {
|
||||
this.$messageBox('取消自动故障失败');
|
||||
});
|
||||
},
|
||||
addRulesCreate() {
|
||||
if (this.triggerMode === 'DEVICE' && this.triggerDevice == '') {
|
||||
this.$messageBox('请选择触发设备');
|
||||
return;
|
||||
}
|
||||
if (this.triggerMode === 'DEVICE' && this.faultRule.condition.triggerDeviceStatus == '') {
|
||||
this.$messageBox('请选择触发状态');
|
||||
return;
|
||||
}
|
||||
if (this.faultRule.faultType == '') {
|
||||
this.$messageBox('请选择故障类型');
|
||||
return;
|
||||
}
|
||||
if (this.triggerMode === 'TIME' && this.faultRule.condition.triggerTime == '') {
|
||||
this.$messageBox('请选择触发时间');
|
||||
return;
|
||||
}
|
||||
if (this.triggerMode === 'DEVICE' && this.faultRule.condition.triggerDeviceType === 'TRAIN' && this.faultRule.condition.triggerDeviceStatus === 'Section' && this.faultRule.condition.triggerAssociatedDeviceCode == '') {
|
||||
this.$messageBox('请选择关联设备');
|
||||
return;
|
||||
}
|
||||
const param = {
|
||||
targetDeviceCode:this.targetDevice.code,
|
||||
targetDeviceType:this.covertType(this.targetDevice._type),
|
||||
faultType: this.faultRule.faultType,
|
||||
condition:{
|
||||
triggerDeviceCode: this.faultRule.condition.triggerDeviceCode || null,
|
||||
triggerDeviceStatus:this.faultRule.condition.triggerDeviceStatus || null,
|
||||
triggerDeviceType :this.faultRule.condition.triggerDeviceType || null,
|
||||
type:this.faultRule.condition.type,
|
||||
triggerTime: this.faultRule.condition.triggerTime || null,
|
||||
triggerAssociatedDeviceCode: this.faultRule.condition.triggerAssociatedDeviceCode || null
|
||||
}
|
||||
};
|
||||
setFailureModeNew(param, this.$route.query.group).then(res=>{
|
||||
this.$message.success('创建故障成功!');
|
||||
this.resetForm();
|
||||
}).catch((error)=>{
|
||||
this.$messageBox('创建故障失败: ' + error.message);
|
||||
});
|
||||
},
|
||||
deviceSelect(em) {
|
||||
if (this.field.toUpperCase() === 'triggerAssociated'.toUpperCase() && em._type.toUpperCase() === 'Section'.toUpperCase()) {
|
||||
if (em._type.toUpperCase() === 'Section'.toUpperCase() && em.parentName) {
|
||||
this.triggerAssociatedDevice = em._type + '-' + em.parentName + '-' + em.name;
|
||||
} else {
|
||||
this.triggerAssociatedDevice = em._type + '-' + em.name;
|
||||
}
|
||||
this.faultRule.condition.triggerAssociatedDeviceCode = em.code;
|
||||
} else if (this.field.toUpperCase() === 'triggerActive'.toUpperCase() && em._type.toUpperCase() === 'Train'.toUpperCase()) {
|
||||
this.faultRule.condition.triggerDeviceType = this.covertType(em._type);
|
||||
this.faultRule.condition.triggerDeviceCode = em.code;
|
||||
if (em._type.toUpperCase() === 'Section'.toUpperCase() && em.parentName) {
|
||||
this.triggerDevice = em._type + '-' + em.parentName + '-' + em.name;
|
||||
} else if (em._type.toUpperCase() === 'Train'.toUpperCase()) {
|
||||
this.triggerDevice = em._type + '-' + em.code;
|
||||
} else {
|
||||
this.triggerDevice = em._type + '-' + em.name;
|
||||
}
|
||||
this.triggerStatusList = [];
|
||||
const faultStatus = FaultStatusEnum[this.faultRule.condition.triggerDeviceType];
|
||||
if (faultStatus) {
|
||||
const list = Object.keys(faultStatus);
|
||||
list.forEach(key=>{
|
||||
this.triggerStatusList.push({label:faultStatus[key], value:key});
|
||||
});
|
||||
}
|
||||
this.field = '';
|
||||
this.faultRule.condition.triggerDeviceStatus = (this.triggerStatusList[0] || {}).value;
|
||||
}
|
||||
},
|
||||
dragEvent() {
|
||||
const offset = this.offset;
|
||||
const dialogHeaderEl = document.querySelector('.falutChooseTitle');
|
||||
const dragDom = document.querySelector('#faultChoose');
|
||||
dialogHeaderEl.style.cursor = 'move';
|
||||
|
||||
/** 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);*/
|
||||
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
|
||||
|
||||
dialogHeaderEl.onmousedown = (e) => {
|
||||
/** 鼠标按下,计算当前元素距离可视区的距离*/
|
||||
const disX = e.clientX - dialogHeaderEl.offsetLeft;
|
||||
const disY = e.clientY - dialogHeaderEl.offsetTop;
|
||||
|
||||
/** 获取到的值带px 正则匹配替换*/
|
||||
let styL, styT;
|
||||
|
||||
/** 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px*/
|
||||
if (sty.left.includes('%')) {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
|
||||
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
|
||||
} else {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
styL = +sty.left.replace(/\px/g, '');
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
styT = +sty.top.replace(/\px/g, '');
|
||||
}
|
||||
|
||||
document.onmousemove = function (e) {
|
||||
/** 通过事件委托,计算移动的距离*/
|
||||
const l = e.clientX - disX;
|
||||
const t = e.clientY - disY;
|
||||
|
||||
/** 移动当前元素*/
|
||||
// dragDom.style.left = `${l + styL}px`;
|
||||
// dragDom.style.top = `${t + styT}px`;
|
||||
|
||||
/** 移动当前元素*/
|
||||
if (l + styL < 0) {
|
||||
dragDom.style.left = `0px`;
|
||||
} else if (l + styL > document.body.clientWidth - dragDom.clientWidth - 10) {
|
||||
dragDom.style.left = `${document.body.clientWidth - dragDom.clientWidth - 10}px`;
|
||||
} else {
|
||||
dragDom.style.left = `${l + styL}px`;
|
||||
}
|
||||
if (t + styT <= offset) {
|
||||
dragDom.style.top = offset + `px`;
|
||||
} else if (t + styT > document.body.clientHeight - dragDom.clientHeight - 10) {
|
||||
dragDom.style.top = `${document.body.clientHeight - dragDom.clientHeight - 10}px`;
|
||||
} else {
|
||||
dragDom.style.top = `${t + styT}px`;
|
||||
}
|
||||
|
||||
/** 将此时的位置传出去*/
|
||||
// binding.value({ x: e.pageX, y: e.pageY });
|
||||
};
|
||||
|
||||
document.onmouseup = function () {
|
||||
document.onmousemove = null;
|
||||
document.onmouseup = null;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
#faultChoose .card .queryList .el-card .el-card__body .el-table--border .el-table__body-wrapper{
|
||||
height: 135px !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
#faultChoose .el-button--mini {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.triggerFaultListLeft{
|
||||
display: inline-block;
|
||||
float: left;
|
||||
width: 730px;
|
||||
}
|
||||
// 谷歌、safari、qq浏览器、360浏览器滚动条样式
|
||||
// 定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸
|
||||
#faultChoose .el-table__body-wrapper::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
// height: 110px;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
/*定义滚动条轨道 内阴影+圆角*/
|
||||
#faultChoose .el-table__body-wrapper::-webkit-scrollbar-track {
|
||||
// box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
|
||||
border-radius: 10px;
|
||||
background-color: #FFFFFF;;
|
||||
}
|
||||
/*定义滑块 内阴影+圆角*/
|
||||
#faultChoose .el-table__body-wrapper::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
// box-shadow: inset 0 0 6px rgba(0,0,0,.3);
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
/*滑块效果*/
|
||||
#faultChoose .el-table__body-wrapper::-webkit-scrollbar-thumb:hover {
|
||||
border-radius: 5px;
|
||||
// box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
|
||||
background: rgba(0,0,0,0.4);
|
||||
}
|
||||
/*IE滚动条颜色*/
|
||||
html {
|
||||
scrollbar-face-color:#bfbfbf;/*滚动条颜色*/
|
||||
scrollbar-highlight-color:#000;
|
||||
scrollbar-3dlight-color:#000;
|
||||
scrollbar-darkshadow-color:#000;
|
||||
scrollbar-Shadow-color:#adadad;/*滑块边色*/
|
||||
scrollbar-arrow-color:rgba(0,0,0,0.4);/*箭头颜色*/
|
||||
scrollbar-track-color:#eeeeee;/*背景颜色*/
|
||||
}
|
||||
</style>
|
||||
<style scoped rel="stylesheet/scss" lang="scss">
|
||||
.triggerFaultInfo{
|
||||
margin-bottom:10px;
|
||||
padding: 10px 10px 10px 15px;
|
||||
}
|
||||
.triggerFaultList{
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.triggerFaultTitle{
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.falutChooseTitle{
|
||||
padding: 15px;
|
||||
cursor: all-scroll;
|
||||
}
|
||||
#faultChoose{
|
||||
width: 1000px;
|
||||
position: absolute;
|
||||
left: 30%;
|
||||
top: 20%;
|
||||
background: #fff;
|
||||
padding:0px 0px 15px 0px;
|
||||
// transform: translate3d(-50%,-50%,0);
|
||||
border-radius: 6px;
|
||||
z-index:999;
|
||||
}
|
||||
.faultChooseFoot{
|
||||
display: inline-block;
|
||||
float: right;
|
||||
margin-right: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.closeFalutChoose{
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.closeFalutChooseIn{
|
||||
font-size: 20px;
|
||||
margin-left: 5px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.targetCard{
|
||||
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
|
||||
border-top: 1px #ebeef5 solid;
|
||||
}
|
||||
.targetFormItem{
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.targetCardHead{
|
||||
padding: 5px;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px #f4f4f4 solid;
|
||||
text-align: right;
|
||||
padding-right: 15px;
|
||||
}
|
||||
</style>
|
118
src/views/newMap/displayCity/demon/setTime.vue
Normal file
118
src/views/newMap/displayCity/demon/setTime.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<el-dialog v-dialogDrag :title="title" :visible.sync="show" width="550px" :before-close="doClose">
|
||||
<el-form ref="form" label-width="120px" :model="formModel" :rules="rules">
|
||||
<el-form-item :label="$t('display.setTime.systemTime')" prop="initTime">
|
||||
<el-time-picker
|
||||
v-model="formModel.initTime"
|
||||
:picker-options="pickerOptions"
|
||||
:placeholder="$t('display.setTime.anyTime')"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="hasNumber" :label="$t('display.setTime.loadTrainNum')" prop="loadNum">
|
||||
<el-input-number v-model="formModel.loadNum" :min="1" :max="maxNumber" :label="$t('display.setTime.selectLoadTrainNum')" />
|
||||
<span> {{ ` (${$t('display.setTime.maxTrainNum')} :${maxNumber}) ` }} </span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="show = false">{{ $t('global.cancel') }}</el-button>
|
||||
<el-button type="primary" :loading="status" @click="handleSure">{{ $t('global.confirm') }}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { prefixIntrger } from '@/utils/date';
|
||||
import { getLoadTrainNumber } from '@/api/simulation';
|
||||
|
||||
// 计划行车时间选择
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
formModel: {
|
||||
initTime: new Date(),
|
||||
loadNum: 1
|
||||
},
|
||||
maxNumber: 1,
|
||||
pickerOptions: { selectableRange: '00:00:00 - 23:59:59' },
|
||||
status: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.$t('display.setTime.setSimulationSystemTime');
|
||||
},
|
||||
hasNumber() {
|
||||
return this.$route.params.mode == 'demon' && this.$route.query.prdType == '04';
|
||||
},
|
||||
group() {
|
||||
return this.$route.query.group;
|
||||
},
|
||||
rules() {
|
||||
return {
|
||||
initTime: [
|
||||
{ required: true, message: this.$t('display.setTime.selectSystemTime'), trigger: 'change' },
|
||||
{
|
||||
validator(rule, value, callback) {
|
||||
if (this.maxNumber == 0) {
|
||||
callback(new Error(this.$t('display.setTime.selectValidStartTime')));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'change',
|
||||
maxNumber: this.maxNumber
|
||||
}
|
||||
],
|
||||
loadNum: [
|
||||
{ required: true, message: this.$t('display.setTime.selectTrainNum'), trigger: 'change' }
|
||||
|
||||
]
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
doShow() {
|
||||
this.formModel.initTime = new Date(this.$store.state.training.initTime || null);
|
||||
this.handleChange(this.formModel.initTime);
|
||||
this.show = true;
|
||||
},
|
||||
doClose() {
|
||||
this.status = false;
|
||||
this.show = false;
|
||||
},
|
||||
handleChange(initTime) {
|
||||
this.formModel.loadNum = 0;
|
||||
if (this.hasNumber) {
|
||||
getLoadTrainNumber({ time: this.formatTime(initTime) }, this.group).then(resp => {
|
||||
this.maxNumber = parseInt(resp.data);
|
||||
});
|
||||
}
|
||||
},
|
||||
formatTime(initTime) {
|
||||
const hh = prefixIntrger(initTime.getHours(), 2);
|
||||
const mm = prefixIntrger(initTime.getMinutes(), 2);
|
||||
const ss = prefixIntrger(initTime.getSeconds(), 2);
|
||||
return `${hh}:${mm}:${ss}`;
|
||||
},
|
||||
handleSure() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.status = true;
|
||||
const model = {
|
||||
initTime: this.formatTime(this.formModel.initTime)
|
||||
};
|
||||
|
||||
if (this.hasNumber) {
|
||||
model['loadNum'] = this.formModel.loadNum;
|
||||
}
|
||||
|
||||
this.$emit('ConfirmSelectBeginTime', model);
|
||||
this.doClose();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
190
src/views/newMap/displayCity/demonMenu.vue
Normal file
190
src/views/newMap/displayCity/demonMenu.vue
Normal file
@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="isAllShow&&project != 'bjd'" class="display_top_draft" :style="allStyle">
|
||||
<div class="btn_hover" @click="menuClick">菜单</div>
|
||||
<el-button-group ref="button_group_box" class="button_group_box" :style="`margin-left:-${btnWidth}px`">
|
||||
<el-button v-if="jl3dmodelShow && !isContest && project !== 'bjd'" size="small" @click="jumpjlmap3dmodel">{{ jl3dmodel }}</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
<Jl3d-Device
|
||||
v-if="deviceif"
|
||||
v-show="deviceShow"
|
||||
ref="Jl3dDevice"
|
||||
:panel-show="deviceShow"
|
||||
@closedevice3dview="jumpjlmap3dmodel"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Jl3dDevice from '@/views/jlmap3d/device/jl3ddevice';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { getSessionStorage } from '@/utils/auth';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
import { getPostByProjectCode } from '@/api/learn';
|
||||
import { ProjectCode } from '@/scripts/ProjectConfig';
|
||||
export default {
|
||||
name:'DemonMenu',
|
||||
components:{
|
||||
Jl3dDevice,
|
||||
},
|
||||
props:{
|
||||
isAllShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
jl3dmodelShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
jl3dnameShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
cctvShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
trafficplanShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
traffictrainShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
scheduleLoadShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
driverShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
schedulePreviewShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
jlmap3dFaultShow:{
|
||||
type:Boolean,
|
||||
require:true
|
||||
},
|
||||
allStyle:{
|
||||
type:String,
|
||||
default() {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hoverBtn: false,
|
||||
btnWidth: 0,
|
||||
group:'',
|
||||
mapId:'',
|
||||
lineCode:'',
|
||||
practiceDisabled:false,
|
||||
deviceif:false,
|
||||
deviceShow: true,
|
||||
drivingShow: false,
|
||||
messageBoard: false,
|
||||
jl3dtrafficplan:this.$t('display.demon.trafficplantext'),
|
||||
jl3dtraffictrain:this.$t('display.demon.traffictraintext'),
|
||||
jl3dpassflow:this.$t('display.demon.passengerflow'),
|
||||
jl3dname: this.$t('display.demon.threeDimensionalView'),
|
||||
jl3dmodel: this.$t('display.demon.deviceView')
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
isDrive() {
|
||||
return this.$route.query.prdType == '04';
|
||||
},
|
||||
project() {
|
||||
return getSessionStorage('project');
|
||||
},
|
||||
isContest() {
|
||||
return this.$route.params.mode === 'demon' && this.project == 'drts';
|
||||
},
|
||||
running() {
|
||||
return this.$store.state.training.started;
|
||||
},
|
||||
isLocal() { // 是否为本地项目
|
||||
return process.env.VUE_APP_PRO === 'local';
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.group = this.$route.query.group;
|
||||
this.mapId = this.$route.query.mapId;
|
||||
this.lineCode = this.$route.query.lineCode;
|
||||
EventBus.$on('loadScene', () => {
|
||||
this.practiceDisabled = true;
|
||||
});
|
||||
EventBus.$on('quitScene', () => {
|
||||
this.practiceDisabled = false;
|
||||
});
|
||||
if (this.project) {
|
||||
getPostByProjectCode(ProjectCode[this.project]).then(resp => {
|
||||
if (resp.data) {
|
||||
this.messageBoard = true;
|
||||
}
|
||||
}).catch(() => {
|
||||
console.log('获取留言板信息失败');
|
||||
});
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
menuClick() {
|
||||
this.hoverBtn = !this.hoverBtn;
|
||||
if (this.hoverBtn) {
|
||||
this.btnWidth = 600;
|
||||
} else {
|
||||
this.btnWidth = 0;
|
||||
}
|
||||
},
|
||||
jumpjlmap3dmodel() {
|
||||
if (this.deviceif == false) {
|
||||
this.deviceif = true;
|
||||
} else {
|
||||
if (this.deviceShow == false) {
|
||||
this.deviceShow = true;
|
||||
} else {
|
||||
this.deviceShow = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.display_top_draft{
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 15px;
|
||||
height: 32px;
|
||||
overflow: hidden;
|
||||
padding-left: 44px;
|
||||
z-index: 35;
|
||||
.btn_hover{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
color: #4e4d4d;
|
||||
font-size: 14px;
|
||||
background: #fff;
|
||||
padding: 8px;
|
||||
border-radius: 5px;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
height: 32px;
|
||||
}
|
||||
.button_group_box{
|
||||
float: left;
|
||||
transition: all 0.5s;
|
||||
overflow: hidden;
|
||||
margin-left: -700px;
|
||||
// transform: translateX(0px);
|
||||
}
|
||||
}
|
||||
</style>
|
307
src/views/newMap/displayCity/index.vue
Normal file
307
src/views/newMap/displayCity/index.vue
Normal file
@ -0,0 +1,307 @@
|
||||
<template>
|
||||
<div class="main" :style="{width: canvasWidth+'px',height:'100%',position:'absolute',overflow:'hidden'}">
|
||||
<template>
|
||||
<transition name="el-zoom-in-bottom">
|
||||
<map-system-draft ref="mapCanvas" @back="back" />
|
||||
</transition>
|
||||
<menu-demon v-if="isDemon" ref="menuDemon" :offset="offset" :offset-bottom="offsetBottom" :data-error="dataError" :text-status-height="textStatusHeight" @start="start" @end="end" />
|
||||
</template>
|
||||
<menu-system-time ref="menuSystemTime" :offset="offset" :group="group" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getSessionStorage } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { OperateMode } from '@/scripts/ConstDic';
|
||||
import { timeFormat } from '@/utils/date';
|
||||
import MapSystemDraft from '@/views/newMap/mapsystemNew/index';
|
||||
import MenuDemon from './menuDemon';
|
||||
import MenuSystemTime from '@/views/newMap/displayCity/menuSystemTime';
|
||||
import { clearSimulation, getSimulationInfoNew, ranAsPlan, exitRunPlan } from '@/api/simulation';
|
||||
import { loadMapDataById } from '@/utils/loaddata';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
|
||||
export default {
|
||||
name: 'DisplayDraft',
|
||||
components: {
|
||||
MapSystemDraft,
|
||||
MenuDemon,
|
||||
MenuSystemTime
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
offset: 15,
|
||||
offsetBottom: 15,
|
||||
tipBottom: 0,
|
||||
textStatusHeight: 0,
|
||||
planRunning:false,
|
||||
dataError: false,
|
||||
group:''
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
...mapGetters([
|
||||
'canvasWidth'
|
||||
]),
|
||||
mode() {
|
||||
return this.$route.params.mode;
|
||||
},
|
||||
project() {
|
||||
return getSessionStorage('project');
|
||||
},
|
||||
isDemon() {
|
||||
return this.mode === 'demon' && this.project != 'drts';
|
||||
},
|
||||
isContest() {
|
||||
return this.mode === 'demon' && this.project == 'drts';
|
||||
},
|
||||
isExam() {
|
||||
return this.mode === 'exam';
|
||||
},
|
||||
isLesson() {
|
||||
return (this.mode === 'teach' || this.mode === 'manage');
|
||||
},
|
||||
isScript() {
|
||||
return this.mode === 'script';
|
||||
},
|
||||
mapId() {
|
||||
return this.$route.query.mapId;
|
||||
},
|
||||
width() {
|
||||
return this.$store.state.app.width;
|
||||
},
|
||||
height() {
|
||||
return this.$store.state.app.height;
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
'$store.state.socket.permissionOver': function () {
|
||||
this.$alert('用户权限已被收回', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
callback: action => {
|
||||
this.back();
|
||||
}
|
||||
});
|
||||
},
|
||||
// 此处代码似乎没什么用,之前从menuSchema复制过来的
|
||||
'$store.state.training.prdType':function(val) {
|
||||
if (val == '01') { this.switchModeInner('01'); } else { this.switchModeInner('02'); }
|
||||
},
|
||||
'$store.state.config.menuBarLoadedCount': function (val) { // menuBar加载完成
|
||||
this.setPosition();
|
||||
},
|
||||
'$store.state.app.windowSizeCount': function() { // 窗口缩放
|
||||
this.setWindowSize();
|
||||
},
|
||||
'$store.state.training.prdType': function (val) { // 根据权限类型计算高度
|
||||
this.setPosition();
|
||||
},
|
||||
'$store.state.map.mapViewLoadedCount': function (val) { // 地图视图加载完成标识 开始加载默认状态
|
||||
if (this.planRunning) {
|
||||
this.$store.dispatch('training/simulationStart');
|
||||
}
|
||||
},
|
||||
$route() {
|
||||
if (!this.isLesson && !this.isExam) {
|
||||
this.initLoadData();
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearSimulation(this.group);
|
||||
this.$store.dispatch('training/reset');
|
||||
// this.$store.dispatch('map/mapClear');
|
||||
},
|
||||
async mounted() {
|
||||
this.setWindowSize();
|
||||
this.initLoadData();
|
||||
},
|
||||
methods:{
|
||||
// 结束加载状态
|
||||
endViewLoading(isSuccess) {
|
||||
if (!isSuccess) {
|
||||
this.$store.dispatch('map/mapClear');
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
EventBus.$emit('viewLoading', false);
|
||||
});
|
||||
},
|
||||
// 仿真错误时,被动退出时调用
|
||||
async back() {
|
||||
if (this.isExam) {
|
||||
await this.$refs.menuExam.back();
|
||||
} else if (this.isLesson) {
|
||||
await this.$refs.lessonMenu.back();
|
||||
} else if (this.isDemon) {
|
||||
await this.$refs.menuDemon.back();
|
||||
} else if (this.isScript) {
|
||||
await this.$refs.menuScript.back();
|
||||
} else if (this.isContest) {
|
||||
await this.$refs.menuDispatherContest.back();
|
||||
}
|
||||
},
|
||||
// 设置各个按钮的定位
|
||||
setPosition() {
|
||||
this.$nextTick(() => {
|
||||
this.offset = 10;
|
||||
this.offsetBottom = 15;
|
||||
const menuBar = document.getElementById('menuBar');
|
||||
const menuTool = document.getElementById('menuTool');
|
||||
const menuBottom = document.getElementById('menuButton');
|
||||
const menuButtonsBox = document.getElementById('menuButtons_box');
|
||||
const textStatus = document.getElementById('textStatus');
|
||||
if (menuBar) {
|
||||
this.offset = (menuBar.offsetHeight || 0) + 15;
|
||||
}
|
||||
if (menuTool) {
|
||||
this.offset = (menuTool.offsetHeight || 0) + 15;
|
||||
}
|
||||
const buttonWidth = this.width - 1200; // B box widht
|
||||
if (menuBottom && buttonWidth < 780) {
|
||||
this.offsetBottom = (menuBottom.offsetHeight || 0) + 15;
|
||||
}
|
||||
if (menuButtonsBox) {
|
||||
this.tipBottom = (menuButtonsBox.offsetHeight || 0) + 15;
|
||||
}
|
||||
if (textStatus) {
|
||||
this.textStatusHeight = textStatus.offsetHeight || 0;
|
||||
textStatus.style.top = this.offset - 15 + 'px';
|
||||
}
|
||||
});
|
||||
},
|
||||
// 缩放设置
|
||||
setWindowSize() {
|
||||
const width = this.width;
|
||||
const height = this.height;
|
||||
this.$store.dispatch('config/resize', { width, height });
|
||||
// this.$store.dispatch('training/updateOffsetStationCode', { offsetStationCode: this.offsetStationCode });
|
||||
},
|
||||
// 初始化
|
||||
initLoadData() {
|
||||
this.group = this.$route.query.group;
|
||||
this.$store.dispatch('training/reset');
|
||||
this.loadSimulationInfo();
|
||||
this.loadMapData();
|
||||
},
|
||||
// 新版地图根据仿真group获取仿真基础信息
|
||||
async loadSimulationInfo() {
|
||||
const resp = await getSimulationInfoNew(this.group);
|
||||
if (resp && resp.code == 200 && resp.data) {
|
||||
if (!resp.data.dataError) {
|
||||
this.$store.dispatch('scriptRecord/updateSimulationPause', resp.data.pause); // 是否暂停判断
|
||||
this.$store.dispatch('training/setInitTime', +new Date(`${new Date().toLocaleDateString()} ${timeFormat(resp.data.systemTime)}`));
|
||||
this.$store.dispatch('training/countTime');
|
||||
this.$store.dispatch('runPlan/setRunPlanInfo', resp.data.runPlan);
|
||||
this.planRunning = resp.data.planRunning;
|
||||
if (resp.data.planRunning) {
|
||||
this.$store.commit('training/start');
|
||||
}
|
||||
} else {
|
||||
this.$messageBox('此地图数据正在维护中,无法运行!');
|
||||
}
|
||||
this.dataError = resp.data.dataError;
|
||||
}
|
||||
},
|
||||
// 通过showMode切换显示效果
|
||||
switchModeInner(swch) {
|
||||
let showMode = '03';
|
||||
if (swch == '01') {
|
||||
showMode = '03';
|
||||
} else if (swch == '02') {
|
||||
showMode = '02';
|
||||
}
|
||||
|
||||
const nameList = Object.keys(this.$store.state.map.map || {});
|
||||
let list = [];
|
||||
nameList.forEach(item => {
|
||||
if (item !== 'skinVO') {
|
||||
const data = this.$store.state.map.map[item];
|
||||
if (data && data.constructor === Array) {
|
||||
list = [...list, ...data];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (swch == '01') {
|
||||
this.$jlmap.updateShowStation(list, this.$store.state.training.centerStationCode); // 显示全部元素
|
||||
} else {
|
||||
this.$jlmap.updateShowStation(list, ''); // 显示全部元素
|
||||
}
|
||||
|
||||
this.$jlmap.updateShowMode(list, showMode); // 二次过滤
|
||||
},
|
||||
// 加载地图数据
|
||||
loadMapData() {
|
||||
if (parseInt(this.mapId)) {
|
||||
this.$store.dispatch('training/changeOperateMode', { mode: OperateMode.NORMAL }); // 默认为正常模式
|
||||
loadMapDataById(this.mapId, 'simulation');
|
||||
} else {
|
||||
this.endViewLoading();
|
||||
}
|
||||
},
|
||||
start(model) { // 开始仿真
|
||||
const data = {
|
||||
time: model.initTime
|
||||
};
|
||||
if (this.$route.query.prdType === '04') {
|
||||
data.loadNumber = model.loadNum;
|
||||
}
|
||||
ranAsPlan(data, this.group).then(res => {
|
||||
this.$store.dispatch('training/setInitTime', +new Date(`${new Date().toLocaleDateString()} ${model.initTime}`));
|
||||
}).catch(error => {
|
||||
let message = '';
|
||||
switch (error.code) {
|
||||
case '5001':
|
||||
message = this.$t('error.mapDataError');
|
||||
break;
|
||||
case '5002':
|
||||
message = this.$t('error.runningChartDataError');
|
||||
break;
|
||||
case '5003':
|
||||
message = this.$t('error.runningChartIsNotLoaded');
|
||||
break;
|
||||
case '5004':
|
||||
message = this.$t('error.runningDataError');
|
||||
break;
|
||||
case '5000':
|
||||
message = this.$t('error.systemError');
|
||||
break;
|
||||
case '4000':
|
||||
message = this.$t('error.simulationDoesNotExist');
|
||||
break;
|
||||
case '4001':
|
||||
message = this.$t('error.simulationOperationIsNotDefined');
|
||||
break;
|
||||
case '4002':
|
||||
message = this.$t('error.simulationOperationProcessingMethodNotFound');
|
||||
break;
|
||||
case '4003':
|
||||
message = this.$t('error.simulationOperationFailed');
|
||||
break;
|
||||
case '4004':
|
||||
message = this.$t('error.operationConflict');
|
||||
break;
|
||||
default:
|
||||
message = '按计划行车异常,请退出重试!';
|
||||
// this.$messageBox('按计划行车异常,请退出重试!');
|
||||
break;
|
||||
}
|
||||
this.$messageBox(message + ',' + this.$t('error.startSimulationFailed'));
|
||||
});
|
||||
},
|
||||
end() {
|
||||
exitRunPlan(this.group).then(() => {
|
||||
this.$store.dispatch('training/over').then(() => {
|
||||
this.$store.dispatch('training/setMapDefaultState').then(() => {
|
||||
this.$store.dispatch('map/clearJlmapTrainView');
|
||||
this.$store.dispatch('map/resetActiveTrainList', false);
|
||||
this.$store.dispatch('map/setTrainWindowShow', false);
|
||||
});
|
||||
});
|
||||
}).catch(() => {
|
||||
this.$messageBox(this.$t('display.demon.endSimulationFail'));
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
306
src/views/newMap/displayCity/menuDemon.vue
Normal file
306
src/views/newMap/displayCity/menuDemon.vue
Normal file
@ -0,0 +1,306 @@
|
||||
<template>
|
||||
<div>
|
||||
<demon-menu
|
||||
ref="demonMenu"
|
||||
:is-all-show="!dataError"
|
||||
:jl3dmodel-show="isShow3dmodel && !isShowScheduling && !isDrive"
|
||||
:jl3dname-show="!isShowScheduling&&!isDrive"
|
||||
:cctv-show="!isShowScheduling"
|
||||
:trafficplan-show="!isShowScheduling"
|
||||
:schedule-load-show="isShowScheduling && !runing"
|
||||
:schedule-preview-show="isShowScheduling && runing"
|
||||
:jlmap3d-fault-show="false"
|
||||
:driver-show="isDrive"
|
||||
:all-style="'top:'+(offset+textStatusHeight)+'px'"
|
||||
/>
|
||||
|
||||
<menu-schema
|
||||
ref="menuSchema"
|
||||
:offset="offset"
|
||||
:data-error="dataError"
|
||||
:offset-bottom="offsetBottom"
|
||||
/>
|
||||
|
||||
<div class="display-draft" :class="{'haerbin_btn_box': $route.query.lineCode == '07'||$route.query.lineCode == '14'}" :style="{bottom: offsetBottom + 'px'}">
|
||||
<el-button-group class="button-group-box">
|
||||
<template v-if="!dataError">
|
||||
<template v-if="!projectDevice">
|
||||
<el-button type="danger" size="small" @click="end">{{ $t('display.demon.initialize') }}</el-button>
|
||||
</template>
|
||||
</template>
|
||||
<el-button v-if="project !='bjd'" type="primary" size="small" @click="back">{{ projectDevice?'退出':$t('display.demon.back') }}</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<!-- 单人仿真 -->
|
||||
<script>
|
||||
import DemonMenu from './demonMenu';
|
||||
import { Notification } from 'element-ui';
|
||||
import MenuSchema from '@/views/newMap/displayCity/menuSchema';
|
||||
import { getGoodsTryUse } from '@/api/management/goods';
|
||||
import {getSimulationInfoNew, clearSimulation } from '@/api/simulation';
|
||||
import { PermissionType } from '@/scripts/ConstDic';
|
||||
import { getCountTime } from '@/utils/index';
|
||||
import { TrainingMode } from '@/scripts/ConstDic';
|
||||
import { quitScriptNew } from '@/api/simulation';
|
||||
import { setGoodsTryUse } from '@/api/management/goods';
|
||||
import {loadScriptNew } from '@/api/simulation';
|
||||
import StatusIcon from '@/views/components/StatusIcon/statusIcon';
|
||||
import Vue from 'vue';
|
||||
import { getSessionStorage } from '@/utils/auth';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
|
||||
export default {
|
||||
name: 'MenuDemon',
|
||||
components: {
|
||||
MenuSchema,
|
||||
DemonMenu,
|
||||
StatusIcon
|
||||
},
|
||||
props: {
|
||||
offset: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
offsetBottom: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
dataError: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
textStatusHeight: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tryTime: 0, // 进入页面多少秒
|
||||
timeNow: 0, // 进入页面 相对时间
|
||||
time: null, // 定时器
|
||||
countTime: 0, // 显示 倒计时
|
||||
remainingTime: 0,
|
||||
userRole:'AUDIENCE',
|
||||
goodsId: this.$route.query.goodsId,
|
||||
try: this.$route.query.try, // 是否是试用权限
|
||||
training: {
|
||||
id: '',
|
||||
name: '',
|
||||
remarks: ''
|
||||
},
|
||||
isScriptRun:false,
|
||||
jl3dname: this.$t('display.demon.threeDimensionalView'),
|
||||
jl3dmodel: this.$t('display.demon.deviceView'),
|
||||
isShow3dmodel :true,
|
||||
isGoback: false,
|
||||
runing:false,
|
||||
prdTypeMap: {
|
||||
'01': '01', // 现地 => 现地
|
||||
'02': '02', // 行调 => 行调
|
||||
'04': '02', // 司机 => 行调
|
||||
'05': '' // 派班 => null
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isShowScheduling() {
|
||||
return this.$route.query.prdType == '05';
|
||||
},
|
||||
isDrive() {
|
||||
return this.$route.query.prdType == '04';
|
||||
},
|
||||
group() {
|
||||
return this.$route.query.group;
|
||||
},
|
||||
projectDevice() {
|
||||
return this.$route.query.projectDevice;
|
||||
},
|
||||
project() {
|
||||
return getSessionStorage('project');
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$store.state.training.subscribeCount': function () {
|
||||
this.group && this.initLoadPage();
|
||||
},
|
||||
'$store.state.socket.simulationRoleList':function(val) {
|
||||
(val || []).forEach(item => {
|
||||
if (item.messageType === 'KICK_OUT' && item.userId == this.$store.state.user.id) {
|
||||
!this.isGoback && this.back();
|
||||
}
|
||||
});
|
||||
},
|
||||
'$store.state.socket.simulationOver':function(val) {
|
||||
!this.isGoback && this.back();
|
||||
},
|
||||
'$store.state.socket.simulationStart':function(val) {
|
||||
if (val) {
|
||||
this.setRuning(true);
|
||||
this.$store.dispatch('training/simulationStart').then(() => {
|
||||
this.$store.dispatch('map/setShowCentralizedStationNum');
|
||||
});
|
||||
}
|
||||
},
|
||||
'$store.state.socket.simulationReset':function(val) {
|
||||
this.setRuning(false);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('training/setPrdType', this.$route.query.prdType);
|
||||
switch (this.$store.state.training.prdType) {
|
||||
case '02': { this.userRole = 'DISPATCHER'; break; }
|
||||
case '01': { this.userRole = 'STATION_SUPERVISOR'; break; }
|
||||
case '04': { this.userRole = 'DRIVER'; break; }
|
||||
case '05': { this.userRole = 'DEPOT_DISPATCHER'; break; }
|
||||
default: { this.userRole = 'AUDIENCE'; break; }
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.time) {
|
||||
this.setTryTime();
|
||||
clearTimeout(this.time);
|
||||
}
|
||||
this.$store.dispatch('scriptRecord/updateSimulationPause', false);
|
||||
this.$store.dispatch('map/resetActiveTrainList', true);
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('training/end', TrainingMode.NORMAL);
|
||||
this.$nextTick(() => {
|
||||
this.$refs.demonMenu.menuClick();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
async initLoadPage() {
|
||||
try {
|
||||
if (this.try != '0') {
|
||||
this.loadInitData();
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
loadInitData() {
|
||||
const data = {
|
||||
mapId: this.$route.query.mapId,
|
||||
prdType: this.$route.query.prdType,
|
||||
permissionType: PermissionType.SIMULATION
|
||||
};
|
||||
getGoodsTryUse(data).then(res => {
|
||||
this.remainingTime = res.data.tryTime;
|
||||
this.timeNow = Date.parse(new Date()) / 1000 + this.remainingTime;
|
||||
if (this.try) {
|
||||
this.time = setInterval(() => {
|
||||
this.tryTime += 1;
|
||||
this.countTime = getCountTime(this.timeNow);
|
||||
if (this.countTime == -1) {
|
||||
this.back();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}).catch(() => {
|
||||
this.$messageBox(this.$t('display.demon.getTimeFail'));
|
||||
});
|
||||
},
|
||||
selectBeginTime() {
|
||||
this.$refs.setTime.doShow();
|
||||
},
|
||||
start(model) {
|
||||
this.$emit('start', model);
|
||||
},
|
||||
setRuning(run) {
|
||||
this.runing = run;
|
||||
},
|
||||
end() {
|
||||
this.$emit('end');
|
||||
},
|
||||
clearAllData() {
|
||||
this.$refs.chatbox.clearAllData();
|
||||
},
|
||||
async back() {
|
||||
this.isGoback = true;
|
||||
if (this.projectDevice) {
|
||||
clearSimulation(this.group).then(res=>{
|
||||
this.$store.dispatch('training/over').then(() => {
|
||||
this.$store.dispatch('LogOut').then(() => {
|
||||
location.reload();
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (this.project === 'bjd') {
|
||||
window.close();
|
||||
} else {
|
||||
this.$store.dispatch('map/setShowCentralizedStationCode', '');
|
||||
history.go(-1);
|
||||
Notification.closeAll();
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
setTryTime() {
|
||||
if (this.try) {
|
||||
const data = { time: this.tryTime, goodsId: this.goodsId };
|
||||
if (data.goodsId) {
|
||||
setGoodsTryUse(data);
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
quit() {
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
@import "src/styles/mixin.scss";
|
||||
|
||||
.display-card {
|
||||
z-index: 9;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
left: 160px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.display-card .el-row {
|
||||
line-height: 32px !important;
|
||||
}
|
||||
|
||||
.display-score {
|
||||
background-color: black;
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
height: 32px;
|
||||
line-height: 24px;
|
||||
border-radius: 4px;
|
||||
padding-left: 2px;
|
||||
margin-left: 10px;
|
||||
font-family: "Microsoft" !important;
|
||||
font-size: 18px !important;
|
||||
color: #fff;
|
||||
}
|
||||
.haerbin_btn_box{
|
||||
width: 450px;
|
||||
bottom: 15px!important;
|
||||
}
|
||||
.display-draft {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 15px;
|
||||
.button-group-box{
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
</style>
|
111
src/views/newMap/displayCity/menuSchema.vue
Normal file
111
src/views/newMap/displayCity/menuSchema.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div class="schema" :style="{top: offset+'px'}">
|
||||
<el-button v-if="!isScheduling" size="small" :type="faultMode ? '':'primary' " @click="changeOperateMode()">{{ faultMode?'切换到普通模式[Tab]':'切换到故障模式[Tab]' }}</el-button>
|
||||
<fault-choose ref="faultChoose" :group="group" :offset="offset" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import FaultChoose from './demon/faultChoose';
|
||||
import { OperateMode } from '@/scripts/ConstDic';
|
||||
import { getByGroupStationList } from '@/api/jmap/map';
|
||||
import { getSessionStorage } from '@/utils/auth';
|
||||
import { loadRunPlanData } from '@/utils/loaddata';
|
||||
import { EventBus } from '@/scripts/event-bus';
|
||||
|
||||
// 右上角操作
|
||||
export default {
|
||||
name: 'MenuSchema',
|
||||
components: {
|
||||
FaultChoose
|
||||
},
|
||||
props: {
|
||||
offset: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
dataError: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mode: OperateMode.NORMAL,
|
||||
OperateMode: OperateMode,
|
||||
viewDisabled: true,
|
||||
faultMode: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
group() {
|
||||
return this.$route.query.group;
|
||||
},
|
||||
isScript() {
|
||||
return this.$route.params.mode === 'script';
|
||||
},
|
||||
isDemon() {
|
||||
return this.$route.params.mode === 'demon';
|
||||
},
|
||||
isScheduling() {
|
||||
return this.$route.query.prdType === '05';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$store.state.training.triggerFaultCount': function () {
|
||||
this.setFault();
|
||||
},
|
||||
'$store.state.runPlan.loadRunPlanCount': function () {
|
||||
this.viewDisabled = false;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
EventBus.$on('CheckFaultModeEvent', () => {
|
||||
if (!this.isScheduling) {
|
||||
this.changeOperateMode();
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
loadRunData() {
|
||||
this.$store.dispatch('runPlan/clear').then(() => {
|
||||
if (this.group) {
|
||||
this.viewDisabled = true;
|
||||
// 获取排序的车站列表
|
||||
getByGroupStationList(this.group).then(response => {
|
||||
this.$store.dispatch('runPlan/setStations', response.data).then(() => {
|
||||
loadRunPlanData(this.group, this.dataError);
|
||||
});
|
||||
}).catch(() => {
|
||||
this.$messageBox(this.$t('display.schema.getStationListFail'));
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
changeOperateMode() {
|
||||
this.faultMode = !this.faultMode;
|
||||
let mode = OperateMode.NORMAL;
|
||||
if (this.faultMode) {
|
||||
mode = OperateMode.FAULT;
|
||||
}
|
||||
this.$store.dispatch('training/changeOperateMode', { mode: mode });
|
||||
},
|
||||
setFault() {
|
||||
this.$refs.faultChoose.doShow();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.schema {
|
||||
z-index: 36;
|
||||
display: inline;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
/deep/ .el-button+.el-button {
|
||||
margin-left: 0px;
|
||||
}
|
||||
</style>
|
154
src/views/newMap/displayCity/menuSystemTime.vue
Normal file
154
src/views/newMap/displayCity/menuSystemTime.vue
Normal file
@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<div v-if="isShowSystemTime" class="display-card" :style="{top: top+'px', right: newRight+'px'}">
|
||||
<template v-if="pause">
|
||||
<span class="display-pause">{{ $t('display.systemTime.timePause') }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<system-time
|
||||
class="display-time"
|
||||
:time="time"
|
||||
/>
|
||||
<div v-if="isShowDate" style="width: 80px;height: 58px;float: right;box-shadow: 0 0 5px #eee;">
|
||||
<div class="display-date-box">{{ dateString }}</div>
|
||||
<div class="display-date-box">{{ dayString }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { prefixIntrger } from '@/utils/date';
|
||||
import SystemTime from '@/views/components/systemTime/index';
|
||||
import { timeFormat } from '@/utils/date';
|
||||
|
||||
// 顶部时间栏显示
|
||||
export default {
|
||||
name: 'MenuSystemTime',
|
||||
components: {
|
||||
SystemTime
|
||||
},
|
||||
props: {
|
||||
offset: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
time: '00:0000',
|
||||
dateString: '00/00/00',
|
||||
dayString: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isShowSystemTime() {
|
||||
return this.$route.params.mode == 'demon' ||
|
||||
this.$route.params.mode == 'dp' ||
|
||||
this.$route.params.mode == 'plan' ||
|
||||
this.$route.params.mode == 'script' ||
|
||||
this.$route.params.mode == 'practice' ||
|
||||
!this.$route.params.mode;
|
||||
},
|
||||
pause() {
|
||||
return this.$store.state.scriptRecord.simulationPause;
|
||||
},
|
||||
isDisplay() {
|
||||
return this.$route.path.includes('displayCity') || this.$route.path.includes('scriptdisplayCity');
|
||||
},
|
||||
isShowDate() { // 西安一 三号线
|
||||
return (this.$route.query.lineCode == 10 || this.$route.query.lineCode == 11) && this.isDisplay;
|
||||
},
|
||||
top() {
|
||||
return this.isShowDate ? (this.$route.query.prdType == '05' ? 5 : this.offset - 10) : this.offset;
|
||||
},
|
||||
newRight() {
|
||||
return this.isShowDate ? this.$store.state.config.width - 420 : this.$store.state.config.width / 2 - 55;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$store.state.training.initTime': function (initTime) {
|
||||
const date = new Date(initTime);
|
||||
this.initDate(date);
|
||||
},
|
||||
'$store.state.socket.simulationTimeSync': function (time) { // 仿真时间更新
|
||||
this.$store.dispatch('training/setInitTime', +new Date(`${new Date().toLocaleDateString()} ${timeFormat(time)}`));
|
||||
const date = new Date(+new Date(`${new Date().toLocaleDateString()} ${timeFormat(time)}`));
|
||||
this.initDate(date);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const initTime = this.$store.state.training.initTime;
|
||||
if (initTime > 0) {
|
||||
const date = new Date(initTime);
|
||||
this.initDate(date);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initDate(date) {
|
||||
this.time = `${prefixIntrger(date.getHours(), 2)}:${prefixIntrger(date.getMinutes(), 2)}${prefixIntrger(date.getSeconds(), 2)}`;
|
||||
const years = date.getFullYear() + '';
|
||||
let months = date.getMonth() + 1 + '';
|
||||
let dates = date.getDate() + '';
|
||||
if (months.length < 2) { months = '0' + months; }
|
||||
if (dates.length < 2) { dates = '0' + dates; }
|
||||
this.dateString = dates + '/' + months + '/' + years.slice(2);
|
||||
const day = date.getDay();
|
||||
switch (day) {
|
||||
case 0:
|
||||
this.dayString = '星 期 日';
|
||||
break;
|
||||
case 1:
|
||||
this.dayString = '星 期 一';
|
||||
break;
|
||||
case 2:
|
||||
this.dayString = '星 期 二';
|
||||
break;
|
||||
case 3:
|
||||
this.dayString = '星 期 三';
|
||||
break;
|
||||
case 4:
|
||||
this.dayString = '星 期 四';
|
||||
break;
|
||||
case 5:
|
||||
this.dayString = '星 期 五';
|
||||
break;
|
||||
case 6:
|
||||
this.dayString = '星 期 六';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
@import "src/styles/mixin.scss";
|
||||
|
||||
.display-card {
|
||||
z-index: 9;
|
||||
display: inline;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.display-pause {
|
||||
font-size: 21px;
|
||||
font-weight: bold;
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
.display-time{
|
||||
padding: 3px 5px;
|
||||
border: 1px solid rgba(255,255,255,.2);
|
||||
box-shadow: 0 2px 12px 0 rgba(255,255,255,.3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.display-card .el-row {
|
||||
line-height: 32px !important;
|
||||
}
|
||||
.display-date-box{
|
||||
height: 29px;
|
||||
line-height: 29px;
|
||||
background: #404040;
|
||||
color: #1DEA1E;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
</style>
|
58
src/views/newMap/displayCity/utils.js
Normal file
58
src/views/newMap/displayCity/utils.js
Normal file
@ -0,0 +1,58 @@
|
||||
import ConstConfig from '@/scripts/ConstConfig';
|
||||
import Cookies from 'js-cookie';
|
||||
import store from '@/store/index';
|
||||
export function covertMemberData (activeTrainList, resp) {
|
||||
let lastData = JSON.stringify(resp);
|
||||
const roleTypeList = ConstConfig.ConstSelect.roleTypeNew;
|
||||
roleTypeList.forEach(function(element) {
|
||||
const rolename = element.value;
|
||||
if (Cookies.get('user_lang') == 'en') {
|
||||
lastData = lastData.replace(new RegExp(rolename, 'g'), element.enLabel);
|
||||
} else {
|
||||
lastData = lastData.replace(new RegExp(rolename, 'g'), element.label);
|
||||
}
|
||||
});
|
||||
lastData = JSON.parse(lastData);
|
||||
const lastMemberList = [];
|
||||
// const electricDispatcherList = [];
|
||||
const deviceListData = [[], [], [], [], [], [], [], []];
|
||||
const driverList = [];
|
||||
lastData.forEach((member, index)=>{
|
||||
if (member.userId && member.userId == store.state.user.id) {
|
||||
member.disabled = true;
|
||||
member.userName = store.state.user.nickname;
|
||||
store.dispatch('training/setOrignalUserRoleId', member.id);
|
||||
} else {
|
||||
member.disabled = false;
|
||||
}
|
||||
const userName = member.userName ? '-' + member.userName : '';
|
||||
const name = member.name ? '-' + member.name : '';
|
||||
if (member.deviceCode) {
|
||||
const device = store.getters['map/getDeviceByCode'](member.deviceCode);
|
||||
member.deviceName = device.name || device.groupNumber;
|
||||
member.label = member.type + member.deviceName + name + userName;
|
||||
member.normalName = member.type + member.deviceName + name;
|
||||
} else {
|
||||
member.deviceName = '';
|
||||
member.label = member.type + name + userName;
|
||||
member.normalName = member.type + name;
|
||||
}
|
||||
const deviceType = ['行调', '通号', '行值', '司机', '车辆段信号楼', '上级部门', '电力调度', '停车场信号楼'];
|
||||
const deviceTypeIndex = deviceType.indexOf(member.type);
|
||||
if (deviceTypeIndex >= 0) {
|
||||
if (deviceTypeIndex == 3) {
|
||||
if (activeTrainList.length > 0) {
|
||||
if (activeTrainList.includes(member.deviceCode)) {
|
||||
deviceListData[deviceTypeIndex].push(member);
|
||||
}
|
||||
}
|
||||
lastMemberList.push(member);
|
||||
driverList.push(member);
|
||||
} else {
|
||||
deviceListData[deviceTypeIndex].push(member);
|
||||
lastMemberList.push(member);
|
||||
}
|
||||
}
|
||||
});
|
||||
return {lastMemberList:lastMemberList, deviceListData:deviceListData, driverList:driverList};
|
||||
}
|
373
src/views/newMap/displayNew/demon/runPlanView2.vue
Normal file
373
src/views/newMap/displayNew/demon/runPlanView2.vue
Normal file
@ -0,0 +1,373 @@
|
||||
<template>
|
||||
<!-- v-dialogDrag -->
|
||||
<el-dialog
|
||||
v-dialogLoading="dialogLoading"
|
||||
:title="title"
|
||||
:visible.sync="dialogShow"
|
||||
width="100%"
|
||||
:before-close="doClose"
|
||||
:close-on-click-modal="false"
|
||||
:modal="false"
|
||||
fullscreen
|
||||
>
|
||||
<div :id="runPlanId" v-loading="loading" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { getPublishMapInfo } from '@/api/jmap/map';
|
||||
import { timeFormat } from '@/utils/date';
|
||||
import echarts from 'echarts';
|
||||
import {toTimeStamp, formatDuring} from '@/utils/date';
|
||||
|
||||
// 运行图预览
|
||||
export default {
|
||||
name: 'RunPlanView',
|
||||
props: {
|
||||
group: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogShow: false,
|
||||
loading: true,
|
||||
runPlanId: 'run-plan-view',
|
||||
myChart: null,
|
||||
PlanConvert: {},
|
||||
series: [],
|
||||
option: {
|
||||
title: {
|
||||
text: '',
|
||||
left: 'center'
|
||||
},
|
||||
grid: {
|
||||
top: '30px',
|
||||
left: '120px',
|
||||
right: '40px',
|
||||
bottom: '80px',
|
||||
containLabel: true,
|
||||
backgroundColor: 'floralwhite'
|
||||
},
|
||||
toolbox: {
|
||||
// right: '20px',
|
||||
// feature: {
|
||||
// dataZoom: {
|
||||
// yAxisIndex: 'none'
|
||||
// },
|
||||
// restore: {},
|
||||
// saveAsImage: {}
|
||||
// }
|
||||
},
|
||||
tooltip: {
|
||||
axisPointer: {
|
||||
trigger: 'item',
|
||||
type: 'cross'
|
||||
},
|
||||
formatter: this.axisTooltip,
|
||||
borderWidth: 1
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: [],
|
||||
axisLine: {
|
||||
onZero: false,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: '#d14a61'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: this.xAxisLableFormat,
|
||||
textStyle: {
|
||||
color: '#333'
|
||||
}
|
||||
},
|
||||
axisPointer: {
|
||||
snap: true,
|
||||
label: {
|
||||
formatter: this.xAxisPointFormat,
|
||||
backgroundColor: 'rgb(255,0,0,0.5)',
|
||||
color: 'white'
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
onZero: false,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
color: '#d14a61'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
interval: 'auto',
|
||||
formatter: this.yAxisLableFormat
|
||||
},
|
||||
axisPointer: {
|
||||
xAxisIndex: 'all',
|
||||
label: {
|
||||
formatter: this.yAxisPointFormat,
|
||||
backgroundColor: 'rgb(0,100,0,0.5)',
|
||||
color: 'white'
|
||||
}
|
||||
},
|
||||
min: 0,
|
||||
max: 0
|
||||
},
|
||||
// graphic: {
|
||||
// type: 'line',
|
||||
// progressive: true
|
||||
// },
|
||||
series: [],
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'inside'
|
||||
},
|
||||
{
|
||||
fiterMode: 'filter',
|
||||
handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
|
||||
handleSize: '80%',
|
||||
handleStyle: {
|
||||
color: '#fff',
|
||||
shadowBlur: 3,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.6)',
|
||||
shadowOffsetX: 2,
|
||||
shadowOffsetY: 2
|
||||
},
|
||||
bottom: '25px'
|
||||
}
|
||||
]
|
||||
},
|
||||
absoluteTime: 2 * 3600,
|
||||
indexKmRangeMap: {},
|
||||
runPlanData: {},
|
||||
dialogLoading: false,
|
||||
initialPlanData: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('runPlan', [
|
||||
'stations'
|
||||
]),
|
||||
title() {
|
||||
return this.$t('display.runPlan.previewRunDiagram');
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$store.state.runPlan.planLoadedCount': async function () {
|
||||
try {
|
||||
await this.loadChartPage();
|
||||
if (this.dialogShow) {
|
||||
await this.loadInitData(this.series);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
'$store.state.runPlan.planUpdateCount': function () {
|
||||
this.updateRunPlanData(this.$store.state.runPlan.updateData);
|
||||
},
|
||||
'$store.state.app.windowSizeCount': function() {
|
||||
this.reSize({ width: this.$store.state.app.width, height: this.$store.state.app.height - 55 });
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
getPublishMapInfo(this.$route.query.mapId).then(res=>{
|
||||
this.PlanConvert = this.$theme.loadPlanConvert(res.data.lineCode);
|
||||
this.initialPlanData = this.$store.state.runPlan.planData;
|
||||
this.loadChartPage();
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.myChart && this.myChart.isDisposed) {
|
||||
this.myChart.dispose();
|
||||
this.myChart = null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async doShow() {
|
||||
try {
|
||||
this.dialogLoading = true;
|
||||
this.dialogShow = true;
|
||||
this.loadInitData(this.series);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
this.dialogLoading = false;
|
||||
}
|
||||
},
|
||||
async doClose() {
|
||||
this.dialogShow = false;
|
||||
},
|
||||
async loadChartPage() {
|
||||
const stations = this.$store.state.runPlan.stations;
|
||||
const planData = this.$store.state.runPlan.planData;
|
||||
this.series = [];
|
||||
this.kmRangeCoordMap = this.PlanConvert.convertStationsToMap(stations);
|
||||
this.pushModels(this.series, [this.PlanConvert.initializeYaxis(stations)]);
|
||||
this.pushModels(this.series, this.PlanConvert.convertDataToModels(planData, stations, this.kmRangeCoordMap, { width: 1, color: '#000' }));
|
||||
},
|
||||
async loadInitData(series) {
|
||||
this.myChart && this.myChart.showLoading();
|
||||
await this.xAxisInit();
|
||||
await this.yAxisInit();
|
||||
await this.loadInitChart(series);
|
||||
this.myChart && this.myChart.hideLoading();
|
||||
},
|
||||
loadInitChart(series) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
if (this.myChart && this.myChart.isDisposed) {
|
||||
this.myChart.clear();
|
||||
}
|
||||
let startValue = 3600 + this.PlanConvert.TranslationTime;
|
||||
const offsetTime = 3600;
|
||||
const initTime = toTimeStamp(formatDuring(this.$store.state.training.initTime));
|
||||
startValue = initTime - this.PlanConvert.TranslationTime;
|
||||
this.option.dataZoom[0].startValue = this.option.dataZoom[1].startValue = startValue - offsetTime;
|
||||
this.option.dataZoom[0].endValue = this.option.dataZoom[1].endValue = startValue + offsetTime;
|
||||
this.option.series = series;
|
||||
this.myChart = echarts.init(document.getElementById(this.runPlanId));
|
||||
if (this.myChart) {
|
||||
this.myChart.setOption(this.option);
|
||||
this.reSize({ width: document.documentElement.clientWidth - 10, height: document.documentElement.clientHeight - 55 });
|
||||
this.myChart.on('click', this.mouseClick);
|
||||
}
|
||||
resolve(true);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
},
|
||||
updateRunPlanData(data) {
|
||||
const stations = this.$store.state.runPlan.stations;
|
||||
const planData = this.$store.state.runPlan.planData;
|
||||
const initialPlanData = this.$store.state.runPlan.initialPlanData;
|
||||
if (data[0] && initialPlanData[data[0].serviceNumber]) {
|
||||
Object.keys(initialPlanData[data[0].serviceNumber].trainMap).forEach(item => {
|
||||
if (initialPlanData[data[0].serviceNumber].trainMap[item + ''].tripNumber == data[0].tripNumber) {
|
||||
data[0].directionCode = initialPlanData[data[0].serviceNumber].trainMap[item + ''].directionCode;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (data[0]) {
|
||||
data[0].secondTime = data[0].second;
|
||||
}
|
||||
this.series = this.PlanConvert.updateDataToModels(data, stations, this.kmRangeCoordMap,
|
||||
planData, this.series, { color: '#FF00DE', width: 2 }
|
||||
);
|
||||
this.myChart && this.myChart.setOption({ series: this.series });
|
||||
},
|
||||
pushModels(series, models) {
|
||||
if (models && models.length) {
|
||||
models.forEach(elem => {
|
||||
if (elem) {
|
||||
series.push(elem);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return series;
|
||||
},
|
||||
popModels(series, models) {
|
||||
if (models && models.length) {
|
||||
models.forEach(elem => {
|
||||
const index = series.indexOf(elem);
|
||||
if (index >= 0) {
|
||||
series.split(index, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return series;
|
||||
},
|
||||
xAxisPointFormat(params) {
|
||||
return timeFormat(params.value);
|
||||
},
|
||||
yAxisPointFormat(params) {
|
||||
return this.PlanConvert.computedFormatYAxis(this.stations, params);
|
||||
},
|
||||
xAxisLableFormat(value, index) {
|
||||
if (value % 60 === 0) {
|
||||
return timeFormat(value);
|
||||
}
|
||||
},
|
||||
yAxisLableFormat(value, index) {
|
||||
return '';
|
||||
},
|
||||
xAxisInit() {
|
||||
const list = [];
|
||||
for (var time = this.PlanConvert.TranslationTime; time < 3600 * 24 + this.PlanConvert.TranslationTime; time++) {
|
||||
list.push(time);
|
||||
}
|
||||
this.option.xAxis[0].data = list;
|
||||
},
|
||||
yAxisInit() {
|
||||
if (Object.keys(this.PlanConvert).length) {
|
||||
this.option.yAxis.min = this.PlanConvert.computedYaxisMinValue(this.stations);
|
||||
this.option.yAxis.max = this.PlanConvert.computedYaxisMaxValue(this.stations);
|
||||
}
|
||||
},
|
||||
axisTooltip(param) {
|
||||
const station = this.stations[Math.floor((param.data[1] - this.PlanConvert.EdgeHeight) / this.PlanConvert.CoordMultiple)] || { name: '', kmRange: '' };
|
||||
return [
|
||||
`Point Data <hr size=1 style="margin: 3px 0">`,
|
||||
`${this.$t('display.runPlan.stationName')}: ${station.name}<br>`,
|
||||
`${this.$t('display.runPlan.stationMark')}: ${station.kmRange} km <br>`,
|
||||
`${this.$t('display.runPlan.arrivalTime')}: ${timeFormat(param.data[0] + this.PlanConvert.TranslationTime)} (${param.data[0]})<br>`
|
||||
].join('');
|
||||
},
|
||||
settingExac(data) {
|
||||
this.absoluteTime = Math.abs(parseInt(data.endValue) - parseInt(data.startValue)) / 1000;
|
||||
this.myChart && this.myChart.setOption({
|
||||
xAxis: this.option.xAxis,
|
||||
yAxis: this.option.yAxis
|
||||
});
|
||||
|
||||
this.myChart && this.myChart.dispatchAction({
|
||||
type: 'dataZoom',
|
||||
dataZoomIndex: [0, 1],
|
||||
startValue: parseInt(data.startValue / 1000),
|
||||
endValue: parseInt(data.endValue / 1000)
|
||||
});
|
||||
},
|
||||
run(start) {
|
||||
this.myChart && this.myChart.dispatchAction({
|
||||
type: 'dataZoom',
|
||||
dataZoomIndex: [0, 1],
|
||||
startValue: parseInt(start - this.absoluteTime / 2),
|
||||
endValue: parseInt(start + this.absoluteTime / 2)
|
||||
});
|
||||
this.loadInitData(this.series);
|
||||
},
|
||||
reSize(opt) {
|
||||
if (this.myChart) {
|
||||
this.myChart.resize({ width: opt.width, height: opt.height, silent: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped rel="stylesheet/scss" lang="scss">
|
||||
/deep/ {
|
||||
.el-dialog__body {
|
||||
padding: 0px !important;
|
||||
background-color: floralwhite !important;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -157,19 +157,19 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scope>
|
||||
.content-route /deep/ .el-dialog__body {
|
||||
width: 100%;
|
||||
height:100%;
|
||||
flex:1;
|
||||
padding: 0 !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.content-route{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/deep/ {
|
||||
.el-dialog__body{
|
||||
width: 100%;
|
||||
height:100%;
|
||||
flex:1;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-box{
|
||||
display:flex;
|
||||
height:100%;
|
||||
|
@ -15,17 +15,17 @@
|
||||
border
|
||||
>
|
||||
<el-table-column prop="name" :label="this.$t('planMonitor.runGraphName')" />
|
||||
<el-table-column v-if="!(/^\/design\/userlist/.test(this.$route.fullPath))" :label="this.$t('global.status')">
|
||||
<!-- <el-table-column v-if="!(/^\/design\/userlist/.test(this.$route.fullPath))" :label="this.$t('global.status')">
|
||||
<template slot-scope="scope">
|
||||
<el-tag>{{ handlerStatus(scope.row) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
</el-table-column> -->
|
||||
<!-- <el-table-column
|
||||
v-if="!(/^\/design\/userlist/.test(this.$route.fullPath))"
|
||||
prop="explanation"
|
||||
show-overflow-tooltip
|
||||
:label="this.$t('planMonitor.explanation')"
|
||||
/>
|
||||
/> -->
|
||||
<el-table-column :label="this.$t('planMonitor.creationDate')">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="success">{{ handleTime(scope.row.createTime) }}</el-tag>
|
||||
@ -33,7 +33,8 @@
|
||||
</el-table-column>
|
||||
<el-table-column :label="this.$t('global.operate')" width="400">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="scope.row.status !=='1'" size="mini" class="button_box" type="success" :loading="scope.row.runplanLoading" @click="handleConfirm(scope.row)">{{ $t('planMonitor.load') }}</el-button>
|
||||
<!-- {{ $t('planMonitor.load') }} -->
|
||||
<el-button v-if="scope.row.status !=='1'" size="mini" class="button_box" type="success" :loading="scope.row.runplanLoading" @click="handleConfirm(scope.row)">编制</el-button>
|
||||
<el-button v-if="isCreate && scope.row.status !=='1'" size="mini" class="button_box" type="primary" @click="handleEdit(scope.row)">{{ $t('planMonitor.modifyName') }}</el-button>
|
||||
<el-button v-if="isCreate && scope.row.status !=='1'" size="mini" class="button_box" type="danger" @click="handleDelete(scope.row)">{{ $t('global.delete') }}</el-button>
|
||||
<el-button v-if="isCreate && scope.row.status ==='0' && hasRelease" size="mini" class="button_box" type="primary" @click="handlePublish(scope.row)">{{ hasRelease?$t('global.release'):$t('planMonitor.applyRelease') }}</el-button>
|
||||
|
@ -40,7 +40,8 @@
|
||||
</el-form>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="导入运行图" name="three">
|
||||
<!-- v-if="hasRelease" -->
|
||||
<!-- <el-tab-pane label="导入运行图" name="three">
|
||||
<el-row>
|
||||
<el-button type="text" class="uploadDemo">
|
||||
<input
|
||||
@ -53,7 +54,7 @@
|
||||
<i class="el-icon-plus" />
|
||||
</el-button>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
</el-tab-pane> -->
|
||||
</el-tabs>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
@ -117,6 +118,10 @@ export default {
|
||||
{ required: true, message: this.$t('rules.enterTheNameOfTheRunGraph'), trigger: 'blur' }
|
||||
]
|
||||
};
|
||||
},
|
||||
hasRelease() {
|
||||
return this.$store.state.user.roles.includes('04') ||
|
||||
this.$store.state.user.roles.includes('05');
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
458
src/views/test/index.vue
Normal file
458
src/views/test/index.vue
Normal file
@ -0,0 +1,458 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :id="iscsId" v-loading="loading" :style="{ width: width +'px', height: height +'px',background:'#425a74' }" class="iscs-canvas" />
|
||||
<el-button-group>
|
||||
<el-button @click="doRemove"> 删除 </el-button>
|
||||
<el-button @click="doBinding">绑定</el-button>
|
||||
<el-button @click="doUnbinding">解绑</el-button>
|
||||
<el-button @click="doSource"> 源数据 </el-button>
|
||||
</el-button-group>
|
||||
<el-input type="textarea" :rows="6" v-model="json" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import Iscs from '@/iscs_new/map';
|
||||
import orders from '@/iscs_new/utils/orders';
|
||||
import shapeType from '@/iscs_new/constant/shapeType';
|
||||
import ShapeBuilder from '@/iscs_new/plugins/shapeBuilder';
|
||||
import ShapeProperty from '@/iscs_new/plugins/shapeProperty';
|
||||
import ShapeContextMenu from '@/iscs_new/plugins/shapeContextMenu';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { exitFullscreen } from '@/utils/screen';
|
||||
import * as utils from '@/iscs_new/utils/utils';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
json: "{}",
|
||||
dataZoom: {
|
||||
offsetX: '0',
|
||||
offsetY: '0',
|
||||
scaleRate: '1'
|
||||
},
|
||||
config: {
|
||||
scaleRate: '1',
|
||||
origin: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
},
|
||||
selected: null, // 选择复制元素
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('iscs', [
|
||||
'iscs'
|
||||
]),
|
||||
iscsId() {
|
||||
return ['iscs', (Math.random().toFixed(5)) * 100000].join('_');
|
||||
},
|
||||
width() {
|
||||
return document.documentElement.clientWidth;
|
||||
},
|
||||
height() {
|
||||
return document.documentElement.clientHeight - 200;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$store.state.config.canvasSizeCount': function (val) {
|
||||
this.resize();
|
||||
},
|
||||
'$store.state.socket.equipmentStatus': function (val) {
|
||||
if (val.length) {
|
||||
this.stateMessage(val);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.destroy();
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
document.getElementById(this.iscsId).oncontextmenu = function (e) {
|
||||
return false;
|
||||
};
|
||||
|
||||
this.$iscs = new Iscs({
|
||||
dom: document.getElementById(this.iscsId),
|
||||
draw: true,
|
||||
config: {
|
||||
renderer: 'canvas',
|
||||
width: this.width,
|
||||
height: this.height
|
||||
},
|
||||
options: {
|
||||
scaleRate: 1,
|
||||
offsetX: 0,
|
||||
offsetY: 0
|
||||
},
|
||||
plugins: [
|
||||
ShapeBuilder,
|
||||
ShapeProperty,
|
||||
ShapeContextMenu
|
||||
]
|
||||
});
|
||||
|
||||
Vue.prototype.$iscs = this.$iscs;
|
||||
this.$iscs.on('viewLoaded', this.onUpdate, this);
|
||||
this.$iscs.on('contextmenu', this.onContextMenu, this);
|
||||
this.$iscs.on('click', this.onClick, this);
|
||||
this.$iscs.on('keyboard', this.onKeyboard, this);
|
||||
|
||||
const opts = { panEnable: true, zoomEnable: true, keyEnable: true, draggle: true, selecting: true, selectable: true, reflect: true }
|
||||
this.$iscs.setMap([
|
||||
{
|
||||
type: 'Device',
|
||||
name: 'test',
|
||||
isActive: false,
|
||||
isFocus: false,
|
||||
shapeList: [
|
||||
{
|
||||
name: 'a',
|
||||
type: 'Rect',
|
||||
shape: {},
|
||||
style: {
|
||||
fill: 'red',
|
||||
stroke: 'black'
|
||||
},
|
||||
stateList: [
|
||||
{ status: 'st1', hide: false, shape: {}, style:{ fill: 'yellow', stroke: 'black'} },
|
||||
{ status: 'st2', hide: false, shape: {}, style:{ fill: 'blue', stroke: 'black'} }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
type: 'Circle',
|
||||
shape: {},
|
||||
style: {
|
||||
fill: 'red',
|
||||
stroke: 'black'
|
||||
},
|
||||
stateList: [
|
||||
{ status: 'st1', hide: false, shape: {}, style:{ fill: 'yellow', stroke: 'black'} },
|
||||
{ status: 'st2', hide: false, shape: {}, style:{ fill: 'blue', stroke: 'black'} }
|
||||
]
|
||||
},
|
||||
],
|
||||
stateList: [
|
||||
{ status: 's1', frameList: [[{name: 'a', status: 'st1'}, {name: 'b', status: 'st1'}], [{name: 'a', status: 'st2'}]], weight: 2, loop: true, delay: 2000, time: 200, needDefault: true },
|
||||
{ status: 's2', frameList: [[{name: 'a', status: 'st2'}, {name: 'b', status: 'st1'}], [{name: 'a', status: 'st1'}, {name: 'b', status: 'st2'}]], weight: 1, loop: true, delay: 5000, time: 500, needDefault: false }
|
||||
]
|
||||
}
|
||||
], {
|
||||
elementList: [
|
||||
{
|
||||
code: '1',
|
||||
name: 'a',
|
||||
type: 'Rect',
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [0, 0],
|
||||
rotation: 0,
|
||||
hide: false,
|
||||
},
|
||||
shape: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 30,
|
||||
height: 30
|
||||
},
|
||||
style: {
|
||||
fill: 'red',
|
||||
stroke: 'black'
|
||||
},
|
||||
composeCode: '100'
|
||||
},
|
||||
{
|
||||
code: '2',
|
||||
name: 'b',
|
||||
type: 'Circle',
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [0, 0],
|
||||
rotation: 0,
|
||||
hide: false,
|
||||
},
|
||||
shape: {
|
||||
cx: 100,
|
||||
cy: 100,
|
||||
r: 10,
|
||||
},
|
||||
style: {
|
||||
fill: 'red',
|
||||
stroke: 'black'
|
||||
},
|
||||
composeCode: '100'
|
||||
},
|
||||
{
|
||||
code: '3',
|
||||
name: 'a',
|
||||
type: 'Rect',
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [0, 0],
|
||||
rotation: Math.PI/4,
|
||||
hide: false,
|
||||
},
|
||||
shape: {
|
||||
x: 200,
|
||||
y: 100,
|
||||
width: 30,
|
||||
height: 30
|
||||
},
|
||||
style: {
|
||||
fill: 'red',
|
||||
stroke: 'black'
|
||||
},
|
||||
composeCode: '101'
|
||||
},
|
||||
{
|
||||
code: '4',
|
||||
name: 'b',
|
||||
type: 'Circle',
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [0, 0],
|
||||
rotation: 0,
|
||||
scale: [0.5, 0.5],
|
||||
hide: false,
|
||||
},
|
||||
shape: {
|
||||
cx: 200,
|
||||
cy: 100,
|
||||
r: 10,
|
||||
},
|
||||
style: {
|
||||
fill: 'red',
|
||||
stroke: 'black'
|
||||
},
|
||||
composeCode: '101'
|
||||
},
|
||||
{
|
||||
code: '5',
|
||||
name: 'c',
|
||||
type: 'Droplet',
|
||||
base: {
|
||||
scale: [0.5, 0.5],
|
||||
position: [0, 0],
|
||||
rotation: 0,
|
||||
hide: false,
|
||||
},
|
||||
shape: {
|
||||
cx: 300,
|
||||
cy: 200,
|
||||
width: 30,
|
||||
height: 30,
|
||||
},
|
||||
style: {
|
||||
fill: 'red',
|
||||
stroke: 'black'
|
||||
},
|
||||
composeCode: ''
|
||||
},
|
||||
{
|
||||
code: '6',
|
||||
name: 'd',
|
||||
type: 'Droplet',
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [0, 0],
|
||||
rotation: Math.PI/2,
|
||||
hide: false,
|
||||
},
|
||||
shape: {
|
||||
cx: 400,
|
||||
cy: 200,
|
||||
width: 20,
|
||||
height: 20,
|
||||
},
|
||||
style: {
|
||||
fill: 'red',
|
||||
stroke: 'black'
|
||||
},
|
||||
composeCode: ''
|
||||
},
|
||||
{
|
||||
code: '7',
|
||||
name: 'a',
|
||||
type: 'Rect',
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [100, 0],
|
||||
rotation: Math.PI/2,
|
||||
hide: false,
|
||||
},
|
||||
shape: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 30,
|
||||
height: 60
|
||||
},
|
||||
style: {
|
||||
fill: 'red',
|
||||
stroke: 'black'
|
||||
},
|
||||
composeCode: ''
|
||||
},
|
||||
],
|
||||
composeList: [
|
||||
{
|
||||
code: '100',
|
||||
type: 'Device',
|
||||
elementCodes: ['1', '2'],
|
||||
base: {
|
||||
scale: [0.5, 0.5],
|
||||
position: [100, 100],
|
||||
rotation: Math.PI/2,
|
||||
hide: false,
|
||||
},
|
||||
composeCode: '1000',
|
||||
},
|
||||
{
|
||||
code: '101',
|
||||
type: 'Device',
|
||||
elementCodes: ['3', '4'],
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [200, 0],
|
||||
rotation: 0,
|
||||
hide: false,
|
||||
},
|
||||
composeCode: '1000'
|
||||
},
|
||||
{
|
||||
code: '1000',
|
||||
type: 'Device',
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [0, 0],
|
||||
rotation: 0,
|
||||
hide: false
|
||||
},
|
||||
elementCodes: ['100', '101'],
|
||||
composeCode: ''
|
||||
}
|
||||
]
|
||||
}, opts);
|
||||
|
||||
window.document.oncontextmenu = function () {
|
||||
return false;
|
||||
};
|
||||
},
|
||||
onUpdate(e) {
|
||||
this.$iscs.update([
|
||||
{ status: 's1', code: '100', type: 'Device' },
|
||||
{ status: 's2', code: '101', type: 'Device' }
|
||||
]);
|
||||
setTimeout(e => {
|
||||
// this.$iscs.update([
|
||||
// { status: 's0', code: '100', type: 'Device' },
|
||||
// { status: 's0', code: '101', type: 'Device' },
|
||||
// ])
|
||||
}, 15000)
|
||||
},
|
||||
// 键盘快捷键事件
|
||||
onKeyboard(hook) {
|
||||
console.log(hook);
|
||||
},
|
||||
// 点击选择事件
|
||||
onClick(em) {
|
||||
this.selected = em;
|
||||
},
|
||||
// 右键点击事件
|
||||
onContextMenu(em) {
|
||||
this.selected = em;
|
||||
},
|
||||
doRemove() {
|
||||
if (this.selected) {
|
||||
this.$iscs.render([
|
||||
{
|
||||
model: this.selected.model,
|
||||
action: { order: orders.Delete, shapeType: shapeType.Compose }
|
||||
}
|
||||
]);
|
||||
}
|
||||
},
|
||||
doBinding() {
|
||||
const controller = this.$iscs.getController();
|
||||
const storage = controller.getStorage()
|
||||
const values = storage.values();
|
||||
if (values.length > 1) {
|
||||
const elem = {
|
||||
model: {
|
||||
code: utils.getUID('compose'),
|
||||
type: 'Device',
|
||||
elementCodes: values.map(el => el.model.code),
|
||||
base: {
|
||||
scale: [1, 1],
|
||||
position: [0, 0],
|
||||
rotation: 0,
|
||||
hide: false,
|
||||
},
|
||||
composeCode: '',
|
||||
},
|
||||
action: { order: orders.Binding, shapeType: shapeType.Compose }
|
||||
}
|
||||
this.$iscs.render([elem]);
|
||||
} else {
|
||||
this.$message.info('请选择两个及其以上数目元素');
|
||||
}
|
||||
},
|
||||
doUnbinding() {
|
||||
if (this.selected) {
|
||||
this.$iscs.render([
|
||||
{
|
||||
model: this.selected.model,
|
||||
action: { order: orders.Unbinding, shapeType: shapeType.Compose }
|
||||
}
|
||||
]);
|
||||
}
|
||||
},
|
||||
doSource() {
|
||||
console.log(this.$iscs.getSource());
|
||||
this.json = JSON.stringify(this.$iscs.getSource())
|
||||
},
|
||||
resize() {
|
||||
this.$nextTick(() => {
|
||||
this.$iscs && this.$iscs.resize({ width: this.width, height: this.height });
|
||||
});
|
||||
},
|
||||
back() {
|
||||
this.group = this.$route.query.group;
|
||||
this.$store.dispatch('training/over').then(() => {
|
||||
putJointTrainingSimulationUserNew(this.group).then(() => {
|
||||
this.$router.replace({ path: `/trainroom`, query: { group: this.group, lineCode:this.$route.query.lineCode } });
|
||||
exitFullscreen();
|
||||
});
|
||||
|
||||
});
|
||||
},
|
||||
destroy() {
|
||||
if (this.$iscs) {
|
||||
this.$iscs.destroy();
|
||||
this.$iscs = null;
|
||||
Vue.prototype.$iscs = null;
|
||||
}
|
||||
},
|
||||
stateMessage(val) {
|
||||
this.$iscs && this.$iscs.setDeviceStatus(val);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.iscs-button{
|
||||
position: absolute;
|
||||
float: right;
|
||||
right: 20px;
|
||||
bottom: 15px;
|
||||
}
|
||||
.iscs-canvas{
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user