Commit 00fa23ee LN

hotayi修改:1.接口增加MachineID验证。2.使用接口验证用户登陆后,自动创建用户。3.Bug修改:QueueCount数量错误

1 个父辈 a8bce055
...@@ -253,7 +253,7 @@ public class SpBoxController { ...@@ -253,7 +253,7 @@ public class SpBoxController {
Criteria c = Criteria.where("storageId").is(storageId) Criteria c = Criteria.where("storageId").is(storageId)
.and("enabled").is(true) .and("enabled").is(true)
.and("used").is(true) .and("used").is(true)
.and("barcode.solderStatus").nin(SOLDER_STATUS.NONE.name(), SOLDER_STATUS.UNDER_REFRIGERATION.name(), SOLDER_STATUS.RETREAT_STORAGE.name()); .and("barcode.solderStatus").nin(null,"",SOLDER_STATUS.NONE.name(), SOLDER_STATUS.UNDER_REFRIGERATION.name(), SOLDER_STATUS.RETREAT_STORAGE.name());
List<StoragePos> taskPosList = storagePosManager.findByQuery(new Query(c)); List<StoragePos> taskPosList = storagePosManager.findByQuery(new Query(c));
List<SpTaskDto> spTaskDtos = new ArrayList<>(); List<SpTaskDto> spTaskDtos = new ArrayList<>();
......
...@@ -5,6 +5,7 @@ import com.neotel.smfcore.common.exception.ValidateException; ...@@ -5,6 +5,7 @@ import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.DateUtil; import com.neotel.smfcore.common.utils.DateUtil;
import com.neotel.smfcore.common.utils.HttpHelper; import com.neotel.smfcore.common.utils.HttpHelper;
import com.neotel.smfcore.common.utils.JsonUtil; import com.neotel.smfcore.common.utils.JsonUtil;
import com.neotel.smfcore.common.utils.RsaUtils;
import com.neotel.smfcore.core.api.bean.ApiResult; import com.neotel.smfcore.core.api.bean.ApiResult;
import com.neotel.smfcore.core.api.bean.CodeValidateParam; import com.neotel.smfcore.core.api.bean.CodeValidateParam;
import com.neotel.smfcore.core.api.listener.BaseSmfApiListener; import com.neotel.smfcore.core.api.listener.BaseSmfApiListener;
...@@ -18,10 +19,16 @@ import com.neotel.smfcore.core.order.service.po.LiteOrder; ...@@ -18,10 +19,16 @@ import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem; import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import com.neotel.smfcore.core.system.service.po.DataLog; import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.custom.hotayi20057.bean.HotayiBean; import com.neotel.smfcore.custom.hotayi20057.bean.HotayiBean;
import com.neotel.smfcore.security.bean.RsaProperties;
import com.neotel.smfcore.security.service.manager.IRoleManager;
import com.neotel.smfcore.security.service.manager.IUserManager;
import com.neotel.smfcore.security.service.po.Role;
import com.neotel.smfcore.security.service.po.User;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings; import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Date; import java.util.Date;
...@@ -54,6 +61,16 @@ public class HotayiApi extends BaseSmfApiListener { ...@@ -54,6 +61,16 @@ public class HotayiApi extends BaseSmfApiListener {
@Autowired @Autowired
private IComponentManager componentManager; private IComponentManager componentManager;
@Autowired
private IUserManager userManager;
@Autowired
private IRoleManager roleManager;
@Autowired
private PasswordEncoder passwordEncoder;
@Override @Override
public boolean isForThisApi(String apiName) { public boolean isForThisApi(String apiName) {
return apiName != null && apiName.equalsIgnoreCase("20057"); return apiName != null && apiName.equalsIgnoreCase("20057");
...@@ -187,7 +204,7 @@ public class HotayiApi extends BaseSmfApiListener { ...@@ -187,7 +204,7 @@ public class HotayiApi extends BaseSmfApiListener {
HotayiBean m10Bean=getM10Bean(task.getBarcode(),1,2); HotayiBean m10Bean=getM10Bean(task.getBarcode(),1,2);
Map<String, Object> paramMap = new HashMap<>(); Map<String, Object> paramMap = new HashMap<>();
paramMap.put("Info", m10Bean.getInfo()); paramMap.put("Info", m10Bean.getInfo());
paramMap.put("Date", m10Bean.getData()); paramMap.put("Data", m10Bean.getData());
try { try {
requestParams = JsonUtil.toJsonStr(paramMap); requestParams = JsonUtil.toJsonStr(paramMap);
...@@ -214,7 +231,7 @@ public class HotayiApi extends BaseSmfApiListener { ...@@ -214,7 +231,7 @@ public class HotayiApi extends BaseSmfApiListener {
HotayiBean m10Bean = getM10Bean(task.getBarcode(), 5, type); HotayiBean m10Bean = getM10Bean(task.getBarcode(), 5, type);
Map<String, Object> paramMap = new HashMap<>(); Map<String, Object> paramMap = new HashMap<>();
paramMap.put("Info", m10Bean.getInfo()); paramMap.put("Info", m10Bean.getInfo());
paramMap.put("Date", m10Bean.getData()); paramMap.put("Data", m10Bean.getData());
try { try {
requestParams = JsonUtil.toJsonStr(paramMap); requestParams = JsonUtil.toJsonStr(paramMap);
...@@ -308,6 +325,10 @@ public class HotayiApi extends BaseSmfApiListener { ...@@ -308,6 +325,10 @@ public class HotayiApi extends BaseSmfApiListener {
String UserLevel = hotayiBean.getInfoItem("UserLevel"); String UserLevel = hotayiBean.getInfoItem("UserLevel");
if (ObjectUtil.isNotEmpty(UserLevel)) { if (ObjectUtil.isNotEmpty(UserLevel)) {
log.info(userName + "登陆验证M22 返回 UserLevel=" + UserLevel); log.info(userName + "登陆验证M22 返回 UserLevel=" + UserLevel);
autoCreateUser(userName,pwd,UserLevel);
return true; return true;
} else { } else {
log.info(userName + "登陆验证M22 返回 UserLevel=" + UserLevel); log.info(userName + "登陆验证M22 返回 UserLevel=" + UserLevel);
...@@ -321,4 +342,55 @@ public class HotayiApi extends BaseSmfApiListener { ...@@ -321,4 +342,55 @@ public class HotayiApi extends BaseSmfApiListener {
throw new ValidateException("smfcore.mesApi.loginCheck.error", "MES Login Error:" + e.getMessage()); throw new ValidateException("smfcore.mesApi.loginCheck.error", "MES Login Error:" + e.getMessage());
} }
} }
private void autoCreateUser(String userName,String pwd,String userLevel) {
try {
// 10 = Administrator
// 20 = Engineer
// 30 = Operator
//查询用户是否存在,不存在自动创建。
User user = userManager.findByUserName(userName);
if (user == null) {
log.info("autoCreateUser 未找到用户,自动创建用户[" + userName + "] ");
String roleName = "operater";
if (userLevel.equals("10")) {
roleName = "admin";
} else if (userLevel.equals("20")) {
roleName = "engineer";
}
Role role = roleManager.getByName(roleName);
if (role != null) {
role = new Role();
role.setName(roleName);
role.setDescription("System automatically created");
role = roleManager.saveRole(role);
log.info("autoCreateUser 自动创建用户[" + userName + "]时未找到role,自动创建role[" + roleName + "]");
}
//自动创建用户
user = new User();
user.setPassword(passwordEncoder.encode(pwd));
user.setUsername(userName);
user.setEmail(userName + "@qq.com");
user.setLanguage("en_US");
user.setRoleId(role.getId());
log.info("autoCreateUser 未找到用户,自动创建用户[" + userName + "]完成 ");
} else {
String dbPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, user.getPassword());
if (!passwordEncoder.matches(dbPass, pwd)) {
log.info("autoCreateUser [" + userName + "]返回 UserLevel=" + userLevel + ",自动重置密码");
//密码不一致时修改密码
userManager.updatePass(user.getUsername(), passwordEncoder.encode(pwd));
}
}
} catch (Exception ex) {
log.error("autoCreateUser error:" + ex.getMessage());
}
}
} }
...@@ -20,6 +20,7 @@ import com.neotel.smfcore.custom.hotayi20057.bean.HotayiBean; ...@@ -20,6 +20,7 @@ import com.neotel.smfcore.custom.hotayi20057.bean.HotayiBean;
import com.neotel.smfcore.security.annotation.AnonymousAccess; import com.neotel.smfcore.security.annotation.AnonymousAccess;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
...@@ -54,6 +55,8 @@ public class HotayiController { ...@@ -54,6 +55,8 @@ public class HotayiController {
@Autowired @Autowired
private IBarcodeManager barcodeManager; private IBarcodeManager barcodeManager;
@Value("${hotayi.MachineID:}")
protected String machineID = "";
/** /**
* 收到M1返回M2 * 收到M1返回M2
* M2 Machine Information * M2 Machine Information
...@@ -87,11 +90,22 @@ public class HotayiController { ...@@ -87,11 +90,22 @@ public class HotayiController {
@AnonymousAccess @AnonymousAccess
public HotayiBean m1(@RequestBody HotayiBean hotayiBean) { public HotayiBean m1(@RequestBody HotayiBean hotayiBean) {
log.info("收到M1请求数据为:{}", JsonUtil.toJsonStr(hotayiBean)); log.info("收到M1请求数据为:{}", JsonUtil.toJsonStr(hotayiBean));
hotayiBean.addInfo("MessageNo","M2");
Map<String,Object> resultData = new HashMap<>(); if (ObjectUtil.isNotEmpty(machineID)) {
resultData.put("Version","1.6"); String MmachineID = hotayiBean.getInfoItem("MachineID");
resultData.put("MESMode",1); if (!machineID.equals(MmachineID)) {
resultData.put("SpecID",100); Locale locale = new Locale("en", "US");
String msg = MessageUtils.getText("smfcore.hotayi.machineID.error", new String[]{machineID, MmachineID}, locale, "machineID inconsistency [" + machineID + "] [" + MmachineID + "]");
hotayiBean.setM90(11, msg);
log.error(msg);
return hotayiBean;
}
}
hotayiBean.addInfo("MessageNo", "M2");
Map<String, Object> resultData = new HashMap<>();
resultData.put("Version", "1.6");
resultData.put("MESMode", 1);
resultData.put("SpecID", 100);
hotayiBean.setData(resultData); hotayiBean.setData(resultData);
return hotayiBean; return hotayiBean;
} }
...@@ -130,6 +144,16 @@ public class HotayiController { ...@@ -130,6 +144,16 @@ public class HotayiController {
@AnonymousAccess @AnonymousAccess
public HotayiBean m3(@RequestBody HotayiBean hotayiBean) { public HotayiBean m3(@RequestBody HotayiBean hotayiBean) {
log.info("收到M3请求数据为:{}", JsonUtil.toJsonStr(hotayiBean)); log.info("收到M3请求数据为:{}", JsonUtil.toJsonStr(hotayiBean));
if (ObjectUtil.isNotEmpty(machineID)) {
String MmachineID = hotayiBean.getInfoItem("MachineID");
if (!machineID.equals(MmachineID)) {
Locale locale = new Locale("en", "US");
String msg = MessageUtils.getText("smfcore.hotayi.machineID.error", new String[]{machineID, MmachineID}, locale, "machineID inconsistency [" + machineID + "] [" + MmachineID + "]");
hotayiBean.setM90(11, msg);
log.error(msg);
return hotayiBean;
}
}
hotayiBean.addInfo("MessageNo","M4"); hotayiBean.addInfo("MessageNo","M4");
Map<String,Object> resultData = new HashMap<>(); Map<String,Object> resultData = new HashMap<>();
int solderPasteCount = 0; int solderPasteCount = 0;
...@@ -141,7 +165,7 @@ public class HotayiController { ...@@ -141,7 +165,7 @@ public class HotayiController {
} }
Criteria c = Criteria.where("storageId").is(storage.getId()) Criteria c = Criteria.where("storageId").is(storage.getId())
.and("enabled").is(true) .and("enabled").is(true)
.and("barcode.solderStatus").nin(SOLDER_STATUS.NONE.name(),SOLDER_STATUS.UNDER_REFRIGERATION.name(),SOLDER_STATUS.RETREAT_STORAGE.name()); .and("barcode.solderStatus").nin(null,"",SOLDER_STATUS.NONE.name(),SOLDER_STATUS.UNDER_REFRIGERATION.name(),SOLDER_STATUS.RETREAT_STORAGE.name());
queueCount = storagePosDao.countByQuery(new Query(c)); queueCount = storagePosDao.countByQuery(new Query(c));
c = Criteria.where("storageId").is(storage.getId()) c = Criteria.where("storageId").is(storage.getId())
...@@ -161,7 +185,16 @@ public class HotayiController { ...@@ -161,7 +185,16 @@ public class HotayiController {
@AnonymousAccess @AnonymousAccess
public HotayiBean m7(@RequestBody HotayiBean hotayiBean) { public HotayiBean m7(@RequestBody HotayiBean hotayiBean) {
log.info("收到M7请求数据为: "+ JsonUtil.toJsonStr(hotayiBean)); log.info("收到M7请求数据为: "+ JsonUtil.toJsonStr(hotayiBean));
if (ObjectUtil.isNotEmpty(machineID)) {
String MmachineID = hotayiBean.getInfoItem("MachineID");
if (!machineID.equals(MmachineID)) {
Locale locale = new Locale("en", "US");
String msg = MessageUtils.getText("smfcore.hotayi.machineID.error", new String[]{machineID, MmachineID}, locale, "machineID inconsistency [" + machineID + "] [" + MmachineID + "]");
hotayiBean.setM90(11, msg);
log.error(msg);
return hotayiBean;
}
}
// { "Info": {"MachineID": "0001","IPAddress": "192.168.0.1","MessageNo": "M7"}, // { "Info": {"MachineID": "0001","IPAddress": "192.168.0.1","MessageNo": "M7"},
// "Data": {"Barcode": "A069-O9","RequestDate": "2023-04-12 17:20","MixerBySecond": "0","StandbyHour": 0}} // "Data": {"Barcode": "A069-O9","RequestDate": "2023-04-12 17:20","MixerBySecond": "0","StandbyHour": 0}}
String barcode = hotayiBean.getDataItem("Barcode"); String barcode = hotayiBean.getDataItem("Barcode");
......
...@@ -86,7 +86,7 @@ public class AuthorizationController { ...@@ -86,7 +86,7 @@ public class AuthorizationController {
// throw new BadRequestException("验证码错误"); // throw new BadRequestException("验证码错误");
// } // }
smfApi.canLogin(authUser.getUsername(),"123456"); smfApi.canLogin(authUser.getUsername(),password);
UsernamePasswordAuthenticationToken authenticationToken = UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(authUser.getUsername(), password); new UsernamePasswordAuthenticationToken(authUser.getUsername(), password);
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
......
...@@ -43,4 +43,6 @@ public interface IRoleManager extends IBaseManager<Role> { ...@@ -43,4 +43,6 @@ public interface IRoleManager extends IBaseManager<Role> {
void deleteRoles(List<Role> roles) throws ValidateException; void deleteRoles(List<Role> roles) throws ValidateException;
void untiedMenu(String menuId) throws ValidateException; void untiedMenu(String menuId) throws ValidateException;
Role getByName(String name);
} }
...@@ -148,4 +148,10 @@ public class RoleManagerImpl implements IRoleManager { ...@@ -148,4 +148,10 @@ public class RoleManagerImpl implements IRoleManager {
} }
} }
@Override
public Role getByName(String name) {
Role role = roleDao.findOneByCondition(new String[] {"name"}, new String[] {name});
return role;
}
} }
...@@ -344,6 +344,7 @@ smfcore.shelf.error.storageError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u6599\u67B6[{0}] ...@@ -344,6 +344,7 @@ smfcore.shelf.error.storageError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u6599\u67B6[{0}]
order.error.executing={0}\u5DF2\u5728\u4EFB\u52A1\u5217\u8868\u4E2D order.error.executing={0}\u5DF2\u5728\u4EFB\u52A1\u5217\u8868\u4E2D
smfcore.queryPos.solderOutFail=[{0}]checkOut fail,currStatus[{1}] smfcore.queryPos.solderOutFail=[{0}]checkOut fail,currStatus[{1}]
smfcore.operationFailure=\u64CD\u4F5C\u5931\u8D25 smfcore.operationFailure=\u64CD\u4F5C\u5931\u8D25
smfcore.hotayi.machineID.error=machineID inconsistency [{0}] [{1}]
#smfclient.nlp.onlyOneTray=\u4E0D\u53EF\u540C\u65F6\u653E\u5165\u591A\u76D8\u7269\u6599:{0} #smfclient.nlp.onlyOneTray=\u4E0D\u53EF\u540C\u65F6\u653E\u5165\u591A\u76D8\u7269\u6599:{0}
#smfclient.nlp.cannotFindPos={0}\u672A\u627E\u5230\u5E93\u4F4D:{1} #smfclient.nlp.cannotFindPos={0}\u672A\u627E\u5230\u5E93\u4F4D:{1}
#smfclient.nlp.inputOk={0}\u5165\u5E93\u5230{1}\u6210\u529F #smfclient.nlp.inputOk={0}\u5165\u5E93\u5230{1}\u6210\u529F
......
...@@ -342,4 +342,5 @@ smfcore.shelf.error.orderError=Task does not match the assigned work order [{0}] ...@@ -342,4 +342,5 @@ smfcore.shelf.error.orderError=Task does not match the assigned work order [{0}]
smfcore.shelf.error.storageError=Task does not match the specified shelf [{0}] smfcore.shelf.error.storageError=Task does not match the specified shelf [{0}]
order.error.executing= {0} Already in the task list order.error.executing= {0} Already in the task list
smfcore.queryPos.solderOutFail=[{0}]checkOut fail,currStatus[{1}] smfcore.queryPos.solderOutFail=[{0}]checkOut fail,currStatus[{1}]
smfcore.operationFailure=Operation failed
\ No newline at end of file \ No newline at end of file
smfcore.operationFailure=Operation failed
smfcore.hotayi.machineID.error=machineID inconsistency [{0}] [{1}]
\ No newline at end of file \ No newline at end of file
...@@ -339,4 +339,5 @@ smfcore.shelf.error.orderError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u5DE5\u5355[{0}]\u ...@@ -339,4 +339,5 @@ smfcore.shelf.error.orderError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u5DE5\u5355[{0}]\u
smfcore.shelf.error.storageError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u6599\u67B6[{0}]\u4E0D\u4E00\u81F4 smfcore.shelf.error.storageError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u6599\u67B6[{0}]\u4E0D\u4E00\u81F4
order.error.executing={0}\u5DF2\u5728\u4EFB\u52A1\u5217\u8868\u4E2D order.error.executing={0}\u5DF2\u5728\u4EFB\u52A1\u5217\u8868\u4E2D
smfcore.queryPos.solderOutFail=[{0}]checkOut fail,currStatus[{1}] smfcore.queryPos.solderOutFail=[{0}]checkOut fail,currStatus[{1}]
smfcore.operationFailure=\u64CD\u4F5C\u5931\u8D25
\ No newline at end of file \ No newline at end of file
smfcore.operationFailure=\u64CD\u4F5C\u5931\u8D25
smfcore.hotayi.machineID.error=machineID inconsistency [{0}] [{1}]
\ No newline at end of file \ No newline at end of file
...@@ -339,4 +339,5 @@ smfcore.shelf.error.orderError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u5DE5\u5355[{0}]\u ...@@ -339,4 +339,5 @@ smfcore.shelf.error.orderError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u5DE5\u5355[{0}]\u
smfcore.shelf.error.storageError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u6599\u67B6[{0}]\u4E0D\u4E00\u81F4 smfcore.shelf.error.storageError=\u4EFB\u52A1\u4E0E\u6307\u5B9A\u6599\u67B6[{0}]\u4E0D\u4E00\u81F4
order.error.executing={0}\u5DF2\u5728\u4EFB\u52A1\u5217\u8868\u4E2D order.error.executing={0}\u5DF2\u5728\u4EFB\u52A1\u5217\u8868\u4E2D
smfcore.queryPos.solderOutFail=[{0}]\u51FA\u5E93\u5931\u8D25\uFF0C\u5F53\u524D\u72B6\u6001\uFF1A[{1}] smfcore.queryPos.solderOutFail=[{0}]\u51FA\u5E93\u5931\u8D25\uFF0C\u5F53\u524D\u72B6\u6001\uFF1A[{1}]
smfcore.operationFailure=\u64CD\u4F5C\u5931\u8D25
\ No newline at end of file \ No newline at end of file
smfcore.operationFailure=\u64CD\u4F5C\u5931\u8D25
smfcore.hotayi.machineID.error=machineID inconsistency [{0}] [{1}]
\ No newline at end of file \ No newline at end of file
...@@ -340,4 +340,5 @@ smfcore.shelf.error.orderError=\u4EFB\u52D9\u8207\u6307\u5B9A\u5DE5\u55AE[{0}]\u ...@@ -340,4 +340,5 @@ smfcore.shelf.error.orderError=\u4EFB\u52D9\u8207\u6307\u5B9A\u5DE5\u55AE[{0}]\u
smfcore.shelf.error.storageError=\u4EFB\u52D9\u8207\u6307\u5B9A\u6599\u67B6[{0}]\u4E0D\u4E00\u81F4 smfcore.shelf.error.storageError=\u4EFB\u52D9\u8207\u6307\u5B9A\u6599\u67B6[{0}]\u4E0D\u4E00\u81F4
order.error.executing={0}\u5DF2\u5728\u4EFB\u52D9\u5217\u8868\u4E2D order.error.executing={0}\u5DF2\u5728\u4EFB\u52D9\u5217\u8868\u4E2D
smfcore.queryPos.solderOutFail=[{0}]\u51FA\u5E93\u5931\u8D25\uFF0C\u5F53\u524D\u72B6\u6001\uFF1A[{1}] smfcore.queryPos.solderOutFail=[{0}]\u51FA\u5E93\u5931\u8D25\uFF0C\u5F53\u524D\u72B6\u6001\uFF1A[{1}]
smfcore.operationFailure=\u64CD\u4F5C\u5931\u8D25
\ No newline at end of file \ No newline at end of file
smfcore.operationFailure=\u64CD\u4F5C\u5931\u8D25
smfcore.hotayi.machineID.error=machineID inconsistency [{0}] [{1}]
\ No newline at end of file \ No newline at end of file
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!