Commit ff487019 authored by wp's avatar wp

商品发布

parent 689a45b9
HELP.md
target/
log/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
......
......@@ -105,10 +105,17 @@ public class NftEvm {
// String hash = ra.evmDeploy(code, abi, "LyNFT", RpcConfig.TX_EVM_DEPLOY_FEE, "LyNFT", null, tokenManager, tokenManagerKey, false);
// System.err.println(hash);
//1HBT7zyMYz7n9jz3JuYhEgFWuEtvpqxQaW
long[] tokenIds = {1, 2, 3};
long[] amounts = {1, 1, 1};
//发行NFT,本次发行的是ERC1155
String hash = ra.evmPublishToken(abi, cAddr, EvmTokenEnum.ERC1155, 0L, "1F5HWw8WB7iGat37RXqbfaQAcHUwpGedko","1F5HWw8WB7iGat37RXqbfaQAcHUwpGedko", null, 1631716701489L, 10000L, "publish", true);
String hash = ra.evmPublishToken(abi, cAddr, EvmTokenEnum.ERC1155, 0L, "1HBT7zyMYz7n9jz3JuYhEgFWuEtvpqxQaW", "1HBT7zyMYz7n9jz3JuYhEgFWuEtvpqxQaW",null, 1L, 1L, "publish", true);
// String hash = ra.evmPublishTokenBatch(abi, cAddr, 0L, "1HBT7zyMYz7n9jz3JuYhEgFWuEtvpqxQaW", "1HBT7zyMYz7n9jz3JuYhEgFWuEtvpqxQaW", null, tokenIds, amounts, "publish", true);
System.err.println(hash);
System.err.println(ra.cycleConfirmTxWithHash(hash,true,1000).getStatus());
System.err.println(ra.cycleConfirmTxWithHash(hash, true, 1000).getStatus());
//NFT转账
// String hash = ra.evmTransfer(abi, cAddr, EvmTokenEnum.ERC1155, 0L, to, tokenId, 100L, "transfer", publisher, null, false);
......
......@@ -65,6 +65,7 @@ public class SpuController {
@PostMapping("/releaseGoods/add")
public ResponseVO add(@RequestBody @Valid GoodsSpuDTO pDTO, @ApiParam(name = "adminId", value = "管理员id")
@RequestHeader String adminId) {
System.err.println("pDTO:" + pDTO);
spuService.goodsNameExist(pDTO.getName());
adminService.adminAuthChecks(adminId, AdminTypeEnum.getMerchantTypeArr());
String merchantId = adminService.getByAdminId(adminId).getMerchantId();
......@@ -145,8 +146,6 @@ public class SpuController {
@RequestParam(required = false) String goodsId,
@ApiParam(name = "goodsName", value = "商品名称")
@RequestParam(required = false) String goodsName,
@ApiParam(name = "status", value = "状态")
@RequestParam(required = false) Integer status,
@ApiParam(name = "addTimeHead", value = "开始时间")
@RequestParam(required = false) Long addTimeHead,
@ApiParam(name = "addTimeTail", value = "结束时间")
......@@ -160,7 +159,7 @@ public class SpuController {
@ApiParam(name = "adminId", value = "管理员id")
@RequestHeader String adminId) {
Admin admin = adminService.getByAdminId(adminId);
IPage<GoodsSpuVO> page = spuService.page(admin.getMerchantId(), admin.getType(), goodsId, goodsName, status,
IPage<GoodsSpuVO> page = spuService.page(admin.getMerchantId(), admin.getType(), goodsId, goodsName, SpuStatusEnum.WAIT_CHECK.getStatus(),
addTimeHead, addTimeTail, goodsType, pageNum, pageSize);
return resFac.getSuccessResponseWithData(page);
}
......
......@@ -49,15 +49,12 @@ public class GoodsRepublishUpdateDTO {
private String imgList;
@ApiModelProperty("商品视频")
// @NotBlank(message = MallResponseError.NULL_PARAM_ERROR)
private String video;
@ApiModelProperty("视频封面")
// @NotBlank(message = MallResponseError.NULL_PARAM_ERROR)
private String videoPoster;
@ApiModelProperty("ntf文件")
// @NotBlank(message = MallResponseError.NULL_PARAM_ERROR)
private String nftFile;
@ApiModelProperty("商品介绍")
......@@ -83,7 +80,6 @@ public class GoodsRepublishUpdateDTO {
private String note;
@ApiModelProperty("溯源信息")
// @NotBlank(message = MallResponseError.NULL_PARAM_ERROR)
private String traceabilityNumber;
@ApiModelProperty("商品规格")
......
package com.fzm.mall.server.admin.goods_center.enums.type;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author wangp
* @date 2021/3/12 13:49
* @description 发币类型
* @since JDK 1.8
*/
public enum CommodityPassTypeEnum {
NO(0),//不发币
INNER(1),//内部发行
OUT(2),//外部绑定
COPY(3);//外部绑定直发
private Integer type;
CommodityPassTypeEnum(Integer type) {
this.type = type;
}
public Integer getType() {
return type;
}
public static List<Integer> getValueList() {
return Arrays.stream(CommodityPassTypeEnum.values())
.map(CommodityPassTypeEnum::getType)
.collect(Collectors.toList());
}
}
package com.fzm.mall.server.admin.goods_center.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -20,6 +18,7 @@ import lombok.EqualsAndHashCode;
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("goods_sku_usufruct")
@ApiModel(value="GoodsSkuUsufruct对象", description="使用权")
public class GoodsSkuUsufruct implements Serializable {
......
package com.fzm.mall.server.admin.goods_center.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
......@@ -17,14 +18,18 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fzm.mall.server.admin.goods_center.service.IGoodsNftService;
import com.fzm.mall.server.admin.goods_center.service.ISkuService;
import com.fzm.mall.server.admin.home_page.dao.MerchantMapper;
import com.fzm.mall.server.admin.util.HttpUtil;
import com.fzm.mall.server.admin.util.UUIDUtil;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
......@@ -41,18 +46,16 @@ public class ExternalTokenServiceImpl extends ServiceImpl<ExternalTokenMapper, E
@Autowired
private ExternalTokenMapper externalTokenMapper;
@Autowired
private MerchantMapper merchantMapper;
@Autowired
private DozerBeanMapper beanMapper;
@Autowired
private IGoodsNftService goodsNftService;
@Autowired
private ISkuService skuService;
@Value("${ly.url}")
private String url;
@Override
public IPage<ExternalTokenDTO> page(Page<ExternalTokenDTO> page, String labelName, String goodsId, String goodsName,
......@@ -113,8 +116,15 @@ public class ExternalTokenServiceImpl extends ServiceImpl<ExternalTokenMapper, E
externalToken.setName(name);
externalToken.setPublishTime(publishTime);
externalToken.setPublisher(publisher);
Map<String, Object> map = new HashMap<>();
map.put("tokenId", tokenId);
String httpGet = HttpUtil.httpGet(url, map);
JSONObject json = JSONObject.parseObject(httpGet);
if (json.getString("code").equals("200")) {
externalToken.setHash(json.getString("data"));
}
//TODO 唐拓接口
externalToken.setHash("xxx");
save(externalToken);
}
}
......
......@@ -87,7 +87,6 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
sku.setSkuId(skuId);
sku.setGoodsId(goodsId);
sku.setCoinName(coinName);
skus.add(sku);
if (commodityPass.equals(1) && !pDTOType.equals(6)) {
//发行商品币
......@@ -127,29 +126,24 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
//发行NFT
ExternalToken externalToken = externalTokenService.queryByLabelNameAndMerchantId(kDTO.getCoinName(), merchantId);
String tokenId = externalToken.getTokenId().toString();
long[] tokenIds = new long[Math.toIntExact(kDTO.getStock())];
long[] amounts = new long[Math.toIntExact(kDTO.getStock())];
long[] nos = new long[Math.toIntExact(kDTO.getStock())];
long[] nos = new long[Math.toIntExact(kDTO.getStock() + 1)];
String[] hashs = new String[Math.toIntExact(kDTO.getStock())];
nos[0] = 0;
for (int i = 0; i < kDTO.getStock(); i++) {
tokenIds[i] = Long.parseLong(tokenId + (i + 1));
amounts[i] = 1;
String hash = chainUtil.evmPublishTokenSplit(merchant.getNftAddr(), Long.parseLong(tokenId + (i + 1)), 1L);
nos[i + 1] = i + 1;
hashs[i] = hash;
}
String hash = chainUtil.evmPublishTokenSplitBatch(merchant.getNftAddr(), tokenIds, amounts);
System.err.println("tokenIds:" + tokenIds);
System.err.println("amounts:" + amounts);
System.err.println("nos:" + nos);
System.err.println("hash:" + hash);
Map<String, Object> map = new HashMap<>();
map.put("goodsId", goodsId);
map.put("hash", hash);
map.put("hashs", hashs);
map.put("prefix", tokenId);
map.put("nos", JSONArray.toJSON(nos));
producer.sendTTL(map, QueueTTLTypeEnum.NFT_USU_TTL, 10 * 1000);
}
}
skus.add(sku);
}
saveBatch(skus);
......@@ -203,8 +197,11 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
@Override
public void republish(List<GoodsSkuDTO> kDTOs, String goodsId, String name, String merchantId, Integer commodityPass, Integer pDTOType) {
Merchant merchant = merchantService.getByMerchantId(merchantId);
int subCount = 0;
int total = (int) kDTOs.stream().filter(GoodsSkuDTO::getRepublish).count();
/*int subCount = 0;
int total = 0;
if (pDTOType.equals(6)) {
total = (int) kDTOs.stream().filter(GoodsSkuDTO::getRepublish).count();
}
//删除旧数据
List<String> skuID = kDTOs.stream().map(GoodsSkuDTO::getSkuId).collect(Collectors.toList());
......@@ -224,7 +221,7 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
update(uw);
}
});
}
}*/
for (GoodsSkuDTO kDTO : kDTOs) {
String skuId = kDTO.getSkuId();
......@@ -246,7 +243,7 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
one.setStatus(1);
// skus.add(one);
if (commodityPass.equals(1) && !pDTOType.equals(6)) {
/*if (commodityPass.equals(1) && !pDTOType.equals(6)) {
if (republish) {
//发行商品币
if (getOne(new QueryWrapper<Sku>().lambda().eq(Sku::getCoinName, coinName)) != null) {
......@@ -281,30 +278,43 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
ExternalToken externalToken = externalTokenService.getOne(qw);
externalToken.setBindNumber(externalToken.getBindNumber().add(new BigDecimal(kDTO.getStock() - oldStock)));
externalTokenService.updateById(externalToken);
}*/
if (commodityPass.equals(1) && pDTOType.equals(6)) {
String tokenId = one.getCoinName().substring(4);
long balance = chainUtil.evmBalance(merchant.getNftAddr(), Long.parseLong(tokenId));
String hash = "";
if (balance != 0) {
hash = chainUtil.evmPublishTokenSplit(merchant.getNftAddr(), Long.parseLong(tokenId), one.getStock());
Map<String, Object> map = new HashMap<>();
map.put("goodsId", goodsId);
map.put("hash", hash);
producer.sendTTL(map, QueueTTLTypeEnum.NFT_ISSUE_TTL, 10 * 1000);
}
}
if (commodityPass.equals(3)) {
if (kDTO.getNftSalesType().equals(2)) {
//发行NFT
ExternalToken externalToken = externalTokenService.queryByLabelNameAndMerchantId(kDTO.getCoinName(), merchantId);
String tokenId = externalToken.getTokenId().toString();
long[] tokenIds = new long[Math.toIntExact(kDTO.getStock())];
long[] amounts = new long[Math.toIntExact(kDTO.getStock())];
long[] nos = new long[Math.toIntExact(kDTO.getStock())];
long[] nos = new long[Math.toIntExact(kDTO.getStock() + 1)];
String[] hashs = new String[Math.toIntExact(kDTO.getStock())];
nos[0] = 0;
for (int i = 0; i < kDTO.getStock(); i++) {
tokenIds[i] = Long.parseLong(tokenId + (i + 1));
amounts[i] = 1;
long balance = chainUtil.evmBalance(merchant.getNftAddr(), Long.parseLong(tokenId + (i + 1)));
if (balance != 0) {
String hash = chainUtil.evmPublishTokenSplit(merchant.getNftAddr(), Long.parseLong(tokenId + (i + 1)), 1L);
hashs[i] = hash;
}
nos[i + 1] = i + 1;
}
String hash = chainUtil.evmPublishTokenSplitBatch(merchant.getNftAddr(), tokenIds, amounts);
System.err.println("tokenIds:" + tokenIds);
System.err.println("amounts:" + amounts);
System.err.println("nos:" + nos);
System.err.println("hash:" + hash);
System.err.println("nos:" + Arrays.toString(nos));
System.err.println("hashs:" + hashs);
Map<String, Object> map = new HashMap<>();
map.put("goodsId", goodsId);
map.put("hash", hash);
map.put("hashs", hashs);
map.put("prefix", tokenId);
map.put("nos", JSONArray.toJSON(nos));
producer.sendTTL(map, QueueTTLTypeEnum.NFT_USU_TTL, 10 * 1000);
......@@ -314,7 +324,7 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
updateById(one);
} else {
if (coinName.equals("RMB")) {
/*if (coinName.equals("RMB")) {
throw new MyException(MallResponseError.COIN_NOT_RMB);
}
......@@ -355,7 +365,7 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
uw.eq(ExternalToken::getCommodityPassId, sku.getCommodityPassId());
externalTokenService.update(uw);
}
save(sku);
save(sku);*/
}
}
}
......
......@@ -17,6 +17,7 @@ import com.fzm.mall.server.admin.exception.MyException;
import com.fzm.mall.server.admin.goods_center.entity.dto.*;
import com.fzm.mall.server.admin.goods_center.entity.vo.*;
import com.fzm.mall.server.admin.goods_center.enums.status.SpuStatusEnum;
import com.fzm.mall.server.admin.goods_center.enums.type.CommodityPassTypeEnum;
import com.fzm.mall.server.admin.goods_center.enums.type.GoodsTypeEnum;
import com.fzm.mall.server.admin.goods_center.mapper.SpuMapper;
import com.fzm.mall.server.admin.goods_center.model.*;
......@@ -93,16 +94,17 @@ public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements ISpuS
} else if (pDTOType.equals(PACK.getType())) {
goodsPackageService.add(pDTO.getPackageDTO(), goodsId);
} else if (pDTOType.equals(NFT.getType())) {
if (pDTO.getCommodityPass() != 3) {
nftService.add(pDTO.getNftdto(), goodsId, pDTO.getName(),
merchantService.getByMerchantId(merchantId).getNftAddr(),
merchantId, timestamp);
if (pDTO.getNftdto().getTzType().equals(1)) {
List<GoodsSkuDTO> objects = pDTO.getSkuList().stream().peek(v -> v.setCoinName(MALLGlobalConfig.NFT_PREFIX + timestamp))
.collect(Collectors.toList());
pDTO.setSkuList(objects);
}
}
}
//商品类目表入库
JSONArray ids = JSON.parseArray(pDTO.getCategoryId());
......@@ -142,9 +144,7 @@ public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements ISpuS
countService.init(goodsId);
//商品入库
if (!save(spu)) {
throw new MyException(MallResponseError.SAVE_ERROR);
}
save(spu);
}
@Override
......@@ -164,7 +164,7 @@ public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements ISpuS
auctionService.edit(pDTO.getAuctionDTO(), goodsId);
} else if (type.equals(PACK.getType())) {
goodsPackageService.edit(pDTO.getPackageDTO(), goodsId);
} else if (type.equals(NFT.getType())) {
} else if (type.equals(NFT.getType()) && !one.getCommodityPass().equals(CommodityPassTypeEnum.COPY.getType())) {
nftService.edit(pDTO.getNftdto(), goodsId);
}
......@@ -217,7 +217,7 @@ public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements ISpuS
auctionService.edit(eDTO.getAuctionDTO(), goodsId);
} else if (type.equals(PACK.getType())) {
goodsPackageService.edit(eDTO.getPackageDTO(), goodsId);
} else if (type.equals(NFT.getType())) {
} else if (type.equals(NFT.getType()) && !one.getCommodityPass().equals(CommodityPassTypeEnum.COPY.getType())) {
nftService.edit(eDTO.getNftdto(), goodsId);
}
......@@ -227,8 +227,8 @@ public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements ISpuS
}
Spu spu = beanMapper.map(eDTO, Spu.class);
if (eDTO.getCommodityPass() == null || eDTO.getCommodityPass().equals(0) || eDTO.getCommodityPass().equals(2) || type.equals(6) ||
(eDTO.getSkuList().get(0) != null && eDTO.getSkuList().get(0).getNftSalesType() == 1)) {
spu.setId(one.getId());
if (eDTO.getCommodityPass() == null || eDTO.getCommodityPass().equals(0) || eDTO.getCommodityPass().equals(2) || (eDTO.getSkuList().get(0) != null && eDTO.getSkuList().get(0).getNftSalesType() == 1)) {
spu.setStatus(SpuStatusEnum.WAIT_CHECK.getStatus());
} else {
spu.setStatus(SpuStatusEnum.ISSUE.getStatus());
......@@ -248,11 +248,7 @@ public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements ISpuS
spu.setDefaultPrice((BigDecimal) (price.get("minPrice")));
}
UpdateWrapper<Spu> uw = new UpdateWrapper<>();
uw.lambda().eq(Spu::getGoodsId, goodsId);
if (!update(spu, uw)) {
throw new MyException(MallResponseError.UPDATE_ERROR);
}
updateById(spu);
}
@Override
......@@ -339,8 +335,10 @@ public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements ISpuS
} else if (type.equals(PACK.getType())) {
vo.setGoodsPackageVO(goodsPackageService.getByGoodsId(goodsId));
} else if (type.equals(NFT.getType())) {
if (spu.getCommodityPass() != 3) {
vo.setGoodsNftVO(nftService.getByGoodsId(goodsId));
}
}
return vo;
}
......
......@@ -3,6 +3,7 @@ package com.fzm.mall.server.admin.mq.consumer.goods_center;
import cn.fzm.chain.simplesdk.constant.TxStatusEnum;
import cn.fzm.chain.simplesdk.model.TxResult;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fzm.mall.server.admin.block_chain.util.ChainUtil;
import com.fzm.mall.server.admin.goods_center.enums.status.SpuStatusEnum;
import com.fzm.mall.server.admin.goods_center.model.GoodsSkuUsufruct;
......@@ -59,25 +60,37 @@ public class NftConsumer {
public void usuCoinsPrice(Map<String, Object> obj) {
try {
String goodsId = obj.get("goodsId") + "";
String hash = obj.get("hash") + "";
String[] hashs = (String[]) obj.get("hashs");
String prefix = obj.get("prefix") + "";
String nos = obj.get("nos") + "";
System.err.println("obj:" + obj);
int length = hashs.length;
//发行token
TxResult tr = chainUtil.cycleConfirmTxWithHash(hash);
for (int i = 0; i < length; i++) {
TxResult tr = chainUtil.cycleConfirmTxWithHash(hashs[i]);
log.info("map=========================" + tr.getStatus());
if (tr.getStatus() != TxStatusEnum.SUCCESS) {
log.error("NFT发行失败,交易HASH:{},失败原因:{}", hash, tr.getErrMsg());
log.error("NFT发行失败,交易HASH:{},失败原因:{}", hashs[i], tr.getErrMsg());
spuService.updateStatus(goodsId, SpuStatusEnum.FAIL.getStatus(), tr.getErrMsg().getValue());
// skuService.updateStatus(skuId, SkuStatusEnum.ISSUE_FAIL.getStatus(), tr.getErrMsg().getValue());
return;
} else {
if (i + 1 == length) {
LambdaQueryWrapper<GoodsSkuUsufruct> qw = new LambdaQueryWrapper<>();
qw.eq(GoodsSkuUsufruct::getPrefix, prefix);
GoodsSkuUsufruct usufruct = goodsSkuUsufructService.getOne(qw);
goodsSkuUsufructService.removeById(usufruct);
spuService.updateStatus(goodsId, SpuStatusEnum.WAIT_CHECK.getStatus(), "");
GoodsSkuUsufruct goodsSkuUsufruct = new GoodsSkuUsufruct();
goodsSkuUsufruct.setPrefix(prefix);
goodsSkuUsufruct.setSerialNo(nos.toString());
goodsSkuUsufructService.save(goodsSkuUsufruct);
}
}
}
} catch (Exception e) {
return;
}
......
......@@ -49,3 +49,7 @@ pay:
ali-pay-url:
we-chat-pay-url:
pay-in-chain: true
#唐拓服务ip端口
ly:
url: http://146.56.218.121:8081/open/nft/hash
\ No newline at end of file
......@@ -34,7 +34,7 @@
SELECT
G.goods_id,G.name,G.thumb,G.status,G.max_price,G.default_price,
M.enterprise_name,M.apply_name AS linkName,M.apply_phone AS linkPhone,G.check_fail_reason,G.type,
G.create_time
G.create_time,G.commodity_pass
FROM
goods_spu G
LEFT JOIN
......
......@@ -2488,3 +2488,15 @@ ALTER TABLE `goods_sku`
ALTER TABLE `external_token`
ADD COLUMN `hash` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '外部hash表';
ALTER TABLE `external_token`
ADD COLUMN `token_id` bigint(32) DEFAULT '0' COMMENT 'nft真实id';
ALTER TABLE `external_token`
ADD COLUMN `goods_type` int(32) DEFAULT '0' COMMENT '通证类型 0:FT(ERC20) 1:NFT(ERC721)';
ALTER TABLE `external_token`
ADD COLUMN `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '通证名称';
ALTER TABLE `external_token`
ADD COLUMN `publish_time` bigint(128) DEFAULT '0' COMMENT '发行时间';
ALTER TABLE `external_token`
ADD COLUMN `publisher` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '发行者';
ALTER TABLE `goods_spu` MODIFY `traceability_number` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '溯源编号';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment