Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
jobily
IoTSharp
提交
50b24fb4
I
IoTSharp
项目概览
jobily
/
IoTSharp
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
I
IoTSharp
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
50b24fb4
编写于
10月 14, 2022
作者:
W
wq1234wq
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
产品列表
上级
bc2a9d0c
变更
11
显示空白变更内容
内联
并排
Showing
11 changed file
with
229 addition
and
87 deletion
+229
-87
IoTSharp/ClientApp/src/app/routes/devices/deviceform/deviceform.component.html
...c/app/routes/devices/deviceform/deviceform.component.html
+7
-3
IoTSharp/ClientApp/src/app/routes/devices/deviceform/deviceform.component.ts
...src/app/routes/devices/deviceform/deviceform.component.ts
+11
-5
IoTSharp/ClientApp/src/app/routes/produce/producedatadictionaryform/producedatadictionaryform.component.ts
...datadictionaryform/producedatadictionaryform.component.ts
+29
-7
IoTSharp/ClientApp/src/app/routes/produce/producedataform/producedataform.component.html
...es/produce/producedataform/producedataform.component.html
+3
-3
IoTSharp/ClientApp/src/app/routes/produce/producedataform/producedataform.component.ts
...utes/produce/producedataform/producedataform.component.ts
+7
-2
IoTSharp/ClientApp/src/app/routes/produce/produceform/produceform.component.ts
...c/app/routes/produce/produceform/produceform.component.ts
+35
-20
IoTSharp/ClientApp/src/app/routes/produce/producelist/producelist.component.html
...app/routes/produce/producelist/producelist.component.html
+8
-2
IoTSharp/ClientApp/src/app/routes/produce/producelist/producelist.component.ts
...c/app/routes/produce/producelist/producelist.component.ts
+68
-7
IoTSharp/Controllers/ProducesController.cs
IoTSharp/Controllers/ProducesController.cs
+57
-38
IoTSharp/Dtos/ProduceDto.cs
IoTSharp/Dtos/ProduceDto.cs
+3
-0
IoTSharp/Models/IPageParam.cs
IoTSharp/Models/IPageParam.cs
+1
-0
未找到文件。
IoTSharp/ClientApp/src/app/routes/devices/deviceform/deviceform.component.html
浏览文件 @
50b24fb4
...
...
@@ -12,6 +12,12 @@
</nz-select>
</se>
<se
label=
"所属产品"
error=
"所属产品"
>
<nz-select
formControlName=
"produceId"
placeholder=
"所属产品"
>
<nz-option
*ngFor=
"let o of deviceproduce"
[nzValue]=
"o.id"
[nzLabel]=
"o.name"
></nz-option>
</nz-select>
</se>
<se
label=
"超时"
error=
"超时"
required
>
<nz-input-number
formControlName=
"timeout"
[nzMin]=
"0"
[nzStep]=
"1"
></nz-input-number>
</se>
...
...
@@ -32,8 +38,6 @@
<button
nz-button
type=
"reset"
(click)=
"close()"
>
取消
</button>
<button
nz-button
nzType=
"primary"
[disabled]=
"form.invalid"
type=
"submit"
[nzLoading]=
"submitting"
>
保存
</button>
<button
nz-button
nzType=
"primary"
type=
"button"
(click)=
"createcert($event)"
*ngIf=
"data.id!=='00000000-0000-0000-0000-000000000000'&&data.identityType==='X509Certificate'"
>
<i
nz-icon
nzType=
"download"
></i>
证书生成
</button>
</se>
</form>
</nz-card>
...
...
IoTSharp/ClientApp/src/app/routes/devices/deviceform/deviceform.component.ts
浏览文件 @
50b24fb4
...
...
@@ -32,7 +32,7 @@ export class DeviceformComponent implements OnInit {
)
{}
form
!
:
FormGroup
;
submitting
=
false
;
deviceproduce
=
[];
devicemodel
:
devicemodel
[]
=
[];
data
:
deviceitem
=
{
...
...
@@ -47,20 +47,26 @@ export class DeviceformComponent implements OnInit {
name
:
[
null
,
[
Validators
.
required
,
Validators
.
pattern
(
/^
(\s
+
\S
+
\s
*
)
*
(?!\s)
.*$/
)]],
deviceType
:
[
null
,
[
Validators
.
required
]],
customerId
:
[
null
,
[]],
// deviceModel
Id: [null, []],
produce
Id
:
[
null
,
[]],
timeout
:
[
300
,
[]],
id
:
[
Guid
.
EMPTY
,
[]],
identityType
:
[
Guid
.
EMPTY
,
[]]
});
this
.
_httpClient
.
post
(
'
api/deviceModel/index
'
,
{
offset
:
0
,
limit
:
100
}).
subscribe
({
// this._httpClient.post('api/deviceModel/index', { offset: 0, limit: 100 }).subscribe({
// next: next => {
// this.devicemodel = next.data.rows;
// },
// error: error => {},
// complete: () => {}
// });
this
.
_httpClient
.
get
(
'
api/produces/list
'
,
{
offset
:
0
,
limit
:
-
1
}).
subscribe
({
next
:
next
=>
{
this
.
device
model
=
next
.
data
.
rows
;
this
.
device
produce
=
next
.
data
.
rows
;
},
error
:
error
=>
{},
complete
:
()
=>
{}
});
if
(
this
.
params
.
id
!==
Guid
.
EMPTY
)
{
concat
(
this
.
_httpClient
.
get
<
appmessage
<
deviceitem
>>
(
'
api/Devices/
'
+
this
.
params
.
id
).
pipe
(
...
...
IoTSharp/ClientApp/src/app/routes/produce/producedatadictionaryform/producedatadictionaryform.component.ts
浏览文件 @
50b24fb4
...
...
@@ -18,7 +18,7 @@ export class ProducedatadictionaryformComponent implements OnInit {
dictionaryData
:
STData
[]
=
[]
columns
:
STColumn
[]
=
[
{
title
:
'
id
'
,
index
:
'
id
'
},
{
title
:
'
字段名称
'
,
index
:
'
keyName
'
,
render
:
'
keyNameTpl
'
},
{
title
:
'
字段显示名称
'
,
index
:
'
displayName
'
,
render
:
'
displayNameTpl
'
},
{
title
:
'
单位
'
,
index
:
'
unit
'
,
render
:
'
unitTpl
'
},
...
...
@@ -72,11 +72,19 @@ export class ProducedatadictionaryformComponent implements OnInit {
ngOnInit
():
void
{
this
.
http
.
get
<
appmessage
<
any
>>
(
'
api/produces/getProduceDictionary?produceId=
'
+
this
.
id
).
subscribe
(
next
=>
{
this
.
http
.
get
<
appmessage
<
any
>>
(
'
api/produces/getProduceDictionary?produceId=
'
+
this
.
id
)
.
subscribe
({
next
:
next
=>
{
this
.
dictionaryData
=
next
.
data
;
},
error
=>
{
},
error
:
error
=>
{
},
complete
:
()
=>
{
}
},
()
=>
{
});
});
}
private
submit
(
i
:
STData
):
void
{
...
...
@@ -99,7 +107,21 @@ export class ProducedatadictionaryformComponent implements OnInit {
}
saveRow
()
{
this
.
http
.
post
(
'
api/produces/editProduceDictionary
'
,
{
produceId
:
this
.
id
,
dictionProduceDictionaryDataaryData
:
this
.
dictionaryData
}).
subscribe
(
next
=>
{
},
error
=>
{
},
()
=>
{
});
this
.
http
.
post
(
'
api/produces/editProduceDictionary
'
,
{
produceId
:
this
.
id
,
produceDictionaryData
:
this
.
dictionaryData
}).
subscribe
(
{
next
:
next
=>
{
if
(
next
.
code
===
10000
)
{
this
.
msg
.
success
(
'
保存成功
'
)
}
else
{
this
.
msg
.
warning
(
'
保存失败:
'
+
next
.
msg
)
}
},
error
:
error
=>
{
},
complete
:
()
=>
{
}
}
);
}
}
IoTSharp/ClientApp/src/app/routes/produce/producedataform/producedataform.component.html
浏览文件 @
50b24fb4
...
...
@@ -27,8 +27,8 @@
</ng-template>
<ng-template
st-row=
"ColumnDataTypeTpl"
let-item
let-index=
"index"
>
<nz-select
*ngIf=
"item.edit"
[ngModel]=
"item.
dataT
ype"
(ngModelChange)=
"st.setRow(index, {
dataT
ype: $event })"
>
<nz-select
*ngIf=
"item.edit"
[ngModel]=
"item.
t
ype"
(ngModelChange)=
"st.setRow(index, {
t
ype: $event })"
>
<nz-option
nzValue=
"Boolean"
nzLabel=
"Boolean"
></nz-option>
<nz-option
nzValue=
"String"
nzLabel=
"String"
></nz-option>
<nz-option
nzValue=
"Long"
nzLabel=
"Long"
></nz-option>
...
...
@@ -39,7 +39,7 @@
<nz-option
nzValue=
"DateTime"
nzLabel=
"DateTime"
></nz-option>
</nz-select>
<ng-container
*ngIf=
"!item.edit"
>
{{ item.
dataT
ype}}
</ng-container>
<ng-container
*ngIf=
"!item.edit"
>
{{ item.
t
ype}}
</ng-container>
</ng-template>
...
...
IoTSharp/ClientApp/src/app/routes/produce/producedataform/producedataform.component.ts
浏览文件 @
50b24fb4
...
...
@@ -19,7 +19,7 @@ export class ProducedataformComponent implements OnInit {
columns
:
STColumn
[]
=
[
{
title
:
'
KeyName
'
,
index
:
'
keyName
'
,
render
:
'
ColumnTitleTpl
'
},
{
title
:
'
数据侧
'
,
index
:
'
dataSide
'
,
render
:
'
ColumnTypeTpl
'
},
{
title
:
'
数据类型
'
,
index
:
'
dataT
ype
'
,
render
:
'
ColumnDataTypeTpl
'
},
{
title
:
'
数据类型
'
,
index
:
'
t
ype
'
,
render
:
'
ColumnDataTypeTpl
'
},
{
title
:
'
操作
'
,
buttons
:
[
...
...
@@ -88,7 +88,12 @@ export class ProducedataformComponent implements OnInit {
}
saveRow
()
{
this
.
http
.
post
(
'
api/produces/editProduceData
'
,
{
produceId
:
this
.
id
,
produceData
:
this
.
produceData
}).
subscribe
(
next
=>
{
},
error
=>
{
},
()
=>
{
});
this
.
http
.
post
(
'
api/produces/editProduceData
'
,
{
produceId
:
this
.
id
,
produceData
:
this
.
produceData
}).
subscribe
(
next
=>
{
if
(
next
.
code
===
10000
)
{
this
.
msg
.
success
(
'
保存成功
'
)
}
else
{
this
.
msg
.
warning
(
'
保存失败:
'
+
next
.
msg
)
}},
error
=>
{
},
()
=>
{
});
}
...
...
IoTSharp/ClientApp/src/app/routes/produce/produceform/produceform.component.ts
浏览文件 @
50b24fb4
...
...
@@ -81,29 +81,44 @@ export class ProduceformComponent implements OnInit {
}
if
(
this
.
id
==
Guid
.
EMPTY
)
{
this
.
_httpClient
.
post
(
'
api/produces/save
'
,
this
.
form
.
value
).
subscribe
(
()
=>
{
{
next
:
next
=>
{
this
.
submitting
=
false
;
if
(
next
.
code
===
10000
)
{
this
.
msg
.
create
(
'
success
'
,
'
产品新增成功
'
);
this
.
close
();
}
},
()
=>
{
error
:
error
=>
{
this
.
msg
.
create
(
'
error
'
,
'
产品新增失败
'
);
this
.
close
();
},
()
=>
{
}
complete
:
()
=>
{
}
}
);
}
else
{
this
.
_httpClient
.
put
(
'
api/produces/update
'
,
this
.
form
.
value
).
subscribe
(
()
=>
{
{
next
:
next
=>
{
this
.
submitting
=
false
;
if
(
next
.
code
===
10000
)
{
this
.
msg
.
create
(
'
success
'
,
'
产品修改成功
'
);
this
.
close
();
}
},
()
=>
{
error
:
error
=>
{
this
.
msg
.
create
(
'
error
'
,
'
产品修改失败
'
);
this
.
close
();
},
()
=>
{
}
complete
:
()
=>
{
}
}
);
}
}
...
...
IoTSharp/ClientApp/src/app/routes/produce/producelist/producelist.component.html
浏览文件 @
50b24fb4
...
...
@@ -35,8 +35,14 @@
<span>{{ 'button.new' | translate }}</span>
</button>-->
<st
#st
[columns]=
"columns"
[data]=
"url"
ps=
"20"
[page]=
"page"
[req]=
"req"
[res]=
"res"
>
<st
#st
[columns]=
"columns"
[data]=
"url"
ps=
"20"
[page]=
"page"
[req]=
"req"
[res]=
"res"
[expand]=
"expand"
expandAccordion
(change)=
"onchange($event)"
>
<ng-template
#expand
let-item
let-index=
"index"
let-column=
"column"
>
<st
[data]=
"item.devices"
[columns]=
"devicecolumns"
>
</st>
</ng-template>
</st>
</nz-card>
</page-header>
IoTSharp/ClientApp/src/app/routes/produce/producelist/producelist.component.ts
浏览文件 @
50b24fb4
import
{
ChangeDetectorRef
,
Component
,
OnInit
,
TemplateRef
,
ViewChild
}
from
'
@angular/core
'
;
import
{
Router
}
from
'
@angular/router
'
;
import
{
STPage
,
STReq
,
STRes
,
STComponent
,
STColumn
,
STData
}
from
'
@delon/abc/st
'
;
import
{
STPage
,
STReq
,
STRes
,
STComponent
,
STColumn
,
STData
,
STChange
,
STColumnTag
,
STColumnBadge
}
from
'
@delon/abc/st
'
;
import
{
ModalHelper
,
SettingsService
,
_HttpClient
}
from
'
@delon/theme
'
;
import
{
Guid
}
from
'
guid-typescript
'
;
import
{
NzDrawerService
}
from
'
ng-zorro-antd/drawer
'
;
...
...
@@ -78,6 +78,36 @@ export class ProducelistComponent implements OnInit {
list
:
'
data.rows
'
}
};
BADGE
:
STColumnBadge
=
{
true
:
{
text
:
'
在线
'
,
color
:
'
success
'
},
false
:
{
text
:
'
离线
'
,
color
:
'
error
'
}
};
TAG
:
STColumnTag
=
{
AccessToken
:
{
text
:
'
AccessToken
'
,
color
:
'
green
'
},
X509Certificate
:
{
text
:
'
X509Certificate
'
,
color
:
'
blue
'
}
};
DeviceTAG
:
STColumnTag
=
{
Device
:
{
text
:
'
设备
'
,
color
:
'
green
'
},
Gateway
:
{
text
:
'
网关
'
,
color
:
'
blue
'
}
};
devicecolumns
:
STColumn
[]
=
[
{
title
:
'
id
'
,
index
:
'
id
'
,
},
{
title
:
'
名称
'
,
index
:
'
name
'
,
render
:
'
name
'
,
type
:
'
link
'
,
},
{
title
:
'
设备类型
'
,
index
:
'
deviceType
'
,
type
:
'
tag
'
,
tag
:
this
.
DeviceTAG
},
{
title
:
'
在线状态
'
,
index
:
'
active
'
,
type
:
'
badge
'
,
badge
:
this
.
BADGE
,
sort
:
true
},
{
title
:
'
最后活动时间
'
,
index
:
'
lastActivityDateTime
'
,
type
:
'
date
'
},
{
title
:
'
认证方式
'
,
index
:
'
identityType
'
,
type
:
'
tag
'
,
tag
:
this
.
TAG
},
]
@
ViewChild
(
'
st
'
,
{
static
:
true
})
st
!
:
STComponent
;
...
...
@@ -169,7 +199,7 @@ export class ProducelistComponent implements OnInit {
editattr
(
id
:
string
):
void
{
var
{
nzMaskClosable
,
width
}
=
this
.
settingService
.
getData
(
'
drawerconfig
'
);
var
title
=
'
属性编辑
'
;
var
title
=
'
属性编辑
'
;
const
drawerRef
=
this
.
drawerService
.
create
<
ProducedataformComponent
,
{
id
:
string
},
string
>
({
nzTitle
:
title
,
nzContent
:
ProducedataformComponent
,
...
...
@@ -189,14 +219,45 @@ export class ProducelistComponent implements OnInit {
this
.
getData
();
});
}
onchange
(
$events
:
STChange
):
void
{
switch
(
$events
.
type
)
{
case
'
expand
'
:
if
(
$events
.
expand
.
expand
)
{
}
break
;
}
}
getdevices
()
{
this
.
http
.
post
(
''
,
{}).
subscribe
({
next
:
next
=>
{
},
error
:
error
=>
{
},
complete
:
()
=>
{
}
})
}
editdic
(
id
:
string
):
void
{
var
{
nzMaskClosable
,
width
}
=
this
.
settingService
.
getData
(
'
drawerconfig
'
);
var
title
=
'
字典编辑
'
;
var
title
=
'
字典编辑
'
;
const
drawerRef
=
this
.
drawerService
.
create
<
ProducedatadictionaryformComponent
,
{
id
:
string
},
string
>
({
nzTitle
:
title
,
nzContent
:
ProducedatadictionaryformComponent
,
...
...
IoTSharp/Controllers/ProducesController.cs
浏览文件 @
50b24fb4
...
...
@@ -51,10 +51,31 @@ namespace IoTSharp.Controllers
condition
=
condition
.
And
(
x
=>
x
.
Name
.
Contains
(
m
.
Name
));
}
if
(
m
.
limit
>
1
)
{
return
new
ApiResult
<
PagedData
<
ProduceDto
>>(
ApiCode
.
Success
,
"OK"
,
new
PagedData
<
ProduceDto
>
{
total
=
await
_context
.
Produces
.
CountAsync
(
condition
),
rows
=
_context
.
Produces
.
Where
(
condition
).
Where
(
condition
).
Skip
((
m
.
offset
)
*
m
.
limit
).
Take
(
m
.
limit
)
rows
=
_context
.
Produces
.
Include
(
c
=>
c
.
Devices
).
Where
(
condition
).
Skip
((
m
.
offset
)
*
m
.
limit
).
Take
(
m
.
limit
)
.
ToList
().
Select
(
c
=>
new
ProduceDto
{
Id
=
c
.
Id
,
DefaultIdentityType
=
c
.
DefaultIdentityType
,
DefaultTimeout
=
c
.
DefaultTimeout
,
Description
=
c
.
Description
,
Name
=
c
.
Name
,
Devices
=
c
.
Devices
}).
ToList
()
});
}
else
{
return
new
ApiResult
<
PagedData
<
ProduceDto
>>(
ApiCode
.
Success
,
"OK"
,
new
PagedData
<
ProduceDto
>
{
total
=
await
_context
.
Produces
.
CountAsync
(),
rows
=
_context
.
Produces
.
Where
(
condition
)
.
ToList
().
Select
(
c
=>
new
ProduceDto
{
Id
=
c
.
Id
,
...
...
@@ -65,6 +86,9 @@ namespace IoTSharp.Controllers
}).
ToList
()
});
}
}
...
...
@@ -95,9 +119,7 @@ namespace IoTSharp.Controllers
{
return
new
ApiResult
<
ProduceAddDto
>(
ApiCode
.
Success
,
"OK"
,
new
ProduceAddDto
{
Id
=
result
.
Id
,
Icon
=
result
.
Icon
,
DefaultDeviceType
=
result
.
DefaultDeviceType
,
DefaultIdentityType
=
result
.
DefaultIdentityType
,
...
...
@@ -238,9 +260,6 @@ namespace IoTSharp.Controllers
var
result
=
_context
.
DataStorage
.
Where
(
c
=>
c
.
DeviceId
==
Guid
.
Empty
).
Select
(
c
=>
new
ProduceDataItemDto
{
KeyName
=
c
.
KeyName
,
DataSide
=
c
.
DataSide
,
Type
=
c
.
Type
}).
ToList
();
return
new
ApiResult
<
List
<
ProduceDataItemDto
>>(
ApiCode
.
Success
,
"Ok"
,
result
);
}
return
new
ApiResult
<
List
<
ProduceDataItemDto
>>(
ApiCode
.
CantFindObject
,
"Produce is not found"
,
null
);
...
...
@@ -263,14 +282,12 @@ namespace IoTSharp.Controllers
var
produce
=
await
_context
.
Produces
.
Include
(
c
=>
c
.
DefaultAttributes
).
SingleOrDefaultAsync
(
c
=>
c
.
Id
==
dto
.
produceId
);
if
(
produce
!=
null
)
{
var
pds
=
_context
.
ProduceDatas
.
Where
(
c
=>
c
.
Owner
==
produce
);
var
pds
=
_context
.
ProduceDatas
.
Where
(
c
=>
c
.
Owner
==
produce
)
.
ToList
()
;
if
(
dto
.
ProduceData
!=
null
&&
dto
.
ProduceData
.
Length
>
0
)
{
var
data
=
dto
.
ProduceData
.
Select
(
c
=>
new
ProduceData
{
KeyName
=
c
.
KeyName
,
DataSide
=
c
.
DataSide
,
Type
=
c
.
Type
,
Owner
=
produce
,
DateTime
=
DateTime
.
Now
}).
ToList
();
foreach
(
var
item
in
data
)
{
var
pd
=
pds
.
FirstOrDefault
(
c
=>
c
.
KeyName
.
ToLower
()
==
item
.
KeyName
.
ToLower
());
if
(
pd
!=
null
)
{
...
...
@@ -369,7 +386,7 @@ namespace IoTSharp.Controllers
}
else
{
var
produceDictionary
=
await
_context
.
ProduceDictionaries
.
SingleOrDefaultAsync
(
c
=>
c
.
Id
==
item
.
Id
);
var
produceDictionary
=
await
_context
.
ProduceDictionaries
.
SingleOrDefaultAsync
(
c
=>
c
.
Id
==
item
.
Id
);
if
(
produceDictionary
!=
null
)
{
produceDictionary
.
KeyName
=
item
.
KeyName
;
...
...
@@ -388,10 +405,12 @@ namespace IoTSharp.Controllers
}
}
}
_context
.
Produces
.
Update
(
produce
);
var
deletedic
=
produce
.
Dictionaries
.
Select
(
c
=>
c
.
Id
).
Except
(
dto
.
ProduceDictionaryData
.
Select
(
c
=>
c
.
Id
)).
ToList
();
_context
.
ProduceDictionaries
.
RemoveRange
(
produce
.
Dictionaries
.
Where
(
c
=>
deletedic
.
Any
(
p
=>
p
==
c
.
Id
)).
ToList
());
await
_context
.
SaveChangesAsync
();
return
new
ApiResult
<
bool
>(
ApiCode
.
Success
,
"Ok"
,
true
);
}
return
new
ApiResult
<
bool
>(
ApiCode
.
CantFindObject
,
"Produce is not found"
,
false
);
}
...
...
IoTSharp/Dtos/ProduceDto.cs
浏览文件 @
50b24fb4
...
...
@@ -21,5 +21,8 @@ namespace IoTSharp.Dtos
public
IdentityType
DefaultIdentityType
{
get
;
set
;
}
=
IdentityType
.
AccessToken
;
public
string
Description
{
get
;
set
;
}
public
List
<
Device
>
Devices
{
get
;
set
;
}
}
}
IoTSharp/Models/IPageParam.cs
浏览文件 @
50b24fb4
...
...
@@ -57,6 +57,7 @@ namespace IoTSharp.Controllers.Models
public
bool
OnlyActive
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
}
public
class
RulePageParam
:
IPageParam
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录