赞
踩
最近接触了Hyperledger Fabric,官网给的app并没有界面,不过有一个单页版的项目,在此基础上做出了一个简易的食品溯源项目
github项目地址
功能:
const middlewares = [ express.static(path.join(__dirname, 'public')),//静态文件 bodyParser.urlencoded({ extended: true }),//解析POST所传参数 cookieParser(),//使用Cookie来进行Flash文字演示 session({ secret: 'super-secret-key', key: 'super-secret-cookie', resave: false, saveUninitialized: false, cookie: { maxAge: 60000} }), flash() ] app.use(middlewares)//激活中间件 app.use(express.static(path.join(__dirname, 'views')));//使用模板 app.set('view engine', 'ejs');//配置模板引擎 require('./routes.js')(app);
app.get('/', function(req, res) {
tuna.index(req, res);
});
...
表单提交流程
填写表单->POST到特定的URL->处理表单信息->重定向到首页
表单的HTML代码编写
source-app/views/form.ejs
<form method="post" action="/re_form" novalidate> <div class="section">食品信息</div> <div class="inner-wrap"> <label>食品编号 <input type="text" name="field1" /></label> <label>食品名称 <input type="text" name="field1" /></label> <label>食品规格 <input type="text" name="field1" /></label> <label>食品生产日期 <input type="text" name="field1" /></label> <label>食品保质期 <input type="text" name="field1" /></label> <label>食品批次号 <input type="text" name="field1" /></label> <label>食品生产许可证编号<input type="text" name="field1" /></label> <label>食品生产商名称 <input type="text" name="field1" /></label> <label>食品生产价格<input type="text" name="field1" /></label> <label>食品生产所在地<input type="text" name="field1" /></label> </div> <div class="button-section"> <input type="submit" name="提交" /> </div> </form>
POST到特定的URL
source-app/routes.js
app.post('/re_form', function(req, res) {
var function_name = 'addProInfo'//调用chaincode中的函数
tuna.re_form(req, res, function_name);
});
表单处理
source-app/controller.js
const request = {
chaincodeId: 'source-app',
fcn: function_name,//调用chaincode中的函数
args: req.body.field1,//获取表单所填信息(函数所需参数)
chainId: 'mychannel',
txId: tx_id
};
调用Chaincode
chaincode/source-app/source-app.go
func (a *FoodChainCode) addProInfo(stub shim.ChaincodeStubInterface, args []string) pb.Response { var err error var FoodInfos FoodInfo if len(args)!=10{ return shim.Error("Incorrect number of arguments.") } FoodInfos.FoodID = args[0] if FoodInfos.FoodID == ""{ return shim.Error("FoodID can not be empty.") } FoodInfos.FoodProInfo.FoodName = args[1] FoodInfos.FoodProInfo.FoodSpec = args[2] FoodInfos.FoodProInfo.FoodMFGDate = args[3] FoodInfos.FoodProInfo.FoodEXPDate = args[4] FoodInfos.FoodProInfo.FoodLOT = args[5] FoodInfos.FoodProInfo.FoodQSID = args[6] FoodInfos.FoodProInfo.FoodMFRSName = args[7] FoodInfos.FoodProInfo.FoodProPrice = args[8] FoodInfos.FoodProInfo.FoodProPlace = args[9] ProInfosJSONasBytes,err := json.Marshal(FoodInfos) if err != nil{ return shim.Error(err.Error()) } err = stub.PutState(FoodInfos.FoodID,ProInfosJSONasBytes) if err != nil{ return shim.Error(err.Error()) } return shim.Success(nil) }
返回Json
source-app/routes.js
app.get('/source/:id', function(req, res) {
var function_name = 'getProInfo'//调用chaincode函数
tuna.get_tuna(req, res, function_name);
});
source-app/controller.js
const request = {
chaincodeId: 'source-app',
txId: tx_id,
fcn: function_name,//调用chaincode函数
args: [key]//函数所需参数
};
调用Chaincode
chaincode/source-app/source-app.go
func(a *FoodChainCode) getProInfo (stub shim.ChaincodeStubInterface,args []string) pb.Response{ if len(args) != 1{ return shim.Error("Incorrect number of arguments.") } FoodID := args[0] resultsIterator,err := stub.GetHistoryForKey(FoodID) if err != nil { return shim.Error(err.Error()) } defer resultsIterator.Close() var foodProInfo ProInfo for resultsIterator.HasNext(){ var FoodInfos FoodInfo response,err :=resultsIterator.Next() if err != nil { return shim.Error(err.Error()) } json.Unmarshal(response.Value,&FoodInfos) if FoodInfos.FoodProInfo.FoodName != ""{ foodProInfo = FoodInfos.FoodProInfo continue } } jsonsAsBytes,err := json.Marshal(foodProInfo)//转为Json格式 if err != nil { return shim.Error(err.Error()) } return shim.Success(jsonsAsBytes) }
例子
访问http://120.27.18.178:3389/source/1001,可以得到以下数据
{"FoodName":"苹果","FoodSpec":"123456","FoodMFGDate":"2018-8-27","FoodEXPDate":"一月","FoodLOT":"123","FoodQSID":"456","FoodMFRSName":"啦啦啦","FoodProPrice":"2","FoodProPlace":"郑州"}
source-app/views/search.ejs
<body ng-app="application" ng-controller="appController"> <div class="form-wrapper"> <input type="text" id="search" placeholder="食品编号..." ng-model="query_id" required> <input type="submit" value="搜索" id="submit" ng-click="querySource()"> </div> <table cellspacing="0" id="query_source"> <tr> <th>食品名称</th> <th>食品规格</th> <th>食品生产日期</th> <th>食品保质期</th> <th>食品批次号</th> <th>食品生产许可证编号</th> <th>食品生产商名称</th> <th>食品生产价格</th> <th>食品生产所在地</th> </tr> <tr> <td>{{query_source.FoodName}}</td> <td>{{query_source.FoodSpec}}</td> <td>{{query_source.FoodMFGDate}}</td> <td>{{query_source.FoodEXPDate}}</td> <td>{{query_source.FoodLOT}}</td> <td>{{query_source.FoodQSID}}</td> <td>{{query_source.FoodMFRSName}}</td> <td>{{query_source.FoodProPrice}}</td> <td>{{query_source.FoodProPlace}}</td> </tr> </table> </body>
AngularJs脚本编写
source-app/public/js/app.js
var app = angular.module('application', []); // Angular Controller app.controller('appController', function($scope, appFactory){ $("#success_holder").hide(); $("#success_create").hide(); $("#error_holder").hide(); $("#error_query").hide(); $scope.querySource = function(){ var id = $scope.query_id; appFactory.querySource(id, function(data){ $scope.query_source = data; if ($scope.query_tuna == "Could not locate tuna"){ console.log() $("#error_query").show(); } else{ $("#error_query").hide(); } }); } }); app.factory('appFactory', function($http){ var factory = {}; factory.querySource = function(id, callback){ $http.get('/source/'+id).success(function(output){ callback(output) }); } });
可以不用搞懂basic-network文件夹(我自己也不懂,不过并不影响写项目,如果读者懂,欢迎指导)
如果有什么不懂的地方或想搞懂更细节的地方,请在评论区留言
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。