Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
李勇
/
McuClient
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
AlexWang
2017-06-22 12:03:11 +0800
Browse Files
Options
Browse Files
Download
Plain Diff
Commit
7029aa76e345e0463552bae07997f7d43ddf67d3
7029aa76
2 parents
67ac606e
51e886c5
合并dev
显示空白字符变更
内嵌
并排对比
正在显示
6 个修改的文件
包含
236 行增加
和
44 行删除
dist/McuClient.js
src/EngineEntrance.js
src/EngineUtils.js
src/GlobalConfig.js
src/MessageTypes.js
src/apes/QuestionApe.js
dist/McuClient.js
查看文件 @
7029aa7
此 diff 太大无法显示。
src/EngineEntrance.js
查看文件 @
7029aa7
...
...
@@ -33,7 +33,7 @@ import QuestionApe from 'apes/QuestionApe';
import
UTF8
from
'utf-8'
;
let
loger
=
Loger
.
getLoger
(
'McuClient'
);
let
_sdkInfo
=
{
"version"
:
"v1.36.
1.20170619
"
,
"author"
:
"www.3mang.com"
};
let
_sdkInfo
=
{
"version"
:
"v1.36.
8.20170620
"
,
"author"
:
"www.3mang.com"
};
//APE
let
_sass
;
...
...
@@ -1233,12 +1233,181 @@ export default class MessageEntrance extends Emiter {
}
}
<<
<<
<<
<
HEAD
//ChatApe
// 发送聊天消息
_sendChatMsg
(
_messageInfo
)
{
if
(
!
_mcu
.
connected
)
{
loger
.
warn
(
GlobalConfig
.
getCurrentStatus
());
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
""
};
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
""
};
===
===
=
//获取课堂所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do
_sassGetClassParamSuccessHandler
(
_data
)
{
loger
.
log
(
'获取课堂课堂信息完成.'
);
//包含整个课堂最全的信息,储存数据
if
(
_data
)
{
GlobalConfig
.
mcuDelay
=
_data
.
h5Delay
||
0
;
//mcu消息延迟的时间间隔,单位(秒),结合客户端传的messageDelay的值使用
GlobalConfig
.
className
=
_data
.
meetingName
||
""
;
GlobalConfig
.
classBeginTime
=
_data
.
beginTime
||
""
;
GlobalConfig
.
classEndTime
=
_data
.
endTime
||
""
;
GlobalConfig
.
userIp
=
_data
.
userIp
||
""
;
GlobalConfig
.
maxVideoChannels
=
_data
.
maxVideoChannels
;
GlobalConfig
.
maxAudioChannels
=
_data
.
maxAudioChannels
;
GlobalConfig
.
maxMediaChannels
=
Math
.
max
(
GlobalConfig
.
maxVideoChannels
,
GlobalConfig
.
maxAudioChannels
);
GlobalConfig
.
ssTunnelAppURL
=
_data
.
ssTunnelAppURL
||
''
;
//屏幕共享插件的地址
//视频质量相关设置,每次加入课堂都按最新的获取设置
GlobalConfig
.
fps
=
_data
.
fps
||
15
;
GlobalConfig
.
gop
=
_data
.
gop
||
3
;
GlobalConfig
.
videoQuality
=
parseInt
(
_data
.
videoQuality
);
GlobalConfig
.
curVideoQuality
=
GlobalConfig
.
videoQuality
;
//是否自动开始(身份是host的时候才用到的)
GlobalConfig
.
isAutoStartClass
=
_data
.
autoRecord
||
0
;
GlobalConfig
.
serverTime
=
_data
.
serverTime
||
new
Date
().
getTime
();
//获取服务器时间戳
GlobalConfig
.
serverAndLoacTimeDistanc
=
(
new
Date
().
getTime
()
-
GlobalConfig
.
serverTime
)
/
1000
;
//当前系统时间和服务器时间的差值 (秒)
loger
.
warn
(
"服务器时间:"
+
GlobalConfig
.
serverTime
+
" 系统时间:"
+
new
Date
().
getTime
()
+
" 时间差:"
+
GlobalConfig
.
serverAndLoacTimeDistanc
);
GlobalConfig
.
setDocListPrepare
(
_data
.
docListPrepare
);
//提前上传的文档列表
GlobalConfig
.
setRecordList
(
_data
.
recordList
);
//录制回放地址
GlobalConfig
.
setDocList
(
_data
.
docList
);
//文档地址
GlobalConfig
.
setMsList
(
_data
.
msList
);
//推流播流服务器地址(需要对列表中的地址进行分类,里面包含了推流和拉流的地址,目前主要是乐视的需要区分开)
GlobalConfig
.
setRsList
(
_data
.
rsList
);
//播放m3u8格式的地址(录制回放时使用)
GlobalConfig
.
setMcuList
(
_data
.
mcuList
);
//mcu
GlobalConfig
.
setMusicList
(
_data
.
musicList
);
//
GlobalConfig
.
setMusicListPrepare
(
_data
.
musicListPrepare
);
//提前上传的声音文件列表
GlobalConfig
.
setVideoCDNAddr
(
_data
.
videoCDNAddr
);
//cdn加速的拉流地址,直播的时候才使用
GlobalConfig
.
setMediaShareList
(
_data
.
sharedMediaList
);
//提前上传的媒体共享文件列表
//MCU地址
if
(
_data
.
mcuList
&&
_data
.
mcuList
.
length
>
0
)
{
//随机选择一个
let
index
=
parseInt
(
Math
.
random
()
*
_data
.
mcuList
.
length
);
GlobalConfig
.
MCUServerIP
=
_data
.
mcuList
[
index
].
ip
||
""
;
GlobalConfig
.
MCUServerPort
=
_data
.
mcuList
[
index
].
port
||
""
;
loger
.
log
(
'初始->MCU->.'
,
GlobalConfig
.
MCUServerIP
,
GlobalConfig
.
MCUServerPort
);
}
//录制回放时m3u8播流地址
if
(
_data
.
rsList
&&
_data
.
rsList
.
length
>
0
)
{
let
index
=
parseInt
(
Math
.
random
()
*
_data
.
rsList
.
length
);
GlobalConfig
.
RS_RECORD_PLAY_IP
=
_data
.
rsList
[
index
].
ip
||
""
;
GlobalConfig
.
RS_RECORD_PLAY_PORT
=
_data
.
rsList
[
index
].
port
||
""
;
loger
.
log
(
'初始->RS->.'
,
GlobalConfig
.
RS_RECORD_PLAY_IP
,
GlobalConfig
.
RS_RECORD_PLAY_PORT
);
}
//上课中音视频推流地址
if
(
GlobalConfig
.
msList
&&
GlobalConfig
.
msList
.
length
>
0
)
{
let
index
=
parseInt
(
Math
.
random
()
*
GlobalConfig
.
msList
.
length
);
GlobalConfig
.
MS_PUBLISH_IP
=
GlobalConfig
.
msList
[
index
].
ip
||
""
;
GlobalConfig
.
MS_PUBLISH_PORT
=
GlobalConfig
.
msList
[
index
].
port
||
""
;
}
loger
.
log
(
'初始->MS->.'
,
GlobalConfig
.
MS_PUBLISH_IP
,
GlobalConfig
.
MS_PUBLISH_PORT
);
//播流的地址和推流地址需要分开的时候,单独设置拉流的地址 rtmp(目前乐视使用)
if
(
GlobalConfig
.
pullRtmpList
&&
GlobalConfig
.
pullRtmpList
.
length
>
0
)
{
//有单独的rtmp拉流地址
let
index
=
parseInt
(
Math
.
random
()
*
GlobalConfig
.
pullRtmpList
.
length
);
GlobalConfig
.
MS_PLAY_RTMP_IP
=
GlobalConfig
.
pullRtmpList
[
index
].
ip
||
""
;
GlobalConfig
.
MS_PLAY_RTMP_PORT
=
GlobalConfig
.
pullRtmpList
[
index
].
port
||
""
;
}
else
{
//如果没有单独的rtmp拉流地址,和推流地址一样即可
GlobalConfig
.
MS_PLAY_RTMP_IP
=
GlobalConfig
.
MS_PUBLISH_IP
;
GlobalConfig
.
MS_PLAY_RTMP_PORT
=
GlobalConfig
.
MS_PUBLISH_PORT
;
}
loger
.
log
(
'初始->MSPull->.'
,
GlobalConfig
.
MS_PLAY_RTMP_IP
,
GlobalConfig
.
MS_PLAY_RTMP_PORT
);
//播流的地址和推流地址需要分开的时候,单独设置拉流的地址 hls(目前乐视使用)
if
(
GlobalConfig
.
hlsList
&&
GlobalConfig
.
hlsList
.
length
>
0
)
{
//有单独的hls拉流地址
let
index
=
parseInt
(
Math
.
random
()
*
GlobalConfig
.
hlsList
.
length
);
GlobalConfig
.
MS_PLAY_HLS_IP
=
GlobalConfig
.
hlsList
[
index
].
ip
||
""
;
GlobalConfig
.
MS_PLAY_HLS_PORT
=
GlobalConfig
.
hlsList
[
index
].
port
||
""
;
}
else
{
//没有单独的hls拉流地址,和录制回放地址一样即可
GlobalConfig
.
MS_PLAY_HLS_IP
=
GlobalConfig
.
RS_RECORD_PLAY_IP
;
GlobalConfig
.
MS_PLAY_HLS_PORT
=
GlobalConfig
.
RS_RECORD_PLAY_PORT
;
}
loger
.
log
(
'初始->MSHls->.'
,
GlobalConfig
.
MS_PLAY_HLS_IP
,
GlobalConfig
.
MS_PLAY_HLS_PORT
);
//直播的时候,拉流(rtmp和hls)需要从 videoCDNAddr中获取
//20170531-新规则,所有课堂类型都支持加速
// if(GlobalConfig.classType==ApeConsts.CLASS_TYPE_2&&GlobalConfig.videoCDNAddrList.length>0){
if
(
GlobalConfig
.
videoCDNAddrList
.
length
>
0
)
{
//videoCDNAddrList中rtmppush和hls是混在一起的,需要分离开;
let
listLen
=
GlobalConfig
.
videoCDNAddrList
.
length
;
for
(
let
i
=
0
;
i
<
listLen
;
i
++
)
{
let
ipItem
=
GlobalConfig
.
videoCDNAddrList
[
i
];
if
(
ipItem
)
{
if
(
ipItem
.
indexOf
(
'hls'
)
>=
0
)
{
//直播的时候m3u8拉流地址
GlobalConfig
.
MS_PLAY_HLS_IP
=
ipItem
;
//ip包含了端口
GlobalConfig
.
MS_PLAY_HLS_PORT
=
""
;
loger
.
log
(
'videoCDNAddr>初始->MSHls'
,
GlobalConfig
.
MS_PLAY_HLS_IP
);
}
else
if
(
ipItem
.
indexOf
(
'rtmppull'
)
>=
0
)
{
//直播的时候rtmp拉流地址
GlobalConfig
.
MS_PLAY_RTMP_IP
=
ipItem
;
//ip包含了端口
GlobalConfig
.
MS_PLAY_RTMP_PORT
=
''
;
loger
.
log
(
'videoCDNAddr->初始->MSPull'
,
GlobalConfig
.
MS_PLAY_RTMP_IP
);
}
}
}
}
else
{
loger
.
log
(
'不需要videoCDNAddr->'
);
}
//文档地址
if
(
_data
.
docList
&&
_data
.
docList
.
length
>
0
)
{
//doc上传地址,随机获取一个
let
index
=
parseInt
(
Math
.
random
()
*
_data
.
docList
.
length
);
loger
.
log
(
"docServer->"
,
_data
.
docList
[
index
]);
GlobalConfig
.
DOCServerIP
=
_data
.
docList
[
index
].
ip
||
""
;
GlobalConfig
.
DOCServerPort
=
_data
.
docList
[
index
].
port
||
""
;
loger
.
log
(
'初始->DOC->.'
,
GlobalConfig
.
DOCServerIP
,
GlobalConfig
.
DOCServerPort
);
}
//record
if
(
_data
.
recordList
&&
_data
.
recordList
.
length
>
0
)
{
let
index
=
parseInt
(
Math
.
random
()
*
_data
.
recordList
.
length
);
GlobalConfig
.
RecordServerIP
=
_data
.
recordList
[
index
].
ip
||
""
;
GlobalConfig
.
RecordServerPort
=
_data
.
recordList
[
index
].
port
||
""
;
loger
.
log
(
'初始->RECORD->.'
,
GlobalConfig
.
RecordServerIP
,
GlobalConfig
.
RecordServerPort
);
}
}
//这里需要考虑是否加延迟处理,课堂信息刚获取完成,客户端需要根据数据创建界面UI,等创建完成后再加入课堂是最合适的(目前没有加延迟)
this
.
_emit
(
MessageTypes
.
CLASS_GET_INFO_SUCCESS
,
GlobalConfig
.
getClassInfo
());
if
(
_data
.
currentInfo
)
{
//根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息
loger
.
log
(
"本地同步最后一次保存过的课堂状态信息"
);
try
{
GlobalConfig
.
setClassStatusInfo
(
JSON
.
parse
(
_data
.
currentInfo
));
}
catch
(
err
)
{
GlobalConfig
.
setClassStatusInfo
(
_data
.
currentInfo
);
}
loger
.
log
(
GlobalConfig
.
classStatusInfo
);
}
else
{
loger
.
log
(
"还没有保存过课堂状信息"
);
}
//录制回放不需要获取ip信息和选点
if
(
GlobalConfig
.
isRecordPlayBack
)
{
if
(
_recordPlayback
)
{
//开启录制回放流程
loger
.
log
(
"开启录制回放流程"
);
_recordPlayback
.
readyRecordPlay
();
}
else
{
loger
.
warn
(
"开启录制回放流程失败->还未创建模块"
);
}
}
else
{
//根据用户的userIp获取信息,选点
this
.
getUserIpInfo
();
}
>>>
>>>
>
51
e886
c5e7fcd06f9e4a662071aaec162c455e1d
}
if
(
_messageInfo
===
null
||
EngineUtils
.
isEmptyObject
(
_messageInfo
))
{
loger
.
log
(
'发送聊天消息失败->参数错误'
,
_messageInfo
);
...
...
@@ -1879,5 +2048,5 @@ export default class MessageEntrance extends Emiter {
}
}
}
}
...
...
src/EngineUtils.js
查看文件 @
7029aa7
...
...
@@ -37,7 +37,7 @@ class EngineUtils{
//生成时间戳毫秒
static
creatTimestamp
(){
let
time
=
parseInt
(
new
Date
().
getTime
()
/
1000
);
//精确到
毫
秒
let
time
=
parseInt
(
new
Date
().
getTime
()
/
1000
);
//精确到秒
return
time
;
}
//生成时间戳 string
...
...
src/GlobalConfig.js
查看文件 @
7029aa7
...
...
@@ -460,6 +460,7 @@ GlobalConfig.allowRecordMaxTime = 14400; //(秒)允许录制的最长时间,
GlobalConfig
.
siteId_letv
=
'shchuanbao'
;
//乐视,MS不需要动态选点的站点
GlobalConfig
.
ssTunnelAppURL
=
''
;
//屏幕共享插件的地址
GlobalConfig
.
serverTime
=
0
;
//服务器当前时间戳
GlobalConfig
.
serverAndLoacTimeDistanc
=
0
;
//本地时间和服务器时间错的差值;
export
default
GlobalConfig
;
...
...
src/MessageTypes.js
查看文件 @
7029aa7
...
...
@@ -89,15 +89,11 @@ MessageTypes.DOC_BROADCAST = "doc_broadcast"; //
MessageTypes
.
MEDIA_SHARED_DELETE
=
"media_shared_delete"
;
//删除媒体文件
MessageTypes
.
MEDIA_SHARED_UPDATE
=
"media_shared_update"
;
//更新媒体文件(添加、变更)
//答题卡
//答题卡
和点名共用
MessageTypes
.
START_ANSWER_QUESTION
=
"start_answer_question"
;
//开始答题
MessageTypes
.
UPDATE_ANSWER_QUESTION
=
"update_answer_question"
;
//更新答题数据
MessageTypes
.
STOP_ANSWER_QUESTION
=
"stop_answer_question"
;
//停止答题
//点名
MessageTypes
.
START_CALL_THE_ROLL
=
"start_call_the_roll"
;
//开始点名
MessageTypes
.
UPDATE_CALL_THE_ROLL
=
"update_call_the_roll"
;
//更新点名数据
MessageTypes
.
STOP_CALL_THE_ROLL
=
"stop_call_the_roll"
;
//停止点名
MessageTypes
.
UPDATE_QUESTION_TIME
=
"update_question_time"
;
//更新答题时间
//白板笔记事件定义
MessageTypes
.
WHITEBOARD_ANNOTATION_UPDATE
=
"whiteboard_annotation_update"
;
// 'whiteboard.annotation.update';
...
...
src/apes/QuestionApe.js
查看文件 @
7029aa7
...
...
@@ -23,8 +23,10 @@ class QuestionApe extends Ape {
ApeConsts
.
QUESTION_SESSION_NAME
,
ApeConsts
.
QUESTION_SESSION_TAG
);
this
.
questionList
=
{};
//MCU同步的题目数据
this
.
questionDataList
=
{};
//Sass保存的题目内容数据
this
.
questionTimer
=
new
TimerCounter
();
//答题卡计时器
this
.
questionTimer
.
addTimerCallBack
(
this
.
questionTimerCounterUptate
.
bind
(
this
),
1
);
//计时器监听
//监听Sass事件
this
.
_sass
=
Sass
;
...
...
@@ -47,6 +49,34 @@ class QuestionApe extends Ape {
this
.
registerObj
(
pdu
.
RCPDU_REG_REGISTER_TABLE
,
ApeConsts
.
CONFERENCE_OBJ_QUESTION_ID
,
ApeConsts
.
CONFERENCE_OBJ_QUESTION_NAME
,
ApeConsts
.
CONFERENCE_OBJ_QUESTION_TAG
,
0
,
new
ArrayBuffer
);
}
//答题卡计时器
questionTimerCounterUptate
()
{
if
(
!
this
.
mcu
.
connected
)
{
loger
.
warn
(
'MCU 连接已经断开'
);
if
(
this
.
questionTimer
){
this
.
questionTimer
.
stopTimer
();
}
}
//console.log("时间差:"+GlobalConfig.serverAndLoacTimeDistanc+' questionTimerCounterUptate',this.questionList);
for
(
let
key
in
this
.
questionList
){
let
question
=
this
.
questionList
[
key
];
if
(
question
){
let
currentTime
=
EngineUtils
.
creatTimestamp
()
-
GlobalConfig
.
serverAndLoacTimeDistanc
;
//将当的时间减去服务器时间差
let
timestamp
=
parseInt
(
question
.
timeLimit
-
(
currentTime
-
question
.
timestamp
));
if
(
timestamp
>=
0
){
loger
.
log
(
"question->type:"
+
question
.
type
,
"倒计时:"
+
timestamp
);
this
.
_emit
(
MessageTypes
.
UPDATE_QUESTION_TIME
,{
type
:
question
.
type
,
itemIdx
:
question
.
itemIdx
,
timestamp
:
timestamp
});
}
else
{
this
.
stopQuestion
({
itemIdx
:
question
.
itemIdx
});
}
}
}
if
(
this
.
questionTimer
&&
Object
.
keys
(
this
.
questionList
).
length
<
1
){
this
.
questionTimer
.
stopTimer
();
}
}
//更新信息
sendUpdaterTable
(
_param
)
{
...
...
@@ -140,34 +170,33 @@ class QuestionApe extends Ape {
//停止答题
loger
.
log
(
"更新答题数据"
);
if
(
GlobalConfig
.
isHost
){
//老师,只统计数据,不答题
//先判断时间是否超时
let
timeDistance
=
EngineUtils
.
creatTimestamp
()
-
model
.
timestamp
;
loger
.
log
(
"答题卡显示倒计时->timeDistance:"
+
timeDistance
);
timeDistance
=
model
.
timeLimit
-
timeDistance
;
if
(
timeDistance
<=
0
){
//答题卡时间到,需要停止
loger
.
log
(
"答题卡时间到->需要停止"
);
this
.
stopQuestion
(
model
);
}
else
{
////老师,只统计数据,不答题
////先判断时间是否超时
//let timeDistance=EngineUtils.creatTimestamp()-model.timestamp;
//loger.log("答题卡显示倒计时->timeDistance:"+timeDistance);
//timeDistance=model.timeLimit-timeDistance;
//if(timeDistance<=0){
// //答题卡时间到,需要停止
// loger.log("答题卡时间到->需要停止");
// this.stopQuestion(model);
//}else {
// this.getQuestionResult(model);
//}
this
.
getQuestionResult
(
model
);
}
}
else
if
(
GlobalConfig
.
isNormal
)
{
//学生->如果自己已经提交过答案就不需要再显示
if
(
model
.
totalUserList
.
indexOf
(
GlobalConfig
.
userId
)
>=
0
){
loger
.
log
(
"已经提交过答案-不需要显示答题卡->userId:"
+
GlobalConfig
.
userId
);
//delete this.questionList[itemIdx];
}
else
{
//显示答题卡数据
this
.
_emit
(
MessageTypes
.
START_ANSWER_QUESTION
,
model
);
}
}
if
(
this
.
questionTimer
){
this
.
questionTimer
.
startTimer
();
}
break
;
//case 4:
// //停止点名
// loger.log("更新点名数据");
// this._emit(MessageTypes.UPDATE_CALL_THE_ROLL,model);
// break;
default
:
break
;
}
...
...
@@ -191,15 +220,17 @@ class QuestionApe extends Ape {
case
1
:
case
2
:
case
3
:
case
4
:
case
100
:
//停止答题
loger
.
log
(
"停止答题->"
,
itemDataInfo
);
this
.
_emit
(
MessageTypes
.
STOP_ANSWER_QUESTION
,
itemDataInfo
);
break
;
case
4
:
//停止点名
loger
.
log
(
"停止点名"
);
this
.
_emit
(
MessageTypes
.
STOP_CALL_THE_ROLL
,
itemDataInfo
);
break
;
//case 100:
// //停止点名
// loger.log("停止点名");
// this._emit(MessageTypes.STOP_CALL_THE_ROLL,itemDataInfo);
// break;
default
:
break
;
}
...
...
@@ -234,7 +265,7 @@ class QuestionApe extends Ape {
modelPdu
.
type
=
parseInt
(
_param
.
type
)
||
0
;
modelPdu
.
questionId
=
parseInt
(
_param
.
questionId
)
||
0
;
modelPdu
.
timeLimit
=
parseInt
(
_param
.
timeLimit
)
||
1
;
//有效时间
modelPdu
.
timestamp
=
parseInt
(
_param
.
timestamp
)
||
EngineUtils
.
creatTimestamp
();
//创建的时间
modelPdu
.
timestamp
=
parseInt
(
_param
.
timestamp
)
||
parseInt
(
EngineUtils
.
creatTimestamp
()
-
GlobalConfig
.
serverAndLoacTimeDistanc
);;
//创建的时间(秒)
modelPdu
.
content
=
_param
.
content
||
[];
//题干
modelPdu
.
options
=
_param
.
options
||
[];
//选项列表
modelPdu
.
answer
=
_param
.
answer
||
[];
//用户选择的选项索引
...
...
@@ -352,16 +383,11 @@ class QuestionApe extends Ape {
_sassCreatQuestionSuccessHandler
(
_data
){
//loger.log("创建答题卡成功",_data);
if
(
_data
){
//this.questionDataList[_data.questionId]=_data;//保存题目数据
//获取当前对方系统时间,再减去服务器时间差
let
timestamp
=
parseInt
(
EngineUtils
.
creatTimestamp
()
-
GlobalConfig
.
serverAndLoacTimeDistanc
);
//创建答题卡的时间(秒)
let
questionItem
=
_data
;
/* //判断是答题还是点名,type=100的时候是点名
if(questionItem.type==100){
questionItem.itemIdx=ApeConsts.CONFERENCE_OBJ_QUESTION_ID+1;
}else {
questionItem.itemIdx=ApeConsts.CONFERENCE_OBJ_QUESTION_ID;
}*/
questionItem
.
itemIdx
=
EngineUtils
.
creatTimestamp
();
questionItem
.
itemIdx
=
timestamp
;
questionItem
.
timestamp
=
timestamp
;
this
.
sendUpdaterTable
(
questionItem
);
}
...
...
请
注册
或
登录
后发表评论