Commit 7c15fb15 sunke

更新紧急料出库不会更新需求单发料数量问题

报警允许按条码查询
1 个父辈 29f2a776
......@@ -41,6 +41,24 @@ public class InquiryShelfBean {
}
}
public static boolean clearShelf(String hSerial, String rfid){
boolean clearResult = false;
if(hSerial != null){
log.info("清理["+hSerial+"]使用的过料架["+rfid+"]");
Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
if(shelfMap != null){
ShelfInfo shelfInfo = findSameShelf(hSerial, rfid);
if(shelfInfo != null){
String tempRfid = shelfInfo.tempRfid();
shelfMap.remove(tempRfid);
hSerialShelfMap.put(hSerial, shelfMap);
clearResult = true;
}
}
}
return clearResult;
}
private static List<ShelfInfo> getSortedCAndDShelfList(DataLog task){
......@@ -322,7 +340,7 @@ public class InquiryShelfBean {
if(shelfMap != null){
for (ShelfInfo shelf : shelfMap.values()) {
String shelfRFID = shelf.getRealRfid();
log.info(shelf.tempRfid() + "判断料架["+shelfRFID+"] = " + rfid);
log.debug(shelf.tempRfid() + "判断料架["+shelfRFID+"] = " + rfid);
if(shelfRFID != null && rfid != null){
if(shelfRFID.equals(rfid)){
//已经绑定过该Temp料架
......@@ -559,9 +577,8 @@ public class InquiryShelfBean {
if(appendInfo.isFirstReelAction()){
//首盘料,解除绑定的位置
if(shelfMap != null){
ShelfInfo shelfInfo = shelfMap.get(task.getTempRfid());
if(shelfInfo != null){
boolean result = shelfInfo.cancelLimitLoc(taskShelfType, barcode);
for (ShelfInfo shelfInfo : shelfMap.values()) {
boolean result = shelfInfo.cancelLimitLoc(barcode);
if(result){
log.info("首盘料["+task.getBarcode()+"]任务取消,解除料架" + shelfInfo.tempRfid() +"锁定架位绑定");
updateShelfInfo(shelfInfo);
......@@ -573,17 +590,20 @@ public class InquiryShelfBean {
//补料盘,解除最后一个料架上的位置
ShelfInfo maxShelf = null;
for (ShelfInfo shelfInfo : shelfMap.values()) {
if(shelfInfo.getShelfType().equals(taskShelfType)){
int limitLoc = shelfInfo.getBarcodeLoc(barcode, taskShelfType);
if(limitLoc > 0){
//已经锁定过
boolean result = shelfInfo.cancelLimitLoc(taskShelfType,barcode);
boolean result = shelfInfo.cancelLimitLoc(barcode);
if(result){
log.info("补料盘["+task.getBarcode()+"]任务取消,解除料架" + shelfInfo.tempRfid() +"的锁定架位绑定");
updateShelfInfo(shelfInfo);
}
if(!shelfInfo.isAShelf()){
//非包装料,只取消一个料架, 包装料需要取消C料架和A料架
return;
}
}else{
if(shelfInfo.getShelfType().equals(taskShelfType)){
if(maxShelf == null || shelfInfo.getRfidIndex() > maxShelf.getRfidIndex()){
maxShelf = shelfInfo;
}
......@@ -620,7 +640,7 @@ public class InquiryShelfBean {
boolean putInResult = bindedShelf.putInLimitLoc(rfid,loc,barcode);
if(putInResult){
updateShelfInfo(bindedShelf);
log.info("包装料["+task.getBarcode()+"]放入料架" + rfid +"["+loc+"]缓存更新成功");
log.info("紧急/分盘料["+task.getBarcode()+"]放入料架" + rfid +"["+loc+"]缓存更新成功");
return new ShelfLoc(rfid,loc);
}
}else{
......@@ -630,7 +650,7 @@ public class InquiryShelfBean {
boolean putInResult = shelfInfo.putInLimitLoc(rfid,loc, barcode);
if(putInResult){
updateShelfInfo(shelfInfo);
log.info("包装物料["+task.getBarcode()+"]使用新料架" + rfid +"["+loc+"]缓存更新成功");
log.info("紧急/分盘料["+task.getBarcode()+"]使用新料架" + rfid +"["+loc+"]缓存更新成功");
return new ShelfLoc(rfid,loc);
}
}
......@@ -641,10 +661,11 @@ public class InquiryShelfBean {
newBShelf.setRfidIndex(rfidIndex);
newBShelf.sethSerial(shelfMapKey);
log.info("添加新料架["+newBShelf.tempRfid() + "]");
loc = bindedShelf.addLimitLoc(barcode, task.getReelType());
boolean putInResult = bindedShelf.putInLimitLoc(rfid,loc,barcode);
loc = newBShelf.addLimitLoc(barcode, task.getReelType());
boolean putInResult = newBShelf.putInLimitLoc(rfid,loc,barcode);
if(putInResult){
log.info("物料["+task.getBarcode()+"]放入料架" + rfid +"["+loc+"]缓存更新成功");
updateShelfInfo(newBShelf);
log.info("紧急/分盘料["+task.getBarcode()+"]放入料架" + rfid +"["+loc+"]缓存更新成功");
return new ShelfLoc(rfid,loc);
}
}
......
......@@ -232,8 +232,7 @@ public class ShelfInfo {
/**
* 为首盘料取消一个锁定的库位
*/
public boolean cancelLimitLoc(String rfidType, String barcode){
if(rfidType.equals(this.getShelfType())){
public boolean cancelLimitLoc(String barcode){
for (ShelfLoc shelfLoc : locMap.values()) {
if(shelfLoc.isInThisLoc(barcode)){
if(shelfLoc.isEmpty()){
......@@ -241,8 +240,8 @@ public class ShelfInfo {
locMap.put(shelfLoc.getLoc(), shelfLoc);
return true;
}else {
log.error("料盘["+barcode+"]解除绑定架位失败,此位置料盘已放入");
}
log.error("料盘["+barcode+"]解除绑定架位"+shelfLoc.getTempRfid()+"["+shelfLoc.getLoc()+"]失败,此位置料盘已放入");
return false;
}
}
}
......@@ -465,6 +464,10 @@ public class ShelfInfo {
return StorageConstants.SHEFL_TYPE.isDShelf(getShelfType());
}
public boolean isAShelf(){
return StorageConstants.SHEFL_TYPE.isAShelf(getShelfType());
}
public void setShelfType(String shelfType) {
this.shelfType = shelfType;
}
......@@ -472,4 +475,17 @@ public class ShelfInfo {
public String tempRfid(){
return gethSerial() + "-" + rfidIndex + shelfType;
}
@Override
public String toString() {
return "ShelfInfo{" +
"hSerial='" + hSerial + '\'' +
", log=" + log +
", rfidIndex=" + rfidIndex +
", realRfid='" + realRfid + '\'' +
", shelfType='" + shelfType + '\'' +
", maxLocCount=" + maxLocCount +
", locMap=" + locMap +
'}';
}
}
......@@ -150,4 +150,16 @@ public class ShelfLoc {
public void setRealRfid(String realRfid) {
this.realRfid = realRfid;
}
@Override
public String toString() {
return "ShelfLoc{" +
"barcode='" + barcode + '\'' +
", realRfid='" + realRfid + '\'' +
", tempRfid='" + tempRfid + '\'' +
", loc=" + loc +
", reelType=" + reelType +
", empty=" + empty +
'}';
}
}
......@@ -445,7 +445,7 @@ public class BarcodeRule {
if(partNumber.startsWith("QT")){
log.info("料号["+partNumber+"]为移远料号,进行料号转换");
try {
partNumber = QisdaApiController.PartNoMapping(partNumber);
partNumber = QisdaApi.PartNoMapping(partNumber);
} catch (ApiException e) {
codeBean.setError(e.getMessage());
return codeBean;
......
......@@ -50,7 +50,7 @@ public class AlarmInfoSearchController extends BaseSearchController {
}
}
super.addLikeParam(request,baseCriteria,"alarmMsg");
query.addCriteria(baseCriteria);
PageList pageList = alarmInfoDao.findByQuery(query, searchCriteria.getPageList());
......
......@@ -24,6 +24,7 @@ import com.myproject.exception.ApiException;
import com.myproject.exception.ValidateException;
import com.myproject.manager.IBarcodeManager;
import com.myproject.manager.IStoragePosManager;
import com.myproject.util.QisdaApi;
import com.myproject.util.StorageConstants;
import com.myproject.webapp.controller.storage.BaseController;
import com.myproject.webapp.controller.webService.DataCache;
......@@ -71,7 +72,7 @@ public class DifferentInventoryController extends BaseController {
qisdaReelMap = readQisda(file);
}else{
log.info("开始与Qisda比对库存");
qisdaReelMap = QisdaApiController.getInventory();
qisdaReelMap = QisdaApi.getInventory();
}
List<StoragePos> posList = storagePosManager.findNotEmpty();
......
......@@ -28,6 +28,7 @@ import com.myproject.exception.ApiException;
import com.myproject.exception.ValidateException;
import com.myproject.manager.IBarcodeManager;
import com.myproject.manager.IStoragePosManager;
import com.myproject.util.QisdaApi;
import com.myproject.util.StorageConstants;
import com.myproject.webapp.controller.qisda.util.OutInfoCache;
import com.myproject.webapp.controller.storage.BaseController;
......@@ -211,6 +212,9 @@ public class QisdaController extends BaseController {
@RequestMapping("/service/store/qisda/bindDn")
@ResponseBody
public String bindDn(HttpServletRequest request){
if(dataCache.getSettings().isStopOut()){
return "x系统更新中,暂停出入库,请稍后再试";
}
String rfid = request.getParameter("rfid");
String dnNo = request.getParameter("dnNo");
String facility = request.getParameter("facility");
......@@ -246,7 +250,7 @@ public class QisdaController extends BaseController {
log.info("未找到DN单["+dnNo+"],从佳世达获取");
boolean isCheck = false;
try {
List<DNItem> dnItems = QisdaApiController.GetDNDetails(dnNo, isCheck);
List<DNItem> dnItems = QisdaApi.GetDNDetails(dnNo, isCheck);
dNItemDao.insertAll(dnItems);
newDnInfo = dNInfoDao.save(newDnInfo);
newDnInfo.addItems(dnItems);
......
......@@ -109,7 +109,7 @@ public class OutInfoCache {
/**
* 更新需求单的发料状态
*/
private void updateStatus(String hSerial){
public void updateStatus(String hSerial){
OutInfo outInfo = outInfoMap.get(hSerial);
if(outInfo != null){
log.info("更新需求单["+hSerial+"]的发料状态 [" + outInfo.getSendStatus()+"]");
......
......@@ -66,9 +66,11 @@ public class StorageUpdateController extends BaseUpdateController {
return getSuccessView();
} else {
try {
storage = storageManager.save(storage);
dataCache.reloadStorage(storage);
//fileUpload.setParam(storage.getId());
saveMessage(request, getText("storage.saveSuccess", request.getLocale()));
//return "redirect:storageUpdate.html?id="+storage.getId();
} catch (Exception e) {
log.error(e);
......
......@@ -228,8 +228,8 @@ public class DataCache{
codeBeanFromRule.setError(null);
codeBeanFromRule.setCodeStr(barcode.getBarcode());
codeBeanFromRule.setBarcode(barcode);
Component component = componentManager.findByPartNumber(barcode.getPartNumber());
codeBeanFromRule.setShowImg(component.getShowImg());
//Component component = componentManager.findByPartNumber(barcode.getPartNumber());
//codeBeanFromRule.setShowImg(component.getShowImg());
return codeBeanFromRule;
}
......@@ -317,7 +317,7 @@ public class DataCache{
}else{
}
codeBeanFromRule.setShowImg(component.getShowImg());
//codeBeanFromRule.setShowImg(component.getShowImg());
}
}
......
......@@ -65,6 +65,8 @@ public interface ITaskService {
*/
String checkout(StoragePos pos, String subSourceId, boolean isSingleOut);
List<DataLog> getAllTasks();
DataLog getFinishedTask(String barcode);
void updateFinishedTask(DataLog task);
......
......@@ -16,6 +16,7 @@ import com.myproject.dao.mongo.qisda.IOutItemDao;
import com.myproject.exception.ValidateException;
import com.myproject.manager.IBarcodeManager;
import com.myproject.manager.IComponentManager;
import com.myproject.util.QisdaApi;
import com.myproject.util.StorageConstants;
import com.myproject.webapp.controller.qisda.util.OutInfoCache;
import com.myproject.webapp.controller.storage.BaseController;
......@@ -236,6 +237,18 @@ public class QisdaDeviceController extends BaseController {
if(hSerial.isEmpty()){
return ResultBean.newErrorResult(-2, "未找到大料架["+bigRfid+"]");
}
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog task : allTasks) {
//如果还有小料任务未完成,说明换了需求单了,放行大料架
if(task.isCheckOutTask() && task.isSmallReel() && !task.isPackageReel()){
AppendInfo appendInfo = task.getAppendInfo();
if(appendInfo.isFirstReelAction() || appendInfo.isTailAction()){
return ResultBean.newErrorResult(-3, "还有小料任务,需求单已更换,大料架["+bigRfid+"]放行");
}
}
}
log.info("收到机器人[3]获取包装料摆放位置信息请求:[packageRfid=" + packageRfid + "]bigRfid=" + bigRfid + "当前工单料需求:["+hSerial+"]");
ShelfInfo packageShelf = inquiryShelfBean.findPackageShelf(hSerial, packageRfid);
......@@ -253,11 +266,6 @@ public class QisdaDeviceController extends BaseController {
}
if(bigShelf != null){
Collection<DataLog> queueTasks = taskService.getQueueTasks();
List<DataLog> allTasks = taskService.getFinishedTasks();
if(!queueTasks.isEmpty()){
allTasks.addAll(queueTasks);
}
//剩余包装料任务
int packageTask = 0;
for (DataLog task : allTasks) {
......@@ -294,7 +302,7 @@ public class QisdaDeviceController extends BaseController {
//包装料架上有料,且大料架有空位,从大料架上查找空位
DataLog task = taskService.getFinishedTask(barcode);
if(task == null){
String msg = "机器人[3]获取包装料摆放位置信息,未找到包装料架[]上条码["+barcode+"]的任务";
String msg = "机器人[3]获取包装料摆放位置信息,未找到条码["+barcode+"]的任务";
log.error(msg);
return ResultBean.newErrorResult(103, msg);
}
......@@ -510,6 +518,48 @@ public class QisdaDeviceController extends BaseController {
}
/**
* 分盘料/紧急料放上料串或料架流出时调用
*/
@RequestMapping(value = "/clearRfid")
@ResponseBody
public ResultBean clearRfid(HttpServletRequest request) {
String rfid = request.getParameter("rfid");
if(rfid == null){
rfid = "";
}
boolean clearResult = InquiryShelfBean.clearShelf(InquiryShelfBean.URGENT_SHELF_MAP_KEY,rfid);
if(!clearResult){
log.info("从分盘料料架中查找["+rfid+"]准备清除");
clearResult = InquiryShelfBean.clearShelf(InquiryShelfBean.CUT_SHELF_MAP_KEY,rfid);
}
log.info("清除料架["+rfid+"]完成:" + clearResult);
return ResultBean.newOkResult(clearResult);
}
/**
* 取消入库任务
*/
@RequestMapping(value = "/cancelPutInTask")
@ResponseBody
public ResultBean cancelPutInTask(HttpServletRequest request) {
String barcode = request.getParameter("barcode");
if(Strings.isBlank(barcode)){
return ResultBean.newErrorResult(2001,"未找到参数barcode");
}
Collection<DataLog> queueTasks = taskService.getQueueTasks();
for (DataLog queueTask : queueTasks) {
if(queueTask.isPutInTask() && queueTask.getBarcode().equals(barcode)){
//只能取消入库任务
boolean cancelResult = taskService.cancelTask(queueTask.getId());
log.info("客户端取消["+barcode+"]的入库任务结果:" + cancelResult);
return ResultBean.newOkResult(cancelResult);
}
}
return ResultBean.newErrorResult(2002, "任务["+barcode+"]取消失败");
}
/**
* 分盘料/紧急料放上料串或料架时调用
*/
@RequestMapping(value = "/afterPutCut")
......@@ -522,19 +572,16 @@ public class QisdaDeviceController extends BaseController {
String barcode = request.getParameter("barcode");
String rfid = request.getParameter("rfid");
String rfidLoc = request.getParameter("rfidLoc");
log.info("收到["+cid+"]紧急/分盘料[" + barcode + "]放入"+rfid+"[" + rfidLoc + "]指令");
log.debug("收到["+cid+"]紧急/分盘料[" + barcode + "]放入"+rfid+"[" + rfidLoc + "]指令");
DataLog task = findFinishedTask(barcode);
if(task == null){
return ResultBean.newErrorResult(301, "任务不存在");
}
if(task != null){
ShelfLoc shelfLoc = inquiryShelfBean.putInCutReel(task,rfid, Integer.valueOf(rfidLoc));
if(shelfLoc != null){
log.info("收到["+cid+"]紧急/分盘料[" + barcode + "]放入"+rfid+"[" + rfidLoc + "]成功");
log.info("["+cid+"]紧急/分盘料[" + barcode + "]放入"+rfid+"[" + rfidLoc + "]成功");
task.setStatus(StorageConstants.OP_STATUS.FINISHED.name());
rfidLoc = shelfLoc.getLoc() + "";
}else{
log.info("收到"+cid+"紧急/分盘料[" + barcode + "]放入"+rfid+"[" + rfidLoc + "]失败");
log.info(""+cid+"紧急/分盘料[" + barcode + "]放入"+rfid+"[" + rfidLoc + "]失败");
task.setStatus(StorageConstants.OP_STATUS.INSHELF.toString());
}
AppendInfo appendInfo = task.getAppendInfo();
......@@ -543,16 +590,13 @@ public class QisdaDeviceController extends BaseController {
task.setAppendInfo(appendInfo);
task = dataLogDao.save(task);
taskService.updateFinishedTask(task);
}
int cutPackageTask = 0;
int urgentPackageTask = 0;
int cutTask = 0;
int urgentTask = 0;
Collection<DataLog> queueTasks = taskService.getQueueTasks();
List<DataLog> allTasks = taskService.getFinishedTasks();
if(!queueTasks.isEmpty()){
allTasks.addAll(queueTasks);
}
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog unFinishedTask : allTasks) {
if(!unFinishedTask.isFinished() && !unFinishedTask.isCancel() && unFinishedTask.isCheckOutTask()){
if(unFinishedTask.isPackageReel()){
......@@ -563,9 +607,9 @@ public class QisdaDeviceController extends BaseController {
urgentPackageTask = urgentPackageTask + 1;
}
}
}else if(task.isCutReel()){
}else if(unFinishedTask.isCutReel()){
cutTask = cutTask + 1;
}else if(task.isUrgentReel()){
}else if(unFinishedTask.isUrgentReel()){
urgentTask = urgentTask + 1;
}
}
......@@ -577,6 +621,16 @@ public class QisdaDeviceController extends BaseController {
resultMap.put("cutTask", cutTask + "");
resultMap.put("urgentTask", urgentTask + "");
if(cutPackageTask + cutTask == 0){
log.info("已无分盘料任务,清空分盘料使用料架/料串");
InquiryShelfBean.clearShelf(InquiryShelfBean.CUT_SHELF_MAP_KEY);
}
if(urgentPackageTask + urgentTask == 0){
log.info("已无紧急料任务,清空紧急料使用料架/料串");
InquiryShelfBean.clearShelf(InquiryShelfBean.URGENT_SHELF_MAP_KEY);
}
return ResultBean.newOkResult(resultMap);
}
......@@ -589,7 +643,7 @@ public class QisdaDeviceController extends BaseController {
String barcode = request.getParameter("barcode");
String statusStr = request.getParameter("status");
String locInfo = request.getParameter("locInfo");
log.info("收到料盘["+barcode+"]更新位置指令["+statusStr+"]=" + locInfo);
log.debug("收到料盘["+barcode+"]更新位置指令["+statusStr+"]=" + locInfo);
DataLog task = findFinishedTask(barcode);
if(task == null){
......@@ -682,7 +736,7 @@ public class QisdaDeviceController extends BaseController {
String latest = outInfo.getShelfLatest();
QisdaApiController.VMIMateriaRecAss(cacheTask, barcodeObj,latest);
QisdaApi.VMIMateriaRecAss(cacheTask, barcodeObj,latest);
//发料完成,更新发料数量
int slotSeq = appendInfo.getSlotIndex();
OutItem outItem = outItemDao.findItem(hSerial, slotSeq);
......
......@@ -28,6 +28,7 @@ import com.myproject.manager.IStoragePosManager;
import com.myproject.model.User;
import com.myproject.service.UserManager;
import com.myproject.util.HttpHelper;
import com.myproject.util.QisdaApi;
import com.myproject.util.StorageConstants;
import com.myproject.webapp.controller.qisda.QisdaController;
import com.myproject.webapp.controller.qisda.util.OutInfoCache;
......@@ -192,6 +193,19 @@ public class TaskService implements ITaskService {
return resultTasks;
}
/**
* 获取所有任务
*/
@Override
public List<DataLog> getAllTasks(){
Collection<DataLog> queueTasks = getQueueTasks();
List<DataLog> allTasks = getFinishedTasks();
if(!queueTasks.isEmpty()){
allTasks.addAll(queueTasks);
}
return allTasks;
}
@Override
public DataLog getFinishedTask(String barcode){
......@@ -834,7 +848,7 @@ public class TaskService implements ITaskService {
log.info("需求单[" + outInfo.gethSerial() + "]任务完成数量:" + outInfo.getTaskFinishNum() + "/" + outInfo.getTaskNum() + "已出仓料盘数量:" + outInfo.getOutReelNum());
outInfoDao.save(outInfo);
InquiryShelfBean.cancelReelTask(task);
QisdaApiController.VMIMateriaRecAss(task, barcode, "E");
QisdaApi.VMIMateriaRecAss(task, barcode, "E");
}
}
finishedTaskMap.remove(task.getBarcode());
......@@ -2015,7 +2029,6 @@ public class TaskService implements ITaskService {
if(outItem != null){
if(barcode.hasCutInfo()){
log.info("分盘料出库,更新需求单出库数量");
//分盘料,需要更新对应的需求单出库数量
final List<Map<String, Object>> cutItems = barcode.getCutItems();
for (Map<String, Object> cutItem : cutItems) {
......@@ -2049,16 +2062,19 @@ public class TaskService implements ITaskService {
outInfo = outInfoDao.findByHSerial(outItem.gethSerial());
int outReelNum = outInfo.getOutReelNum();
outInfo.setOutReelNum(outReelNum + 1);
if(outItem.isUrgentAction() || outItem.isReelCutAction()){
outInfo.setTaskFinishNum(outInfo.getTaskFinishNum() + 1);
}
outInfo = outInfoDao.save(outInfo);
String latest = outInfo.getOutLatest();
QisdaApiController.OutFinished(task, barcode, latest);
if (latest.equals("L")) {
log.info("工单[" + outItem.getSo() + "]的最后一盘出库完成,发送缺料通知");
log.info("工单[" + outItem.getSo() + "]需求单["+outItem.gethSerial()+"]的最后一盘出库完成,发送缺料通知");
List<OutItem> outItemList = outItemDao.findByHSerial(outItem.gethSerial());
boolean lessBind = false;
QisdaApiController.VMILocationOutFeedback(outItemList, lessBind);
QisdaApi.VMILocationOutFeedback(outItemList, lessBind);
}
}
......
......@@ -43,6 +43,15 @@
</div>
</div>
<div class="col-md-6 col-sm-6">
<div class="form-group form-inline">
<div class="input-group margin-top-10">
<span class="input-group-addon"><fmt:message key="条码"/></span>
<input type="text" class="form-control input-xlarge" name="alarmMsg" value="${alarmMsg}"/>
</div>
</div>
</div>
<div class="col-md-2">
<button class="btn purple margin-top-10" type="submit"><i class="fa fa-search"></i>
<fmt:message key="button.search"/>
......
......@@ -164,6 +164,9 @@
<%--&lt;%&ndash;<display:column property="barcode.amount" titleKey="数量"/>&ndash;%&gt;--%>
<%--<display:column property="barcode.lockName" titleKey="menu.inRule"/>--%>
<display:column property="posName" titleKey="checkOut.pos" sortProperty="posName" sortable="true"/>
<display:column titleKey="尺寸">
${pos.sizeStr}
</display:column>
<display:column property="barcode.appendInfo.facility" titleKey="Facility" sortProperty="barcode.appendInfo.facility" sortable="true"/>
<display:column titleKey="时间" sortProperty="barcode.updateDate" sortable="true">
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!