Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
孙克
/
RC1250-AssemblyLine
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 58d1a0b3
由
LN
编写于
2022-11-11 10:34:13 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
托盘号处理。
1 个父辈
1287733b
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
286 行增加
和
164 行删除
source/DeviceLibrary/assemblyLine/EquipBase.cs
source/DeviceLibrary/assemblyLine/MoveEquip.cs
source/DeviceLibrary/assemblyLine/MoveEquip_Partial.cs
source/DeviceLibrary/assemblymanager/RFIDManagercs.cs
source/DeviceLibrary/assemblyLine/EquipBase.cs
查看文件 @
58d1a0b
...
...
@@ -226,8 +226,8 @@ namespace OnlineStore.DeviceLibrary
isNoAirCheck
=
false
;
preTrayNum
=
0
;
currTrayNum
=
0
;
StopReadRfid
();
ClearAllBuff
();
//
StopReadRfid();
//
ClearAllBuff();
}
public
void
ChangeDebug
(
bool
isDebug
)
{
...
...
@@ -342,147 +342,147 @@ namespace OnlineStore.DeviceLibrary
}
}
#
region
获取
rfid
缓存功能
internal
ConcurrentQueue
<
RFIDBuff
>
RfidBuff
=
new
ConcurrentQueue
<
RFIDBuff
>();
internal
bool
pauseReadRfid
=
true
;
//internal Thread readBuffRfidThread;
internal
System
.
Timers
.
Timer
readBuffRfidTimer
;
internal
void
StartReadRfid
()
{
pauseReadRfid
=
false
;
}
internal
void
StopReadRfid
()
{
pauseReadRfid
=
true
;
}
internal
bool
UpdateTrayNumFromBuff
()
{
trayCount
++;
//此处先对托盘号进行验证
preTrayNum
=
currTrayNum
;
if
(!
TrayManager
.
HasCheck1
(
DeviceID
))
{
currTrayNum
=
TrayManager
.
Move5TrayNum
;
LogUtil
.
LOGGER
.
Info
(
Name
+
" ["
+
trayCount
+
"] IP ["
+
RFIDManager
.
GetRFIP
(
DeviceID
)
+
"] ["
+
preTrayNum
+
"] 当前托盘 ["
+
currTrayNum
+
"] 使用横移分流2缓存托盘号 Move5TrayNum "
);
}
else
{
currTrayNum
=
GetTrayBuffNum
(
DeviceID
);
LogUtil
.
LOGGER
.
Info
(
Name
+
" ["
+
trayCount
+
"] IP ["
+
RFIDManager
.
GetRFIP
(
DeviceID
)
+
"] ["
+
preTrayNum
+
"] 当前托盘 ["
+
currTrayNum
+
"]"
);
if
(
preTrayNum
.
Equals
(
currTrayNum
)
&&
currTrayNum
>
0
)
{
TrayManager
.
TrayErrorMsg
=
DateTime
.
Now
.
ToLongTimeString
()
+
" "
+
Name
+
"托盘号出现错乱:上一个托盘["
+
preTrayNum
+
"] 当前托盘 ["
+
currTrayNum
+
"],连续两个托盘号一样"
;
LogUtil
.
error
(
Name
+
"托盘号错乱:上一个托盘["
+
preTrayNum
+
"] 当前托盘 ["
+
currTrayNum
+
"],连续两个托盘号一样"
);
}
else
if
(!
TrayManager
.
CheckIsRightNum
(
currTrayNum
,
preTrayNum
))
{
TrayManager
.
TrayErrorMsg
=
DateTime
.
Now
.
ToLongTimeString
()
+
" "
+
Name
+
"托盘号出现错乱:上一个托盘["
+
preTrayNum
+
"] 当前托盘 ["
+
currTrayNum
+
"],托盘号不连续"
;
LogUtil
.
error
(
Name
+
"托盘号错乱:上一个托盘["
+
preTrayNum
+
"] 当前托盘 ["
+
currTrayNum
+
"],托盘号不连续"
);
}
}
return
true
;
}
object
locReadRfid
=
new
object
();
internal
void
ReadRfidBuff
(
object
sender
,
System
.
Timers
.
ElapsedEventArgs
e
)
{
if
(
Monitor
.
TryEnter
(
locReadRfid
))
{
string
ip
=
RFIDManager
.
GetRFIP
(
DeviceID
);
try
{
//while (true)
{
if
(
pauseReadRfid
)
{
return
;
}
if
(
RfidBuff
.
Count
>
2
)
{
LogUtil
.
debug
(
$
"[{Name}][{ip}]RFID缓存数量大于2个,强制清除队列缓存:{JsonHelper.SerializeObject(RfidBuff)}"
);
ClearAllBuff
();
}
//获取盘号
RFIDData
data
=
RFIDManager
.
ReadRFID
(
ip
,
true
);
if
(
data
.
Num
==
0
)
return
;
RFIDBuff
rFIDBuff
=
new
RFIDBuff
()
{
FIDData
=
data
};
int
idx
=
RfidBuff
.
ToList
().
FindIndex
(
s
=>
s
.
TrayNum
.
Equals
(
rFIDBuff
.
TrayNum
));
if
(
idx
==
-
1
)
{
RfidBuff
.
Enqueue
(
rFIDBuff
);
LogUtil
.
debug
(
$
"[{Name}][{ip}]RFID加入缓存:{JsonHelper.SerializeObject(rFIDBuff)}"
);
}
Thread
.
Sleep
(
50
);
}
}
catch
(
Exception
ex
)
{
LogUtil
.
error
(
$
"【{Name}】【{ip}】ReadRfidBuff 出错"
,
ex
);
}
finally
{
Monitor
.
Exit
(
locReadRfid
);
}
}
}
RFIDData
getFirstTrayNum
(
string
ip
)
{
if
(
RfidBuff
!=
null
&&
RfidBuff
.
TryDequeue
(
out
RFIDBuff
rFID
))
{
LogUtil
.
debug
(
$
"[{Name}][{ip}]取第一个RFID:{JsonHelper.SerializeObject(rFID)}"
);
return
rFID
.
FIDData
;
}
else
return
new
RFIDData
();
}
internal
void
ClearAllBuff
()
{
if
(
RfidBuff
.
Count
>
0
)
{
RfidBuff
=
new
ConcurrentQueue
<
RFIDBuff
>();
LogUtil
.
debug
(
$
"[{Name}]清除所有RFID缓存"
);
}
}
int
DefaultTrayNum
=
RFIDManager
.
DefaultTrayNum
;
private
int
GetTrayBuffNum
(
int
subType
)
{
if
(
DefaultTrayNum
>
0
)
{
return
DefaultTrayNum
;
}
if
(
subType
.
Equals
(
104
))
{
return
LineManager
.
Line
.
Sw23TrayNum
;
}
else
if
(
subType
.
Equals
(
101
))
{
return
LineManager
.
Line
.
Sw41TrayNum
;
}
string
ip
=
RFIDManager
.
GetRFIP
(
subType
);
RFIDData
data
;
data
=
getFirstTrayNum
(
ip
);
if
(
data
!=
null
)
{
if
(
data
.
RFType
.
Equals
(
'E'
))
{
return
data
.
Num
;
}
else
if
(
data
.
RFType
>
0
)
{
LogUtil
.
error
(
"RFID [ "
+
ip
+
" ] 读到数据 "
+
data
.
NumStr
()
+
" 返回盘号 0"
);
}
else
{
LogUtil
.
debug
(
"RFID [ "
+
ip
+
" ] 读到数据 "
+
data
.
NumStr
()
+
" 返回盘号 0"
);
}
return
0
;
}
return
0
;
}
//
internal ConcurrentQueue<RFIDBuff> RfidBuff = new ConcurrentQueue<RFIDBuff>();
//
internal bool pauseReadRfid = true;
//
//
internal Thread readBuffRfidThread;
//
internal System.Timers.Timer readBuffRfidTimer;
//
internal void StartReadRfid()
//
{
//
pauseReadRfid = false;
//
}
//
internal void StopReadRfid()
//
{
//
pauseReadRfid = true;
//
}
//
internal bool UpdateTrayNumFromBuff()
//
{
//
trayCount++;
//
//此处先对托盘号进行验证
//
preTrayNum = currTrayNum;
//
if (!TrayManager.HasCheck1(DeviceID))
//
{
//
currTrayNum = TrayManager.Move5TrayNum;
//
LogUtil.LOGGER.Info(Name + " [" + trayCount + "] IP [" + RFIDManager.GetRFIP(DeviceID) + "] [" + preTrayNum + "] 当前托盘 [" + currTrayNum + "] 使用横移分流2缓存托盘号 Move5TrayNum ");
//
}
//
else
//
{
//
currTrayNum = GetTrayBuffNum(DeviceID);
//
LogUtil.LOGGER.Info(Name + " [" + trayCount + "] IP [" + RFIDManager.GetRFIP(DeviceID) + "] [" + preTrayNum + "] 当前托盘 [" + currTrayNum + "]");
//
if (preTrayNum.Equals(currTrayNum) && currTrayNum > 0)
//
{
//
TrayManager.TrayErrorMsg = DateTime.Now.ToLongTimeString() + " " + Name + "托盘号出现错乱:上一个托盘[" + preTrayNum + "] 当前托盘 [" + currTrayNum + "],连续两个托盘号一样";
//
LogUtil.error(Name + "托盘号错乱:上一个托盘[" + preTrayNum + "] 当前托盘 [" + currTrayNum + "],连续两个托盘号一样");
//
}
//
else if (!TrayManager.CheckIsRightNum(currTrayNum, preTrayNum))
//
{
//
TrayManager.TrayErrorMsg = DateTime.Now.ToLongTimeString() + " " + Name + "托盘号出现错乱:上一个托盘[" + preTrayNum + "] 当前托盘 [" + currTrayNum + "],托盘号不连续";
//
LogUtil.error(Name + "托盘号错乱:上一个托盘[" + preTrayNum + "] 当前托盘 [" + currTrayNum + "],托盘号不连续");
//
}
//
}
//
return true;
//
}
//
object locReadRfid = new object();
//
internal void ReadRfidBuff(object sender, System.Timers.ElapsedEventArgs e)
//
{
//
if(Monitor.TryEnter(locReadRfid))
//
{
//
string ip = RFIDManager.GetRFIP(DeviceID);
//
try
//
{
//
//while (true)
//
{
//
if (pauseReadRfid)
//
{
//
return;
//
}
//
if (RfidBuff.Count > 2)
//
{
//
LogUtil.debug($"[{Name}][{ip}]RFID缓存数量大于2个,强制清除队列缓存:{JsonHelper.SerializeObject(RfidBuff)}");
//
ClearAllBuff();
//
}
//
//获取盘号
//
RFIDData data = RFIDManager.ReadRFID(ip, true);
//
if (data.Num == 0)
//
return;
//
RFIDBuff rFIDBuff = new RFIDBuff() { FIDData = data };
//
int idx = RfidBuff.ToList().FindIndex(s => s.TrayNum.Equals(rFIDBuff.TrayNum));
//
if (idx == -1)
//
{
//
RfidBuff.Enqueue(rFIDBuff);
//
LogUtil.debug($"[{Name}][{ip}]RFID加入缓存:{JsonHelper.SerializeObject(rFIDBuff)}");
//
}
//
Thread.Sleep(50);
//
}
//
}
//
catch (Exception ex)
//
{
//
LogUtil.error($"【{Name}】【{ip}】ReadRfidBuff 出错", ex);
//
}
//
finally
//
{
//
Monitor.Exit(locReadRfid);
//
}
//
}
//
}
//
RFIDData getFirstTrayNum(string ip)
//
{
//
if (RfidBuff != null && RfidBuff.TryDequeue(out RFIDBuff rFID))
//
{
//
LogUtil.debug($"[{Name}][{ip}]取第一个RFID:{JsonHelper.SerializeObject(rFID)}");
//
return rFID.FIDData;
//
}
//
else
//
return new RFIDData();
//
}
//
internal void ClearAllBuff()
//
{
//
if (RfidBuff.Count > 0)
//
{
//
RfidBuff = new ConcurrentQueue<RFIDBuff>();
//
LogUtil.debug($"[{Name}]清除所有RFID缓存");
//
}
//
}
//
int DefaultTrayNum = RFIDManager.DefaultTrayNum;
//
private int GetTrayBuffNum(int subType)
//
{
//
if (DefaultTrayNum > 0)
//
{
//
return DefaultTrayNum;
//
}
//
if (subType.Equals(104))
//
{
//
return LineManager.Line.Sw23TrayNum;
//
}
//
else if (subType.Equals(101))
//
{
//
return LineManager.Line.Sw41TrayNum;
//
}
//
string ip = RFIDManager.GetRFIP(subType);
//
RFIDData data;
//
data = getFirstTrayNum(ip);
//
if (data != null)
//
{
//
if (data.RFType.Equals('E'))
//
{
//
return data.Num;
//
}
//
else if (data.RFType > 0)
//
{
//
LogUtil.error("RFID [ " + ip + " ] 读到数据 " + data.NumStr() + " 返回盘号 0");
//
}
//
else
//
{
//
LogUtil.debug("RFID [ " + ip + " ] 读到数据 " + data.NumStr() + " 返回盘号 0");
//
}
//
return 0;
//
}
//
return 0;
//
}
#
endregion
internal
bool
UpdateTrayNum
()
{
...
...
source/DeviceLibrary/assemblyLine/MoveEquip.cs
查看文件 @
58d1a0b
...
...
@@ -61,11 +61,11 @@ namespace OnlineStore.DeviceLibrary
ClampNeedCheck
=
config
.
DIList
.
ContainsKey
(
IO_Type
.
ClampCylinder_Check
);
UpdownAxis
=
new
AxisBean
(
config
.
UpDown_Axis
,
Name
);
readBuffRfidTimer
=
new
System
.
Timers
.
Timer
();
readBuffRfidTimer
.
Enabled
=
false
;
readBuffRfidTimer
.
Interval
=
300
;
readBuffRfidTimer
.
Elapsed
+=
ReadRfidBuff
;
readBuffRfidTimer
.
AutoReset
=
true
;
//
readBuffRfidTimer = new System.Timers.Timer();
//
readBuffRfidTimer.Enabled = false;
//
readBuffRfidTimer.Interval = 300;
//
readBuffRfidTimer.Elapsed += ReadRfidBuff;
//
readBuffRfidTimer.AutoReset = true;
}
public
override
bool
StartRun
(
bool
isDebug
=
false
)
...
...
@@ -186,7 +186,7 @@ namespace OnlineStore.DeviceLibrary
//readBuffRfidThread = new Thread(ReadRfidBuff);
//readBuffRfidThread.IsBackground = true;
//readBuffRfidThread.Start();
readBuffRfidTimer
.
Enabled
=
true
;
//
readBuffRfidTimer.Enabled = true;
LogInfo
(
MoveInfo
.
MoveType
+
" 完成!"
);
runStatus
=
LineRunStatus
.
Runing
;
MoveInfo
.
EndMove
();
...
...
@@ -242,7 +242,7 @@ namespace OnlineStore.DeviceLibrary
CheckAndMove
(
IO_Type
.
ClampCylinder_Slack
,
IO_VALUE
.
LOW
);
CheckAndMove
(
IO_Type
.
ClampCylinder_Tighten
,
IO_VALUE
.
LOW
);
runStatus
=
LineRunStatus
.
Wait
;
readBuffRfidTimer
.
Enabled
=
false
;
//
readBuffRfidTimer.Enabled = false;
}
...
...
source/DeviceLibrary/assemblyLine/MoveEquip_Partial.cs
查看文件 @
58d1a0b
...
...
@@ -857,8 +857,8 @@ namespace OnlineStore.DeviceLibrary
SecondMoveInfo
.
NewMove
(
LineMoveType
.
CheckFixture
);
SecondMoveInfo
.
NextMoveStep
(
LineMoveStep
.
MIO_00_Stop1Down
);
ClearTrayRFID
();
ClearAllBuff
();
StartReadRfid
();
//
ClearAllBuff();
//
StartReadRfid();
CheckLog
(
" 托盘检测:料盘检测StopCylinder_Check1 "
+
SecondMoveInfo
.
SLog
+
"阻挡气缸1-1下降 , 等待 StopCylinder_Check1=0,清理托盘RFID,开始记录rfid缓存"
);
IOMove
(
IO_Type
.
StopCylinder_Down1
,
IO_VALUE
.
HIGH
);
//TrayManager.StopDTime
SecondMoveInfo
.
OneWaitCanEndStep
=
true
;
...
...
@@ -955,18 +955,19 @@ namespace OnlineStore.DeviceLibrary
{
try
{
try
{
StopReadRfid
();
LogUtil
.
debug
(
$
"【{Name}】停止记录rfid缓存"
);
}
catch
(
Exception
ex1
)
{
LogUtil
.
error
(
$
"【{Name}】停止记录rfid缓存:"
,
ex1
);
}
//
try
//
{
// //
StopReadRfid();
//
LogUtil.debug($"【{Name}】停止记录rfid缓存");
//
}
//
catch (Exception ex1)
//
{
//
LogUtil.error($"【{Name}】停止记录rfid缓存:", ex1);
//
}
//判断是否需要顶升
bool
isNeed
=
false
;
UpdateTrayNumFromBuff
();
//UpdateTrayNumFromBuff();
UpdateTrayNum
();
bool
isFull
=
TrayManager
.
TrayIsFull
(
currTrayNum
);
if
(
TrayManager
.
RightTrayCode
(
currTrayNum
,
preTrayNum
,
false
))
{
...
...
source/DeviceLibrary/assemblymanager/RFIDManagercs.cs
查看文件 @
58d1a0b
...
...
@@ -18,7 +18,7 @@ namespace OnlineStore.DeviceLibrary
public
static
int
DefaultTrayNum
=
ConfigAppSettings
.
GetIntValue
(
Setting_Init
.
DefaultTrayNum
);
private
static
ReadAll
readAll
=
new
ReadAll
(
"TheRFID"
);
private
static
bool
IsOpen
=
false
;
private
static
ConcurrentDictionary
<
string
,
string
>
LastRfidMap
=
new
ConcurrentDictionary
<
string
,
string
>();
private
static
ConcurrentDictionary
<
string
,
List
<
RfidCacheInfo
>>
LastRfidMap
=
new
ConcurrentDictionary
<
string
,
List
<
RfidCacheInfo
>>();
public
static
void
Open
()
{
if
(
IsOpen
)
...
...
@@ -33,6 +33,7 @@ namespace OnlineStore.DeviceLibrary
port
=
13000
;
}
LogUtil
.
info
(
"RFID Server Open,port="
+
port
);
readAll
.
Received
+=
ReadAll_Received
;
readAll
.
Start
();
IsOpen
=
true
;
}
...
...
@@ -41,6 +42,99 @@ namespace OnlineStore.DeviceLibrary
LogUtil
.
error
(
"Open 出错:"
+
ex
.
ToString
());
}
}
private
static
void
ReadAll_Received
(
string
ip
,
string
id
)
{
List
<
RfidCacheInfo
>
list
=
LastRfidMap
.
GetOrAdd
(
ip
,
new
List
<
RfidCacheInfo
>());
int
count
=
list
.
Count
;
if
(
count
>
0
)
{
RfidCacheInfo
last
=
list
[
count
-
1
];
if
(!
last
.
Data
.
StrData
.
Equals
(
id
))
{
RFIDData
data
=
new
RFIDData
(
id
);
list
.
Add
(
new
RfidCacheInfo
(
data
));
if
(
list
.
Count
>
3
)
{
list
.
RemoveAt
(
0
);
}
LogUtil
.
debug
(
"ReadAll_Received["
+
ip
+
"]["
+
id
+
"]加入缓存"
);
LastRfidMap
.
AddOrUpdate
(
ip
,
list
,(
key
,
value
)=>
value
);
}
}
}
private
static
bool
CheckTrayNum
(
string
ip
,
int
num
)
{
RFIDData
data
=
new
RFIDData
(
ip
);
List
<
RfidCacheInfo
>
list
=
LastRfidMap
.
GetOrAdd
(
ip
,
new
List
<
RfidCacheInfo
>());
if
(
list
.
Count
>
0
)
{
int
readNumIndex
=
-
1
;
string
listStr
=
""
;
for
(
int
i
=
0
;
i
<
list
.
Count
;
i
++)
{
RfidCacheInfo
cacheInfo
=
list
[
i
];
if
(
cacheInfo
.
Data
.
Num
.
Equals
(
num
))
{
listStr
+=
"【"
+
cacheInfo
.
Data
.
Num
+
","
+
cacheInfo
.
Used
+
","
+
cacheInfo
.
UpdateTime
.
ToLongTimeString
()
+
"】"
;
readNumIndex
=
i
;
}
}
if
(
readNumIndex
==
-
1
)
{
list
.
Add
(
new
RfidCacheInfo
(
data
,
true
));
if
(
list
.
Count
>
3
)
{
list
.
RemoveAt
(
0
);
}
LastRfidMap
.
AddOrUpdate
(
ip
,
list
,
(
key
,
value
)
=>
value
);
LogUtil
.
error
(
"CheckTrayNum托盘号验证: ["
+
ip
+
"]["
+
num
+
"],未找到此托盘缓存,增加次托盘到缓存。缓存数据:"
+
listStr
);
return
true
;
}
else
if
(
readNumIndex
==
(
list
.
Count
-
1
))
{
//是最后一个
if
(
list
[
readNumIndex
].
Used
)
{
LogUtil
.
error
(
"CheckTrayNum托盘号验证失败: ["
+
ip
+
"]["
+
num
+
"],缓存记录当前托盘已使用。缓存数据:"
+
listStr
);
return
false
;
}
else
{
//更改状态
list
[
readNumIndex
].
Used
=
true
;
LastRfidMap
.
AddOrUpdate
(
ip
,
list
,
(
key
,
value
)
=>
value
);
//上一个已使用
if
(
list
.
Count
>
readNumIndex
-
1
)
{
if
(!
list
[
readNumIndex
-
1
].
Used
)
{
LogUtil
.
error
(
"CheckTrayNum托盘号验证失败: ["
+
ip
+
"]["
+
num
+
"],缓存记录上一个托盘未使用,更新当前托盘为已用。缓存数据:"
+
listStr
);
return
false
;
}
}
}
}
//不是最后一个
else
{
//更改状态
list
[
readNumIndex
].
Used
=
true
;
LastRfidMap
.
AddOrUpdate
(
ip
,
list
,
(
key
,
value
)
=>
value
);
LogUtil
.
error
(
"CheckTrayNum托盘号验证失败: ["
+
ip
+
"]["
+
num
+
"],当前托盘索引="
+
readNumIndex
+
",总缓存托盘数="
+
list
.
Count
+
",不是最后一个缓存托盘号,更新当前托盘为已用。缓存数据:"
+
listStr
);
return
false
;
}
}
return
true
;
}
public
static
int
GetTrayNum
(
int
subType
,
bool
isClear
=
false
)
{
if
(
DefaultTrayNum
>
0
)
...
...
@@ -63,7 +157,17 @@ namespace OnlineStore.DeviceLibrary
{
if
(
data
.
RFType
.
Equals
(
'E'
))
{
return
data
.
Num
;
bool
result
=
CheckTrayNum
(
ip
,
data
.
Num
);
if
(!
result
)
{
LogUtil
.
error
(
"RFID [ "
+
ip
+
" ] 读到数据 "
+
data
.
NumStr
()
+
" 缓存验证失败,返回盘号 0"
);
return
0
;
}
else
{
return
data
.
Num
;
}
}
else
if
(
data
.
RFType
>
0
)
{
...
...
@@ -76,6 +180,7 @@ namespace OnlineStore.DeviceLibrary
return
0
;
}
return
0
;
}
public
static
void
ClearTrayNum
(
int
subType
)
...
...
@@ -235,4 +340,20 @@ namespace OnlineStore.DeviceLibrary
return
false
;
}
}
public
class
RfidCacheInfo
{
public
RfidCacheInfo
(
RFIDData
data
,
bool
userd
=
false
)
{
this
.
Data
=
data
;
this
.
Used
=
false
;
this
.
UpdateTime
=
DateTime
.
Now
;
}
public
RFIDData
Data
{
get
;
set
;
}
public
bool
Used
=
false
;
public
DateTime
UpdateTime
=
DateTime
.
Now
;
}
}
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论