Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
卡
卡车调度系统
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
caicaicai
卡车调度系统
Commits
16f688d2
Commit
16f688d2
authored
Apr 22, 2022
by
caicaicai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改
parent
2939f995
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
491 additions
and
10 deletions
+491
-10
background.js
src/background.js
+84
-0
index.vue
...iews/MLargeScreen/components/intelligentSchedul/index.vue
+403
-6
index.vue
src/views/MLargeScreen/index.vue
+2
-2
vue.config.js
vue.config.js
+2
-2
No files found.
src/background.js
0 → 100644
View file @
16f688d2
'
use strict
'
import
{
app
,
protocol
,
BrowserWindow
}
from
'
electron
'
import
{
createProtocol
}
from
'
vue-cli-plugin-electron-builder/lib
'
import
installExtension
,
{
VUEJS_DEVTOOLS
}
from
'
electron-devtools-installer
'
const
isDevelopment
=
process
.
env
.
NODE_ENV
!==
'
production
'
// Scheme must be registered before the app is ready
protocol
.
registerSchemesAsPrivileged
([
{
scheme
:
'
app
'
,
privileges
:
{
secure
:
true
,
standard
:
true
}
}
])
async
function
createWindow
()
{
// Create the browser window.
const
win
=
new
BrowserWindow
({
width
:
800
,
height
:
600
,
webPreferences
:
{
// Required for Spectron testing
enableRemoteModule
:
!!
process
.
env
.
IS_TEST
,
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration
:
process
.
env
.
ELECTRON_NODE_INTEGRATION
,
contextIsolation
:
!
process
.
env
.
ELECTRON_NODE_INTEGRATION
}
})
if
(
process
.
env
.
WEBPACK_DEV_SERVER_URL
)
{
// Load the url of the dev server if in development mode
await
win
.
loadURL
(
process
.
env
.
WEBPACK_DEV_SERVER_URL
)
if
(
!
process
.
env
.
IS_TEST
)
win
.
webContents
.
openDevTools
()
}
else
{
createProtocol
(
'
app
'
)
// Load the index.html when not in development
win
.
loadURL
(
'
app://./index.html
'
)
}
}
// Quit when all windows are closed.
app
.
on
(
'
window-all-closed
'
,
()
=>
{
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if
(
process
.
platform
!==
'
darwin
'
)
{
app
.
quit
()
}
})
app
.
on
(
'
activate
'
,
()
=>
{
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if
(
BrowserWindow
.
getAllWindows
().
length
===
0
)
createWindow
()
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app
.
on
(
'
ready
'
,
async
()
=>
{
if
(
isDevelopment
&&
!
process
.
env
.
IS_TEST
)
{
// Install Vue Devtools
try
{
await
installExtension
(
VUEJS_DEVTOOLS
)
}
catch
(
e
)
{
console
.
error
(
'
Vue Devtools failed to install:
'
,
e
.
toString
())
}
}
createWindow
()
})
// Exit cleanly on request from parent process in development mode.
if
(
isDevelopment
)
{
if
(
process
.
platform
===
'
win32
'
)
{
process
.
on
(
'
message
'
,
(
data
)
=>
{
if
(
data
===
'
graceful-exit
'
)
{
app
.
quit
()
}
})
}
else
{
process
.
on
(
'
SIGTERM
'
,
()
=>
{
app
.
quit
()
})
}
}
src/views/MLargeScreen/components/intelligentSchedul/index.vue
View file @
16f688d2
...
...
@@ -130,6 +130,13 @@
<
script
>
import
{
Tools
,
HttpReq
,
Dates
}
from
'
@/assets/js/common.js
'
;
import
*
as
echarts
from
'
echarts
'
;
//加载必须要的core,demo简化起见采用的直接加载类库,实际使用时应当采用异步按需加载
import
Recorder
from
'
recorder-core
'
// //需要使用到的音频格式编码引擎的js文件统统加载进来,这些引擎文件会比较大
import
'
recorder-core/src/engine/mp3
'
import
'
recorder-core/src/engine/mp3-engine
'
// //可选的扩展
import
'
recorder-core/src/extensions/waveview
'
export
default
{
data
()
{
...
...
@@ -147,6 +154,16 @@ export default {
dispatchDetailsList
:[],
//智能调度情况表
dispatchBtnTitle
:
'
人工调度
'
,
dispatchBtnTitle1
:
'
人工调度
'
,
type
:
"
mp3
"
,
bitRate
:
16
,
sampleRate
:
16000
,
rec
:
0
,
duration
:
0
,
powerLevel
:
0
,
recOpenDialogShow
:
0
,
logs
:[],
}
},
created
(){
},
...
...
@@ -201,14 +218,17 @@ export default {
//车辆区域分布Echarts
this
.
carsAreaDistributionEcharts
();
})
//开启录音
this
.
recOpen
();
//页面刚进入时开启长连接
this
.
initWebSocket
();
this
.
heartbeatTimer
=
setInterval
(()
=>
{
this
.
reconnect
();
},
10000
)
//
this.initWebSocket();
//
this.heartbeatTimer = setInterval(() => {
//
this.reconnect();
//
}, 10000)
}
else
{
//关闭录音
this
.
recClose
();
this
.
whetherShow
=
false
;
}
},
...
...
@@ -448,12 +468,389 @@ export default {
}
},
recOpen
:
function
(){
var
This
=
this
;
var
rec
=
this
.
rec
=
Recorder
({
type
:
This
.
type
,
bitRate
:
This
.
bitRate
,
sampleRate
:
This
.
sampleRate
,
onProcess
:
function
(
buffers
,
powerLevel
,
duration
,
sampleRate
){
This
.
duration
=
duration
;
This
.
powerLevel
=
powerLevel
;
This
.
wave
.
input
(
buffers
[
buffers
.
length
-
1
],
powerLevel
,
sampleRate
);
}
});
This
.
dialogInt
=
setTimeout
(
function
(){
//定时8秒后打开弹窗,用于监测浏览器没有发起权限请求的情况
This
.
showDialog
();
},
8000
);
rec
.
open
(
function
(){
This
.
dialogCancel
();
This
.
reclog
(
"
已打开:
"
+
This
.
type
+
"
"
+
This
.
sampleRate
+
"
hz
"
+
This
.
bitRate
+
"
kbps
"
,
2
);
This
.
wave
=
Recorder
.
WaveView
({
elem
:
"
.ctrlProcessWave
"
});
},
function
(
msg
,
isUserNotAllow
){
This
.
dialogCancel
();
This
.
reclog
((
isUserNotAllow
?
"
UserNotAllow,
"
:
""
)
+
"
打开失败:
"
+
msg
,
1
);
});
This
.
waitDialogClickFn
=
function
(){
This
.
dialogCancel
();
This
.
reclog
(
"
打开失败:权限请求被忽略,用户主动点击的弹窗
"
,
1
);
};
},
recClose
:
function
(){
var
rec
=
this
.
rec
;
this
.
rec
=
null
;
if
(
rec
){
rec
.
close
();
this
.
reclog
(
"
已关闭
"
);
}
else
{
this
.
reclog
(
"
未打开录音
"
,
1
);
};
},
recStart
:
function
(){
if
(
!
this
.
rec
||!
Recorder
.
IsOpen
()){
//this.reclog("未打开录音",1);
this
.
recOpen
()
//return;
}
this
.
rec
.
start
();
var
set
=
this
.
rec
.
set
;
this
.
reclog
(
"
录制中:
"
+
set
.
type
+
"
"
+
set
.
sampleRate
+
"
hz
"
+
set
.
bitRate
+
"
kbps
"
);
this
.
$notify
({
title
:
'
录制中!
'
,
type
:
'
success
'
,
duration
:
5000
});
},
recPause
:
function
(){
if
(
this
.
rec
&&
Recorder
.
IsOpen
()){
this
.
rec
.
pause
();
}
else
{
this
.
reclog
(
"
未打开录音
"
,
1
);
};
},
recResume
:
function
(){
if
(
this
.
rec
&&
Recorder
.
IsOpen
()){
this
.
rec
.
resume
();
}
else
{
this
.
reclog
(
"
未打开录音
"
,
1
);
};
},
recStop
:
function
(){
if
(
!
(
this
.
rec
&&
Recorder
.
IsOpen
())){
This
.
reclog
(
"
未打开录音
"
,
1
);
This
.
$notify
({
title
:
'
未打开录音!
'
,
type
:
'
warning
'
,
duration
:
2500
});
return
;
}
var
This
=
this
;
var
rec
=
This
.
rec
;
rec
.
stop
(
function
(
blob
,
duration
){
This
.
reclog
(
"
已录制:
"
,
""
,{
blob
:
blob
,
duration
:
duration
,
rec
:
rec
});
This
.
$notify
({
title
:
'
已录制!
'
,
type
:
'
success
'
,
duration
:
2500
});
},
function
(
s
){
This
.
$notify
({
title
:
'
录音失败,
'
+
s
,
type
:
'
warning
'
,
duration
:
2500
});
This
.
reclog
(
"
录音失败:
"
+
s
,
1
);
});
this
.
recOpen
();
},
recPlayLast
:
function
(){
if
(
!
this
.
recLogLast
){
this
.
reclog
(
"
请先录音,然后停止后再播放
"
,
1
);
return
;
};
this
.
recplay
(
this
.
recLogLast
.
idx
);
},
recUploadLast
:
function
(){
let
carNumberString
=
''
;
this
.
selectCarRadioArray
.
forEach
((
item
,
index
)
=>
{
carNumberString
=
carNumberString
+
item
.
number
+
'
;
'
;
})
carNumberString
=
carNumberString
+
'
pcBigScreen
'
;
this
.
carAllNumberString
=
carNumberString
;
var
This
=
this
;
if
(
!
this
.
recLogLast
){
this
.
reclog
(
"
请先录音,然后停止后再上传
"
,
1
);
This
.
$notify
({
title
:
'
请先录音,然后停止后再上传!
'
,
type
:
'
warning
'
,
duration
:
2500
});
return
;
};
var
blob
=
this
.
recLogLast
.
res
.
blob
;
//本例子假设使用原始XMLHttpRequest请求方式,实际使用中自行调整为自己的请求方式
//录音结束时拿到了blob文件对象,可以用FileReader读取出内容,或者用FormData上传
var
api
=
"
https://xx.xx/test_request
"
;
var
onreadystatechange
=
function
(
title
){
return
function
(){
if
(
xhr
.
readyState
==
4
){
if
(
xhr
.
status
==
200
){
This
.
reclog
(
title
+
"
上传成功
"
,
2
);
}
else
{
This
.
reclog
(
title
+
"
没有完成上传,演示上传地址无需关注上传结果,只要浏览器控制台内Network面板内看到的请求数据结构是预期的就ok了。
"
,
"
#d8c1a0
"
);
console
.
error
(
title
+
"
上传失败
"
,
xhr
.
status
,
xhr
.
responseText
);
};
};
};
};
This
.
reclog
(
"
开始上传到
"
+
api
+
"
,请求稍后...
"
,
"
#f60
"
);
/***方式一:将blob文件转成base64纯文本编码,使用普通application/x-www-form-urlencoded表单上传***/
var
reader
=
new
FileReader
();
reader
.
onloadend
=
function
(){
var
postData
=
""
;
postData
+=
"
mime=
"
+
encodeURIComponent
(
blob
.
type
);
//告诉后端,这个录音是什么格式的,可能前后端都固定的mp3可以不用写
postData
+=
"
&upfile_b64=
"
+
encodeURIComponent
((
/.+;
\s
*base64
\s
*,
\s
*
(
.+
)
$/i
.
exec
(
reader
.
result
)
||
[])[
1
])
//录音文件内容,后端进行base64解码成二进制
//...其他表单参数
// var xhr=new XMLHttpRequest();
// xhr.open("POST", api);
// xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
// xhr.onreadystatechange=onreadystatechange("上传方式一【Base64】");
// xhr.send(postData);
//发送语音数据
if
(
This
.
websocket
.
readyState
===
1
)
{
// that.websock.readyState = 1 表示连接成功,可以立即发送信息
//console.log(`{"toUserId":"${This.userName1}","contentText":"${postData}"}`);
This
.
websocketsend
(
`{"toUserId":"
${
This
.
carAllNumberString
}
","contentText":"
${
postData
}
","fromUserId":"调度中心大屏"}`
);
This
.
$notify
({
title
:
'
上传成功!
'
,
type
:
'
success
'
,
duration
:
2500
});
}
else
if
(
This
.
websocket
.
readyState
===
0
)
{
// 表示正在连接,设置300ms后发送信息
setTimeout
(
function
()
{
This
.
websocketsend
(
`{"toUserId":"
${
This
.
carAllNumberString
}
","contentText":"
${
postData
}
","fromUserId":"调度中心大屏"}`
);
This
.
$notify
({
title
:
'
上传成功!
'
,
type
:
'
success
'
,
duration
:
2500
});
},
300
);
}
else
{
// 连接未创建或者创建失败,则重新创建连接,并设置500ms后发送信息
This
.
initWebSocket
();
setTimeout
(
function
()
{
This
.
websocketsend
(
`{"toUserId":"
${
This
.
carAllNumberString
}
","contentText":"
${
postData
}
","fromUserId":"调度中心大屏"}`
);
This
.
$notify
({
title
:
'
上传成功!
'
,
type
:
'
success
'
,
duration
:
2500
});
},
500
);
}
};
reader
.
readAsDataURL
(
blob
);
},
reclog
:
function
(
msg
,
color
,
res
){
var
obj
=
{
idx
:
this
.
logs
.
length
,
msg
:
msg
,
color
:
color
,
res
:
res
,
playMsg
:
""
,
down
:
0
,
down64Val
:
""
};
if
(
res
&&
res
.
blob
){
this
.
recLogLast
=
obj
;
};
this
.
logs
.
splice
(
0
,
0
,
obj
);
},
recplay
:
function
(
idx
){
var
This
=
this
;
var
o
=
this
.
logs
[
this
.
logs
.
length
-
idx
-
1
];
o
.
play
=
(
o
.
play
||
0
)
+
1
;
var
logmsg
=
function
(
msg
){
o
.
playMsg
=
'
<span style="color:green">
'
+
o
.
play
+
'
</span>
'
+
This
.
getTime
()
+
"
"
+
msg
;
};
logmsg
(
""
);
var
audio
=
this
.
$refs
.
LogAudioPlayer
;
audio
.
controls
=
true
;
if
(
!
(
audio
.
ended
||
audio
.
paused
)){
audio
.
pause
();
};
audio
.
onerror
=
function
(
e
){
logmsg
(
'
<span style="color:red">播放失败[
'
+
audio
.
error
.
code
+
'
]
'
+
audio
.
error
.
message
+
'
</span>
'
);
};
audio
.
src
=
(
window
.
URL
||
webkitURL
).
createObjectURL
(
o
.
res
.
blob
);
audio
.
play
();
},
recdown
:
function
(
idx
){
var
This
=
this
;
var
o
=
this
.
logs
[
this
.
logs
.
length
-
idx
-
1
];
o
.
down
=
(
o
.
down
||
0
)
+
1
;
o
=
o
.
res
;
var
name
=
"
rec-
"
+
o
.
duration
+
"
ms-
"
+
(
o
.
rec
.
set
.
bitRate
||
"
-
"
)
+
"
kbps-
"
+
(
o
.
rec
.
set
.
sampleRate
||
"
-
"
)
+
"
hz.
"
+
(
o
.
rec
.
set
.
type
||
(
/
\w
+$/
.
exec
(
o
.
blob
.
type
)
||
[])[
0
]
||
"
unknown
"
);
var
downA
=
document
.
createElement
(
"
A
"
);
downA
.
href
=
(
window
.
URL
||
webkitURL
).
createObjectURL
(
o
.
blob
);
downA
.
download
=
name
;
downA
.
click
();
},
recdown64
:
function
(
idx
){
var
This
=
this
;
var
o
=
this
.
logs
[
this
.
logs
.
length
-
idx
-
1
];
var
reader
=
new
FileReader
();
reader
.
onloadend
=
function
()
{
o
.
down64Val
=
reader
.
result
;
};
reader
.
readAsDataURL
(
o
.
res
.
blob
);
},
getTime
:
function
(){
var
now
=
new
Date
();
var
t
=
(
"
0
"
+
now
.
getHours
()).
substr
(
-
2
)
+
"
:
"
+
(
"
0
"
+
now
.
getMinutes
()).
substr
(
-
2
)
+
"
:
"
+
(
"
0
"
+
now
.
getSeconds
()).
substr
(
-
2
);
return
t
;
},
intp
:
function
(
s
,
len
){
s
=
s
==
null
?
"
-
"
:
s
+
""
;
if
(
s
.
length
>=
len
)
return
s
;
return
(
"
_______
"
+
s
).
substr
(
-
len
);
},
showDialog
:
function
(){
//我们可以选择性的弹一个对话框:为了防止移动端浏览器存在第三种情况:用户忽略,并且(或者国产系统UC系)浏览器没有任何回调
if
(
!
/mobile/i
.
test
(
navigator
.
userAgent
)){
return
;
//只在移动端开启没有权限请求的检测
};
this
.
recOpenDialogShow
=
1
;
},
dialogCancel
:
function
(){
clearTimeout
(
this
.
dialogInt
);
this
.
recOpenDialogShow
=
0
;
},
waitDialogClick
:
function
(){
this
.
dialogCancel
();
this
.
waitDialogClickFn
();
},
selectSituation
(
item
){
this
.
recClose
();
// Blobdata 就是后端返回给你的Blob数据
const
reader
=
new
FileReader
();
const
booo
=
new
Blob
([
item
.
contentText
]);
reader
.
readAsArrayBuffer
(
booo
);
reader
.
onload
=
(
e
)
=>
{
const
bufer
=
e
.
srcElement
.
result
;
const
blob
=
this
.
addWavHeader
(
bufer
,
16000
,
16
,
1
);
this
.
srcUrl
=
window
.
URL
.
createObjectURL
(
blob
);
};
},
addWavHeader
(
samples
,
sampleRateTmp
,
sampleBits
,
channelCount
)
{
const
dataLength
=
samples
.
byteLength
;
/* 新的buffer类,预留44bytes的heaer空间 */
const
buffer
=
new
ArrayBuffer
(
44
+
dataLength
);
/* 转为 Dataview, 利用API来填充字节 */
const
view
=
new
DataView
(
buffer
);
let
offset
=
0
;
/* ChunkID, 4 bytes, 资源交换文件标识符 */
this
.
writeString
(
view
,
offset
,
'
RIFF
'
);
offset
+=
4
;
/* ChunkSize, 4 bytes, 下个地址开始到文件尾总字节数,即文件大小-8 */
view
.
setUint32
(
offset
,
/* 32 */
36
+
dataLength
,
true
);
offset
+=
4
;
/* Format, 4 bytes, WAV文件标志 */
this
.
writeString
(
view
,
offset
,
'
WAVE
'
);
offset
+=
4
;
/* Subchunk1 ID, 4 bytes, 波形格式标志 */
this
.
writeString
(
view
,
offset
,
'
fmt
'
);
offset
+=
4
;
/* Subchunk1 Size, 4 bytes, 过滤字节,一般为 0x10 = 16 */
view
.
setUint32
(
offset
,
16
,
true
);
offset
+=
4
;
/* Audio Format, 2 bytes, 格式类别 (PCM形式采样数据) */
view
.
setUint16
(
offset
,
1
,
true
);
offset
+=
2
;
/* Num Channels, 2 bytes, 通道数 */
view
.
setUint16
(
offset
,
channelCount
,
true
);
offset
+=
2
;
/* SampleRate, 4 bytes, 采样率,每秒样本数,表示每个通道的播放速度 */
view
.
setUint32
(
offset
,
sampleRateTmp
,
true
);
offset
+=
4
;
/* ByteRate, 4 bytes, 波形数据传输率 (每秒平均字节数) 通道数×每秒数据位数×每样本数据位/8 */
view
.
setUint32
(
offset
,
sampleRateTmp
*
channelCount
*
(
sampleBits
/
8
),
true
);
offset
+=
4
;
/* BlockAlign, 2 bytes, 快数据调整数 采样一次占用字节数 通道数×每样本的数据位数/8 */
view
.
setUint16
(
offset
,
channelCount
*
(
sampleBits
/
8
),
true
);
offset
+=
2
;
/* BitsPerSample, 2 bytes, 每样本数据位数 */
view
.
setUint16
(
offset
,
sampleBits
,
true
);
offset
+=
2
;
/* Subchunk2 ID, 4 bytes, 数据标识符 */
this
.
writeString
(
view
,
offset
,
'
data
'
);
offset
+=
4
;
/* Subchunk2 Size, 4 bytes, 采样数据总数,即数据总大小-44 */
view
.
setUint32
(
offset
,
dataLength
,
true
);
offset
+=
4
;
if
(
sampleBits
===
16
)
{
this
.
floatTo16BitPCM
(
view
,
samples
);
}
else
if
(
sampleBits
===
8
)
{
this
.
floatTo8BitPCM
(
view
,
samples
);
}
else
{
this
.
floatTo32BitPCM
(
view
,
samples
);
}
return
new
Blob
([
view
],
{
type
:
'
audio/wav
'
});
},
writeString
(
view
,
offset
,
string
)
{
for
(
let
i
=
0
;
i
<
string
.
length
;
i
+=
1
)
{
view
.
setUint8
(
offset
+
i
,
string
.
charCodeAt
(
i
));
}
},
floatTo32BitPCM
(
output
,
input
)
{
const
oinput
=
new
Int32Array
(
input
);
let
newoffset
=
44
;
for
(
let
i
=
0
;
i
<
oinput
.
length
;
i
+=
1
,
newoffset
+=
4
)
{
output
.
setInt32
(
newoffset
,
oinput
[
i
],
true
);
}
},
floatTo16BitPCM
(
output
,
input
)
{
const
oinput
=
new
Int16Array
(
input
);
let
newoffset
=
44
;
for
(
let
i
=
0
;
i
<
oinput
.
length
;
i
+=
1
,
newoffset
+=
2
)
{
output
.
setInt16
(
newoffset
,
oinput
[
i
],
true
);
}
},
floatTo8BitPCM
(
output
,
input
)
{
const
oinput
=
new
Int8Array
(
input
);
let
newoffset
=
44
;
for
(
let
i
=
0
;
i
<
oinput
.
length
;
i
+=
1
,
newoffset
+=
1
)
{
output
.
setInt8
(
newoffset
,
oinput
[
i
],
true
);
}
},
},
beforeDestroy
()
{
//页面销毁时关闭长连接
this
.
websocketclose
();
//关闭心跳
this
.
heartbeatTimer
=
null
;
if
(
this
.
heartbeatTimer
)
{
clearInterval
(
this
.
heartbeatTimer
);
}
},
}
</
script
>
...
...
src/views/MLargeScreen/index.vue
View file @
16f688d2
...
...
@@ -39,9 +39,9 @@
<span
class=
"el-icon-location"
></span>
</div>
-->
<!-- 地图区域 -->
<div
id=
"centerDiv"
class=
"mapcontainer1"
>
<
!--
<
div
id=
"centerDiv"
class=
"mapcontainer1"
>
<mars3dViewerMap
:url=
"configUrl"
@
onload=
"onMapload"
/>
</div>
</div>
-->
</div>
</
template
>
...
...
vue.config.js
View file @
16f688d2
...
...
@@ -24,8 +24,8 @@ module.exports = {
lintOnSave
:
process
.
env
.
NODE_ENV
===
'
development
'
,
productionSourceMap
:
false
,
devServer
:
{
//
host: 'localhost', // 也可以直接写IP地址这样方便真机测试
host
:
'
192.168.0.101
'
,
// 也可以直接写IP地址这样方便真机测试
host
:
'
localhost
'
,
// 也可以直接写IP地址这样方便真机测试
//
host: '192.168.0.101', // 也可以直接写IP地址这样方便真机测试
port
:
port
,
open
:
true
,
overlay
:
{
...
...
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