优化代码
This commit is contained in:
parent
134ccdaded
commit
62cd098bdd
3
src/iscs_new/config/defaultState.js
Normal file
3
src/iscs_new/config/defaultState.js
Normal file
@ -0,0 +1,3 @@
|
||||
export default {
|
||||
|
||||
}
|
@ -253,7 +253,7 @@ export default class Controller extends Eventful {
|
||||
this.setCursorStyle('auto');
|
||||
}
|
||||
|
||||
// this._locking = false; 设置false时,拖动完成后,需要重新激活
|
||||
// this.setLocking(false); 设置false时,拖动完成后,需要重新激活
|
||||
this._target = null;
|
||||
}
|
||||
|
||||
@ -286,7 +286,7 @@ export default class Controller extends Eventful {
|
||||
click(e) {
|
||||
const event = new MouseEvent(e);
|
||||
if (event.code) {
|
||||
this._locking = true;
|
||||
this.setLocking(true)
|
||||
} else {
|
||||
this.selectHandle.clear();
|
||||
this.selectingHandle.clear();
|
||||
@ -340,6 +340,10 @@ export default class Controller extends Eventful {
|
||||
this._locking = false;
|
||||
}
|
||||
|
||||
setLocking(lock=false) {
|
||||
this._locking = lock;
|
||||
}
|
||||
|
||||
destroy () {
|
||||
this.dispose();
|
||||
}
|
||||
|
@ -2,10 +2,9 @@ import shapeType from '../constant/shapeType';
|
||||
|
||||
// 图形抽象层
|
||||
class AbstractShape {
|
||||
constructor({model, defaultStyle, option, shapeFactory}) {
|
||||
constructor({model, option, shapeFactory}) {
|
||||
this.model = model;
|
||||
this.option = option;
|
||||
this.defaultStyle = defaultStyle;
|
||||
this.shapeFactory = shapeFactory;
|
||||
}
|
||||
|
||||
@ -30,6 +29,12 @@ class AbstractShape {
|
||||
|
||||
// 销毁图形
|
||||
destroy() {}
|
||||
|
||||
// 获取包围框
|
||||
getBoundingRect() {}
|
||||
|
||||
// 获取依赖图形
|
||||
getDepShapes() {}
|
||||
}
|
||||
|
||||
export default AbstractShape;
|
||||
|
@ -6,6 +6,9 @@ export default {
|
||||
// number 0 控制图形的前后顺序。z2 值小的图形会被 z2 值大的图形覆盖。z2 相比 z1 优先级更低,而且不会创建新的 Canvas。
|
||||
z2: {
|
||||
prop: 'z', label: '层级 z2', type: 'select', defValue: 10,
|
||||
},
|
||||
name: {
|
||||
|
||||
},
|
||||
// boolean false 是否进行裁剪。
|
||||
culling: {
|
||||
|
@ -34,4 +34,4 @@ class FormBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
export default formBuilder;
|
||||
export default FormBuilder;
|
||||
|
@ -96,7 +96,7 @@ export default class ImageDraggable extends graphic.Group {
|
||||
this.handle.e.target &&
|
||||
this.offset) {
|
||||
if (!eventTool.isMiddleOrRightButtonOnMouseUpDown(e)) {
|
||||
const type = this.handle.e.target.model._type;
|
||||
const type = this.handle.e.target.model.type;
|
||||
const dx = Math.round(e.offsetX-this.offset.x);
|
||||
const dy = Math.round(e.offsetY-this.offset.y);
|
||||
|
||||
@ -112,7 +112,7 @@ export default class ImageDraggable extends graphic.Group {
|
||||
if (this.target &&
|
||||
this.handle.e.target &&
|
||||
this.offset) {
|
||||
const type = this.handle.e.target.model._type;
|
||||
const type = this.handle.e.target.model.type;
|
||||
const dx = Math.round(e.offsetX-this.offset.x);
|
||||
const dy = Math.round(e.offsetY-this.offset.y);
|
||||
this.setShape(...this.handle.normalizedDiff(dx, dy));
|
||||
|
@ -19,15 +19,7 @@ class Compose extends AbstractShape {
|
||||
|
||||
// 设置高亮
|
||||
active() {
|
||||
let unionRect = null;
|
||||
this.model.elementCodes.forEach(code => {
|
||||
const element = this.shapeFactory.getShapeByCode(code)
|
||||
if (element && element.instance && !element.instance.invisible) {
|
||||
const rect = element.instance.getBoundingRect().clone();
|
||||
unionRect ? unionRect.union(rect): (unionRect = rect);
|
||||
}
|
||||
})
|
||||
|
||||
const unionRect = this.getBoundingRect();
|
||||
if (unionRect) {
|
||||
this.shapeFactory.trigger(shapeEvent.ShowHightLight, unionRect);
|
||||
}
|
||||
@ -35,7 +27,7 @@ class Compose extends AbstractShape {
|
||||
|
||||
// 取消高亮
|
||||
inactive() {
|
||||
this.shapeFactory.trigger(shapeEvent.HideHightLight, new BoundingRect(0,0,0,0));
|
||||
this.shapeFactory.trigger(shapeEvent.HideHightLight);
|
||||
}
|
||||
|
||||
// 设置获取焦点
|
||||
@ -50,7 +42,35 @@ class Compose extends AbstractShape {
|
||||
setState(state) {}
|
||||
|
||||
// 销毁图形
|
||||
destroy() {}
|
||||
destroy() {
|
||||
this.model.elementCodes.forEach(code => {
|
||||
const element = this.shapeFactory.getShapeByCode(code);
|
||||
if (element &&
|
||||
element.model) {
|
||||
element.model.composeCode = '';
|
||||
element.instance.attr(element.model)
|
||||
}
|
||||
})
|
||||
this.model.elementCodes = [];
|
||||
}
|
||||
|
||||
// 获取依赖图形
|
||||
getDepShapes() {
|
||||
return this.model.elementCodes.map(code => this.shapeFactory.getShapeByCode(code)).filter(el => el)
|
||||
}
|
||||
|
||||
// 获取包围框
|
||||
getBoundingRect() {
|
||||
let unionRect = null;
|
||||
this.model.elementCodes.forEach(code => {
|
||||
const element = this.shapeFactory.getShapeByCode(code)
|
||||
if (element && element.instance && !element.instance.invisible) {
|
||||
const rect = element.instance.getBoundingRect().clone();
|
||||
unionRect ? unionRect.union(rect): (unionRect = rect);
|
||||
}
|
||||
})
|
||||
return unionRect;
|
||||
}
|
||||
}
|
||||
|
||||
export default Compose;
|
||||
|
@ -82,7 +82,7 @@ class Element extends AbstractShape {
|
||||
|
||||
// 取消高亮
|
||||
inactive() {
|
||||
this.shapeFactory.trigger(shapeEvent.HideHightLight, this.instance.getBoundingRect());
|
||||
this.shapeFactory.trigger(shapeEvent.HideHightLight);
|
||||
}
|
||||
|
||||
// 设置获取焦点
|
||||
@ -97,7 +97,28 @@ class Element extends AbstractShape {
|
||||
setState(state) {}
|
||||
|
||||
// 销毁图形
|
||||
destroy() {}
|
||||
destroy() {
|
||||
const compose = this.shapeFactory.getShapeByCode(this.model.composeCode);
|
||||
if (compose &&
|
||||
compose.model &&
|
||||
compose.model.elementCodes) {
|
||||
const index = compose.model.elementCodes.findIndex(this.model.code);
|
||||
if (index >= 0) {
|
||||
compose.model.elementCodes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取依赖图形
|
||||
getDepShapes() {
|
||||
return []
|
||||
}
|
||||
|
||||
|
||||
// 获取包围框
|
||||
getBoundingRect() {
|
||||
return this.instance.getBoundingRect();
|
||||
}
|
||||
}
|
||||
|
||||
export default Element;
|
||||
|
@ -7,6 +7,7 @@ import Element from './element';
|
||||
import shapeType from '../constant/shapeType';
|
||||
import shapeRender from '../constant/shapeRender';
|
||||
import shapeEvent from '../constant/shapeEvent';
|
||||
import orders from '../utils/orders';
|
||||
|
||||
const None = e => null;
|
||||
const shapeBuilderMap = {
|
||||
@ -14,6 +15,28 @@ const shapeBuilderMap = {
|
||||
[shapeType.Compose]: Compose
|
||||
}
|
||||
|
||||
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.ADD:
|
||||
list.push(model);
|
||||
break;
|
||||
case orders.UNBINDING:
|
||||
case orders.DELETE:
|
||||
i >= 0 && list.splice(i, 1);
|
||||
break;
|
||||
case orders.UPDATE:
|
||||
Object.assign(list[i]||{}, model)
|
||||
break;
|
||||
}
|
||||
|
||||
return updateModel;
|
||||
}
|
||||
class ShapeFactory extends Eventful {
|
||||
constructor(map) {
|
||||
super();
|
||||
@ -53,30 +76,21 @@ class ShapeFactory extends Eventful {
|
||||
return this;
|
||||
}
|
||||
|
||||
parse(source={}, defaultStyle={}, walk=None) {
|
||||
parse(source={}, walk=None) {
|
||||
try {
|
||||
this.source = source;
|
||||
zrUtil.each(source.elementList ||[], el => {
|
||||
walk(this.storageShape(this.createShape(el, defaultStyle, {...shapeRender, _type: shapeType.Element})));
|
||||
zrUtil.each(source.elementList ||[], model => {
|
||||
walk(this.storageShape(this.createShape(model, {...shapeRender, shapeType: shapeType.Element})));
|
||||
}, this);
|
||||
|
||||
zrUtil.each(source.composeList ||[], el => {
|
||||
this.storageShape(this.createShape(el, defaultStyle, {...shapeRender, _type: shapeType.Compose}));
|
||||
zrUtil.each(source.composeList ||[], model => {
|
||||
this.storageShape(this.createShape(model, {...shapeRender, shapeType: shapeType.Compose}));
|
||||
}, this);
|
||||
} catch (error) {
|
||||
console.error('[ERROR] ', error);
|
||||
}
|
||||
}
|
||||
|
||||
createShape(model={}, defaultStyle={}, option={}) {
|
||||
let shape = null;
|
||||
const shapeBuilder = shapeBuilderMap[option._type];
|
||||
if (shapeBuilder) {
|
||||
shape = new shapeBuilder({model, defaultStyle, option, shapeFactory: this});
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
storageShape(shape) {
|
||||
if (shape && shape.model) {
|
||||
this.mapShape[shape.model.code] = shape;
|
||||
@ -84,42 +98,32 @@ class ShapeFactory extends Eventful {
|
||||
return shape;
|
||||
}
|
||||
|
||||
createShape(model={}, option={}) {
|
||||
let shape = null;
|
||||
const shapeBuilder = shapeBuilderMap[option.shapeType];
|
||||
if (shapeBuilder) {
|
||||
shape = new shapeBuilder({model, option, shapeFactory: this});
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
removeShape(shape) {
|
||||
if (shape && shape.model) {
|
||||
this.trigger(shapeEvent.HideHightLight);
|
||||
shape.destroy();
|
||||
delete this.mapShape[shape.model.code];
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
updateSource(model={}) {
|
||||
switch (model._type) {
|
||||
case shapeType.Compose: return { model: update2List(model, 'composeList'), option: {...shapeRender, _type: shapeType.Compose}};
|
||||
case shapeType.Element: return { model: update2List(model, 'elementList'), option: {...shapeRender, _type: shapeType.Element}};
|
||||
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;
|
||||
}
|
||||
|
||||
update2List(model={}, name='') {
|
||||
const list = this.source[name];
|
||||
const dispose = model._dispose;
|
||||
const entries = Object.entries(model).filter(el => !['_type', '_dispose'].includes(el[0]));
|
||||
const cleanModel = Object.fromEntries(entries);
|
||||
let retModel = cleanModel;
|
||||
|
||||
if (list && list instanceof Array) {
|
||||
const i = list.findIndex(elem => { return elem.code == model.code; });
|
||||
if (i < 0) {
|
||||
list.push(cleanModel)
|
||||
} else {
|
||||
retModel = dispose ? list.splice(i, 1) : Object.assign(list[i], cleanModel);
|
||||
}
|
||||
} else {
|
||||
source[name] = [cleanModel];
|
||||
}
|
||||
|
||||
return retModel;
|
||||
}
|
||||
|
||||
getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
@ -8,7 +8,9 @@ import Option from './option';
|
||||
import Controller from './controller';
|
||||
import StateHandle from './stateHandle';
|
||||
import ShapeFactory from './factory';
|
||||
import defaultStyle from './config/defaultStyle';
|
||||
import orders from './utils/orders';
|
||||
import shapeRender from './constant/shapeRender';
|
||||
import shapeType from './constant/shapeType';
|
||||
|
||||
const renderer = 'canvas';
|
||||
const devicePixelRatio = 1;
|
||||
@ -31,12 +33,6 @@ class JMap {
|
||||
__Keydown: '__keydown__'
|
||||
};
|
||||
|
||||
// 默认状态
|
||||
this.defaultState = this.loadDefaultState();
|
||||
|
||||
// 默认皮肤
|
||||
this.defaultStyle = this.loadDefaultStyle();
|
||||
|
||||
// 初始化Map实例
|
||||
this.initMapInstance(opts);
|
||||
}
|
||||
@ -75,14 +71,6 @@ class JMap {
|
||||
};
|
||||
}
|
||||
|
||||
loadDefaultState(state) {
|
||||
return {};
|
||||
}
|
||||
|
||||
loadDefaultStyle(style) {
|
||||
return defaultStyle;
|
||||
}
|
||||
|
||||
setMap(templates=[], source={}, eventOpts={}) {
|
||||
// 绑定事件
|
||||
this.$controller.enable(eventOpts);
|
||||
@ -154,7 +142,7 @@ class JMap {
|
||||
repaint(source={}) {
|
||||
this.$shapeFactory.clear();
|
||||
this.$painter.clear();
|
||||
this.$shapeFactory.parse(source, this.defaultStyle, shape => {
|
||||
this.$shapeFactory.parse(source, shape => {
|
||||
if (shape) {
|
||||
this.$painter.add(shape);
|
||||
}
|
||||
@ -162,19 +150,35 @@ class JMap {
|
||||
}
|
||||
|
||||
render(list=[]) {
|
||||
list.forEach(el => {
|
||||
const dispose = el._dispose;
|
||||
const oldShape = this.$shapeFactory.getShapeByCode(el.code);
|
||||
const block = this.$shapeFactory.updateSource(el);
|
||||
list.forEach(({model, action}) => {
|
||||
const updateModel = this.$shapeFactory.updateSource(model, action);
|
||||
const shape = this.$shapeFactory.getShapeByCode(updateModel.code);
|
||||
const deps = shape.getDepShapes();
|
||||
const oldShape = this.$shapeFactory.removeShape(shape);
|
||||
const newShape = this.$shapeFactory.createShape(updateModel, {...shapeRender, ...action});
|
||||
|
||||
if (dispose) {
|
||||
this.$painter.remove(oldShape);
|
||||
this.$shapeFactory.removeShape(oldShape);
|
||||
} else if (block) {
|
||||
const createShape = this.$shapeFactory.createShape(block.model, block.option);
|
||||
this.$painter.remove(oldShape);
|
||||
this.$shapeFactory.storageShape(createShape)
|
||||
this.$painter.add(createShape);
|
||||
if (updateModel) {
|
||||
switch(action.order) {
|
||||
case orders.ADD:
|
||||
this.$shapeFactory.storageShape(newShape)
|
||||
this.$painter.add(newShape);
|
||||
break;
|
||||
case orders.DELETE:
|
||||
this.$painter.remove(oldShape);
|
||||
deps.forEach(shape => {
|
||||
this.$shapeFactory.updateSource(shape.model, {...action, shapeType: shapeType.Element});
|
||||
this.$painter.remove(shape);
|
||||
});
|
||||
break;
|
||||
case orders.UPDATE:
|
||||
this.$painter.remove(oldShape);
|
||||
this.$shapeFactory.storageShape(newShape)
|
||||
this.$painter.add(newShape);
|
||||
break;
|
||||
case orders.UNBINDING:
|
||||
this.$painter.remove(oldShape);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -228,10 +232,6 @@ class JMap {
|
||||
return this.defaultState;
|
||||
}
|
||||
|
||||
getDefaultStyle() {
|
||||
return this.defaultStyle;
|
||||
}
|
||||
|
||||
getShapeByCode(code) {
|
||||
return this.$shapeFactory.getShapeByCode(code);
|
||||
}
|
||||
|
@ -47,28 +47,26 @@ class Painter extends Group {
|
||||
}
|
||||
|
||||
add(shape) {
|
||||
try {
|
||||
if (shape && shape.model) {
|
||||
const shapeLevel = this.mapShapeLevel[shape.model.type];
|
||||
shapeLevel.add(shape.instance);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (shapeLevel && shape.instance) {
|
||||
shapeLevel.add(shape.instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remove(shape) {
|
||||
try {
|
||||
if (shape && shape.model) {
|
||||
const shapeLevel = this.mapShapeLevel[shape.model.type];
|
||||
shapeLevel.remove(shape.instance);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (shapeLevel && shape.instance) {
|
||||
shapeLevel.remove(shape.instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update(shape) {
|
||||
try {
|
||||
if (shape && shape.model) {
|
||||
//
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,16 +15,16 @@ export default class SelectHandle {
|
||||
|
||||
onSelected(e) {
|
||||
if (e.target) {
|
||||
this.e = {...e };
|
||||
this.e = {...e};
|
||||
if (['Control'].includes(this.$controller.getKeyStr())) {
|
||||
console.log(this.$controller.isSelected(e.target.model.code));
|
||||
if (this.$controller.isSelected(e.target.model.code)) {
|
||||
this.delSelected(e.target);
|
||||
} else {
|
||||
this.addSelected(e.target);
|
||||
}
|
||||
} else if (this.$controller.selectingHandle.isSelecting()) {
|
||||
this.addSelected(e.target);
|
||||
} else {
|
||||
console.log(2222)
|
||||
this.clear();
|
||||
this.addSelected(e.target);
|
||||
}
|
||||
@ -33,23 +33,11 @@ export default class SelectHandle {
|
||||
|
||||
addSelected(target) {
|
||||
this.$controller.storage.set(target.model.code, target);
|
||||
|
||||
target.active();
|
||||
|
||||
if (!target.highLightInstance) {
|
||||
target.highLightInstance = this.createSelected(target);
|
||||
this.$painter.addToLevel(shapeLayer.HightLight)(target.highLightInstance);
|
||||
}
|
||||
}
|
||||
|
||||
delSelected(target) {
|
||||
target.inactive();
|
||||
|
||||
if (target.highLightInstance) {
|
||||
this.$painter.removeFromLevel(shapeLayer.HightLight)(target.highLightInstance);
|
||||
target.highLightInstance = null;
|
||||
}
|
||||
|
||||
this.$controller.storage.delete(target.model.code);
|
||||
}
|
||||
|
||||
@ -61,7 +49,7 @@ export default class SelectHandle {
|
||||
|
||||
createSelected(target) {
|
||||
if (this.$map.draggle) {
|
||||
switch (target.model._type) {
|
||||
switch (target.model.type) {
|
||||
case graphic.Line:
|
||||
return new LineDraggable(this);
|
||||
case graphic.Image:
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as graphic from './core/graphic.js';
|
||||
import shapeRender from './constant/shapeRender';
|
||||
import shapeLayer from './constant/shapeLayer';
|
||||
import shapeType from './constant/shapeType.js';
|
||||
|
||||
function shapeStyleBuilder() {
|
||||
return {
|
||||
@ -56,11 +57,11 @@ export default class SelectingHandle {
|
||||
|
||||
const selectingRect = this.selecting.getBoundingRect();
|
||||
Object.values(this.$map.getMapShape()).forEach(el => {
|
||||
if (el.instance && selectingRect.intersect(el.instance.getBoundingRect())) {
|
||||
if (el.model.composeCode) {
|
||||
this.setSelected(this.$map.getShapeByCode(el.model.composeCode));
|
||||
} else {
|
||||
if (el.model && this.checkSelectingRectContainShape(selectingRect, el)) {
|
||||
console.log(1111111);
|
||||
if (!el.model.composeCode) {
|
||||
this.setSelected(el);
|
||||
this.$controller.setLocking(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -78,6 +79,11 @@ export default class SelectingHandle {
|
||||
this.$painter.removeFromLevel(shapeLayer.SelectIng)(this.selecting);
|
||||
}
|
||||
|
||||
checkSelectingRectContainShape(rect, shape) {
|
||||
const shapeRect = shape.getBoundingRect();
|
||||
return shapeRect? rect.intersect(shapeRect): false;
|
||||
}
|
||||
|
||||
normalizedArea(begin, end) {
|
||||
const options = this.$map.getOption();
|
||||
const x = (begin.x + options.offsetX) / options.scaleRate;
|
||||
|
7
src/iscs_new/utils/orders.js
Normal file
7
src/iscs_new/utils/orders.js
Normal file
@ -0,0 +1,7 @@
|
||||
export default {
|
||||
ADD: '__ADD__',
|
||||
DELETE: '__DEL__',
|
||||
UPDATE: '__UPT__',
|
||||
BINDING: '__BINDING__',
|
||||
UNBINDING: '__UNBINDING__',
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
<el-row>
|
||||
<el-input type="textarea" :rows="4" v-model="json" />
|
||||
<el-button @click="doRemove"> 删除 </el-button>
|
||||
<el-button @click="doUnbinding">解绑</el-button>
|
||||
<el-button @click="doSource"> 源数据 </el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
@ -14,9 +15,12 @@
|
||||
<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 { mapGetters } from 'vuex';
|
||||
import { exitFullscreen } from '@/utils/screen';
|
||||
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@ -173,6 +177,7 @@ export default {
|
||||
onSelected(em) {
|
||||
if (em) {
|
||||
this.selected = this.$iscs.getShapeByCode(em.code)
|
||||
console.log(em, this.selected);
|
||||
}
|
||||
},
|
||||
// 右键点击事件
|
||||
@ -208,7 +213,22 @@ export default {
|
||||
},
|
||||
doRemove() {
|
||||
if (this.selected) {
|
||||
this.$iscs.render({...model, _dispose: true});
|
||||
this.$iscs.render([
|
||||
{
|
||||
model: this.selected.model,
|
||||
action: { order: orders.DELETE, shapeType: shapeType.Compose }
|
||||
}
|
||||
]);
|
||||
}
|
||||
},
|
||||
doUnbinding() {
|
||||
if (this.selected) {
|
||||
this.$iscs.render([
|
||||
{
|
||||
model: this.selected.model,
|
||||
action: { order: orders.UNBINDING, shapeType: shapeType.Compose }
|
||||
}
|
||||
]);
|
||||
}
|
||||
},
|
||||
doSource() {
|
||||
|
Loading…
Reference in New Issue
Block a user