Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
B
bigDataSystem
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张伯涛
bigDataSystem
Commits
24d54da4
Commit
24d54da4
authored
Dec 16, 2024
by
LiXuyang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
落标检查-跳转运维
parent
462faf29
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
727 additions
and
27 deletions
+727
-27
index.vue
...s/dataStandards/labelDropInspection/labelDetail/index.vue
+5
-7
index.vue
...ataStandards/labelDropInspection/labelOperation/index.vue
+544
-20
operation.data.ts
...ards/labelDropInspection/labelOperation/operation.data.ts
+34
-0
operationData.ts
...dards/labelDropInspection/labelOperation/operationData.ts
+144
-0
No files found.
src/views/dataStandards/labelDropInspection/labelDetail/index.vue
View file @
24d54da4
...
...
@@ -257,13 +257,11 @@
});
}
// 跳转运维
// async function handleOperation() {
// localStorage.setItem('type', '4');
// await router.push({
// path: '/dataIntegration/taskOM/index',
// });
// window.location.reload();
// }
function
handleOperation
()
{
router
.
push
({
path
:
'/dataStandards/labelDropInspection/labelOperation'
,
});
}
// 添加数据标准 弹窗
function
addDataStandard
()
{
...
...
src/views/dataStandards/labelDropInspection/labelOperation/index.vue
View file @
24d54da4
<
template
>
<PageWrapper
dense
contentFullHeight
fixedHeight
>
<PageWrapper
dense
>
<template
#
headerContent
>
<div
class=
"header"
>
<div
class=
"title"
>
所有数据质量任务
</div>
<div
class=
"title"
>
所有数据质量任务
</div>
<Select
mode=
"multiple"
:max-tag-count=
"1"
...
...
@@ -32,11 +32,14 @@
<Select
class=
"select"
v-model:value=
"queryParams.runType"
:options=
"runTypeOptions"
/>
</div>
<div
class=
"extra"
>
<a-button
class=
"refresh"
><SyncOutlined
/>
刷新
</a-button>
<a-button
class=
"refresh"
@
click=
"handleRefresh"
>
<SyncOutlined
/>
刷新
</a-button>
</div>
</div>
<div
class=
"h-tabs"
>
<div
class=
"tab-chart"
></div>
<div
class=
"tab-chart"
id=
"tab-chart"
></div>
<div
class=
"tab-txt"
:class=
"
{ active: checked === index }"
...
...
@@ -56,34 +59,195 @@
</div>
</div>
<div
class=
"detail"
>
<div
class=
"table"
>
<div
class=
"column"
>
<Checkbox
class=
"checkBox"
/>
<Icon
class=
"icon"
/>
<div
class=
"table w-1/3"
>
<div
class=
"header"
>
<Checkbox
class=
"checkBox"
v-model:checked=
"checkAll"
@
change=
"handleSelectAll"
/>
<Input
class=
"input"
v-model:value=
"searchKey"
placeholder=
"关键字搜索"
>
<template
#
suffix
>
<SearchOutlined
/>
</
template
>
</Input>
<div
class=
"bt-group"
>
<!--纸飞机-->
<a-button
type=
"link"
:disabled=
"getDisabled()"
@
click=
"handleUpload()"
class=
"button"
>
<Icon
class=
"icon"
icon=
"ion:paper-plane-outline"
/>
</a-button>
<!--上线-->
<a-button
type=
"link"
:disabled=
"getDisabled()"
@
click=
"handleUpload()"
class=
"button"
>
<Icon
class=
"icon"
icon=
"ion:cloud-upload-outline"
@
click=
"handleUp()"
/>
</a-button>
<!--下线-->
<a-button
type=
"link"
:disabled=
"getDisabled()"
@
click=
"handleUpload()"
class=
"button"
>
<Icon
class=
"icon"
icon=
"ion:cloud-download-outline"
@
click=
"handleDown()"
/>
</a-button>
<!--运行/计时-->
<a-button
type=
"link"
:disabled=
"getDisabled()"
@
click=
"handleUpload()"
class=
"button"
>
<Icon
class=
"icon"
icon=
"ion:play-circle-outline"
@
click=
"handleDebug()"
/>
</a-button>
<!--禁用/删除-->
<a-button
type=
"link"
:disabled=
"getDisabled()"
@
click=
"handleUpload()"
class=
"button"
>
<Icon
class=
"icon"
icon=
"ion:ban-outline"
@
click=
"handleDelete()"
/>
</a-button>
<!--运行-->
<a-button
type=
"link"
:disabled=
"getDisabled()"
@
click=
"handleUpload()"
class=
"button"
>
<Icon
class=
"icon"
icon=
"ion:caret-forward-outline"
@
click=
"handleRun()"
/>
</a-button>
</div>
</div>
<div
class=
"column"
:class=
"{ active: selectIndex === index }"
v-for=
"(item, index) in leftList"
:key=
"item"
@
click=
"handleColumn(index, item)"
>
<Checkbox
class=
"checkBox"
v-model:checked=
"item.checked"
/>
<RiseOutlined
class=
"icon"
/>
<div
class=
"txt"
>
<div
class=
"title"
>
{{ item.title }}
</div>
<div
class=
"des"
>
{{ item.des }}
</div>
</div>
<div
class=
"type"
>
<div
class=
"type"
:class=
"{ 'active-type': selectIndex === index }"
>
{{ item.type }}
</div>
<div
class=
"num"
>
{{ item.num }}
</div>
</div>
</div>
<div
class=
"info w-2/3"
>
<div
class=
"flex"
>
<div
class=
"flex-1 title"
>
<RiseOutlined
class=
"h-icon"
/>
<div
class=
"h-txt"
>
<div
class=
"h-des"
>
{{ data.title }}
</div>
<div
class=
"h-path"
>
{{ data.des }}
</div>
</div>
</div>
<div
class=
"h-bt-group"
>
<CaretRightOutlined
class=
"icon"
/>
<EditOutlined
class=
"icon"
/>
</div>
</div>
<div
class=
"data"
>
<Row
:gutter=
"[10, 15]"
>
<Col
:span=
"12"
>
<div
class=
"info-field"
>
<div
class=
"label"
>
调度周期:
</div>
<div>
{{ data.cycle ? data.cycle : '-' }}
</div>
</div>
</Col>
<Col
:span=
"12"
>
<div
class=
"info-field"
>
<div
class=
"label"
>
发布状态:
</div>
<div>
{{ data.status }}
</div>
</div>
</Col>
<Col
:span=
"12"
>
<div
class=
"info-field"
>
<div
class=
"label"
>
创建者:
</div>
<div>
{{ data.createBy }}
</div>
</div>
</Col>
<Col
:span=
"12"
>
<div
class=
"info-field"
>
<div
class=
"label"
>
创建时间:
</div>
<div>
{{ data.createTime }}
</div>
</div>
</Col>
</Row>
</div>
<div
class=
"run-table"
>
<BasicTable
@
register=
"runTable"
>
<
template
#
toolbar
>
<a-button
:disabled=
"getRunSelectRows().length
<
=
0
"
type=
"link"
>
重跑
</a-button>
<a-button
:disabled=
"getRunSelectRows().length
<
=
0
"
type=
"link"
>
错误恢复
</a-button>
<a-button
:disabled=
"getRunSelectRows().length
<
=
0
"
type=
"link"
>
取消执行
</a-button>
</
template
>
<
template
#
runStatus=
"{ text, record }"
>
<div
class=
"icon-column"
>
<CheckCircleFilled
v-if=
"text === '成功'"
class=
"icon"
/>
<CloseCircleFilled
v-else
class=
"icon-fail"
/>
<span>
{{
text
}}
</span>
</div>
</
template
>
<
template
#
checkResult=
"{ text, record }"
>
<div
class=
"icon-column"
>
<CheckCircleFilled
v-if=
"text === '合格'"
class=
"icon"
/>
<CloseCircleFilled
v-else
class=
"icon-fail"
/>
<span>
{{
text
}}
</span>
</div>
</
template
>
<
template
#
bodyCell=
"{ column, record }"
>
<template
v-if=
"column.key === 'action'"
>
<TableAction
:actions=
"[
{
label: '查看',
},
{
label: '重跑',
},
{
label: '取消执行',
},
]"
/>
</
template
>
</template>
</BasicTable>
</div>
</div>
</div>
</template>
</PageWrapper>
</template>
<
script
lang=
"ts"
setup
>
import
{
Select
,
RadioGroup
,
RadioButton
,
Checkbox
}
from
'ant-design-vue'
;
import
{
SyncOutlined
}
from
'@ant-design/icons-vue'
;
import
{
Select
,
RadioGroup
,
RadioButton
,
Checkbox
,
Input
,
Row
,
Col
}
from
'ant-design-vue'
;
import
{
SyncOutlined
,
RiseOutlined
,
SearchOutlined
,
CaretRightOutlined
,
EditOutlined
,
CloseCircleFilled
,
CheckCircleFilled
,
}
from
'@ant-design/icons-vue'
;
import
{
searchOptions
,
daysOptions
,
...
...
@@ -91,18 +255,22 @@
resultOptions
,
runTypeOptions
,
headList
,
leftList
,
}
from
'./operationData'
;
import
PageWrapper
from
'@/components/Page/src/PageWrapper.vue'
;
import
{
ref
}
from
'vue'
;
import
{
onMounted
,
ref
}
from
'vue'
;
import
Icon
from
'@/components/Icon/Icon.vue'
;
import
BasicTable
from
'@/components/Table/src/BasicTable.vue'
;
import
{
useTable
}
from
'@/components/Table'
;
import
{
tableListtab1
}
from
'@/views/auditLog/mock'
;
import
{
columns
,
searchFormSchema
}
from
'@/views/auditLog/audi.data'
;
import
{
BasicTableProps
,
useTable
}
from
'@/components/Table'
;
import
{
runTableColumn
}
from
'@/views/dataStandards/labelDropInspection/labelOperation/operation.data'
;
import
TableAction
from
'@/components/Table/src/components/TableAction.vue'
;
import
{
useMessage
}
from
'@/hooks/web/useMessage'
;
import
*
as
echarts
from
'echarts'
;
// 初始化
const
{
createMessage
,
createConfirm
}
=
useMessage
();
const
queryParams
=
ref
({
searchArea
:
[],
searchArea
:
[
'个人工作区'
,
'共享工作区'
],
timeType
:
'调度时间'
,
days
:
'最近30d'
,
uploadStatus
:
'全部'
,
...
...
@@ -111,6 +279,15 @@
});
const
checked
=
ref
(
0
);
// 数据
const
data
=
ref
(
leftList
.
value
[
0
]);
const
checkAll
=
ref
();
const
searchKey
=
ref
();
const
selectIndex
=
ref
(
0
);
const
dataList
=
ref
(
leftList
.
value
[
0
].
list
);
onMounted
(()
=>
{
renderingEcharts
();
});
/**
* 方法
*/
...
...
@@ -119,9 +296,195 @@
checked
.
value
=
index
;
// 更新数据
}
// 全选
function
handleSelectAll
()
{
if
(
checkAll
.
value
)
{
leftList
.
value
.
forEach
((
item
)
=>
{
item
.
checked
=
true
;
});
}
else
{
leftList
.
value
.
forEach
((
item
)
=>
{
item
.
checked
=
false
;
});
}
}
// 点击切换
function
handleColumn
(
index
,
item
)
{
selectIndex
.
value
=
index
;
data
.
value
=
item
;
dataList
.
value
=
item
.
list
;
reload
();
}
// 刷新
function
handleRefresh
()
{
createMessage
.
success
(
'刷新成功!'
);
}
// 发布
function
handleUpload
()
{
createConfirm
({
iconType
:
'warning'
,
title
:
'确认发布'
,
content
:
'确认批量发布选中数据吗?'
,
onOk
()
{
createMessage
.
success
(
'发布成功!'
);
reload
();
},
});
}
// 上线
function
handleUp
()
{
createConfirm
({
iconType
:
'warning'
,
title
:
'确认上线'
,
content
:
'确认批量上线选中数据吗?'
,
onOk
()
{
createMessage
.
success
(
'上线成功!'
);
reload
();
},
});
}
// 下线
function
handleDown
()
{
createConfirm
({
iconType
:
'warning'
,
title
:
'确认下线'
,
content
:
'确认批量下线选中数据吗?'
,
onOk
()
{
createMessage
.
success
(
'下线成功!'
);
reload
();
},
});
}
// 调试
function
handleDebug
()
{
createConfirm
({
iconType
:
'warning'
,
title
:
'确认调试'
,
content
:
'确认批量调试选中数据吗?'
,
onOk
()
{
createMessage
.
success
(
'调试成功!'
);
reload
();
},
});
}
// 调试
function
handleDelete
()
{
createConfirm
({
iconType
:
'warning'
,
title
:
'确认删除'
,
content
:
'确认批量删除选中数据吗?'
,
onOk
()
{
createMessage
.
success
(
'删除成功!'
);
reload
();
},
});
}
// 调试
function
handleRun
()
{
createConfirm
({
iconType
:
'warning'
,
title
:
'确认运行'
,
content
:
'确认批量运行选中数据吗?'
,
onOk
()
{
createMessage
.
success
(
'运行成功!'
);
reload
();
},
});
}
// 查看是否禁用
function
getDisabled
()
{
let
flag
=
true
;
leftList
.
value
.
forEach
((
item
)
=>
{
if
(
item
.
checked
)
{
flag
=
false
;
}
});
return
flag
;
}
// echarts图
function
renderingEcharts
()
{
const
data
=
headList
.
map
((
item
)
=>
{
return
{
value
:
item
.
num
,
name
:
item
.
des
,
};
});
console
.
log
(
'map'
,
data
);
type
EChartsOption
=
echarts
.
EChartsOption
;
const
chartDom
=
document
.
getElementById
(
'tab-chart'
)
!
;
const
myChart
=
echarts
.
init
(
chartDom
);
let
option
:
EChartsOption
;
option
=
{
tooltip
:
{
trigger
:
'item'
,
},
series
:
[
{
type
:
'pie'
,
radius
:
[
'40%'
,
'70%'
],
avoidLabelOverlap
:
false
,
label
:
{
show
:
false
,
position
:
'center'
,
},
labelLine
:
{
show
:
false
,
},
data
:
data
,
},
],
};
option
&&
myChart
.
setOption
(
option
);
}
/**
* 列表
*/
const
[
runTable
,
{
getSelectRows
:
getRunSelectRows
,
reload
}]
=
useTable
({
title
:
'执行记录'
,
// 定高
// scroll: { y: 150 },
// 数据
api
:
async
(
params
)
=>
{
console
.
log
(
'params:'
,
params
);
const
response
=
{
pageNu
:
'1'
,
pageSize
:
'10'
,
pages
:
'1'
,
total
:
dataList
.
value
.
length
,
code
:
''
,
message
:
''
,
data
:
dataList
.
value
,
};
return
{
...
response
};
},
// 列
columns
:
runTableColumn
,
rowSelection
:
true
,
striped
:
false
,
// 搜索
showIndexColumn
:
false
,
showTableSetting
:
false
,
bordered
:
true
,
actionColumn
:
{
width
:
200
,
title
:
'操作'
,
dataIndex
:
'action'
,
},
}
as
BasicTableProps
);
</
script
>
<
style
scoped
>
...
...
@@ -132,10 +495,12 @@
.title
{
font-size
:
18px
;
}
.select
{
width
:
250px
;
}
}
.search
{
display
:
flex
;
...
...
@@ -143,6 +508,7 @@
display
:
flex
;
gap
:
10px
;
flex
:
1
;
.group
{
.button
{
}
...
...
@@ -158,35 +524,193 @@
align-items
:
center
;
}
}
.extra
{
.refresh
{
}
}
}
.h-tabs
{
display
:
flex
;
justify-content
:
center
;
gap
:
20px
;
margin
:
20px
0
;
.tab-chart
{
width
:
200px
;
height
:
100px
;
}
.tab-txt
{
width
:
160px
;
padding
:
10px
0
10px
15px
;
cursor
:
pointer
;
.txt-num
{
font-size
:
20px
;
font-weight
:
bolder
;
}
.txt-des
{
margin-top
:
10px
;
}
}
.active
{
background-color
:
#f4f7fb
;
border-bottom
:
2px
solid
#319ffd
;
}
}
.detail
{
display
:
flex
;
border
:
2px
solid
#ebeef6
;
.header
{
padding
:
2px
15px
;
display
:
flex
;
gap
:
10px
;
background-color
:
#f4f7fb
;
.checkBox
{
}
.input
{
flex
:
1
;
}
.bt-group
{
display
:
flex
;
gap
:
10px
;
.button
{
padding
:
0
;
}
.icon
{
}
}
}
.table
{
.column
{
padding
:
4px
15px
;
display
:
flex
;
gap
:
10px
;
align-items
:
center
;
.icon
{
font-size
:
20px
;
color
:
#27b94d
;
}
.txt
{
flex
:
1
;
.title
{
font-size
:
16px
;
font-weight
:
bolder
;
}
.des
{
color
:
#b6bac6
;
}
}
.type
{
padding
:
2px
8px
;
border-radius
:
11px
;
background-color
:
#dff0ff
;
color
:
#6fb9ff
;
}
.active-type
{
background-color
:
#ffffff
;
color
:
black
;
}
.num
{
padding
:
2px
8px
;
border-radius
:
12px
;
background-color
:
#ffffff
;
}
}
.active
{
background-color
:
#e8ecf7
;
}
}
.info
{
border-left
:
2px
solid
#ebeef6
;
padding
:
5px
15px
;
.title
{
display
:
flex
;
flex-direction
:
row
;
gap
:
10px
;
.h-back
{
font-size
:
20px
;
}
.h-icon
{
font-size
:
30px
;
color
:
#27b94d
;
}
.h-txt
{
display
:
flex
;
flex-direction
:
column
;
.h-des
{
font-weight
:
bolder
;
}
.h-path
{
color
:
#9ea4b4
;
}
}
}
.h-bt-group
{
display
:
flex
;
gap
:
10px
;
.icon
{
font-size
:
20px
!important
;
cursor
:
pointer
;
}
}
.data
{
padding
:
15px
;
.info-field
{
padding
:
0
15px
;
display
:
flex
;
gap
:
10px
;
.label
{
width
:
120px
;
}
}
}
.run-table
{
.icon-column
{
display
:
flex
;
justify-content
:
center
;
gap
:
4px
;
.icon
{
color
:
#46c498
;
}
.icon-fail
{
color
:
#d35e5e
;
}
}
}
}
}
</
style
>
src/views/dataStandards/labelDropInspection/labelOperation/operation.data.ts
View file @
24d54da4
import
{
BasicColumn
}
from
'@/components/Table'
;
export
const
runTableColumn
:
BasicColumn
[]
=
[
{
title
:
'调度时间'
,
dataIndex
:
'time'
,
},
{
title
:
'执行时间'
,
dataIndex
:
'runTime'
,
},
{
title
:
'执行时长'
,
dataIndex
:
'runLength'
,
width
:
80
,
},
{
title
:
'运行状态'
,
dataIndex
:
'runStatus'
,
width
:
80
,
slots
:
{
customRender
:
'runStatus'
},
},
{
title
:
'执行模式'
,
dataIndex
:
'runMode'
,
width
:
120
,
},
{
title
:
'检查结果'
,
dataIndex
:
'checkResult'
,
width
:
80
,
slots
:
{
customRender
:
'checkResult'
},
},
];
src/views/dataStandards/labelDropInspection/labelOperation/operationData.ts
View file @
24d54da4
import
{
ref
}
from
"vue"
;
export
const
searchOptions
=
[
{
label
:
'个人工作区'
,
...
...
@@ -94,3 +96,145 @@ export const headList = [
icon
:
'ant-design:check-circle-outlined'
,
},
];
export
const
leftList
=
ref
([
{
title
:
'db32'
,
des
:
'admin-个人工作区/db32'
,
type
:
'已下线'
,
num
:
'2'
,
cycle
:
null
,
status
:
'未发布'
,
createBy
:
'admin'
,
createTime
:
'2022/09/28 11:51:31'
,
list
:
[
{
time
:
'2023-07-15 18:42:11'
,
runTime
:
'2023-05-23 07:16:25'
,
runLength
:
'6s'
,
runStatus
:
'成功'
,
runMode
:
'重跑'
,
checkResult
:
'合格'
,
},
{
time
:
'2023-09-10 04:29:09'
,
runTime
:
'2023-03-22 01:35:51'
,
runLength
:
'1s'
,
runStatus
:
'失败'
,
runMode
:
'自动执行'
,
checkResult
:
'不合格'
,
},
],
},
{
title
:
'Trinotest'
,
des
:
'admin-个人工作区/一级文件夹/二级文件夹/Trinotest'
,
type
:
'已上线'
,
num
:
'7'
,
cycle
:
null
,
status
:
'已发布'
,
createBy
:
'admin'
,
createTime
:
'2023/11/06 11:33:51'
,
list
:
[
{
time
:
'2024-02-01 09:28:33'
,
runTime
:
'2023-12-13 08:22:40'
,
runLength
:
'9s'
,
runStatus
:
'成功'
,
runMode
:
'手动执行'
,
checkResult
:
'合格'
,
},
{
time
:
'2024-03-14 06:11:09'
,
runTime
:
'2023-10-05 11:48:15'
,
runLength
:
'3s'
,
runStatus
:
'成功'
,
runMode
:
'自动执行'
,
checkResult
:
'合格'
,
},
],
},
{
title
:
'bingtest'
,
des
:
'admin-个人工作区/bingtest'
,
type
:
'已上线'
,
num
:
'18'
,
cycle
:
null
,
status
:
'未发布'
,
createBy
:
'admin'
,
createTime
:
'2023/05/16 15:42:17'
,
list
:
[
{
time
:
'2023-06-17 17:22:53'
,
runTime
:
'2024-01-04 04:56:10'
,
runLength
:
'7s'
,
runStatus
:
'失败'
,
runMode
:
'重跑'
,
checkResult
:
'不合格'
,
},
{
time
:
'2024-01-30 13:47:01'
,
runTime
:
'2023-12-12 09:14:39'
,
runLength
:
'10s'
,
runStatus
:
'超时'
,
runMode
:
'自动执行'
,
checkResult
:
'合格'
,
},
],
},
{
title
:
'编码规则检查'
,
des
:
'admin-个人工作区/编码规则检查'
,
type
:
'已下线'
,
num
:
'1'
,
cycle
:
null
,
status
:
'已发布'
,
createBy
:
'admin'
,
createTime
:
'2023/08/16 10:26:59'
,
list
:
[
{
time
:
'2023-11-04 01:12:47'
,
runTime
:
'2023-09-11 02:36:25'
,
runLength
:
'5s'
,
runStatus
:
'失败'
,
runMode
:
'手动执行'
,
checkResult
:
'不合格'
,
},
{
time
:
'2023-12-21 23:39:30'
,
runTime
:
'2023-08-18 10:13:58'
,
runLength
:
'8s'
,
runStatus
:
'成功'
,
runMode
:
'重跑'
,
checkResult
:
'合格'
,
},
],
},
{
title
:
'检查性别不是男性的人数'
,
des
:
'admin-个人工作区/案例/检查性别不是男性的人数'
,
type
:
'已上线'
,
num
:
'1'
,
cycle
:
null
,
status
:
'未发布'
,
createBy
:
'admin'
,
createTime
:
'2022/09/2811:51:31'
,
list
:
[
{
time
:
'2024-02-25 14:25:38'
,
runTime
:
'2023-06-11 03:08:47'
,
runLength
:
'2s'
,
runStatus
:
'成功'
,
runMode
:
'自动执行'
,
checkResult
:
'不合格'
,
},
{
time
:
'2024-04-20 06:15:22'
,
runTime
:
'2023-05-17 11:28:09'
,
runLength
:
'4s'
,
runStatus
:
'超时'
,
runMode
:
'重跑'
,
checkResult
:
'合格'
,
},
],
},
]);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment