Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
frontend
/
qqxb-self-service
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
69e484e6
authored
May 29, 2020
by
展昭
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
对接数据,修改对接方法.
parent
92743715
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
142 additions
and
101 deletions
.env.development
.env.production
.env.staging
src/router/employee/employee-router.ts
src/servicesImpl/employee/employeeImpl.ts
src/utils/http.ts
src/utils/method.ts
src/utils/public.ts
src/utils/urls.ts
src/views/SelectIdentity.vue
.env.development
View file @
69e484e6
VUE_APP_OIDC_CONFIG = '{ "authority": "http://106.120.107.150:5000", "client_id": "teamix-personal-center-web-pc", "client_secret": "123456", "redirect_uri": "http://localhost:8080/callback.html", "response_type": "id_token token", "scope": "openid workapps.client api.workapps.user","post_logout_redirect_uri":"http://localhost:8080", "silent_redirect_uri": "http://localhost:8080/silent-renew.html", "automaticSilentRenew": true,"accessTokenExpiringNotificationTime":60,"filterProtocolClaims":true,"loadUserInfo":true,"loadUserInfo":true }'
VUE_APP_BASE_URL= "http://organization.test.hrs100.cn:18080/"
VUE_APP_BASE_URL= http://organization.test.hrs100.cn:18080
VUE_APP_USERINFO_URL=http://106.120.107.145:7778/v1/qqxb/user/api
# https开关
VUE_APP_OPEN_HTTPS=false
.env.production
View file @
69e484e6
VUE_APP_OIDC_CONFIG = '{ "authority": "https://passport.teammix.com", "client_id": "qqxb-activity-web-mobile", "client_secret": "qqxb#teammix#2019", "redirect_uri": "https://invite.activity.h5.hrs100.com/callback.html", "response_type": "id_token token", "scope": "workapps.client api.workapps.user api.workapps.org api.workapps.open openid","post_logout_redirect_uri":"https://invite.activity.h5.hrs100.com", "silent_redirect_uri": "https://invite.activity.h5.hrs100.com/silent-renew-oidc.html", "automaticSilentRenew": true,"accessTokenExpiringNotificationTime":60,"filterProtocolClaims":true,"loadUserInfo":true }'
#VUE_APP_API_BASEURL = 'https://apiplus.qinqinxiaobao.com/v1/qqxb/user/api'
VUE_APP_USERINFO_URL="";
.env.staging
View file @
69e484e6
VUE_APP_OIDC_CONFIG = '{ "authority": "http://106.120.107.150:5000", "client_id": "qqxb-activity-web-mobile", "client_secret": "123456", "redirect_uri": "http://106.120.107.150:7774/callback.html", "response_type": "id_token token", "scope": "workapps.client api.workapps.user api.workapps.org api.workapps.open openid","post_logout_redirect_uri":"http://106.120.107.150:7774", "silent_redirect_uri": "http://106.120.107.150:7774/silent-renew-oidc.html", "automaticSilentRenew": true,"automaticSilentSignin":true,"accessTokenExpiringNotificationTime":60,"filterProtocolClaims":true,"loadUserInfo":true }'
#VUE_APP_API_BASEURL = 'http://106.120.107.145:7778/v1/qqxb/user/api'
VUE_APP_BASE_URL= http://organization.test.hrs100.cn:18080
VUE_APP_USERINFO_URL=http://106.120.107.145:7778/v1/qqxb/user/api
src/router/employee/employee-router.ts
View file @
69e484e6
...
...
@@ -16,7 +16,7 @@ export default [
component
:
()
=>
import
(
"@/views/SelectIdentity.vue"
),
meta
:
{
title
:
'身份选择'
,
requiresAuth
:
fals
e
requiresAuth
:
tru
e
}
},
{
...
...
src/servicesImpl/employee/employeeImpl.ts
View file @
69e484e6
...
...
@@ -3,6 +3,7 @@ import store from '@/store';
import
{
EmployeeInterface
}
from
'@/services/employee/employeeService'
;
import
urls
from
'@/utils/urls'
;
/**
* 员工服务类
*/
...
...
@@ -42,13 +43,8 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
async
getUserInfo
(
params
:
any
):
Promise
<
any
>
{
console
.
log
(
this
.
header
);
// let result = await request.get("http://qinqinxiaobao.com", "", this.header);
// console.log(result);
return
{
id
:
1
,
name
:
"333"
}
const
url
=
urls
.
userInfoUrl
+
`/userAuthDetails`
;
return
request
.
postWithAuthHeader
(
url
,
params
,
this
.
header
)
}
/**
...
...
@@ -56,7 +52,7 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
getWorkInfoList
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/
${
params
.
edId
}
/work`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/
${
params
.
edId
}
/work`
;
return
request
.
get
(
url
,
params
,
this
.
header
)
}
...
...
@@ -66,7 +62,7 @@ class EmployeeService implements EmployeeInterface {
*/
public
getWorkInfoDetail
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/
${
params
.
edId
}
/work/detail`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/
${
params
.
edId
}
/work/detail`
;
return
request
.
get
(
url
,
params
,
this
.
header
)
}
...
...
@@ -75,7 +71,7 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
getPersonInfo
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/
${
params
.
edId
}
/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/
${
params
.
edId
}
/info`
;
return
request
.
get
(
url
,
params
,
this
.
header
)
}
...
...
@@ -84,7 +80,7 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
savePersonInfo
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/
${
params
.
edId
}
/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/
${
params
.
edId
}
/info`
;
return
request
.
post
(
url
,
params
,
this
.
header
)
}
...
...
@@ -93,7 +89,7 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
getContactInfo
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/
${
params
.
edId
}
/contact/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/
${
params
.
edId
}
/contact/info`
;
return
request
.
get
(
url
,
params
,
this
.
header
)
}
...
...
@@ -102,7 +98,7 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
saveContactInfo
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/contact/
${
params
.
edId
}
/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/contact/
${
params
.
edId
}
/info`
;
return
request
.
post
(
url
,
params
,
this
.
header
)
}
...
...
@@ -111,7 +107,7 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
getSocialInfo
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/
${
params
.
edId
}
/unit/relation`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/
${
params
.
edId
}
/unit/relation`
;
return
request
.
get
(
url
,
params
,
this
.
header
)
}
...
...
@@ -120,7 +116,7 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
saveSocialInfo
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/unit/relation/save`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/unit/relation/save`
;
return
request
.
post
(
url
,
params
,
this
.
header
)
}
...
...
@@ -129,7 +125,7 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
getWageCardInfo
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/contact/
${
params
.
edId
}
/salary/card/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/contact/
${
params
.
edId
}
/salary/card/info`
;
return
request
.
get
(
url
,
params
,
this
.
header
)
}
...
...
@@ -138,7 +134,7 @@ class EmployeeService implements EmployeeInterface {
* @params params
*/
public
saveWageCardInfo
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/contact/salary/card/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/contact/salary/card/info`
;
return
request
.
post
(
url
,
params
,
this
.
header
)
}
...
...
@@ -147,7 +143,7 @@ class EmployeeService implements EmployeeInterface {
* @param params 请求参数
*/
public
getEduExperience
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/
${
params
.
edId
}
/education`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/
${
params
.
edId
}
/education`
;
return
request
.
get
(
url
,
params
,
this
.
header
)
}
...
...
@@ -157,7 +153,7 @@ class EmployeeService implements EmployeeInterface {
* @param params
*/
public
getEduExperienceDetial
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/
${
params
.
edId
}
/education/detial`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/
${
params
.
edId
}
/education/detial`
;
return
request
.
get
(
url
,
params
,
this
.
header
)
}
...
...
@@ -166,7 +162,7 @@ class EmployeeService implements EmployeeInterface {
* @param params
*/
public
addEduExperience
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/edu/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/edu/info`
;
return
request
.
post
(
url
,
params
,
this
.
header
)
}
...
...
@@ -175,7 +171,7 @@ class EmployeeService implements EmployeeInterface {
* @param params
*/
public
updateEduExperience
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/edu/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/edu/info`
;
return
request
.
put
(
url
,
params
,
this
.
header
)
}
...
...
@@ -184,7 +180,7 @@ class EmployeeService implements EmployeeInterface {
* @param params
*/
public
getTechnologyExperience
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/
${
params
.
edId
}
/expertise/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/
${
params
.
edId
}
/expertise/info`
;
return
request
.
get
(
url
,
params
,
this
.
header
)
}
...
...
@@ -193,7 +189,7 @@ class EmployeeService implements EmployeeInterface {
* @param params
*/
public
updateTechnologyExperience
(
params
:
any
):
Promise
<
any
>
{
let
url
=
`/api/user/employee/expertise/info`
;
let
url
=
urls
.
employeeUrl
+
`/api/user/employee/expertise/info`
;
return
request
.
put
(
url
,
params
,
this
.
header
)
}
...
...
src/utils/http.ts
View file @
69e484e6
...
...
@@ -4,7 +4,6 @@ import { ResponseData } from '@/types/index';
let
http
:
AxiosInstance
|
any
;
http
=
axios
.
create
({
baseURL
:
process
.
env
.
VUE_APP_BASE_URL
,
timeout
:
60000
,
});
...
...
src/utils/method.ts
View file @
69e484e6
...
...
@@ -37,6 +37,23 @@ class Request {
/**
*
* POST 请求
* @param url 请求链接
* @param params 请求参数
* @param headers 请求头信息
*/
public
postWithAuthHeader
(
url
:
string
,
params
:
any
=
{},
headers
:
any
=
{})
{
let
options
:
any
=
{};
if
(
headers
)
{
options
.
headers
=
headers
;
}
return
new
Promise
((
resolve
,
reject
)
=>
{
resolve
(
http
.
post
(
`
${
url
}
?
${
GetCommonPms
(
true
)}
`
,
params
,
options
));
})
}
/**
*
* PUT 请求
* @param url 请求链接
* @param params 请求参数
...
...
src/utils/public.ts
View file @
69e484e6
...
...
@@ -4,111 +4,111 @@
*/
export
function
isTel
(
tel
:
string
)
{
return
/^1
\d{10}
$/
.
test
(
tel
);
}
}
/**
/**
* 验证邮箱
* @param email 邮箱
*/
export
function
isEmail
(
email
:
string
)
{
export
function
isEmail
(
email
:
string
)
{
return
/^
([
a-zA-Z
]
|
[
0-9
])(\w
|
\-)
+@
[
a-zA-Z0-9
]
+
\.([
a-zA-Z
]{2,4})
$/
.
test
(
email
);
}
}
/**
/**
* 验证密码格式(8-16位,数字和英文字母的组合)
* @param password 密码
*/
export
function
isPassWord
(
password
:
string
)
{
export
function
isPassWord
(
password
:
string
)
{
// console.log(password);
return
/^
(?=
.*
?[
0-9
])(?=
.*
?[
A-Za-z
])[
0-9A-Za-z
]{8,16}
$/
.
test
(
password
);
}
}
/**
/**
* 验证银行卡号
* @param banknum 银行卡号
*/
export
function
isBankNum
(
banknum
:
string
)
{
export
function
isBankNum
(
banknum
:
string
)
{
return
/^
([
1-9
]{1})(\d{15}
|
\d{18})
$/
.
test
(
banknum
);
}
}
/**
/**
* 验证身份证号
* @param id 身份证号
*/
export
function
isIdCard
(
id
:
string
)
{
export
function
isIdCard
(
id
:
string
)
{
return
/^
\d{6}(
18|19|20
)\d{2}(
0
\d
|10|11|12
)([
0-2
]\d
|30|31
)\d{3}(\d
|X|x
)
$/
.
test
(
id
);
}
}
/**
/**
* 模糊手机号
* @param mobile 手机号
*/
export
function
fuzzyMobile
(
mobile
:
string
)
{
export
function
fuzzyMobile
(
mobile
:
string
)
{
let
mobileFront
=
mobile
.
slice
(
0
,
3
);
let
mobileEnd
=
mobile
.
slice
(
7
);
return
mobileFront
+
'****'
+
mobileEnd
;
}
}
/**
/**
* 模糊邮箱
* @param email 邮箱
*/
export
function
fuzzyEmail
(
email
:
string
)
{
export
function
fuzzyEmail
(
email
:
string
)
{
let
emailFront
=
email
.
slice
(
0
,
1
);
let
index
=
email
.
indexOf
(
'@'
);
let
emailEnd
=
email
.
slice
(
index
);
return
emailFront
+
'****'
+
emailEnd
;
}
}
/**
/**
* 姓名格式化为‘'*' + 尾字’
* @param name 姓名
*/
export
function
fuzzyName
(
name
:
string
)
{
export
function
fuzzyName
(
name
:
string
)
{
// console.log(name);
return
'*'
+
name
.
slice
(
-
1
);
}
}
/**
/**
* 身份证号格式化为‘首1+'******'+尾1’
* @param idnum 身份证
*/
export
function
fuzzyIdNum
(
idnum
:
string
)
{
export
function
fuzzyIdNum
(
idnum
:
string
)
{
if
(
idnum
===
""
)
{
return
""
;
}
return
(
idnum
||
""
).
slice
(
0
,
1
)
+
'****************'
+
(
idnum
||
""
).
slice
(
-
1
);
}
}
/**
/**
* 银行卡号格式化为‘首4+'******'+尾4’
* @param banknunm 银行卡号
*/
export
function
fuzzyBankNum
(
banknunm
:
string
)
{
export
function
fuzzyBankNum
(
banknunm
:
string
)
{
if
(
banknunm
===
""
)
{
return
""
;
}
return
(
banknunm
||
""
).
slice
(
0
,
4
)
+
'********'
+
(
banknunm
||
""
).
slice
(
-
4
);
}
}
/**
/**
* 获取性别
* @param sex 性别数字
*/
export
function
gender
(
sex
:
number
)
{
export
function
gender
(
sex
:
number
)
{
let
genderArr
=
[
''
,
'男'
,
'女'
];
if
(
sex
>
0
)
{
return
genderArr
[
sex
];
}
else
{
return
''
;
}
}
}
/**
/**
* 获取认证方式
* @param value 认证关键字
*/
export
function
authMethod
(
value
:
string
)
{
export
function
authMethod
(
value
:
string
)
{
let
bankArray
:
{
[
key
:
string
]:
string
}
=
{
"MANUAL"
:
"手动认证"
,
"TWO"
:
"二要素认证"
,
...
...
@@ -122,26 +122,26 @@ export function isTel(tel: string) {
}
}
return
""
;
}
}
/**
/**
* 检测字符串是否为空
* @param value 字符串
*/
export
function
isNullOrEmpty
(
value
:
string
)
{
export
function
isNullOrEmpty
(
value
:
string
)
{
if
(
value
===
null
||
value
===
undefined
||
value
===
""
)
{
return
false
;
}
return
true
;
}
}
/**
/**
* 节流调用
* @param this 当前调用对象
* @param fn 是我们需要包装的事件回调
* @param delay 是时间间隔的阈值
*/
export
function
throttle
(
this
:
any
,
fn
:
Function
,
delay
:
number
)
{
export
function
throttle
(
this
:
any
,
fn
:
Function
,
delay
:
number
)
{
// last为上一次触发回调的时间, timer是定时器
let
last
=
0
,
timer
:
any
=
null
;
...
...
@@ -168,14 +168,14 @@ export function isTel(tel: string) {
fn
.
apply
(
context
,
args
);
}
};
}
}
/**
/**
* 字符串转16进制
* @param s 字符串
*/
function
bin2hex
(
s
:
string
)
{
function
bin2hex
(
s
:
string
)
{
var
i
,
l
,
o
=
""
,
...
...
@@ -186,12 +186,12 @@ export function isTel(tel: string) {
o
+=
n
.
length
<
2
?
"0"
+
n
:
n
;
}
return
o
;
}
}
/**
/**
* 获取画布
*/
function
getCanvas
()
{
function
getCanvas
()
{
var
canvas
=
document
.
createElement
(
"canvas"
);
var
ctx
=
canvas
.
getContext
(
"2d"
);
ctx
!
.
fillStyle
=
"#f60"
;
...
...
@@ -200,12 +200,12 @@ export function isTel(tel: string) {
var
bin
=
atob
(
b64
);
var
crc
=
bin2hex
(
bin
.
slice
(
-
16
,
-
12
));
return
crc
;
}
}
/**
/**
* 获取系统信息
*/
function
getOsInfo
()
{
function
getOsInfo
()
{
var
userAgent
=
navigator
.
userAgent
.
toLowerCase
();
var
name
=
"Unknown"
;
var
version
=
"Unknown"
;
...
...
@@ -265,12 +265,12 @@ export function isTel(tel: string) {
// os.version = version;
return
version
;
//document.write("系统:" + os.name + "版本:" + os.name)
}
}
/**
/**
* 获取浏览器信息
*/
function
getBrowerInfo
()
{
function
getBrowerInfo
()
{
var
Browser
:
any
=
Browser
||
(
function
(
window
)
{
...
...
@@ -420,43 +420,51 @@ export function isTel(tel: string) {
}
// document.write(Browser.client.name + " " + Browser.client.version);
return
Browser
;
}
}
/**
/**
* 获取公共参数
*/
export
function
GetCommonPms
(
)
{
export
function
GetCommonPms
(
special
:
boolean
=
false
)
{
const
v
=
"1.0.1"
;
const
did
=
getCanvas
();
const
dh
=
getOsInfo
();
const
BrowerInfo
=
getBrowerInfo
();
const
db
=
BrowerInfo
.
client
.
name
;
const
dv
=
BrowerInfo
.
client
.
version
;
if
(
!
special
)
{
const
t
=
new
Date
().
getTime
();
const
pms
=
`v=
${
v
}
&&did=
${
did
}
&&dh=
${
dh
}
&&db=
${
db
}
&&dv=
${
dv
}
&&dm=&&lat=&&lng=&&t=
${
t
}
`
;
return
pms
;
}
else
{
const
pms
=
`v=
${
v
}
&&did=
${
did
}
&&dh=
${
dh
}
&&db=
${
db
}
&&dv=
${
dv
}
&&dm=&&lat=&&lng=&&t=`
;
return
pms
;
}
/**
}
/**
* 判断是否是移动端
*/
export
function
isMobileBrowser
()
{
export
function
isMobileBrowser
()
{
if
(
/Android|webOS|iPhone|iPod|BlackBerry/i
.
test
(
navigator
.
userAgent
))
{
return
true
;
}
return
false
;
}
}
function
padLeftZero
(
str
:
string
)
{
function
padLeftZero
(
str
:
string
)
{
return
(
'00'
+
str
).
substr
(
str
.
length
)
}
}
/**
/**
* 时间转换成字符串
* @param date 时间
* @param fmt 转换格式
*/
export
function
formatDate
(
date
:
Date
,
fmt
=
'yyyy-MM-dd hh:mm:ss'
)
{
export
function
formatDate
(
date
:
Date
,
fmt
=
'yyyy-MM-dd hh:mm:ss'
)
{
if
(
!
date
)
{
return
""
;
}
...
...
@@ -480,12 +488,12 @@ export function isTel(tel: string) {
}
}
return
fmt
;
}
}
/**
/**
* 获取当前所在系统
*/
export
function
CheckPlatform
()
{
export
function
CheckPlatform
()
{
if
(
/Win/i
.
test
(
navigator
.
platform
))
{
return
"PC-WINDOWS"
;
}
else
if
(
/Mac/i
.
test
(
navigator
.
platform
))
{
...
...
@@ -499,4 +507,4 @@ export function isTel(tel: string) {
}
else
{
return
""
;
}
}
\ No newline at end of file
}
\ No newline at end of file
src/utils/urls.ts
View file @
69e484e6
...
...
@@ -8,10 +8,10 @@ class Urls {
*/
employeeUrl
:
String
=
process
.
env
.
VUE_APP_BASE_URL
;
/
/ /
**
// * 认证中心
//
*/
// tokenUrl: String = process.env.VUE_APP_LOGIN
_URL;
/**
* 获取用户信息
*/
userInfoUrl
:
String
=
process
.
env
.
VUE_APP_USERINFO
_URL
;
}
...
...
src/views/SelectIdentity.vue
View file @
69e484e6
...
...
@@ -27,14 +27,28 @@
<
script
lang=
'ts'
>
import
{
Component
,
Vue
}
from
"vue-property-decorator"
;
@
Component
@
Component
({
components
:
{}
})
export
default
class
SelectIdentity
extends
Vue
{
private
id_no
:
string
=
""
;
private
toFlex
():
void
{
this
.
$router
.
push
({
name
:
"FlexEmployee"
});
this
.
$router
.
push
({
name
:
"FlexEmployee"
,
query
:
{
id_no
:
this
.
id_no
}
});
}
private
toIndex
():
void
{
this
.
$router
.
push
({
name
:
"Index"
});
this
.
$router
.
push
({
name
:
"Index"
,
query
:
{
id_no
:
this
.
id_no
}
});
}
created
()
{
this
.
$server
.
EmployeeService
.
getUserInfo
({}).
then
(
res
=>
{
if
(
res
.
data
&&
res
.
data
.
uthStatus
&&
res
.
data
.
uthStatus
>
2
)
{
this
.
id_no
=
res
.
data
.
personalIdCardNo
;
}
else
{
//TODO: 跳转到实名认证
}
});
}
}
</
script
>
...
...
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