Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
electron-printer
Overview
Overview
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zhuzhequan
electron-printer
Commits
f6e6d6d9
Commit
f6e6d6d9
authored
Aug 10, 2024
by
朱哲铨
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
代码优化
parent
0834896a
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
244 additions
and
240 deletions
+244
-240
README.md
+6
-6
src/backend/entity/function.js
+210
-214
src/backend/routes/index.js
+11
-1
src/backend/server.js
+3
-3
src/backend/utils/index.js
+0
-0
src/background.js
+3
-4
src/main.js
+11
-12
src/preload.js
+0
-0
src/preloadOther.js
+0
-0
No files found.
README.md
View file @
f6e6d6d9
...
...
@@ -496,8 +496,8 @@
function.js Slice管理
be_sysConfig.js 系统设置
routes 目录: 存放 exporess 路由
be_routes
.js 路由定义
be_nodeSrv
.js express 服务器
index
.js 路由定义
server
.js express 服务器
```
-
增加 lowdb 支持
...
...
@@ -575,11 +575,11 @@
-
Web Server 服务器
代码: src/backend/webserver/
be_nodeSrv
.js:
代码: src/backend/webserver/
server
.js:
```javascript
import express from "express";
import router from "./routes/
be_routes
.js";
import router from "./routes/
index
.js";
const PORT = 3000;
const webApp = express();
...
...
@@ -615,7 +615,7 @@
-
Express的API 路由:
代码: src/backend/webserver/routes/
be_routes
.js
代码: src/backend/webserver/routes/
index
.js
```javascript
import express from "express";
...
...
@@ -681,7 +681,7 @@
import { app, protocol, BrowserWindow, Menu } from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
+ import webApp from "@/backend/webserver/
be_nodeSrv
.js";
+ import webApp from "@/backend/webserver/
server
.js";
...
```
...
...
src/backend/
webserver/
entity/function.js
→
src/backend/entity/function.js
View file @
f6e6d6d9
...
...
@@ -2,7 +2,7 @@ import {
downloadImage
,
toSend
,
writeProfileXml
}
from
"@/backend/
webserver/
utils"
;
}
from
"@/backend/utils"
;
const
compressing
=
require
(
"compressing"
);
var
uuid
=
require
(
"uuid"
);
...
...
@@ -10,234 +10,230 @@ const path = require("path");
const
fs
=
require
(
"fs"
);
const
os
=
require
(
"os"
);
import
axios
from
"axios"
;
var
multiparty
=
require
(
"multiparty"
);
let
fn
=
new
Object
();
export
default
{
getPodProductionInfo
:
async
(
req
,
res
)
=>
{
const
token
=
req
.
headers
[
"jwt-token"
];
const
company
=
req
.
headers
[
"company"
];
const
productionNo
=
req
.
body
.
productionNo
;
try
{
let
{
data
}
=
await
axios
.
post
(
`https://
${
company
}
/api/podDesignCenter/getPodImageByProduction`
,
{
productionNo
},
{
headers
:
{
"jwt-token"
:
token
}
}
);
console
.
log
(
data
);
if
(
data
.
code
===
200
&&
data
.
data
&&
data
.
data
.
length
>
0
)
{
let
f
=
data
.
data
.
find
(
el
=>
!
el
.
productionFile
);
data
.
data
.
forEach
(
el
=>
{
if
(
!
el
.
productionFile
.
includes
(
"http"
))
{
el
.
productionFile
=
el
.
productionFile
.
replace
(
"/data/upload/erp/"
,
""
);
el
.
productionFile
=
`https://
${
company
}
/upload/erp
${
el
.
productionFile
}
`
;
}
});
if
(
f
)
{
return
res
.
json
({
code
:
500
,
msg
:
"存在地址错误的素材图"
});
}
fn
.
getPodProductionInfo
=
async
(
req
,
res
)
=>
{
const
token
=
req
.
headers
[
"jwt-token"
];
const
company
=
req
.
headers
[
"company"
];
const
productionNo
=
req
.
body
.
productionNo
;
try
{
let
{
data
}
=
await
axios
.
post
(
`https://
${
company
}
/api/podDesignCenter/getPodImageByProduction`
,
{
productionNo
},
{
headers
:
{
"jwt-token"
:
token
}
}
);
console
.
log
(
data
);
if
(
data
.
code
===
200
&&
data
.
data
&&
data
.
data
.
length
>
0
)
{
let
f
=
data
.
data
.
find
(
el
=>
!
el
.
productionFile
);
data
.
data
.
forEach
(
el
=>
{
if
(
!
el
.
productionFile
.
includes
(
"http"
))
{
el
.
productionFile
=
el
.
productionFile
.
replace
(
"/data/upload/erp/"
,
""
);
el
.
productionFile
=
`https://
${
company
}
/upload/erp
${
el
.
productionFile
}
`
;
downloadImage
(
data
.
data
)
.
then
(
data
=>
{
res
.
json
({
code
:
200
,
data
});
})
.
catch
(
err
=>
{
res
.
json
({
code
:
500
,
msg
:
err
});
});
}
else
{
res
.
json
({
code
:
200
,
msg
:
"未找到素材图"
,
data
:
[]
});
}
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
},
findByPodProductionNo
:
async
(
req
,
res
)
=>
{
const
token
=
req
.
headers
[
"jwt-token"
];
const
company
=
req
.
headers
[
"company"
];
const
q
=
req
.
body
;
try
{
let
{
data
}
=
await
axios
.
get
(
`https://
${
company
}
/api/pod/podProductionInfo/findByPodProductionNo`
,
{
params
:
q
,
headers
:
{
"jwt-token"
:
token
}
}
});
if
(
f
)
{
return
res
.
json
({
code
:
500
,
msg
:
"存在地址错误的素材图"
});
);
res
.
json
(
data
);
}
catch
(
err
)
{
res
.
json
({
code
:
500
,
msg
:
err
});
}
},
getCompanyList
:
async
(
req
,
res
)
=>
{
try
{
let
{
data
}
=
await
axios
.
get
(
"https://platform.jomalls.com/api/tools/getCompanyList"
);
res
.
send
(
data
);
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
},
commitApply
:
async
(
req
,
res
)
=>
{
const
company
=
req
.
headers
[
"company"
];
const
q
=
req
.
body
;
try
{
let
{
data
}
=
await
axios
.
post
(
`https://
${
company
}
/api/sysDeviceInfo/commitApply`
,
q
);
res
.
send
(
data
);
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
},
completeDelivery
:
async
(
req
,
res
)
=>
{
const
token
=
req
.
headers
[
"jwt-token"
];
const
company
=
req
.
headers
[
"company"
];
const
q
=
req
.
body
;
try
{
let
{
data
}
=
await
axios
.
post
(
`https://
${
company
}
/api/pod/podProductionInfo/completeDelivery`
,
q
,
{
headers
:
{
"jwt-token"
:
token
}
}
);
res
.
json
(
data
);
}
catch
(
err
)
{
res
.
json
({
code
:
500
,
msg
:
err
});
}
},
downloadByDesignId
:
async
(
req
,
res
)
=>
{
let
q
=
req
.
body
;
try
{
let
dir
=
path
.
join
(
os
.
homedir
(),
"/Desktop/"
+
q
.
productionNo
+
".zip"
);
const
zipStream
=
new
compressing
.
zip
.
Stream
();
for
(
let
k
in
q
.
imgList
)
{
const
p
=
path
.
join
(
process
.
cwd
(),
"./print/Input/"
+
q
.
imgList
[
k
].
fileName
);
zipStream
.
addEntry
(
p
);
}
downloadImage
(
data
.
data
)
.
then
(
data
=>
{
res
.
json
({
code
:
200
,
data
});
const
destStream
=
fs
.
createWriteStream
(
dir
);
zipStream
.
pipe
(
destStream
)
.
on
(
"finish"
,
()
=>
{
console
.
log
(
"success"
);
res
.
json
({
code
:
200
,
msg
:
q
.
productionNo
+
".zip"
+
"已下载到桌面"
});
})
.
catch
(
err
=>
{
res
.
json
({
code
:
500
,
msg
:
err
});
.
on
(
"error"
,
()
=>
{
res
.
json
({
code
:
500
,
msg
:
"文件下载失败"
});
});
}
else
{
res
.
json
({
code
:
200
,
msg
:
"未找到素材图"
,
data
:
[]
});
// let ws=fs.createWriteStream(dir );
// console.log(downloadByDesignId)
//
// ws.write(downloadByDesignId.data);
// ws.on('drain',function () {
// console.log("内存干了");
// });
// ws.on('error',function (err) {
// res.json({code: 500, msg: '文件下载失败'})
// });
// ws.on('close',function (err) {
//
// });
// ws.end()
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
};
fn
.
findByPodProductionNo
=
async
(
req
,
res
)
=>
{
const
token
=
req
.
headers
[
"jwt-token"
];
const
company
=
req
.
headers
[
"company"
];
const
q
=
req
.
body
;
try
{
let
{
data
}
=
await
axios
.
get
(
`https://
${
company
}
/api/pod/podProductionInfo/findByPodProductionNo`
,
{
params
:
q
,
headers
:
{
"jwt-token"
:
token
}
}
);
res
.
json
(
data
);
}
catch
(
err
)
{
res
.
json
({
code
:
500
,
msg
:
err
});
}
};
fn
.
getCompanyList
=
async
(
req
,
res
)
=>
{
try
{
let
{
data
}
=
await
axios
.
get
(
"https://platform.jomalls.com/api/tools/getCompanyList"
);
res
.
send
(
data
);
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
};
fn
.
commitApply
=
async
(
req
,
res
)
=>
{
const
company
=
req
.
headers
[
"company"
];
const
q
=
req
.
body
;
try
{
let
{
data
}
=
await
axios
.
post
(
`https://
${
company
}
/api/sysDeviceInfo/commitApply`
,
q
);
res
.
send
(
data
);
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
};
fn
.
completeDelivery
=
async
(
req
,
res
)
=>
{
const
token
=
req
.
headers
[
"jwt-token"
];
const
company
=
req
.
headers
[
"company"
];
const
q
=
req
.
body
;
try
{
let
{
data
}
=
await
axios
.
post
(
`https://
${
company
}
/api/pod/podProductionInfo/completeDelivery`
,
q
,
{
headers
:
{
"jwt-token"
:
token
}
}
);
res
.
json
(
data
);
}
catch
(
err
)
{
res
.
json
({
code
:
500
,
msg
:
err
});
}
};
fn
.
downloadByDesignId
=
async
(
req
,
res
)
=>
{
let
q
=
req
.
body
;
try
{
let
dir
=
path
.
join
(
os
.
homedir
(),
"/Desktop/"
+
q
.
productionNo
+
".zip"
);
const
zipStream
=
new
compressing
.
zip
.
Stream
();
},
uploadImage
:
async
(
req
,
res
)
=>
{
try
{
const
p
=
path
.
join
(
process
.
cwd
(),
"./print/Input/"
);
let
fileName
=
uuid
.
v4
()
+
".png"
;
console
.
log
(
fileName
);
for
(
let
k
in
q
.
imgList
)
{
const
p
=
path
.
join
(
const
form
=
new
multiparty
.
Form
({
uploadDir
:
p
});
form
.
parse
(
req
,
function
(
err
,
fields
,
files
)
{
console
.
log
(
fields
,
files
,
err
);
if
(
err
)
{
res
.
send
({
code
:
500
,
err
});
}
else
{
fs
.
renameSync
(
files
.
file
[
0
].
path
,
path
.
join
(
p
,
fileName
));
res
.
json
({
code
:
200
,
data
:
{
fileName
,
url
:
path
.
join
(
process
.
cwd
(),
"./print/Input/"
+
fileName
)
}
});
}
});
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
},
getPngImg
:
async
(
req
,
res
)
=>
{
try
{
const
filePath
=
path
.
join
(
process
.
cwd
(),
"./print/Input/"
+
q
.
imgList
[
k
].
fileName
`./print/Input/
${
req
.
body
.
fileName
}
`
);
zipStream
.
addEntry
(
p
);
}
const
destStream
=
fs
.
createWriteStream
(
dir
);
zipStream
.
pipe
(
destStream
)
.
on
(
"finish"
,
()
=>
{
console
.
log
(
"success"
);
res
.
json
({
code
:
200
,
msg
:
q
.
productionNo
+
".zip"
+
"已下载到桌面"
});
})
.
on
(
"error"
,
()
=>
{
res
.
json
({
code
:
500
,
msg
:
"文件下载失败"
});
});
// let ws=fs.createWriteStream(dir );
// console.log(downloadByDesignId)
//
// ws.write(downloadByDesignId.data);
// ws.on('drain',function () {
// console.log("内存干了");
// });
// ws.on('error',function (err) {
// res.json({code: 500, msg: '文件下载失败'})
// });
// ws.on('close',function (err) {
//
// });
// ws.end()
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
};
fn
.
uploadImage
=
async
(
req
,
res
)
=>
{
try
{
const
p
=
path
.
join
(
process
.
cwd
(),
"./print/Input/"
);
let
fileName
=
uuid
.
v4
()
+
".png"
;
console
.
log
(
fileName
);
const
form
=
new
multiparty
.
Form
({
uploadDir
:
p
});
form
.
parse
(
req
,
function
(
err
,
fields
,
files
)
{
console
.
log
(
fields
,
files
,
err
);
if
(
err
)
{
res
.
send
({
code
:
500
,
err
});
}
else
{
fs
.
renameSync
(
files
.
file
[
0
].
path
,
path
.
join
(
p
,
fileName
));
res
.
json
({
code
:
200
,
data
:
{
fileName
,
url
:
path
.
join
(
process
.
cwd
(),
"./print/Input/"
+
fileName
)
}
console
.
log
(
filePath
);
// 给客户端返回一个文件流 type类型
res
.
set
(
"content-type"
,
{
png
:
"image/png"
,
jpg
:
"image/jpeg"
});
//设置返回类型
let
stream
=
fs
.
createReadStream
(
filePath
);
let
responseData
=
[];
//存储文件流
if
(
stream
)
{
//判断状态
stream
.
on
(
"data"
,
function
(
chunk
)
{
responseData
.
push
(
chunk
);
});
stream
.
on
(
"end"
,
function
()
{
const
finalData
=
Buffer
.
concat
(
responseData
);
res
.
write
(
finalData
);
res
.
end
();
});
}
});
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
};
fn
.
getPngImg
=
async
(
req
,
res
)
=>
{
try
{
const
filePath
=
path
.
join
(
process
.
cwd
(),
`./print/Input/
${
req
.
body
.
fileName
}
`
);
console
.
log
(
filePath
);
// 给客户端返回一个文件流 type类型
res
.
set
(
"content-type"
,
{
png
:
"image/png"
,
jpg
:
"image/jpeg"
});
//设置返回类型
let
stream
=
fs
.
createReadStream
(
filePath
);
let
responseData
=
[];
//存储文件流
if
(
stream
)
{
//判断状态
stream
.
on
(
"data"
,
function
(
chunk
)
{
responseData
.
push
(
chunk
);
});
stream
.
on
(
"end"
,
function
()
{
const
finalData
=
Buffer
.
concat
(
responseData
);
res
.
write
(
finalData
);
res
.
end
();
});
}
catch
(
err
)
{
res
.
send
({
code
:
500
,
msg
:
err
});
}
}
catch
(
err
)
{
res
.
send
({
code
:
500
,
msg
:
err
});
}
};
fn
.
login
=
async
(
req
,
res
)
=>
{
const
{
loginName
,
company
,
password
,
deviceId
}
=
req
.
body
;
try
{
let
{
data
}
=
await
axios
.
post
(
`https://
${
company
}
/api/sysLogin/login`
,
{
loginName
,
password
,
deviceId
});
},
login
:
async
(
req
,
res
)
=>
{
const
{
loginName
,
company
,
password
,
deviceId
}
=
req
.
body
;
try
{
let
{
data
}
=
await
axios
.
post
(
`https://
${
company
}
/api/sysLogin/login`
,
{
loginName
,
password
,
deviceId
});
res
.
send
(
data
);
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
res
.
send
(
data
);
}
catch
(
err
)
{
console
.
log
(
err
);
res
.
json
({
code
:
500
,
msg
:
err
});
}
},
toPrint
:
(
req
,
res
)
=>
{
let
body
=
req
.
body
;
writeProfileXml
(
body
);
// 写入xml文件
// GTXproCMD.exe print -X "Profile\\CO12.xml" -I "Input\\sample.png" -A "Output\\pO12.arxp" -S 03000400 -L 02540254
toSend
(
body
)
.
then
(
r
=>
{
res
.
send
({
code
:
200
,
msg
:
"操作成功"
});
})
.
catch
(
err
=>
{
res
.
send
({
code
:
500
,
msg
:
err
});
});
}
};
fn
.
toPrint
=
(
req
,
res
)
=>
{
let
body
=
req
.
body
;
writeProfileXml
(
body
);
// 写入xml文件
// GTXproCMD.exe print -X "Profile\\CO12.xml" -I "Input\\sample.png" -A "Output\\pO12.arxp" -S 03000400 -L 02540254
toSend
(
body
)
.
then
(
r
=>
{
res
.
send
({
code
:
200
,
msg
:
"操作成功"
});
})
.
catch
(
err
=>
{
res
.
send
({
code
:
500
,
msg
:
err
});
});
};
export
{
fn
as
default
};
src/backend/
webserver/routes/be_routes
.js
→
src/backend/
routes/index
.js
View file @
f6e6d6d9
...
...
@@ -5,16 +5,26 @@ import fn from "../entity/function.js";
let
router
=
express
.
Router
();
// 执行打印命令
router
.
post
(
"/toPrint"
,
fn
.
toPrint
);
// 登录接口
router
.
post
(
"/login"
,
fn
.
login
);
// 获取本地文件返回
router
.
post
(
"/getPngImg"
,
fn
.
getPngImg
);
// 上传文件到本地
router
.
post
(
"/uploadImage"
,
fn
.
uploadImage
);
// 获取公司列表
router
.
get
(
"/getCompanyList"
,
fn
.
getCompanyList
);
// 提交授权申请
router
.
post
(
"/commitApply"
,
fn
.
commitApply
);
// 下载素材到本地
router
.
post
(
"/downloadByDesignId"
,
fn
.
downloadByDesignId
);
// 获取 生产单号返回素材地址
router
.
post
(
"/getPodProductionInfo"
,
fn
.
getPodProductionInfo
);
// 提交生产完成
router
.
post
(
"/completeDelivery"
,
fn
.
completeDelivery
);
// 根据生产单号查询详情
router
.
post
(
"/findByPodProductionNo"
,
fn
.
findByPodProductionNo
);
export
{
router
as
default
};
export
{
router
as
default
};
src/backend/
webserver/be_nodeSrv
.js
→
src/backend/
server
.js
View file @
f6e6d6d9
import
express
from
"express"
;
import
router
from
"./routes/
be_routes
.js"
;
import
router
from
"./routes/
index
.js"
;
const
PORT
=
3000
;
const
webApp
=
express
();
...
...
@@ -9,12 +9,12 @@ webApp.use(express.urlencoded({ extended: false }));
webApp
.
use
(
"/"
,
router
);
// catch 404
webApp
.
use
((
req
,
res
,
next
)
=>
{
webApp
.
use
((
req
,
res
)
=>
{
res
.
status
(
404
).
send
(
"Sorry! 404 Error."
);
});
// error handler, 4个参数
webApp
.
use
((
err
,
req
,
res
,
next
)
=>
{
webApp
.
use
((
err
,
req
,
res
)
=>
{
// set locals, only providing error in development
res
.
locals
.
message
=
err
.
message
;
res
.
locals
.
error
=
req
.
app
.
get
(
"env"
)
===
"development"
?
err
:
{};
...
...
src/backend/
webserver/
utils/index.js
→
src/backend/utils/index.js
View file @
f6e6d6d9
File moved
src/background.js
View file @
f6e6d6d9
"use strict"
;
import
{
contextBridge
,
ipcMain
,
ipcRenderer
}
from
"electron"
;
import
{
app
,
protocol
,
BrowserWindow
,
Menu
,
screen
}
from
"electron"
;
import
{
ipcMain
}
from
"electron"
;
import
{
app
,
protocol
,
BrowserWindow
,
screen
}
from
"electron"
;
import
{
createProtocol
}
from
"vue-cli-plugin-electron-builder/lib"
;
import
webApp
from
"@/backend/
webserver/be_nodeSrv
.js"
;
import
webApp
from
"@/backend/
server
.js"
;
let
isCreateWin
=
false
;
const
isDevelopment
=
process
.
env
.
NODE_ENV
!==
"production"
;
let
win
;
...
...
src/main.js
View file @
f6e6d6d9
...
...
@@ -2,14 +2,14 @@ import Vue from "vue";
import
App
from
"./App.vue"
;
import
router
from
"./router"
;
import
store
from
"./store"
;
import
VueI18n
from
'vue-i18n'
;
import
VueI18n
from
"vue-i18n"
;
import
VueCompositionApi
from
"@vue/composition-api"
;
import
{
Message
}
from
"element-ui"
;
// 挂载到$message上
import
api
from
'@/utils/axios'
import
api
from
"@/utils/axios"
;
import
ElementUI
from
"element-ui"
;
import
"element-ui/lib/theme-chalk/index.css"
;
import
dataStore
from
'electron-store'
;
import
dataStore
from
"electron-store"
;
const
DataStore
=
new
dataStore
();
...
...
@@ -18,20 +18,19 @@ Vue.use(ElementUI);
Vue
.
use
(
VueCompositionApi
);
Vue
.
use
(
VueI18n
);
Vue
.
prototype
.
$message
=
Message
Vue
.
prototype
.
$dataStore
=
DataStore
Vue
.
prototype
.
$store
=
store
Vue
.
prototype
.
$api
=
api
Vue
.
prototype
.
$message
=
Message
Vue
.
prototype
.
$message
=
Message
;
Vue
.
prototype
.
$dataStore
=
DataStore
;
Vue
.
prototype
.
$store
=
store
;
Vue
.
prototype
.
$api
=
api
;
Vue
.
prototype
.
$message
=
Message
;
const
i18n
=
new
VueI18n
({
locale
:
'zh'
,
locale
:
"zh"
,
messages
:
{
'zh'
:
require
(
'./i18n/zh.js'
),
'en'
:
require
(
'./i18n/en.js'
)
zh
:
require
(
"./i18n/zh.js"
),
en
:
require
(
"./i18n/en.js"
)
}
});
new
Vue
({
router
,
store
,
...
...
src/preload.js
deleted
100644 → 0
View file @
0834896a
src/preloadOther.js
deleted
100644 → 0
View file @
0834896a
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