Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
IoTSharp
IoTSharp
提交
b0ac5b0d
IoTSharp
项目概览
IoTSharp
/
IoTSharp
11 个月 前同步成功
通知
15
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
IoTSharp
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b0ac5b0d
编写于
2月 16, 2022
作者:
W
wq1234wq
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
toolbox
上级
bfb8e3d1
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
165 addition
and
170 deletion
+165
-170
IoTSharp/ClientApp/src/app/routes/device/devicegraph/devicegraph.component.html
.../app/routes/device/devicegraph/devicegraph.component.html
+7
-3
IoTSharp/ClientApp/src/app/routes/device/devicegraph/devicegraph.component.ts
...rc/app/routes/device/devicegraph/devicegraph.component.ts
+131
-165
IoTSharp/ClientApp/src/app/routes/device/devicegraph/panels/toolpaneldirective.ts
...pp/routes/device/devicegraph/panels/toolpaneldirective.ts
+8
-0
IoTSharp/ClientApp/src/app/routes/device/devicegraph/panels/toolspanel.ts
...pp/src/app/routes/device/devicegraph/panels/toolspanel.ts
+14
-1
IoTSharp/ClientApp/src/app/routes/routes.module.ts
IoTSharp/ClientApp/src/app/routes/routes.module.ts
+5
-1
未找到文件。
IoTSharp/ClientApp/src/app/routes/device/devicegraph/devicegraph.component.html
浏览文件 @
b0ac5b0d
<nz-header
nzTheme=
"light"
style=
"background-color: yellowgreen"
>
<button
nz-button
nzType=
"primary"
nzShape=
"round"
(click)=
"save
diagram
()"
>
保存
<i
nz-icon
nzType=
"download"
></i></button>
<button
nz-button
nzType=
"primary"
nzShape=
"round"
(click)=
"save
sense
()"
>
保存
<i
nz-icon
nzType=
"download"
></i></button>
</nz-header>
<nz-layout
class=
"inner-layout"
style=
"padding: 10px"
>
...
...
@@ -28,11 +28,15 @@
style=
"float: left; width: 100%"
></div>
</nz-content>
<nz-sider
nzTheme=
"light"
nzWidth=
"400px"
style=
"padding: 1rem"
>
<ng-template
toolpanelcontainer
>
</ng-template>
<nz-tabset>
<
!-- <
nz-tabset>
<nz-tab nzTitle="设备属性"></nz-tab>
<nz-tab nzTitle="端口配置">
<button nz-button [nzType]="'primary'" (click)="newport(-1)" acl [acl-ability]="37">
...
...
@@ -63,6 +67,6 @@
</st>
</nz-tab>
<nz-tab nzTitle="杂项"> </nz-tab>
</nz-tabset>
</nz-tabset>
-->
</nz-sider>
</nz-layout>
IoTSharp/ClientApp/src/app/routes/device/devicegraph/devicegraph.component.ts
浏览文件 @
b0ac5b0d
import
{
ChangeDetectorRef
,
Component
,
ElementRef
,
Input
,
OnInit
,
Type
,
ViewChild
}
from
'
@angular/core
'
;
import
{
ChangeDetectorRef
,
Component
,
ComponentFactoryResolver
,
ElementRef
,
Input
,
OnInit
,
Type
,
ViewChild
}
from
'
@angular/core
'
;
import
{
Graph
,
NodeView
,
Shape
}
from
'
@antv/x6
'
;
import
{
STColumn
,
STColumnTag
,
STComponent
,
STData
}
from
'
@delon/abc/st
'
;
...
...
@@ -6,6 +6,12 @@ import { SettingsService } from '@delon/theme';
import
{
Subscription
}
from
'
rxjs
'
;
import
{
DeviceItem
,
port
}
from
'
./models/data
'
;
import
{
Device
,
GateWay
}
from
'
./models/shape
'
;
import
{
ConnectionedgeComponent
}
from
'
./panels/connectionedge/connectionedge.component
'
;
import
{
DevivceshapeComponent
}
from
'
./panels/devivceshape/devivceshape.component
'
;
import
{
GatewayshapeComponent
}
from
'
./panels/gatewayshape/gatewayshape.component
'
;
import
{
PortshapeComponent
}
from
'
./panels/portshape/portshape.component
'
;
import
{
toolpaneldirective
}
from
'
./panels/toolpaneldirective
'
;
import
{
IToolsPanel
,
PanelItem
}
from
'
./panels/toolspanel
'
;
@
Component
({
selector
:
'
app-devicegraph
'
,
...
...
@@ -13,6 +19,28 @@ import { Device, GateWay } from './models/shape';
styleUrls
:
[
'
./devicegraph.component.less
'
],
})
export
class
DevicegraphComponent
implements
OnInit
{
@
ViewChild
(
toolpaneldirective
,
{
static
:
true
})
toolpanelcontainer
!
:
toolpaneldirective
;
//注册工具面板
toolpanels
=
[
new
PanelItem
<
IToolsPanel
>
(
'
device
'
,
DevivceshapeComponent
,
{
}),
new
PanelItem
<
IToolsPanel
>
(
'
gateway
'
,
GatewayshapeComponent
,
{
// someneedtransferdata: "yourdata,don't forget declara a @Input someneedtransferdata Property ",
}),
new
PanelItem
<
IToolsPanel
>
(
'
edge
'
,
ConnectionedgeComponent
,
{
// someneedtransferdata: "yourdata,don't forget declara a @Input someneedtransferdata Property ",
}),
new
PanelItem
<
IToolsPanel
>
(
'
port
'
,
PortshapeComponent
,
{
// someneedtransferdata: "yourdata,don't forget declara a @Input someneedtransferdata Property ",
})
];
selectedstyle
=
{
body
:
{
stroke
:
'
#00ff00
'
,
...
...
@@ -101,65 +129,10 @@ export class DevicegraphComponent implements OnInit {
GraphShape
:
''
,
},
ports
:
{
in
:
[{
portname
:
'
port1
'
,
id
:
1
,
type
:
1
,
iotype
:
1
}],
},
},
{
devicename
:
'
设备2
'
,
id
:
'
22
'
,
type
:
'
device
'
,
logo
:
'
control
'
,
image
:
'
./assets/logo.png
'
,
remark
:
'
这是一个设备,拖动它放到设计器上
'
,
prop
:
{
GraphStroke
:
'
#d9d9d9
'
,
GraphStrokeWidth
:
1
,
GraphTextFill
:
''
,
GraphTextFontSize
:
''
,
GraphPostionX
:
''
,
GraphPostionY
:
''
,
GraphFill
:
''
,
GraphTextRefX
:
''
,
GraphHeight
:
''
,
GraphTextRefY
:
''
,
GraphTextAnchor
:
''
,
GraphTextVerticalAnchor
:
''
,
GraphTextFontFamily
:
''
,
GraphWidth
:
''
,
GraphShape
:
''
,
},
ports
:
{
in
:
[{
portname
:
'
port1
'
,
id
:
2
,
type
:
1
,
iotype
:
1
}],
},
},
{
devicename
:
'
设备3
'
,
id
:
'
33
'
,
type
:
'
device
'
,
logo
:
'
control
'
,
image
:
'
./assets/logo.png
'
,
remark
:
'
这是一个设备,拖动它放到设计器上
'
,
prop
:
{
GraphStroke
:
'
#d9d9d9
'
,
GraphStrokeWidth
:
1
,
GraphTextFill
:
''
,
GraphTextFontSize
:
''
,
GraphPostionX
:
''
,
GraphPostionY
:
''
,
GraphFill
:
''
,
GraphTextRefX
:
''
,
GraphHeight
:
''
,
GraphTextRefY
:
''
,
GraphTextAnchor
:
''
,
GraphTextVerticalAnchor
:
''
,
GraphTextFontFamily
:
''
,
GraphWidth
:
''
,
GraphShape
:
''
,
},
ports
:
{
in
:
[{
portname
:
'
port1
'
,
id
:
3
,
type
:
1
,
iotype
:
1
}],
in
:
[{
portname
:
'
温度
'
,
id
:
'
1
'
,
type
:
1
,
iotype
:
1
}],
},
},
{
devicename
:
'
网关1
'
,
id
:
'
44
'
,
...
...
@@ -231,103 +204,26 @@ export class DevicegraphComponent implements OnInit {
},
ports
:
{
in
:
[
{
portname
:
'
port1
'
,
id
:
18
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port2
'
,
id
:
19
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port3
'
,
id
:
20
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port4
'
,
id
:
21
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port5
'
,
id
:
22
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port6
'
,
id
:
23
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port7
'
,
id
:
24
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port1
'
,
id
:
'
18
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port2
'
,
id
:
'
19
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port3
'
,
id
:
'
20
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port4
'
,
id
:
'
21
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port5
'
,
id
:
'
22
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port6
'
,
id
:
'
23
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port7
'
,
id
:
'
24
'
,
type
:
1
,
iotype
:
1
},
],
out
:
[
{
portname
:
'
port1
'
,
id
:
25
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port2
'
,
id
:
26
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port3
'
,
id
:
27
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port4
'
,
id
:
28
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port5
'
,
id
:
29
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port6
'
,
id
:
30
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port7
'
,
id
:
31
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port1
'
,
id
:
'
25
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port2
'
,
id
:
'
26
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port3
'
,
id
:
'
27
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port4
'
,
id
:
'
28
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port5
'
,
id
:
'
29
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port6
'
,
id
:
'
30
'
,
type
:
1
,
iotype
:
1
},
{
portname
:
'
port7
'
,
id
:
'
31
'
,
type
:
1
,
iotype
:
1
},
],
},
},
{
devicename
:
'
设备4
'
,
id
:
'
66
'
,
type
:
'
device
'
,
logo
:
'
control
'
,
image
:
'
./assets/logo.png
'
,
remark
:
'
这是一个设备,拖动它放到设计器上
'
,
prop
:
{
GraphStroke
:
'
#d9d9d9
'
,
GraphStrokeWidth
:
1
,
GraphTextFill
:
''
,
GraphTextFontSize
:
''
,
GraphPostionX
:
''
,
GraphPostionY
:
''
,
GraphFill
:
''
,
GraphTextRefX
:
''
,
GraphHeight
:
''
,
GraphTextRefY
:
''
,
GraphTextAnchor
:
''
,
GraphTextVerticalAnchor
:
''
,
GraphTextFontFamily
:
''
,
GraphWidth
:
''
,
GraphShape
:
''
,
},
ports
:
{
in
:
[{
portname
:
'
port1
'
,
id
:
32
,
type
:
1
,
iotype
:
1
}]
},
},
{
devicename
:
'
设备5
'
,
id
:
'
77
'
,
type
:
'
device
'
,
logo
:
'
control
'
,
image
:
'
./assets/logo.png
'
,
remark
:
'
这是一个设备,拖动它放到设计器上
'
,
prop
:
{
GraphStroke
:
'
#d9d9d9
'
,
GraphStrokeWidth
:
1
,
GraphTextFill
:
''
,
GraphTextFontSize
:
''
,
GraphPostionX
:
''
,
GraphPostionY
:
''
,
GraphFill
:
''
,
GraphTextRefX
:
''
,
GraphHeight
:
''
,
GraphTextRefY
:
''
,
GraphTextAnchor
:
''
,
GraphTextVerticalAnchor
:
''
,
GraphTextFontFamily
:
''
,
GraphWidth
:
''
,
GraphShape
:
''
,
},
ports
:
{
in
:
[{
portname
:
'
port1
'
,
id
:
33
,
type
:
1
,
iotype
:
1
}]
},
},
{
devicename
:
'
设备6
'
,
id
:
'
88
'
,
type
:
'
device
'
,
logo
:
'
control
'
,
image
:
'
./assets/logo.png
'
,
remark
:
'
这是一个设备,拖动它放到设计器上
'
,
prop
:
{
GraphStroke
:
'
#d9d9d9
'
,
GraphStrokeWidth
:
1
,
GraphTextFill
:
''
,
GraphTextFontSize
:
''
,
GraphPostionX
:
''
,
GraphPostionY
:
''
,
GraphFill
:
''
,
GraphTextRefX
:
''
,
GraphHeight
:
''
,
GraphTextRefY
:
''
,
GraphTextAnchor
:
''
,
GraphTextVerticalAnchor
:
''
,
GraphTextFontFamily
:
''
,
GraphWidth
:
''
,
GraphShape
:
''
,
},
ports
:
{
in
:
[{
portname
:
'
port1
'
,
id
:
34
,
type
:
1
,
iotype
:
1
}]
},
},
{
devicename
:
'
设备7
'
,
id
:
'
99
'
,
...
...
@@ -352,7 +248,7 @@ export class DevicegraphComponent implements OnInit {
GraphWidth
:
''
,
GraphShape
:
''
,
},
ports
:
{
in
:
[{
portname
:
'
port1
'
,
id
:
35
,
type
:
1
,
iotype
:
1
}]
},
ports
:
{
in
:
[{
portname
:
'
湿度
'
,
id
:
'
35
'
,
type
:
1
,
iotype
:
1
}]
},
},
];
...
...
@@ -402,17 +298,60 @@ export class DevicegraphComponent implements OnInit {
x
:
'
50%
'
,
y
:
'
10%
'
,
offset
:
{
x
:
-
0
,
y
:
-
0
},
onClick
:
this
.
toolbtnclick
,
//闭包了哟
onClick
:
this
.
toolbtnclick
,
},
},
];
constructor
(
cdr
:
ChangeDetectorRef
,
private
settingService
:
SettingsService
)
{
}
constructor
(
cdr
:
ChangeDetectorRef
,
private
settingService
:
SettingsService
,
private
componentFactoryResolver
:
ComponentFactoryResolver
)
{
}
newport
(
id
)
{
this
.
selcetedDevice
.
ports
.
in
=
[...
this
.
selcetedDevice
.
ports
.
in
,
{
id
:
'
0
'
,
portname
:
'
新端口
'
,
type
:
1
,
iotype
:
1
}];
console
.
log
(
this
.
selcetedDevice
.
ports
.
in
);
}
private
createpanel
(
panel
:
string
,
BizData
:
any
)
{
const
componentFactory
=
this
.
componentFactoryResolver
.
resolveComponentFactory
(
this
.
toolpanels
.
find
(
c
=>
c
.
name
===
panel
)?.
component
);
const
viewContainerRef
=
this
.
toolpanelcontainer
.
viewContainerRef
;
const
componentRef
=
viewContainerRef
.
createComponent
<
DevivceshapeComponent
>
(
componentFactory
);
componentRef
.
instance
.
BizData
=
BizData
;
// switch(panel){
// case 'device':{
// const componentFactory = this.componentFactoryResolver.resolveComponentFactory(DevivceshapeComponent);
// const viewContainerRef = this.toolpanelcontainer.viewContainerRef;
// const componentRef = viewContainerRef.createComponent<DevivceshapeComponent>(componentFactory);
// componentRef.instance.BizData=BizData;
// }
// break;
// case 'gateway':{
// const componentFactory = this.componentFactoryResolver.resolveComponentFactory(GatewayshapeComponent);
// const viewContainerRef = this.toolpanelcontainer.viewContainerRef;
// const componentRef = viewContainerRef.createComponent<DevivceshapeComponent>(componentFactory);
// componentRef.instance.BizData=BizData;
// } break;
// case 'edge':{
// const componentFactory = this.componentFactoryResolver.resolveComponentFactory(ConnectionedgeComponent);
// const viewContainerRef = this.toolpanelcontainer.viewContainerRef;
// const componentRef = viewContainerRef.createComponent<DevivceshapeComponent>(componentFactory);
// componentRef.instance.BizData=BizData;
// } break;
// case 'port':{
// const componentFactory = this.componentFactoryResolver.resolveComponentFactory(PortshapeComponent);
// const viewContainerRef = this.toolpanelcontainer.viewContainerRef;
// const componentRef = viewContainerRef.createComponent<DevivceshapeComponent>(componentFactory);
// componentRef.instance.BizData=BizData;
// }
// }
}
private
submit
(
i
:
STData
):
void
{
this
.
updateEdit
(
i
,
false
);
}
...
...
@@ -529,21 +468,47 @@ export class DevicegraphComponent implements OnInit {
});
this
.
graph
.
on
(
'
cell:click
'
,
({
e
,
x
,
y
,
cell
,
view
})
=>
{
var
device
=
cell
as
Device
;
var
port
=
device
.
getPort
(
e
.
target
.
attributes
.
port
.
value
);
device
.
setPortProp
(
port
.
id
,
'
attrs/circle
'
,
{
fill
:
'
#0000ff
'
,
stroke
:
'
#fff
'
})
var
matadata
=
cell
.
getProp
(
'
Biz
'
)
as
DeviceItem
;
if
(
matadata
)
{
switch
(
matadata
.
type
)
{
case
'
device
'
:
{
if
(
e
.
target
.
attributes
?.
port
?.
value
)
{
var
device
=
cell
as
Device
var
port
=
device
.
getPort
(
e
.
target
.
attributes
.
port
.
value
);
device
.
setPortProp
(
port
.
id
,
'
attrs/circle
'
,
{
fill
:
'
#0000ff
'
,
stroke
:
'
#fff
'
})
}
}
break
;
case
'
gateway
'
:
{
if
(
e
.
target
.
attributes
?.
port
?.
value
)
{
var
gateway
=
cell
as
GateWay
var
port
=
gateway
.
getPort
(
e
.
target
.
attributes
.
port
.
value
);
gateway
.
setPortProp
(
port
.
id
,
'
attrs/circle
'
,
{
fill
:
'
#0000ff
'
,
stroke
:
'
#fff
'
})
}
}
break
;
}
}
});
this
.
graph
.
on
(
'
edge:click
'
,
({
e
,
x
,
y
,
edge
,
view
})
=>
{
})
})
this
.
graph
.
on
(
'
cell:mousedown
'
,
({
cell
})
=>
{
// cell.removeTools(); //只读状态下移除Node中的操作按钮
});
this
.
graph
.
on
(
'
node:click
'
,
(
e
,
x
,
y
,
node
,
view
)
=>
{
this
.
createpanel
(
'
device
'
,
{});
var
matadata
=
e
.
node
.
getProp
(
'
Biz
'
);
this
.
graph
.
getNodes
;
...
...
@@ -625,6 +590,7 @@ export class DevicegraphComponent implements OnInit {
offsetX
:
this
.
dragEndlocation
.
offsetX
,
offsetY
:
this
.
dragEndlocation
.
offsetY
,
Biz
:
$event
.
dropData
,
portdata
:
{
group
:
{
in
:
{
...
...
@@ -665,7 +631,7 @@ export class DevicegraphComponent implements OnInit {
ports
:
ports
,
},
};
this
.
createshape
(
data
);
this
.
createshape
(
data
,
'
device
'
);
break
;
...
...
@@ -766,12 +732,12 @@ export class DevicegraphComponent implements OnInit {
ports
:
ports
,
},
};
this
.
createshape
(
data
);
this
.
createshape
(
data
,
'
gateway
'
);
break
;
}
}
createshape
(
data
:
any
)
{
createshape
(
data
:
any
,
type
:
string
)
{
var
node
=
this
.
graph
.
addNode
(
new
GateWay
({
label
:
data
.
label
,
...
...
@@ -797,7 +763,7 @@ export class DevicegraphComponent implements OnInit {
this
.
data
.
splice
(
this
.
data
.
indexOf
(
data
.
Biz
),
1
);
}
dragEnd
(
event
)
{
}
...
...
@@ -808,9 +774,9 @@ export class DevicegraphComponent implements OnInit {
dragEndlocation
:
any
;
load
()
{
}
load
sense
()
{
}
save
diagram
()
{
save
sense
()
{
var
edges
=
this
.
graph
.
getEdges
();
var
nodes
=
this
.
graph
.
getNodes
();
var
shapes
=
[];
...
...
IoTSharp/ClientApp/src/app/routes/device/devicegraph/panels/toolpaneldirective.ts
0 → 100644
浏览文件 @
b0ac5b0d
import
{
Directive
,
ViewContainerRef
}
from
'
@angular/core
'
;
@
Directive
({
selector
:
'
[toolpanelcontainer]
'
,
})
export
class
toolpaneldirective
{
constructor
(
public
viewContainerRef
:
ViewContainerRef
)
{
}
}
\ No newline at end of file
IoTSharp/ClientApp/src/app/routes/device/devicegraph/panels/toolspanel.ts
浏览文件 @
b0ac5b0d
...
...
@@ -11,4 +11,17 @@ export interface IToolsPanel {
export
interface
IBizData
{
}
\ No newline at end of file
}
import
{
Type
}
from
'
@angular/core
'
;
export
class
PanelItem
<
IToolsPanel
>
{
constructor
(
public
name
:
String
// it should be uniqe
,
public
component
:
Type
<
any
>
,
public
data
:
any
)
{}
}
\ No newline at end of file
IoTSharp/ClientApp/src/app/routes/routes.module.ts
浏览文件 @
b0ac5b0d
...
...
@@ -74,9 +74,13 @@ import { ConnectionedgeComponent } from './device/devicegraph/panels/connectione
import
{
DevivceshapeComponent
}
from
'
./device/devicegraph/panels/devivceshape/devivceshape.component
'
;
import
{
GatewayshapeComponent
}
from
'
./device/devicegraph/panels/gatewayshape/gatewayshape.component
'
;
import
{
PortshapeComponent
}
from
'
./device/devicegraph/panels/portshape/portshape.component
'
;
import
{
toolpaneldirective
}
from
'
./device/devicegraph/panels/toolpaneldirective
'
;
const
COMPONENTS
:
Array
<
Type
<
null
>>
=
[];
const
Directive
:
Type
<
void
>
[]
=
[
fielddirective
,
controldirective
];
const
Directive
:
Type
<
void
>
[]
=
[
fielddirective
,
controldirective
,
toolpaneldirective
];
@
NgModule
({
imports
:
[
SharedModule
,
RouteRoutingModule
,
G2BarModule
,
G2GaugeModule
,
NzIconModule
,
WidgetsModule
,
ClipboardModule
],
declarations
:
[
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录