Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
mes-kanban
Project
Project
Details
Activity
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
ximai
mes-kanban
Commits
127e9578
Commit
127e9578
authored
Nov 06, 2024
by
沈翠玲
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
希迈对接接口
parent
196744fe
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
493 additions
and
449 deletions
+493
-449
deviceAbnormal.tsx
...oductionComprehens/components/Abnormal/deviceAbnormal.tsx
+45
-45
index.tsx
...kanban/productionComprehens/components/Abnormal/index.tsx
+5
-15
productAbnormal.tsx
...ductionComprehens/components/Abnormal/productAbnormal.tsx
+45
-45
qualityAbnormal.tsx
...ductionComprehens/components/Abnormal/qualityAbnormal.tsx
+78
-54
index.tsx
...ban/productionComprehens/components/MonthlyPlan/index.tsx
+2
-6
monthlyPlanChart.tsx
...ionComprehens/components/MonthlyPlan/monthlyPlanChart.tsx
+1
-1
index.tsx
...ban/productionComprehens/components/PassingRate/index.tsx
+197
-44
index.tsx
...ban/productionComprehens/components/ProcessFail/index.tsx
+3
-4
index.tsx
...n/productionComprehens/components/ProcessOutput/index.tsx
+2
-2
index.tsx
...ban/productionComprehens/components/SettingForm/index.tsx
+2
-2
index.less
src/pages/kanban/productionComprehens/index.less
+2
-2
index.tsx
src/pages/kanban/productionComprehens/index.tsx
+90
-151
api.ts
src/pages/kanban/productionComprehens/services/api.ts
+4
-60
typing.d.ts
src/pages/kanban/productionComprehens/services/typing.d.ts
+13
-14
index.tsx
...ges/kanban/qipingComprehens/components/Abnormal/index.tsx
+2
-2
index.tsx
...anban/qipingComprehens/components/ProcessOutput/index.tsx
+2
-2
No files found.
src/pages/kanban/productionComprehens/components/Abnormal/deviceAbnormal.tsx
View file @
127e9578
...
@@ -105,9 +105,9 @@ const formatOptions = (data: any) => {
...
@@ -105,9 +105,9 @@ const formatOptions = (data: any) => {
data
:
[],
data
:
[],
};
};
option
.
series
.
push
({
...
temp
,
name
:
'当月异常'
,
data
:
[
data
.
currentMonthNumber
]
});
option
.
series
.
push
({
...
temp
,
name
:
'当月异常'
,
data
:
[
data
.
totalCt
]
});
option
.
series
.
push
({
...
temp
,
name
:
'未关闭'
,
data
:
[
data
.
createIssueNumber
]
});
option
.
series
.
push
({
...
temp
,
name
:
'未关闭'
,
data
:
[
data
.
unCloseCt
]
});
option
.
series
.
push
({
...
temp
,
name
:
'超期'
,
data
:
[
data
.
beyondNumber
]
});
option
.
series
.
push
({
...
temp
,
name
:
'超期'
,
data
:
[
data
.
expireUnClose
]
});
return
option
;
return
option
;
};
};
...
@@ -141,48 +141,48 @@ const Main: React.FC<{ data: any; setting: ErrorDetailSetting }> = ({ data, sett
...
@@ -141,48 +141,48 @@ const Main: React.FC<{ data: any; setting: ErrorDetailSetting }> = ({ data, sett
if
(
chartRef
.
current
!==
null
)
{
if
(
chartRef
.
current
!==
null
)
{
const
chart
=
getInstanceByDom
(
chartRef
.
current
);
const
chart
=
getInstanceByDom
(
chartRef
.
current
);
chart
?.
off
(
'click'
);
chart
?.
off
(
'click'
);
chart
?.
on
(
'click'
,
(
params
)
=>
{
//
chart?.on('click', (params) => {
if
(
params
.
seriesName
==
'当月异常'
)
{
//
if (params.seriesName == '当月异常') {
setCriteria
({
//
setCriteria({
workshopName
:
setting
.
workshopName
,
//
workshopName: setting.workshopName,
status
:
'2,3,5'
,
//
status: '2,3,5',
createdDateFrom
:
moment
()
//
createdDateFrom: moment()
.
date
(
1
)
//
.date(1)
.
hour
(
0
)
//
.hour(0)
.
minute
(
0
)
//
.minute(0)
.
second
(
0
)
//
.second(0)
.
millisecond
(
0
)
//
.millisecond(0)
.
format
(
'YYYY-MM-DD HH:mm'
),
//
.format('YYYY-MM-DD HH:mm'),
createdDateTo
:
moment
(
params
.
to
).
format
(
'YYYY-MM-DD HH:mm'
),
//
createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
current
:
1
,
//
current: 1,
pageSize
:
10
,
//
pageSize: 10,
});
//
});
}
else
if
(
params
.
seriesName
==
'未关闭'
)
{
//
} else if (params.seriesName == '未关闭') {
setCriteria
({
//
setCriteria({
workshopName
:
setting
.
workshopName
,
//
workshopName: setting.workshopName,
createdDateFrom
:
null
,
//
createdDateFrom: null,
createdDateTo
:
null
,
//
createdDateTo: null,
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
//
//createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
status
:
'2,3'
,
//
status: '2,3',
current
:
1
,
//
current: 1,
pageSize
:
10
,
//
pageSize: 10,
});
//
});
}
else
if
(
params
.
seriesName
==
'超期'
)
{
//
} else if (params.seriesName == '超期') {
setCriteria
({
//
setCriteria({
workshopName
:
setting
.
workshopName
,
//
workshopName: setting.workshopName,
createdDateFrom
:
null
,
//
createdDateFrom: null,
createdDateTo
:
null
,
//
createdDateTo: null,
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
//
//createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
status
:
'2,3'
,
//
status: '2,3',
gtErrorDays
:
setting
.
abnormalOverdueSetting
.
diffDayEquipment
,
//
gtErrorDays: setting.abnormalOverdueSetting.diffDayEquipment,
current
:
1
,
//
current: 1,
pageSize
:
10
,
//
pageSize: 10,
});
//
});
}
//
}
setIsModalOpen
(
true
);
//
setIsModalOpen(true);
});
//
});
}
}
},
[
setting
]);
},
[
setting
]);
...
...
src/pages/kanban/productionComprehens/components/Abnormal/index.tsx
View file @
127e9578
...
@@ -32,32 +32,22 @@ const Abnormal: React.FC<{
...
@@ -32,32 +32,22 @@ const Abnormal: React.FC<{
<
div
className=
{
styles
.
itemContainer
}
>
<
div
className=
{
styles
.
itemContainer
}
>
<
ProductAbnormal
data=
{
abnormalProdData
}
setting=
{
setting
}
/>
<
ProductAbnormal
data=
{
abnormalProdData
}
setting=
{
setting
}
/>
</
div
>
</
div
>
<
div
className=
{
styles
.
itemContainer
}
>
<
QualityAbnormal
data=
{
abnormalQualityData
}
setting=
{
setting
}
/>
</
div
>
<
div
className=
{
styles
.
itemContainer
}
>
<
div
className=
{
styles
.
itemContainer
}
>
<
DeviceAbnormal
data=
{
abnormalDeviceData
}
setting=
{
setting
}
/>
<
DeviceAbnormal
data=
{
abnormalDeviceData
}
setting=
{
setting
}
/>
</
div
>
</
div
>
<
div
className=
{
styles
.
bottomContainer
}
>
<
div
className=
{
styles
.
bottomContainer
}
>
<
div
className=
{
styles
.
bottomItem
}
>
<
div
className=
{
styles
.
bottomItem
}
>
<
p
>
设备正常数:
</
p
>
<
p
>
设备正常数:
</
p
>
<
h2
onClick=
{
()
=>
openModal
(
1
)
}
>
{
abnormalDeviceData
.
deviceNorNumber
}
</
h2
>
<
h2
onClick=
{
()
=>
openModal
(
1
)
}
>
{
abnormalDeviceData
.
equipCt
}
</
h2
>
</
div
>
</
div
>
<
div
className=
{
styles
.
bottomItemRight
}
style=
{
{
marginLeft
:
'10px'
}
}
>
<
div
className=
{
styles
.
bottomItemRight
}
style=
{
{
marginLeft
:
'10px'
}
}
>
<
p
>
设备异常数:
</
p
>
<
p
>
设备异常数:
</
p
>
<
h2
onClick=
{
()
=>
openModal
(
2
)
}
>
{
abnormalDeviceData
.
deviceEcpNumber
}
</
h2
>
<
h2
onClick=
{
()
=>
openModal
(
2
)
}
>
{
abnormalDeviceData
.
equipErrorCt
}
</
h2
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className=
{
styles
.
itemContainer
}
>
<
Modal
<
QualityAbnormal
data=
{
abnormalQualityData
}
setting=
{
setting
}
/>
title=
{
'设备台账'
}
</
div
>
visible=
{
isModalOpen
}
footer=
{
null
}
width=
{
'70%'
}
onCancel=
{
closeModal
}
>
<
DeviceCountTable
values=
{
criteria
}
/>
</
Modal
>
</>
</>
);
);
};
};
...
...
src/pages/kanban/productionComprehens/components/Abnormal/productAbnormal.tsx
View file @
127e9578
...
@@ -112,9 +112,9 @@ const formatOptions = (data: any) => {
...
@@ -112,9 +112,9 @@ const formatOptions = (data: any) => {
data
:
[],
data
:
[],
};
};
option
.
series
.
push
({
...
temp
,
name
:
'当月异常'
,
data
:
[
data
.
currentMonthNumber
]
});
option
.
series
.
push
({
...
temp
,
name
:
'当月异常'
,
data
:
[
data
.
totalCt
]
});
option
.
series
.
push
({
...
temp
,
name
:
'未关闭'
,
data
:
[
data
.
createIssueNumber
]
});
option
.
series
.
push
({
...
temp
,
name
:
'未关闭'
,
data
:
[
data
.
unCloseCt
]
});
option
.
series
.
push
({
...
temp
,
name
:
'超期'
,
data
:
[
data
.
beyondNumber
]
});
option
.
series
.
push
({
...
temp
,
name
:
'超期'
,
data
:
[
data
.
expireUnClose
]
});
return
option
;
return
option
;
};
};
...
@@ -148,48 +148,48 @@ const Main: React.FC<{ data: any; setting: ErrorDetailSetting }> = ({ data, sett
...
@@ -148,48 +148,48 @@ const Main: React.FC<{ data: any; setting: ErrorDetailSetting }> = ({ data, sett
if
(
chartRef
.
current
!==
null
)
{
if
(
chartRef
.
current
!==
null
)
{
const
chart
=
getInstanceByDom
(
chartRef
.
current
);
const
chart
=
getInstanceByDom
(
chartRef
.
current
);
chart
?.
off
(
'click'
);
chart
?.
off
(
'click'
);
chart
?.
on
(
'click'
,
(
params
)
=>
{
//
chart?.on('click', (params) => {
if
(
params
.
seriesName
==
'当月异常'
)
{
//
if (params.seriesName == '当月异常') {
setCriteria
({
//
setCriteria({
workshopName
:
setting
.
workshopName
,
//
workshopName: setting.workshopName,
status
:
'1,2,3,4'
,
//
status: '1,2,3,4',
createdDateFrom
:
moment
()
//
createdDateFrom: moment()
.
date
(
1
)
//
.date(1)
.
hour
(
0
)
//
.hour(0)
.
minute
(
0
)
//
.minute(0)
.
second
(
0
)
//
.second(0)
.
millisecond
(
0
)
//
.millisecond(0)
.
format
(
'YYYY-MM-DD HH:mm'
),
//
.format('YYYY-MM-DD HH:mm'),
createdDateTo
:
moment
().
format
(
'YYYY-MM-DD HH:mm'
),
//
createdDateTo: moment().format('YYYY-MM-DD HH:mm'),
current
:
1
,
//
current: 1,
pageSize
:
10
,
//
pageSize: 10,
});
//
});
}
else
if
(
params
.
seriesName
==
'未关闭'
)
{
//
} else if (params.seriesName == '未关闭') {
setCriteria
({
//
setCriteria({
workshopName
:
setting
.
workshopName
,
//
workshopName: setting.workshopName,
createdDateFrom
:
null
,
//
createdDateFrom: null,
createdDateTo
:
null
,
//
createdDateTo: null,
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//createdDateTo: moment().format('YYYY-MM-DD HH:mm'),
//
//createdDateTo: moment().format('YYYY-MM-DD HH:mm'),
status
:
'1,2,3'
,
//
status: '1,2,3',
current
:
1
,
//
current: 1,
pageSize
:
10
,
//
pageSize: 10,
});
//
});
}
else
if
(
params
.
seriesName
==
'超期'
)
{
//
} else if (params.seriesName == '超期') {
setCriteria
({
//
setCriteria({
workshopName
:
setting
.
workshopName
,
//
workshopName: setting.workshopName,
createdDateFrom
:
null
,
//
createdDateFrom: null,
createdDateTo
:
null
,
//
createdDateTo: null,
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//createdDateTo: moment().format('YYYY-MM-DD HH:mm'),
//
//createdDateTo: moment().format('YYYY-MM-DD HH:mm'),
status
:
'1,2,3'
,
//
status: '1,2,3',
gtErrorDays
:
setting
.
abnormalOverdueSetting
.
diffDayProduction
,
//
gtErrorDays: setting.abnormalOverdueSetting.diffDayProduction,
current
:
1
,
//
current: 1,
pageSize
:
10
,
//
pageSize: 10,
});
//
});
}
//
}
setIsModalOpen
(
true
);
//
setIsModalOpen(true);
});
//
});
}
}
},
[
setting
]);
},
[
setting
]);
...
...
src/pages/kanban/productionComprehens/components/Abnormal/qualityAbnormal.tsx
View file @
127e9578
...
@@ -11,6 +11,7 @@ type ErrorDetailSetting = KANBAN.ProductionComprehens.ErrorDetailSetting;
...
@@ -11,6 +11,7 @@ type ErrorDetailSetting = KANBAN.ProductionComprehens.ErrorDetailSetting;
const
formatOptions
=
(
data
:
any
)
=>
{
const
formatOptions
=
(
data
:
any
)
=>
{
const
option
=
{
const
option
=
{
tooltip
:
{},
color
:
[
color
:
[
{
{
type
:
'linear'
,
type
:
'linear'
,
...
@@ -71,16 +72,29 @@ const formatOptions = (data: any) => {
...
@@ -71,16 +72,29 @@ const formatOptions = (data: any) => {
show
:
false
,
show
:
false
,
},
},
grid
:
{
grid
:
{
bottom
:
1
0
,
bottom
:
2
0
,
top
:
20
,
top
:
20
,
},
},
xAxis
:
{
xAxis
:
{
type
:
'value'
,
type
:
'category'
,
show
:
false
,
show
:
true
,
axisLabel
:
{
color
:
'#fff'
,
fontSize
:
16
,
},
axisTick
:
{
show
:
false
,
},
axisLine
:
{
show
:
false
,
}
},
},
yAxis
:
{
yAxis
:
{
type
:
'
category
'
,
type
:
'
value
'
,
data
:
[
'质量'
],
data
:
[
'质量'
],
splitLine
:
{
show
:
false
},
axisLabel
:
{
axisLabel
:
{
color
:
'#fff'
,
color
:
'#fff'
,
fontSize
:
16
,
fontSize
:
16
,
...
@@ -96,9 +110,10 @@ const formatOptions = (data: any) => {
...
@@ -96,9 +110,10 @@ const formatOptions = (data: any) => {
};
};
const
temp
=
{
const
temp
=
{
type
:
'
bar
'
,
type
:
'
line
'
,
name
:
''
,
name
:
''
,
barGap
:
0
,
barGap
:
0
,
smooth
:
true
,
label
:
{
label
:
{
show
:
true
,
show
:
true
,
position
:
'right'
,
position
:
'right'
,
...
@@ -106,10 +121,19 @@ const formatOptions = (data: any) => {
...
@@ -106,10 +121,19 @@ const formatOptions = (data: any) => {
},
},
data
:
[],
data
:
[],
};
};
const
now
=
moment
();
option
.
series
.
push
({
...
temp
,
name
:
'当月异常'
,
data
:
[
data
.
currentMonthNumber
]
});
option
.
series
.
push
({
...
temp
,
name
:
'未关闭'
,
data
:
[
data
.
createIssueNumber
]
});
// 存储最近七天日期的数组
option
.
series
.
push
({
...
temp
,
name
:
'超期'
,
data
:
[
data
.
beyondNumber
]
});
const
lastSevenDays
=
[];
for
(
let
i
=
0
;
i
<
7
;
i
++
)
{
lastSevenDays
.
push
(
moment
(
now
).
subtract
(
i
,
'days'
).
format
(
'DD/MM'
));
}
console
.
log
(
'lastSevenDays'
,
lastSevenDays
)
option
[
'xAxis'
][
'data'
]
=
lastSevenDays
.
reverse
()
// option.series.push({ ...temp, name: '当月异常', data: [data.totalCt] });
// option.series.push({ ...temp, name: '未关闭', data: [data.unCloseCt] });
option
.
series
.
push
({
...
temp
,
name
:
'设备故障总数'
,
data
:
data
.
reverse
()}
);
return
option
;
return
option
;
};
};
...
@@ -143,51 +167,51 @@ const Main: React.FC<{ data: any; setting: ErrorDetailSetting }> = ({ data, sett
...
@@ -143,51 +167,51 @@ const Main: React.FC<{ data: any; setting: ErrorDetailSetting }> = ({ data, sett
if
(
chartRef
.
current
!==
null
)
{
if
(
chartRef
.
current
!==
null
)
{
const
chart
=
getInstanceByDom
(
chartRef
.
current
);
const
chart
=
getInstanceByDom
(
chartRef
.
current
);
chart
?.
off
(
'click'
);
chart
?.
off
(
'click'
);
chart
?.
on
(
'click'
,
(
params
)
=>
{
//
chart?.on('click', (params) => {
if
(
params
.
seriesName
==
'当月异常'
)
{
//
if (params.seriesName == '当月异常') {
setCriteria
({
//
setCriteria({
werks
:
setting
.
werks
,
//
werks: setting.werks,
fevor
:
setting
.
fevors
,
//
fevor: setting.fevors,
status
:
'1,2,3'
,
//
status: '1,2,3',
createdDateFrom
:
moment
()
//
createdDateFrom: moment()
.
date
(
1
)
//
.date(1)
.
hour
(
0
)
//
.hour(0)
.
minute
(
0
)
//
.minute(0)
.
second
(
0
)
//
.second(0)
.
millisecond
(
0
)
//
.millisecond(0)
.
format
(
'YYYY-MM-DD HH:mm'
),
//
.format('YYYY-MM-DD HH:mm'),
createdDateTo
:
moment
(
params
.
to
).
format
(
'YYYY-MM-DD HH:mm'
),
//
createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
current
:
1
,
//
current: 1,
pageSize
:
10
,
//
pageSize: 10,
});
//
});
}
else
if
(
params
.
seriesName
==
'未关闭'
)
{
//
} else if (params.seriesName == '未关闭') {
setCriteria
({
//
setCriteria({
werks
:
setting
.
werks
,
//
werks: setting.werks,
fevor
:
setting
.
fevors
,
//
fevor: setting.fevors,
createdDateFrom
:
null
,
//
createdDateFrom: null,
createdDateTo
:
null
,
//
createdDateTo: null,
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
//
//createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
status
:
'1,2'
,
//
status: '1,2',
current
:
1
,
//
current: 1,
pageSize
:
10
,
//
pageSize: 10,
});
//
});
}
else
if
(
params
.
seriesName
==
'超期'
)
{
//
} else if (params.seriesName == '超期') {
setCriteria
({
//
setCriteria({
werks
:
setting
.
werks
,
//
werks: setting.werks,
fevor
:
setting
.
fevors
,
//
fevor: setting.fevors,
createdDateFrom
:
null
,
//
createdDateFrom: null,
createdDateTo
:
null
,
//
createdDateTo: null,
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//
//createdDateFrom: moment().date(1).hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DD HH:mm'),
//createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
//
//createdDateTo: moment(params.to).format('YYYY-MM-DD HH:mm'),
status
:
'1,2'
,
//
status: '1,2',
gtErrorDays
:
setting
.
abnormalOverdueSetting
.
diffDayQuality
,
//
gtErrorDays: setting.abnormalOverdueSetting.diffDayQuality,
current
:
1
,
//
current: 1,
pageSize
:
10
,
//
pageSize: 10,
});
//
});
}
//
}
setIsModalOpen
(
true
);
//
setIsModalOpen(true);
});
//
});
}
}
},
[
setting
]);
},
[
setting
]);
...
...
src/pages/kanban/productionComprehens/components/MonthlyPlan/index.tsx
View file @
127e9578
...
@@ -121,12 +121,8 @@ const Main: React.FC<{ data: MonthlyPlanProps; kanbanId: string | undefined }> =
...
@@ -121,12 +121,8 @@ const Main: React.FC<{ data: MonthlyPlanProps; kanbanId: string | undefined }> =
<
h2
onClick=
{
(
e
)
=>
clickNum
(
e
,
2
)
}
>
{
data
.
endOnTimeRatio
}
%
</
h2
>
<
h2
onClick=
{
(
e
)
=>
clickNum
(
e
,
2
)
}
>
{
data
.
endOnTimeRatio
}
%
</
h2
>
</
div
>
</
div
>
<
div
className=
{
styles
.
centerTopItem
}
onClick=
{
()
=>
clickBg
(
3
)
}
>
<
div
className=
{
styles
.
centerTopItem
}
onClick=
{
()
=>
clickBg
(
3
)
}
>
<
p
>
入库准时
</
p
>
<
p
>
产品合格
</
p
>
<
h2
onClick=
{
(
e
)
=>
clickNum
(
e
,
3
)
}
>
{
data
.
stockInOnTimeRatio
}
%
</
h2
>
<
h2
onClick=
{
(
e
)
=>
clickNum
(
e
,
3
)
}
>
{
data
.
qualifiedRatio
}
%
</
h2
>
</
div
>
<
div
className=
{
styles
.
centerTopItem
}
onClick=
{
()
=>
clickBg
(
4
)
}
>
<
p
>
周期准时
</
p
>
<
h2
onClick=
{
(
e
)
=>
clickNum
(
e
,
4
)
}
>
{
data
.
periodicAccordRatio
}
%
</
h2
>
</
div
>
</
div
>
<
div
className=
{
styles
.
centerTopItem
}
style=
{
{
marginRight
:
'0px'
}
}
>
<
div
className=
{
styles
.
centerTopItem
}
style=
{
{
marginRight
:
'0px'
}
}
>
<
p
>
历史月待完工
</
p
>
<
p
>
历史月待完工
</
p
>
...
...
src/pages/kanban/productionComprehens/components/MonthlyPlan/monthlyPlanChart.tsx
View file @
127e9578
...
@@ -118,8 +118,8 @@ const formatOptions = (data: any) => {
...
@@ -118,8 +118,8 @@ const formatOptions = (data: any) => {
};
};
option
.
series
.
push
({
...
temp
,
name
:
'月计划'
,
data
:
[
data
.
monthPlanQuantity
]
});
option
.
series
.
push
({
...
temp
,
name
:
'月计划'
,
data
:
[
data
.
monthPlanQuantity
]
});
option
.
series
.
push
({
...
temp
,
name
:
'累计日计划'
,
data
:
[
data
.
accuDailyPlanQuantity
]
});
option
.
series
.
push
({
...
temp
,
name
:
'实际完工'
,
data
:
[
data
.
actualFinishQuantity
]
});
option
.
series
.
push
({
...
temp
,
name
:
'实际完工'
,
data
:
[
data
.
actualFinishQuantity
]
});
option
.
series
.
push
({
...
temp
,
name
:
'超期完工'
,
data
:
[
data
.
expireFinishQuantity
]
});
return
option
;
return
option
;
};
};
...
...
src/pages/kanban/productionComprehens/components/PassingRate/index.tsx
View file @
127e9578
import
PassTower
from
'./passTower'
;
import
React
,
{
useEffect
,
useRef
,
useState
}
from
'react'
;
import
PassSlice
from
'./passSlice'
;
import
*
as
echarts
from
'echarts/lib/echarts'
;
import
styles
from
'../../index.less'
;
import
type
{
ECharts
}
from
'echarts'
;
import
{
Modal
}
from
'antd'
;
import
{
getInstanceByDom
}
from
'echarts'
;
import
{
useState
}
from
'react'
;
import
PassingRateChart
from
'./passingRateChart'
;
import
{
queryCountWeldingPassRateTrendChart
}
from
'../../services/api'
;
const
PassingRate
:
React
.
FC
<
{
data
:
any
;
kanbanId
:
string
|
undefined
}
>
=
({
data
,
kanbanId
})
=>
{
type
ProcessOutProps
=
{
data
:
KANBAN
.
ProductionComprehens
.
ProcessYieldData
[];
setting
:
any
;
};
const
formatOptions
=
(
data
:
any
)
=>
{
const
option
=
{
color
:
[
{
type
:
'linear'
,
x
:
0
,
y
:
0
,
x2
:
0
,
y2
:
1
,
colorStops
:
[
{
offset
:
1
,
color
:
'#011126'
,
// 100% 处的颜色
},
{
offset
:
0
,
color
:
'#00ced3'
,
// 0% 处的颜色
},
],
global
:
false
,
// 缺省为 false
},
{
type
:
'linear'
,
x
:
0
,
y
:
0
,
x2
:
0
,
y2
:
1
,
colorStops
:
[
{
offset
:
1
,
color
:
'#011126'
,
},
{
offset
:
0
,
color
:
'#3ba7cc'
,
},
],
global
:
false
,
// 缺省为 false
},
{
type
:
'linear'
,
x
:
0
,
y
:
0
,
x2
:
0
,
y2
:
1
,
colorStops
:
[
{
offset
:
1
,
color
:
'#011126'
,
},
{
offset
:
0
,
color
:
'#7bb249'
,
},
],
global
:
false
,
// 缺省为 false
},
],
xAxis
:
{
// type: 'category',
data
:
[],
nameTextStyle
:
{
color
:
'#fff'
,
fontSize
:
14
,
},
axisLabel
:
{
interval
:
0
,
color
:
'#fff'
,
fontSize
:
14
,
},
axisTick
:
{
show
:
false
,
},
axisLine
:
{
show
:
false
,
},
},
dataZoom
:
[
{
type
:
'slider'
,
show
:
false
,
startValue
:
0
,
endValue
:
3
,
},
],
grid
:
{
left
:
5
,
// right: 60,
bottom
:
30
,
},
legend
:
{
show
:
false
},
yAxis
:
{
show
:
false
,
type
:
'value'
,
},
series
:
[],
};
if
(
data
&&
data
.
length
)
{
const
xAxisData
=
data
.
map
((
item
:
any
)
=>
item
.
cause
);
const
series
=
[{
type
:
'bar'
,
barGap
:
0
,
label
:
{
show
:
true
,
position
:
'top'
,
color
:
'#fff'
,
},
data
:
data
.
map
((
item
:
any
)
=>
item
.
ct
),
}];
option
.
xAxis
.
data
=
xAxisData
;
option
.
series
=
series
;
}
console
.
log
(
'option'
,
option
)
return
option
;
};
const
Main
:
React
.
FC
<
ProcessOutProps
>
=
({
data
,
setting
})
=>
{
const
chartRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
[
isModalOpen
,
setIsModalOpen
]
=
useState
(
false
);
const
[
isModalOpen
,
setIsModalOpen
]
=
useState
(
false
);
const
closeModal
=
()
=>
setIsModalOpen
(
false
);
const
closeModal
=
()
=>
setIsModalOpen
(
false
);
const
[
chartData
,
setChartData
]
=
useState
<
KANBAN
.
ProductionComprehens
.
PassRateTrendChart
[]
>
([]);
const
[
processParams
,
setProcessParams
]
=
useState
({
const
openModal
=
async
()
=>
{
dataRange
:
1
,
if
(
!
kanbanId
)
{
processName
:
''
,
return
;
current
:
1
,
pageSize
:
10
,
kanbanSettingId
:
''
,
});
useEffect
(()
=>
{
// Initialize chart
let
chart
:
ECharts
|
undefined
;
if
(
chartRef
.
current
!==
null
)
{
chart
=
echarts
.
init
(
chartRef
.
current
);
}
}
const
{
data
:
cData
}
=
await
queryCountWeldingPassRateTrendChart
({
kanbanSettingId
:
kanbanId
,
// Add chart resize listener
});
// ResizeObserver is leading to a bit janky UX
setChartData
(
cData
);
function
resizeChart
()
{
setIsModalOpen
(
true
);
chart
?.
resize
();
};
}
window
.
addEventListener
(
'resize'
,
resizeChart
);
// Return cleanup function
return
()
=>
{
chart
?.
off
(
'click'
);
chart
?.
dispose
();
window
.
removeEventListener
(
'resize'
,
resizeChart
);
};
},
[]);
useEffect
(()
=>
{
let
timer
:
NodeJS
.
Timer
|
null
=
null
;
// Update chart
if
(
chartRef
.
current
!==
null
)
{
if
(
timer
!==
null
)
clearInterval
(
timer
);
const
chart
=
getInstanceByDom
(
chartRef
.
current
);
const
option
=
formatOptions
(
data
);
chart
?.
setOption
(
option
);
chart
?.
off
(
'click'
);
chart
?.
on
(
'click'
,
(
p
)
=>
{
if
(
p
.
seriesName
===
'完成量'
)
{
console
.
log
(
setting
.
productionComprehensKanbanSettingId
,
'----'
);
setProcessParams
({
dataRange
:
setting
.
dataRange
,
processName
:
p
.
name
,
current
:
1
,
pageSize
:
10
,
kanbanSettingId
:
setting
.
productionComprehensKanbanSettingId
,
});
setIsModalOpen
(
true
);
}
});
// 如果数据工序大于5那么需要自动轮训播放
if
(
option
.
xAxis
.
data
.
length
>
4
&&
setting
.
rowMovingTime
>
0
)
{
timer
=
setInterval
(()
=>
{
option
.
dataZoom
[
0
].
startValue
++
;
if
(
option
.
dataZoom
[
0
].
endValue
++
>=
option
.
xAxis
.
data
.
length
-
1
)
{
option
.
dataZoom
[
0
].
startValue
=
0
;
option
.
dataZoom
[
0
].
endValue
=
3
;
}
chart
?.
setOption
(
option
);
},
setting
.
rowMovingTime
*
1000
);
}
}
return
()
=>
{
if
(
timer
!==
null
)
clearInterval
(
timer
);
};
},
[
data
,
setting
]);
return
(
return
(
<>
<>
<
Modal
<
div
ref=
{
chartRef
}
style=
{
{
height
:
'260px'
}
}
/>
title=
{
'焊接一次通过率'
}
visible=
{
isModalOpen
}
footer=
{
null
}
width=
{
'70%'
}
onCancel=
{
closeModal
}
>
<
PassingRateChart
data=
{
chartData
}
/>
</
Modal
>
<
div
className=
{
styles
.
rightTopBottomItem
}
onClick=
{
openModal
}
style=
{
{
background
:
'#040f24'
}
}
>
<
p
>
整台
</
p
>
<
div
style=
{
{
height
:
'150px'
}
}
>
<
PassTower
data=
{
data
.
wholeSetPassRate
}
/>
</
div
>
</
div
>
<
div
className=
{
styles
.
rightTopBottomItem
}
style=
{
{
marginRight
:
'0px'
}
}
>
<
p
>
按片
</
p
>
<
div
style=
{
{
height
:
'150px'
}
}
>
<
PassSlice
data=
{
data
.
piecePassRate
}
/>
</
div
>
</
div
>
</>
</>
);
);
};
};
export
default
PassingRate
;
export
default
Main
;
\ No newline at end of file
src/pages/kanban/productionComprehens/components/ProcessFail/index.tsx
View file @
127e9578
...
@@ -106,10 +106,9 @@ const formatOptions = (data: any) => {
...
@@ -106,10 +106,9 @@ const formatOptions = (data: any) => {
};
};
if
(
data
&&
data
.
length
)
{
if
(
data
&&
data
.
length
)
{
const
lenged
=
[
const
lenged
=
[
{
label
:
'基准率'
,
field
:
'standRatio'
},
{
label
:
'合格率'
,
field
:
'qualifiedRate'
}
{
label
:
'未通过率'
,
field
:
'defectRatio'
},
];
];
const
xAxisData
=
data
.
map
((
item
:
any
)
=>
item
.
step
Name
);
const
xAxisData
=
data
.
map
((
item
:
any
)
=>
item
.
process
Name
);
const
series
=
lenged
.
map
((
item
)
=>
{
const
series
=
lenged
.
map
((
item
)
=>
{
return
{
return
{
type
:
'bar'
,
type
:
'bar'
,
...
@@ -215,7 +214,7 @@ const Main: React.FC<ProcessFailProps> = ({ data, setting }) => {
...
@@ -215,7 +214,7 @@ const Main: React.FC<ProcessFailProps> = ({ data, setting }) => {
return
(
return
(
<>
<>
<
Modal
<
Modal
title=
{
proName
+
'
工序当月一次未通过
率'
}
title=
{
proName
+
'
当月工序合格
率'
}
visible=
{
isModalOpen
}
visible=
{
isModalOpen
}
footer=
{
null
}
footer=
{
null
}
width=
{
'70%'
}
width=
{
'70%'
}
...
...
src/pages/kanban/productionComprehens/components/ProcessOutput/index.tsx
View file @
127e9578
...
@@ -121,9 +121,9 @@ const formatOptions = (data: any) => {
...
@@ -121,9 +121,9 @@ const formatOptions = (data: any) => {
const
lenged
=
[
const
lenged
=
[
{
label
:
'计划量'
,
field
:
'planQuantity'
},
{
label
:
'计划量'
,
field
:
'planQuantity'
},
{
label
:
'完成量'
,
field
:
'finishQuantity'
},
{
label
:
'完成量'
,
field
:
'finishQuantity'
},
{
label
:
'
手持量'
,
field
:
'han
dQuantity'
},
{
label
:
'
合格量'
,
field
:
'qualifie
dQuantity'
},
];
];
const
xAxisData
=
data
.
map
((
item
:
any
)
=>
item
.
step
Name
);
const
xAxisData
=
data
.
map
((
item
:
any
)
=>
item
.
process
Name
);
const
series
=
lenged
.
map
((
item
)
=>
{
const
series
=
lenged
.
map
((
item
)
=>
{
return
{
return
{
type
:
'bar'
,
type
:
'bar'
,
...
...
src/pages/kanban/productionComprehens/components/SettingForm/index.tsx
View file @
127e9578
...
@@ -82,7 +82,7 @@ const SettingForm: React.FC<SettingFormProps> = (props) => {
...
@@ -82,7 +82,7 @@ const SettingForm: React.FC<SettingFormProps> = (props) => {
min=
{
1
}
min=
{
1
}
fieldProps=
{
{
precision
:
0
}
}
fieldProps=
{
{
precision
:
0
}
}
/>
/>
<
ProFormSelect
{
/*
<ProFormSelect
name="productionComprehensKanbanSettingId"
name="productionComprehensKanbanSettingId"
label="看板设置"
label="看板设置"
required
required
...
@@ -109,7 +109,7 @@ const SettingForm: React.FC<SettingFormProps> = (props) => {
...
@@ -109,7 +109,7 @@ const SettingForm: React.FC<SettingFormProps> = (props) => {
{ label: '排产计划量', value: 2 },
{ label: '排产计划量', value: 2 },
]}
]}
/>
/>
</
ProForm
.
Group
>
</ProForm.Group>
*/
}
</
DrawerForm
>
</
DrawerForm
>
);
);
};
};
...
...
src/pages/kanban/productionComprehens/index.less
View file @
127e9578
...
@@ -214,8 +214,8 @@
...
@@ -214,8 +214,8 @@
}
}
}
}
.rightTopBottomContainer {
.rightTopBottomContainer {
display: flex
;
width: 100%
;
justify-content: space-between
;
background: #040f24
;
margin-top: 5px;
margin-top: 5px;
}
}
.rightTopBottomItem {
.rightTopBottomItem {
...
...
src/pages/kanban/productionComprehens/index.tsx
View file @
127e9578
This diff is collapsed.
Click to expand it.
src/pages/kanban/productionComprehens/services/api.ts
View file @
127e9578
...
@@ -45,7 +45,7 @@ export async function queryProductionComprehensKanbanData() {
...
@@ -45,7 +45,7 @@ export async function queryProductionComprehensKanbanData() {
}
}
export
async
function
queryProductionComprehensProcessOutputData
(
body
:
ProcessOutputParams
)
{
export
async
function
queryProductionComprehensProcessOutputData
(
body
:
ProcessOutputParams
)
{
return
request
<
Api
.
ServiceResult
<
ProcessYieldData
[]
>>
(
'/api/
processYieldData1/kanbanData
'
,
{
return
request
<
Api
.
ServiceResult
<
ProcessYieldData
[]
>>
(
'/api/
kanban/task/currentMonthStat
'
,
{
method
:
'POST'
,
method
:
'POST'
,
headers
:
{
headers
:
{
'Content-Type'
:
'application/json'
,
'Content-Type'
:
'application/json'
,
...
@@ -53,57 +53,11 @@ export async function queryProductionComprehensProcessOutputData(body: ProcessOu
...
@@ -53,57 +53,11 @@ export async function queryProductionComprehensProcessOutputData(body: ProcessOu
data
:
body
,
data
:
body
,
});
});
}
}
export
async
function
queryProcessDefectRatioData
(
body
:
{
kanbanSettingId
:
string
})
{
return
request
<
Api
.
ServiceResult
<
ProcessDefectRatioData
[]
>>
(
'/api/processDefectRatioData/kanbanData'
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
,
},
data
:
body
,
},
);
}
export
async
function
queryWorkOrderMonthlyIndexData1
(
body
:
{
kanbanSettingId
:
string
})
{
return
request
<
Api
.
ServiceResult
<
WorkOrderMonthlyIndexData
>>
(
'/api/workOrderMonthlyIndexData1/kanbanData'
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
,
},
data
:
body
,
},
);
}
// 设备异常
export
async
function
queryComprehensiveDeviceEcpData
(
body
:
{
settingId
:
string
})
{
return
request
<
Api
.
ServiceResult
<
ComprehensiveDeviceEcpDataCount
>>
(
'/api/comprehensiveDeviceEcpData/count'
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
,
},
params
:
body
,
},
);
}
// 生产异常
export
async
function
queryComprehensiveProdEcpData
(
body
:
{
settingId
:
string
})
{
return
request
<
Api
.
ServiceResult
<
ComprehensiveDataCount
>>
(
'/api/comprehensiveProdEcpData/count'
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
,
},
params
:
body
,
});
}
// 质量异常
// 质量异常
export
async
function
queryComprehensiveQualityEcpData
(
body
:
{
settingId
:
string
})
{
export
async
function
currentMonthStat
(
body
:
{
settingId
:
string
})
{
return
request
<
Api
.
ServiceResult
<
ComprehensiveDataCount
>>
(
return
request
<
Api
.
ServiceResult
<
ComprehensiveDataCount
>>
(
'/api/
comprehensiveQualityEcpData/coun
t'
,
'/api/
kanban/abnormal/currentMonthSta
t'
,
{
{
method
:
'POST'
,
method
:
'POST'
,
headers
:
{
headers
:
{
...
@@ -113,16 +67,6 @@ export async function queryComprehensiveQualityEcpData(body: { settingId: string
...
@@ -113,16 +67,6 @@ export async function queryComprehensiveQualityEcpData(body: { settingId: string
},
},
);
);
}
}
// 焊接通过率
export
async
function
queryCountWeldingPassRate
(
body
:
{
settingId
:
string
})
{
return
request
<
Api
.
ServiceResult
<
CountWeldingPassRate
>>
(
'/api/batchInfo/countWeldingPassRate'
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
,
},
params
:
body
,
});
}
// 焊接通过率趋势图
// 焊接通过率趋势图
export
async
function
queryCountWeldingPassRateTrendChart
(
data
:
{
kanbanSettingId
:
string
})
{
export
async
function
queryCountWeldingPassRateTrendChart
(
data
:
{
kanbanSettingId
:
string
})
{
return
request
<
Api
.
ServiceResult
<
PassRateTrendChart
[]
>>
(
return
request
<
Api
.
ServiceResult
<
PassRateTrendChart
[]
>>
(
...
...
src/pages/kanban/productionComprehens/services/typing.d.ts
View file @
127e9578
...
@@ -23,14 +23,14 @@ declare namespace KANBAN.ProductionComprehens {
...
@@ -23,14 +23,14 @@ declare namespace KANBAN.ProductionComprehens {
};
};
type
ProcessYieldData
=
{
type
ProcessYieldData
=
{
step
Name
:
string
;
process
Name
:
string
;
finishQuantity
:
number
;
finishQuantity
:
number
;
planQuantity
:
number
;
planQuantity
:
number
;
han
dQuantity
:
number
;
qualifie
dQuantity
:
number
;
};
};
type
ProcessDefectRatioData
=
{
type
ProcessDefectRatioData
=
{
step
Name
:
string
;
process
Name
:
string
;
standRatio
:
number
;
standRatio
:
number
;
defectRatio
:
number
;
defectRatio
:
number
;
};
};
...
@@ -38,27 +38,26 @@ declare namespace KANBAN.ProductionComprehens {
...
@@ -38,27 +38,26 @@ declare namespace KANBAN.ProductionComprehens {
type
WorkOrderMonthlyIndexData
=
{
type
WorkOrderMonthlyIndexData
=
{
startOnTimeRatio
:
number
;
startOnTimeRatio
:
number
;
endOnTimeRatio
:
number
;
endOnTimeRatio
:
number
;
stockInOnTimeRatio
:
number
;
qualifiedRatio
:
number
;
periodicAccordRatio
:
number
;
hisPendingQuantity
:
number
;
hisPendingQuantity
:
number
;
monthPlanQuantity
:
number
;
monthPlanQuantity
:
number
;
accuDailyPlan
Quantity
:
number
;
expireFinish
Quantity
:
number
;
actualFinishQuantity
:
number
;
actualFinishQuantity
:
number
;
monthPlanConcludeRatio
:
number
;
monthPlanConcludeRatio
:
number
;
};
};
type
ComprehensiveDeviceEcpDataCount
=
{
type
ComprehensiveDeviceEcpDataCount
=
{
createIssueNumber
:
number
;
unCloseCt
:
number
;
beyondNumber
:
number
;
expireUnClose
:
number
;
currentMonthNumber
:
number
;
totalCt
:
number
;
deviceEcpNumber
:
number
;
equipErrorCt
:
number
;
deviceNorNumber
:
number
;
equipCt
:
number
;
};
};
type
ComprehensiveDataCount
=
{
type
ComprehensiveDataCount
=
{
createIssueNumber
:
number
;
totalCt
:
number
;
beyondNumber
:
number
;
expireUnClose
:
number
;
currentMonthNumber
:
number
;
unCloseCt
:
number
;
};
};
type
CountWeldingPassRate
=
{
type
CountWeldingPassRate
=
{
...
...
src/pages/kanban/qipingComprehens/components/Abnormal/index.tsx
View file @
127e9578
...
@@ -41,11 +41,11 @@ const Abnormal: React.FC<{
...
@@ -41,11 +41,11 @@ const Abnormal: React.FC<{
<
div
className=
{
styles
.
bottomContainer
}
>
<
div
className=
{
styles
.
bottomContainer
}
>
<
div
className=
{
styles
.
bottomItem
}
>
<
div
className=
{
styles
.
bottomItem
}
>
<
p
>
设备正常数:
</
p
>
<
p
>
设备正常数:
</
p
>
<
h2
onClick=
{
()
=>
openModal
(
1
)
}
>
{
abnormalDeviceData
.
deviceNorNumber
}
</
h2
>
<
h2
>
{
abnormalDeviceData
.
deviceNorNumber
}
</
h2
>
</
div
>
</
div
>
<
div
className=
{
styles
.
bottomItemRight
}
style=
{
{
marginLeft
:
'10px'
}
}
>
<
div
className=
{
styles
.
bottomItemRight
}
style=
{
{
marginLeft
:
'10px'
}
}
>
<
p
>
设备异常数:
</
p
>
<
p
>
设备异常数:
</
p
>
<
h2
onClick=
{
()
=>
openModal
(
2
)
}
>
{
abnormalDeviceData
.
deviceEcpNumber
}
</
h2
>
<
h2
>
{
abnormalDeviceData
.
deviceEcpNumber
}
</
h2
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/pages/kanban/qipingComprehens/components/ProcessOutput/index.tsx
View file @
127e9578
...
@@ -121,9 +121,9 @@ const formatOptions = (data: any) => {
...
@@ -121,9 +121,9 @@ const formatOptions = (data: any) => {
const
lenged
=
[
const
lenged
=
[
{
label
:
'计划量'
,
field
:
'planQuantity'
},
{
label
:
'计划量'
,
field
:
'planQuantity'
},
{
label
:
'完成量'
,
field
:
'finishQuantity'
},
{
label
:
'完成量'
,
field
:
'finishQuantity'
},
{
label
:
'
手持量'
,
field
:
'han
dQuantity'
},
{
label
:
'
合格量'
,
field
:
'qualifie
dQuantity'
},
];
];
const
xAxisData
=
data
.
map
((
item
:
any
)
=>
item
.
step
Name
);
const
xAxisData
=
data
.
map
((
item
:
any
)
=>
item
.
process
Name
);
const
series
=
lenged
.
map
((
item
)
=>
{
const
series
=
lenged
.
map
((
item
)
=>
{
return
{
return
{
type
:
'bar'
,
type
:
'bar'
,
...
...
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