Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
polysoft-nafmii
/
polysoft-parent
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit 2e9ea9d6
authored
May 10, 2021
by
zhoujinghao
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
导入相关代码提交
1 parent
8001151d
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
206 additions
and
198 deletions
nafmii-admin/src/main/java/org/nafmii/admin/user/controller/ImportExcelController.java → nafmii-admin/src/main/java/org/nafmii/admin/att/controller/ImportExcelController.java
nafmii-admin/src/main/java/org/nafmii/admin/user/dao/ImportExcelMapper.java → nafmii-admin/src/main/java/org/nafmii/admin/att/dao/ImportExcelMapper.java
nafmii-admin/src/main/java/org/nafmii/admin/user/dto/ImportExcelDto.java → nafmii-admin/src/main/java/org/nafmii/admin/att/dto/ImportExcelDto.java
nafmii-admin/src/main/java/org/nafmii/admin/user/service/IImportExcelService.java → nafmii-admin/src/main/java/org/nafmii/admin/att/service/ImportExcelService.java
nafmii-admin/src/main/java/org/nafmii/admin/att/service/impl/AttServiceImpl.java
nafmii-admin/src/main/java/org/nafmii/admin/att/service/impl/ImportExcelServiceImpl.java
nafmii-admin/src/main/java/org/nafmii/admin/att/service/test.java
nafmii-admin/src/main/java/org/nafmii/admin/att/utils/NoModelDataListener.java
nafmii-admin/src/main/java/org/nafmii/admin/user/service/impl/ImportExcelServiceImpl.java
nafmii-admin/src/main/resources/mapper/AttachmentInfoMapper.xml
nafmii-admin/src/main/resources/mapper/ImportExcelMapper.xml
nafmii-common/pom.xml
nafmii-admin/src/main/java/org/nafmii/admin/
user
/controller/ImportExcelController.java
→
nafmii-admin/src/main/java/org/nafmii/admin/
att
/controller/ImportExcelController.java
View file @
2e9ea9d
package
org
.
nafmii
.
admin
.
user
.
controller
;
package
org
.
nafmii
.
admin
.
att
.
controller
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.nafmii.admin.
user.service.I
ImportExcelService
;
import
org.nafmii.admin.
att.service.
ImportExcelService
;
import
org.nafmii.common.response.ApiResponse
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
...
...
@@ -15,10 +15,10 @@ import java.io.IOException;
@RestController
@RequestMapping
(
"/nafmii/admin/import"
)
@Api
(
tags
=
"
3.0.0"
,
description
=
"中心端批量导入Excel接口
"
)
@Api
(
tags
=
"
2.0.1"
,
description
=
"中心端批量导入Excel接口【zjh】
"
)
public
class
ImportExcelController
{
@Resource
private
I
I
mportExcelService
iImportExcelService
;
private
ImportExcelService
iImportExcelService
;
@ApiOperation
(
value
=
"中心端批量导入Excel"
,
notes
=
"中心端批量导入Excel"
)
@PostMapping
(
"/batchImportExcel"
)
...
...
nafmii-admin/src/main/java/org/nafmii/admin/
user
/dao/ImportExcelMapper.java
→
nafmii-admin/src/main/java/org/nafmii/admin/
att
/dao/ImportExcelMapper.java
View file @
2e9ea9d
package
org
.
nafmii
.
admin
.
user
.
dao
;
package
org
.
nafmii
.
admin
.
att
.
dao
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
org.nafmii.admin.
user
.dto.ImportExcelDto
;
import
org.nafmii.admin.
att
.dto.ImportExcelDto
;
/**
* <p>
...
...
nafmii-admin/src/main/java/org/nafmii/admin/
user
/dto/ImportExcelDto.java
→
nafmii-admin/src/main/java/org/nafmii/admin/
att
/dto/ImportExcelDto.java
View file @
2e9ea9d
package
org
.
nafmii
.
admin
.
user
.
dto
;
package
org
.
nafmii
.
admin
.
att
.
dto
;
import
io.swagger.annotations.ApiModel
;
import
lombok.Data
;
...
...
nafmii-admin/src/main/java/org/nafmii/admin/
user/service/I
ImportExcelService.java
→
nafmii-admin/src/main/java/org/nafmii/admin/
att/service/
ImportExcelService.java
View file @
2e9ea9d
package
org
.
nafmii
.
admin
.
user
.
service
;
package
org
.
nafmii
.
admin
.
att
.
service
;
import
org.nafmii.common.response.ApiResponse
;
import
org.springframework.web.multipart.MultipartFile
;
...
...
@@ -13,7 +13,7 @@ import java.io.IOException;
* @author suncq
* @since 2021-04-27
*/
public
interface
I
I
mportExcelService
{
public
interface
ImportExcelService
{
/**
* @author:suncq
* @Function:中心端批量导入Excel
...
...
nafmii-admin/src/main/java/org/nafmii/admin/att/service/impl/AttServiceImpl.java
View file @
2e9ea9d
...
...
@@ -39,13 +39,13 @@ import java.util.*;
@Slf4j
public
class
AttServiceImpl
implements
AttService
{
@Value
(
"${att.upload.docBase}"
)
private
String
ftpPath
;
@Value
(
"${att.upload.path}"
)
private
String
downLoad
;
@Value
(
"${web.upload.path}"
)
private
String
fileRootPath
;
//
@Value("${att.upload.docBase}")
//
private String ftpPath;
//
@Value("${att.upload.path}")
//
private String downLoad;
//
//
@Value("${web.upload.path}")
//
private String fileRootPath;
@Resource
private
AttachmentInfoMapper
infoMapper
;
...
...
@@ -65,7 +65,7 @@ public class AttServiceImpl implements AttService {
if
(!
localFile
.
getParentFile
().
exists
()){
//文件夹目录不存在创建目录
localFile
.
getParentFile
().
mkdirs
();
//存放图片的路径地址
StringBuilder
sb
=
new
StringBuilder
(
ftpPath
).
append
(
"/"
);
StringBuilder
sb
=
new
StringBuilder
(
""
).
append
(
"/"
);
String
path
=
sb
.
toString
();
lastPath
=
path
;
try
{
...
...
@@ -120,7 +120,7 @@ public class AttServiceImpl implements AttService {
e
.
printStackTrace
();
}
//存放图片的路径地址
StringBuilder
sb
=
new
StringBuilder
(
ftpPath
).
append
(
"/"
);
StringBuilder
sb
=
new
StringBuilder
(
""
).
append
(
"/"
);
String
path
=
sb
.
toString
();
lastPath
=
path
;
// fileFtp.uploadFile(path,newName,file.getInputStream());
...
...
@@ -134,7 +134,7 @@ public class AttServiceImpl implements AttService {
attachVo
.
setDelFlag
(
CommonEnum
.
USED
.
getCode
());
attachVo
.
setDescription
(
description
);
attachVo
.
setFilePath
(
filePath
);
attachVo
.
setFileUrl
(
downLoad
+
"/"
+
newName
);
attachVo
.
setFileUrl
(
""
+
"/"
+
newName
);
attachList
.
add
(
attachVo
);
}
//ftp上传
...
...
nafmii-admin/src/main/java/org/nafmii/admin/att/service/impl/ImportExcelServiceImpl.java
0 → 100644
View file @
2e9ea9d
package
org
.
nafmii
.
admin
.
att
.
service
.
impl
;
import
com.alibaba.excel.EasyExcel
;
import
com.alibaba.excel.enums.CellExtraTypeEnum
;
import
lombok.extern.slf4j.Slf4j
;
import
org.nafmii.admin.att.dto.ImportExcelDto
;
import
org.nafmii.admin.att.service.ImportExcelService
;
import
org.nafmii.admin.att.dao.ImportExcelMapper
;
import
org.nafmii.admin.att.utils.NoModelDataListener
;
import
org.nafmii.common.response.ApiResponse
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.multipart.MultipartFile
;
import
javax.annotation.Resource
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
/**
* <p>
* 中心端批量导入Excel
* </p>
*
* @author suncq
* @since 2021-04-27
*/
@Slf4j
@Service
public
class
ImportExcelServiceImpl
implements
ImportExcelService
{
@Resource
private
ImportExcelMapper
importExcelMapper
;
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
ApiResponse
batchImportExcel
(
MultipartFile
file
)
throws
IOException
{
List
<
Object
>
dataList
=
new
ArrayList
();
List
<
Map
<
Integer
,
String
>>
list
=
EasyExcel
.
read
(
file
.
getInputStream
(),
new
NoModelDataListener
())
.
extraRead
(
CellExtraTypeEnum
.
MERGE
)
.
ignoreEmptyRow
(
true
)
.
autoTrim
(
true
)
.
headRowNumber
(
1
)
.
sheet
(
0
)
.
doReadSync
();
log
.
info
(
"导入后生成的数据源=============>"
+
list
);
if
(!
list
.
isEmpty
())
{
for
(
Map
<
Integer
,
String
>
data
:
list
)
{
String
v1
=
data
.
get
(
0
);
String
v2
=
data
.
get
(
1
);
String
v3
=
data
.
get
(
2
);
ImportExcelDto
excelDto
=
new
ImportExcelDto
();
excelDto
.
setColumn1
(
v1
);
excelDto
.
setColumn2
(
v2
);
excelDto
.
setColumn3
(
v3
);
log
.
info
(
"导入处理后生成的数据源=============>"
+
excelDto
);
importExcelMapper
.
insertExcelData
(
excelDto
);
}
}
return
new
ApiResponse
(
ApiResponse
.
SUCCESS
,
ApiResponse
.
SUCCESS_TEXT
);
}
}
\ No newline at end of file
nafmii-admin/src/main/java/org/nafmii/admin/att/service/test.java
deleted
100644 → 0
View file @
8001151
package
org
.
nafmii
.
admin
.
att
.
service
;
/**
* @author:zhoujh
* @Function:TODO
* @date 2021/5/7 14:41
* @ClassName:
* @version:
* @remark:
*/
public
class
test
{
}
nafmii-admin/src/main/java/org/nafmii/admin/att/utils/NoModelDataListener.java
0 → 100644
View file @
2e9ea9d
package
org
.
nafmii
.
admin
.
att
.
utils
;
import
com.alibaba.excel.context.AnalysisContext
;
import
com.alibaba.excel.event.AnalysisEventListener
;
import
com.alibaba.excel.exception.ExcelDataConvertException
;
import
com.alibaba.excel.metadata.CellExtra
;
import
java.util.ArrayList
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author:zhoujh
* @Function:TODO
* @date 2021/5/8 11:23
* @ClassName:
* @version:
* @remark:
*/
public
class
NoModelDataListener
extends
AnalysisEventListener
<
Map
<
Integer
,
String
>>
{
/**
* 所有列到字段名的映射
* */
private
Map
<
Integer
,
String
>
index2FieldMap
;
/**
* 解析出的数据
*/
private
LinkedHashMap
<
Integer
,
Map
<
Integer
,
String
>>
row2DataMap
=
new
LinkedHashMap
<>();
/**
* 合并单元格
*/
private
List
<
CellExtra
>
extraMergeInfoList
=
new
ArrayList
<>();
public
NoModelDataListener
(){}
public
NoModelDataListener
(
Map
<
Integer
,
String
>
index2FieldMap
){
this
.
index2FieldMap
=
index2FieldMap
;
}
@Override
public
void
invoke
(
Map
<
Integer
,
String
>
rowData
,
AnalysisContext
analysisContext
)
{
//读取到的每行数据,其key是以0开始的索引
row2DataMap
.
put
(
analysisContext
.
readRowHolder
().
getRowIndex
(),
rowData
)
;
}
@Override
public
void
doAfterAllAnalysed
(
AnalysisContext
analysisContext
)
{
//所有行都解析完成
this
.
explainMergeData
(
row2DataMap
,
extraMergeInfoList
)
;
}
/**
* 某行的数据解析失败
* */
@Override
public
void
onException
(
Exception
exception
,
AnalysisContext
context
)
{
System
.
err
.
println
(
"解析失败,但是继续解析下一行: "
+
exception
.
getMessage
());
// 如果是某一个单元格的转换异常 能获取到具体行号
if
(
exception
instanceof
ExcelDataConvertException
)
{
ExcelDataConvertException
excelDataConvertException
=
(
ExcelDataConvertException
)
exception
;
System
.
err
.
println
(
"第{}行,第{}列解析异常"
+
excelDataConvertException
.
getRowIndex
()
+
excelDataConvertException
.
getColumnIndex
());
}
}
@Override
public
void
extra
(
CellExtra
extra
,
AnalysisContext
context
)
{
switch
(
extra
.
getType
()){
case
MERGE:
{
extraMergeInfoList
.
add
(
extra
);
break
;
}
case
HYPERLINK:
{
break
;
}
case
COMMENT:
{
}
default
:
{
}
}
}
/**
* 处理合并单元格
* @param data 解析数据
* @param extraMergeInfoList 合并单元格信息
* @return 填充好的解析数据
*/
private
void
explainMergeData
(
Map
<
Integer
,
Map
<
Integer
,
String
>>
data
,
List
<
CellExtra
>
extraMergeInfoList
)
{
//循环所有合并单元格信息
extraMergeInfoList
.
forEach
(
cellExtra
->
{
int
firstRowIndex
=
cellExtra
.
getFirstRowIndex
();
int
lastRowIndex
=
cellExtra
.
getLastRowIndex
();
int
firstColumnIndex
=
cellExtra
.
getFirstColumnIndex
();
int
lastColumnIndex
=
cellExtra
.
getLastColumnIndex
();
Map
<
Integer
,
String
>
rdata
=
data
.
get
(
cellExtra
.
getRowIndex
())
;
String
val
=
null
;
if
(
rdata
!=
null
){
val
=
rdata
.
get
(
cellExtra
.
getColumnIndex
())
;
}
//遍历每行
Map
<
Integer
,
String
>
rowData
=
null
;
for
(
int
i
=
firstRowIndex
;
i
<=
lastRowIndex
;
i
++){
rowData
=
data
.
get
(
i
)
;
if
(
rowData
==
null
){
continue
;
}
for
(
int
c
=
firstColumnIndex
;
c
<=
lastColumnIndex
;
c
++){
rowData
.
put
(
c
,
val
)
;
}
}
});
}
}
nafmii-admin/src/main/java/org/nafmii/admin/user/service/impl/ImportExcelServiceImpl.java
deleted
100644 → 0
View file @
8001151
package
org
.
nafmii
.
admin
.
user
.
service
.
impl
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.poi.hssf.usermodel.HSSFWorkbook
;
import
org.apache.poi.ss.usermodel.Cell
;
import
org.apache.poi.ss.usermodel.Row
;
import
org.apache.poi.ss.usermodel.Sheet
;
import
org.apache.poi.ss.usermodel.Workbook
;
import
org.apache.poi.ss.util.CellRangeAddress
;
import
org.apache.poi.xssf.usermodel.XSSFWorkbook
;
import
org.nafmii.admin.user.dao.ImportExcelMapper
;
import
org.nafmii.admin.user.dto.ImportExcelDto
;
import
org.nafmii.admin.user.service.IImportExcelService
;
import
org.nafmii.common.response.ApiResponse
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.multipart.MultipartFile
;
import
javax.annotation.Resource
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* <p>
* 中心端批量导入Excel
* </p>
*
* @author suncq
* @since 2021-04-27
*/
@Slf4j
@Service
public
class
ImportExcelServiceImpl
implements
IImportExcelService
{
@Resource
private
ImportExcelMapper
importExcelMapper
;
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
ApiResponse
batchImportExcel
(
MultipartFile
file
)
throws
IOException
{
List
<
ImportExcelDto
>
list
=
new
ArrayList
<
ImportExcelDto
>();
String
fileName
=
file
.
getOriginalFilename
();
byte
[]
byteArr
=
file
.
getBytes
();
InputStream
inputStream
=
new
ByteArrayInputStream
(
byteArr
);
boolean
isE2007
=
false
;
//判断是否是excel2007格式
if
(
fileName
.
endsWith
(
"xlsx"
))
{
isE2007
=
true
;
}
InputStream
input
=
inputStream
;
//建立输入流
Workbook
wb
;
//根据文件格式(2003或者2007)来初始化
if
(
isE2007
)
{
wb
=
new
XSSFWorkbook
(
input
);
}
else
{
wb
=
new
HSSFWorkbook
(
input
);
}
Sheet
sheet
=
wb
.
getSheetAt
(
0
);
//获得第一个表单
int
rowCount
=
sheet
.
getLastRowNum
()
+
1
;
//总行数
for
(
int
i
=
1
;
i
<
rowCount
;
i
++)
{
ImportExcelDto
dto
=
new
ImportExcelDto
();
Row
row
;
int
columns
=
sheet
.
getRow
(
i
).
getLastCellNum
();
//单行列数
for
(
int
j
=
0
;
j
<
columns
;
j
++)
{
if
(
isMergedRegion
(
sheet
,
i
,
j
))
{
if
(
j
==
0
){
dto
.
setColumn1
(
getMergedRegionValue
(
sheet
,
i
,
j
));
}
else
if
(
j
==
1
){
dto
.
setColumn2
(
getMergedRegionValue
(
sheet
,
i
,
j
));
}
else
if
(
j
==
2
){
dto
.
setColumn3
(
getMergedRegionValue
(
sheet
,
i
,
j
));
}
}
else
{
row
=
sheet
.
getRow
(
i
);
if
(
j
==
0
){
dto
.
setColumn1
(
String
.
valueOf
(
row
.
getCell
(
j
)));
}
else
if
(
j
==
1
){
dto
.
setColumn2
(
String
.
valueOf
(
row
.
getCell
(
j
)));
}
else
if
(
j
==
2
){
dto
.
setColumn3
(
String
.
valueOf
(
toString
()));
}
}
}
list
.
add
(
dto
);
}
if
(!
list
.
isEmpty
())
{
for
(
ImportExcelDto
data
:
list
)
{
int
i
=
importExcelMapper
.
insertExcelData
(
data
);
if
(
i
<
0
)
{
return
new
ApiResponse
(
ApiResponse
.
FAIL
,
ApiResponse
.
FAIL_TEXT
);
}
}
}
else
{
return
new
ApiResponse
(
ApiResponse
.
FAIL
,
"导入时数据为空,导入失败"
);
}
return
new
ApiResponse
(
ApiResponse
.
SUCCESS
,
ApiResponse
.
SUCCESS_TEXT
);
}
/**
* 获取单元格的值
* @param cell
* @return
*/
public
String
getCellValue
(
Cell
cell
)
{
if
(
cell
==
null
)
return
""
;
return
cell
.
getStringCellValue
();
}
/**
* 获取合并单元格的值
* @param sheet
* @param row
* @param column
* @return
*/
public
String
getMergedRegionValue
(
Sheet
sheet
,
int
row
,
int
column
)
{
int
sheetMergeCount
=
sheet
.
getNumMergedRegions
();
for
(
int
i
=
0
;
i
<
sheetMergeCount
;
i
++)
{
CellRangeAddress
ca
=
sheet
.
getMergedRegion
(
i
);
int
firstColumn
=
ca
.
getFirstColumn
();
int
lastColumn
=
ca
.
getLastColumn
();
int
firstRow
=
ca
.
getFirstRow
();
int
lastRow
=
ca
.
getLastRow
();
if
(
row
>=
firstRow
&&
row
<=
lastRow
)
{
if
(
column
>=
firstColumn
&&
column
<=
lastColumn
)
{
Row
fRow
=
sheet
.
getRow
(
firstRow
);
Cell
fCell
=
fRow
.
getCell
(
firstColumn
);
return
getCellValue
(
fCell
);
}
}
}
return
null
;
}
/**
* 判断指定的单元格是否是合并单元格
* @param sheet
* @param row 行下标
* @param column 列下标
* @return
*/
private
boolean
isMergedRegion
(
Sheet
sheet
,
int
row
,
int
column
)
{
int
sheetMergeCount
=
sheet
.
getNumMergedRegions
();
for
(
int
i
=
0
;
i
<
sheetMergeCount
;
i
++)
{
CellRangeAddress
range
=
sheet
.
getMergedRegion
(
i
);
int
firstColumn
=
range
.
getFirstColumn
();
int
lastColumn
=
range
.
getLastColumn
();
int
firstRow
=
range
.
getFirstRow
();
int
lastRow
=
range
.
getLastRow
();
if
(
row
>=
firstRow
&&
row
<=
lastRow
)
{
if
(
column
>=
firstColumn
&&
column
<=
lastColumn
)
{
return
true
;
}
}
}
return
false
;
}
}
\ No newline at end of file
nafmii-admin/src/main/resources/mapper/AttachmentInfoMapper.xml
View file @
2e9ea9d
...
...
@@ -3,7 +3,7 @@
<mapper
namespace=
"org.nafmii.admin.dao.AttachmentInfoMapper"
>
<!-- 通用查询映射结果 -->
<resultMap
id=
"BaseResultMap"
type=
"org.nafmii.admin.entity.AttachmentInfoPO"
>
<resultMap
id=
"BaseResultMap"
type=
"org.nafmii.admin.
att.
entity.AttachmentInfoPO"
>
<id
column=
"ID"
property=
"id"
/>
<result
column=
"FILE_NAME"
property=
"fileName"
/>
<result
column=
"FILE_URL"
property=
"fileUrl"
/>
...
...
nafmii-admin/src/main/resources/mapper/ImportExcelMapper.xml
View file @
2e9ea9d
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"org.nafmii.admin.
user
.dao.ImportExcelMapper"
>
<mapper
namespace=
"org.nafmii.admin.
att
.dao.ImportExcelMapper"
>
<!-- 通用查询映射结果 -->
<resultMap
id=
"BaseResultMap"
type=
"org.nafmii.admin.
user
.dto.ImportExcelDto"
>
<resultMap
id=
"BaseResultMap"
type=
"org.nafmii.admin.
att
.dto.ImportExcelDto"
>
<result
column=
"COLUMN1"
property=
"column1"
/>
<result
column=
"COLUMN2"
property=
"column2"
/>
<result
column=
"COLUMN3"
property=
"column3"
/>
</resultMap>
<insert
id =
"insertExcelData"
parameterType=
"org.nafmii.admin.
user
.dto.ImportExcelDto"
>
<insert
id =
"insertExcelData"
parameterType=
"org.nafmii.admin.
att
.dto.ImportExcelDto"
>
insert into IMPORT_EXCEL_TEST
(COLUMN1,COLUMN2,COLUMN3)
values(#{data.column1},
...
...
nafmii-common/pom.xml
View file @
2e9ea9d
...
...
@@ -175,7 +175,7 @@
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
easyexcel
</artifactId>
<version>
2.
1.6
</version>
<version>
2.
2.7
</version>
</dependency>
<dependency>
<groupId>
com.google.guava
</groupId>
...
...
Write
Preview
Markdown
is supported
Attach a file
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 post a comment