You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

364 lines
9.1 KiB

package main
import (
"github.com/hyperledger/fabric-chaincode-go/shim"
"github.com/hyperledger/fabric-protos-go/peer"
"fmt"
"encoding/json"
"bytes"
)
type Education struct {
ObjectType string `json:"docType"`
Name string `json:"Name"` // 姓名
Gender string `json:"Gender"` // 性别
Nation string `json:"Nation"` // 民族
EntityID string `json:"EntityID"` // 身份证号
Place string `json:"Place"` // 籍贯
BirthDay string `json:"BirthDay"` // 出生日期
EnrollDate string `json:"EnrollDate"` // 入学日期
GraduationDate string `json:"GraduationDate"` // 毕(结)业日期
SchoolName string `json:"SchoolName"` // 学校名称
Major string `json:"Major"` // 专业
QuaType string `json:"QuaType"` // 学历类别
Length string `json:"Length"` // 学制
Mode string `json:"Mode"` // 学习形式
Level string `json:"Level"` // 层次
Graduation string `json:"Graduation"` // 毕(结)业
CertNo string `json:"CertNo"` // 证书编号
Photo string `json:"Photo"` // 照片
Historys []HistoryItem // 当前edu的历史记录
}
type HistoryItem struct {
TxId string
Education Education
}
type EducationChaincode struct {
}
func (t *EducationChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response{
fmt.Println(" ==== Init ====")
return shim.Success(nil)
}
func (t *EducationChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response{
// 获取用户意图
fun, args := stub.GetFunctionAndParameters()
if fun == "addEdu"{
return t.addEdu(stub, args) // 添加信息
}else if fun == "queryEduByCertNoAndName" {
return t.queryEduByCertNoAndName(stub, args) // 根据证书编号及姓名查询信息
}else if fun == "queryEduInfoByEntityID" {
return t.queryEduInfoByEntityID(stub, args) // 根据身份证号码及姓名查询详情
}else if fun == "updateEdu" {
return t.updateEdu(stub, args) // 根据证书编号更新信息
}else if fun == "delEdu"{
return t.delEdu(stub, args) // 根据证书编号删除信息
}
return shim.Error("指定的函数名称错误")
}
const DOC_TYPE = "eduObj"
// 保存edu
// args: education
func PutEdu(stub shim.ChaincodeStubInterface, edu Education) ([]byte, bool) {
edu.ObjectType = DOC_TYPE
b, err := json.Marshal(edu)
if err != nil {
return nil, false
}
// 保存edu状态
err = stub.PutState(edu.EntityID, b)
if err != nil {
return nil, false
}
return b, true
}
// 根据身份证号码查询信息状态
// args: entityID
func GetEduInfo(stub shim.ChaincodeStubInterface, entityID string) (Education, bool) {
var edu Education
// 根据身份证号码查询信息状态
b, err := stub.GetState(entityID)
if err != nil {
return edu, false
}
if b == nil {
return edu, false
}
// 对查询到的状态进行反序列化
err = json.Unmarshal(b, &edu)
if err != nil {
return edu, false
}
// 返回结果
return edu, true
}
// 根据指定的查询字符串实现富查询
func getEduByQueryString(stub shim.ChaincodeStubInterface, queryString string) ([]byte, error) {
resultsIterator, err := stub.GetQueryResult(queryString)
if err != nil {
return nil, err
}
defer resultsIterator.Close()
// buffer is a JSON array containing QueryRecords
var buffer bytes.Buffer
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
queryResponse, err := resultsIterator.Next()
if err != nil {
return nil, err
}
// Add a comma before array members, suppress it for the first array member
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
// Record is a JSON object, so we write as-is
buffer.WriteString(string(queryResponse.Value))
bArrayMemberAlreadyWritten = true
}
fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", buffer.String())
return buffer.Bytes(), nil
}
// 添加信息
// args: educationObject
// 身份证号为 key, Education 为 value
func (t *EducationChaincode) addEdu(stub shim.ChaincodeStubInterface, args []string) peer.Response {
if len(args) != 2{
return shim.Error("给定的参数个数不符合要求")
}
var edu Education
err := json.Unmarshal([]byte(args[0]), &edu)
if err != nil {
return shim.Error("反序列化信息时发生错误")
}
// 查重: 身份证号码必须唯一
_, exist := GetEduInfo(stub, edu.EntityID)
if exist {
return shim.Error("要添加的身份证号码已存在")
}
_, bl := PutEdu(stub, edu)
if !bl {
return shim.Error("保存信息时发生错误")
}
err = stub.SetEvent(args[1], []byte{})
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte("信息添加成功"))
}
// 根据证书编号及姓名查询信息
// args: CertNo, name
func (t *EducationChaincode) queryEduByCertNoAndName(stub shim.ChaincodeStubInterface, args []string) peer.Response {
if len(args) != 2 {
return shim.Error("给定的参数个数不符合要求")
}
CertNo := args[0]
name := args[1]
// 拼装CouchDB所需要的查询字符串(是标准的一个JSON串)
// queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"eduObj\", \"CertNo\":\"%s\"}}", CertNo)
queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"%s\", \"CertNo\":\"%s\", \"Name\":\"%s\"}}", DOC_TYPE, CertNo, name)
// 查询数据
result, err := getEduByQueryString(stub, queryString)
if err != nil {
return shim.Error("根据证书编号及姓名查询信息时发生错误")
}
if result == nil {
return shim.Error("根据指定的证书编号及姓名没有查询到相关的信息")
}
return shim.Success(result)
}
// 根据身份证号码查询详情(溯源)
// args: entityID
func (t *EducationChaincode) queryEduInfoByEntityID(stub shim.ChaincodeStubInterface, args []string) peer.Response {
if len(args) != 1 {
return shim.Error("给定的参数个数不符合要求")
}
// 根据身份证号码查询edu状态
b, err := stub.GetState(args[0])
if err != nil {
return shim.Error("根据身份证号码查询信息失败")
}
if b == nil {
return shim.Error("根据身份证号码没有查询到相关的信息")
}
// 对查询到的状态进行反序列化
var edu Education
err = json.Unmarshal(b, &edu)
if err != nil {
return shim.Error("反序列化edu信息失败")
}
// 获取历史变更数据
iterator, err := stub.GetHistoryForKey(edu.EntityID)
if err != nil {
return shim.Error("根据指定的身份证号码查询对应的历史变更数据失败")
}
defer iterator.Close()
// 迭代处理
var historys []HistoryItem
var hisEdu Education
for iterator.HasNext() {
hisData, err := iterator.Next()
if err != nil {
return shim.Error("获取edu的历史变更数据失败")
}
var historyItem HistoryItem
historyItem.TxId = hisData.TxId
json.Unmarshal(hisData.Value, &hisEdu)
if hisData.Value == nil {
var empty Education
historyItem.Education = empty
}else {
historyItem.Education = hisEdu
}
historys = append(historys, historyItem)
}
edu.Historys = historys
// 返回
result, err := json.Marshal(edu)
if err != nil {
return shim.Error("序列化edu信息时发生错误")
}
return shim.Success(result)
}
// 根据身份证号更新信息
// args: educationObject
func (t *EducationChaincode) updateEdu(stub shim.ChaincodeStubInterface, args []string) peer.Response {
if len(args) != 2{
return shim.Error("给定的参数个数不符合要求")
}
var info Education
err := json.Unmarshal([]byte(args[0]), &info)
if err != nil {
return shim.Error("反序列化edu信息失败")
}
// 根据身份证号码查询信息
result, bl := GetEduInfo(stub, info.EntityID)
if !bl{
return shim.Error("根据身份证号码查询信息时发生错误")
}
result.Name = info.Name
result.BirthDay = info.BirthDay
result.Nation = info.Nation
result.Gender = info.Gender
result.Place = info.Place
result.EntityID = info.EntityID
result.Photo = info.Photo
result.EnrollDate = info.EnrollDate
result.GraduationDate = info.GraduationDate
result.SchoolName = info.SchoolName
result.Major = info.Major
result.QuaType = info.QuaType
result.Length = info.Length
result.Mode = info.Mode
result.Level = info.Level
result.Graduation = info.Graduation
result.CertNo = info.CertNo;
_, bl = PutEdu(stub, result)
if !bl {
return shim.Error("保存信息信息时发生错误")
}
err = stub.SetEvent(args[1], []byte{})
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte("信息更新成功"))
}
// 根据身份证号删除信息(暂不提供)
// args: entityID
func (t *EducationChaincode) delEdu(stub shim.ChaincodeStubInterface, args []string) peer.Response {
if len(args) != 2{
return shim.Error("给定的参数个数不符合要求")
}
/*var edu Education
result, bl := GetEduInfo(stub, info.EntityID)
err := json.Unmarshal(result, &edu)
if err != nil {
return shim.Error("反序列化信息时发生错误")
}*/
err := stub.DelState(args[0])
if err != nil {
return shim.Error("删除信息时发生错误")
}
err = stub.SetEvent(args[1], []byte{})
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte("信息删除成功"))
}
func main(){
err := shim.Start(new(EducationChaincode))
if err != nil{
fmt.Printf("启动EducationChaincode时发生错误: %s", err)
}
}