最近学习webase-front的使用,基于springboot与vue写了一个简单的溯源管理平台。
合约基于官网提供的溯源合约Traceability,下面写了详细的注释
Goods合约
pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;
contract Goods{
struct TraceData{
//操作人地址
address addr; //Operator address
//商品状态
int16 status; //goods status
//操作时间
uint timestamp; //Operator time
//数据摘要
string remark; //Digested Data
}
//商品编号
uint64 _goodsId;
//当前商品状态
int16 _status; //current status
//存储追溯数据的数组
TraceData[] _traceData;
//定义状态改变事件
event newStatus( address addr, int16 status, uint timestamp, string remark);
//构造函数,默认调用此方法为增加商品
constructor(uint64 goodsId) public{
_goodsId = goodsId;
_traceData.push(TraceData({addr:tx.origin, status:0, timestamp:now, remark:"create"}));
emit newStatus(tx.origin, 0, now, "create");
}
//改变商品状态
function changeStatus(int16 goodsStatus, string memory remark) public {
_status = goodsStatus;
_traceData.push(TraceData({addr:tx.origin, status:goodsStatus, timestamp:now, remark:remark}));
emit newStatus(tx.origin, goodsStatus, now, remark);
}
//获取商品状态
function getStatus()public view returns(int16){
return _status;
}
//获取商品追溯信息
function getTraceInfo()public view returns(TraceData[] memory _data){
return _traceData;
}
}
Traceability合约
pragma solidity ^0.4.25;
import "./Goods.sol";
contract Traceability{
struct GoodsData{
Goods traceGoods;
bool valid;
}
bytes32 _category;
mapping(uint64=>GoodsData) private _goods;
constructor(bytes32 goodsTp) public {
_category = goodsTp;
}
event newGoodsEvent(uint64 goodsId);
function createGoods(uint64 goodsId) public returns(Goods){
require(!_goods[goodsId].valid, "is really exists");
_goods[goodsId].valid = true;
Goods traceGoods = new Goods(goodsId);
emit newGoodsEvent(goodsId);
_goods[goodsId].traceGoods = traceGoods;
return traceGoods;
}
function changeGoodsStatus(uint64 goodsId, int16 goodsStatus, string memory remark) public{
require(_goods[goodsId].valid, "not exists");
_goods[goodsId].traceGoods.changeStatus(goodsStatus, remark);
}
function getStatus(uint64 goodsId)public view returns(int16){
require(_goods[goodsId].valid, "not exists");
return _goods[goodsId].traceGoods.getStatus();
}
function getGoods(uint64 goodsId)public view returns(Goods){
require(_goods[goodsId].valid, "not exists");
return _goods[goodsId].traceGoods;
}
}
TraceabilityFactory合约
pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;
import "./Traceability.sol";
//本合约支持产品操作。包含产品类hash的创建,产品溯源创建,产品示例的创建,改变状态追踪,获取当前状态,获取溯源产品地址
contract TraceabilityFactory{
struct GoodsTrace{
Traceability trace;
bool valid;
}
// 声明映射,将货物类别与GoodsTrace结构体对应
mapping(bytes32=>GoodsTrace) private _goodsCategory;
//用于通知新的溯源商品类别已创建
event newTraceEvent(bytes32 goodsGroup);
//Create traceability commodity category
function createTraceability(bytes32 goodsGroup) public returns(Traceability) {
// 判断货物类别是否已经存在
require(!_goodsCategory[goodsGroup].valid,"The trademark already exists" );
// 创建Traceability合约实例
Traceability category = new Traceability(goodsGroup);
// 将货物类别标记为已验证
_goodsCategory[goodsGroup].valid = true;
// 将Traceability合约实例与货物类别进行对应
_goodsCategory[goodsGroup].trace = category;
// 触发newTraceEvent事件,通知新的溯源商品类别已创建
emit newTraceEvent(goodsGroup);
// 返回Traceability合约实例
return category;
}
// 根据所属产品组的goodsGroup,创建并初始化溯源合约,返回Traceability合约
function getTraceability(bytes32 goodsGroup) private view returns(Traceability) {
// 判断货物类别是否存在
require(_goodsCategory[goodsGroup].valid,"The trademark has not exists" );
// 返回Traceability合约实例
return _goodsCategory[goodsGroup].trace;
}
// 根据所属产品组的goodsGroup,以及当前产品ID,创建并初始化本产品,返回产品地址
function createTraceGoods(bytes32 goodsGroup, uint64 goodsId) public returns(Goods) {
// 获取对应货物类别的Traceability合约实例
Traceability category = getTraceability(goodsGroup);
// 调用Traceability合约中的createGoods函数创建溯源商品
return category.createGoods(goodsId);
}
//根据所属产品组的goodsGroup,以及当前产品ID,更改产品的状态,和当前标志
function changeTraceGoods(bytes32 goodsGroup, uint64 goodsId, int16 goodsStatus, string memory remark) public {
// 获取对应货物类别的Traceability合约实例
Traceability category = getTraceability(goodsGroup);
// 调用Traceability合约中的changeGoodsStatus函数更改商品状态
category.changeGoodsStatus(goodsId, goodsStatus, remark);
}
//根据所属产品组的goodsGroup,以及当前产品ID,获取当前产品的状态
function getStatus(bytes32 goodsGroup, uint64 goodsId) public view returns(int16) {
// 获取对应货物类别的Traceability合约实例
Traceability category = getTraceability(goodsGroup);
// 调用Traceability合约中的getStatus函数查询商品当前状态
return category.getStatus(goodsId);
}
// 根据所属产品组的goodsGroup,以及当前产品ID,获取当前产品的地址
function getTraceInfo(bytes32 goodsGroup, uint64 goodsId) public view returns(Goods) {
// 获取对应货物类别的Traceability合约实例
Traceability category = getTraceability(goodsGroup);
// 调用Traceability合约中的getGoods函数查询商品的整个溯源过程
return category.getGoods(goodsId);
}
//根据产品名创建产品组hash值,返回bytes32类型的goodsGroup
function getGoodsGroup(string memory name) public pure returns (bytes32) {
return keccak256(abi.encode(name));
}
}
这里展示一下页面的流程
新建一个商品类别,这里设置为苹果
创建类别成功的提示,这里我们已经创建的一个苹果的类别
页面的逻辑我设置成了创建类别会自动选择这个类别,所以我们创建成功后的当前类别就是苹果,我们输入1创建这个类别的id为1的商品。
在更新商品状态中,创建完id为1的商品也会自动选择到这个商品(ID:1)来,这里的1为status(状态,0为创建中,1为运输中,2为销售中),这里的话看合约规定或者按你自己想要的来改了,运输中就是remarks(备注)。
更新状态成功的提示
现在我们查询一下商品信息,查看ID为1的商品信息。可以看到已经成功记录我们的溯源信息。
这是很简单的示例,适合初学者。不过第一次弄可能确实有些困难,后端代码和前端代码太长了这里我就不放出来了,有需要的小伙伴可以私信我加我qq或者到我的咸鱼:夏沫mds,我也可以帮忙解答哦。