基于fisco-bcos的共享病例智能合约的设计与实现【4】

本文详细介绍了如何使用fisco-bcos框架设计医院、科室和医生的智能合约,包括添加、删除和修改操作,以及RBAC(Role-BasedAccessControl)权限控制,以实现医院信息管理和医生科室绑定功能。
摘要由CSDN通过智能技术生成

环境

fisco-bcos 2.8
ubuntu 20
solidity 0.4.25[版本有点老,也可以用0.6的版本 ]

前言

大家可以阅读上篇对于这个系统的部分合约讲解
上一篇 基于fisco-bcos的共享病例智能合约的设计与实现【3】
这篇将介绍如何用RBAC合约结合医生合约,并且还需要介绍医院 和科室合约【因为医生需要和医院和科室进行绑定】。

重新梳理一下医生和医院科室的关系

在现实中,在每个医院里,都有不同的科室,每个科室也有不同的医生,所以医院和科室是一对多关系,科室和医生也是一对多关系。
所以写合约的时候我们需要考虑先后顺序的问题

科室合约

pragma solidity^0.4.25;

// 科室信息智能合约
// 对医院科室的增删改查
contract Department{

    string public DepartmentName;
    uint256 public Phone;
    string public Detail;
    

    address[] public doctorList;
    mapping(address=>bool) docktorMapping;
    

    // 医生管理员根据医院实际情况添加科室信息
    constructor(string _name,uint256 _phone,string _detail ) public{
        DepartmentName = _name;
        Phone = _phone;
        Detail = _detail;
   
    }
    
    
    function getDepartmentDetailByD() public view returns(string,uint256,string){
        return (DepartmentName,Phone,Detail);
    }
    
    function updateByDepartmentByD(string _name,uint256 _phone,string _detail){
        if(keccak256(abi.encode(_name)) != keccak256(abi.encode(""))){
                DepartmentName = _name;            
        }
        if(_phone !=0){
            Phone = _phone;    
        }
        if(keccak256(abi.encode(_detail)) != keccak256(abi.encode(""))){
              Detail  = _detail;        
          }
    }
    
    
    
    function addDoctorByD(address _doctor) public{
        doctorList.push(_doctor);
        docktorMapping[_doctor] = true;
    }
    
    function getDoctorListByD() public view returns(address[]){
        return doctorList;
    }
    
    function hasDoctorByD(address _doctor) public view returns(bool){
        return docktorMapping[_doctor];
    }
    
    function removeDoctorByD(address _doctor) public{
        docktorMapping[_doctor] = false;
        for(uint256 i = 0;i<doctorList.length;i++){
            if(_doctor == doctorList[i]){
                for(uint256 j = i;j<doctorList.length-1;j++){
                    doctorList[j] = doctorList[j+1];
                }
                doctorList.length--;
            }
        }
    }
    
}

科室合约里的变量里有 科室名,电话和科室简述,另外还有医生List和医生mapping,当医生添加到科室的时候,需要list 保存其医生地址, 至于mapping ,是方便由于验证医生是否在此科室里【如hasDoctorByD 方法】

医院合约

pragma solidity^0.4.25;

// 医院信息管理智能合约
//用于各个医院的信息登记

contract Hospital {
   uint256 public HospitalID;
   string public HospitalName;
   uint256  public Phone;
   string public Detail;
   
   address[] public departmentList;
   mapping(address=> bool) departmentMapping;
   
//   初始化医院相关信息,包括医院名称、咨询电话和简介 
    constructor(uint256 id,string _name,uint256 _phone,string _detail) public{
        HospitalID = id;
        HospitalName = _name;
        Phone = _phone;
        Detail = _detail;
    }
    
    
    function getHospitalDetialByH() public view returns(uint256,string,uint256,string){
        return (HospitalID,HospitalName,Phone,Detail);
    }
    
    function updateByHospitalMsgByH(string _name,uint256 _phone,string _detail) public {
        if (keccak256(abi.encode(_name)) != keccak256(abi.encode(""))){
            HospitalName = _name;
        }
        
        if(_phone != 0){
            Phone = _phone;
        }
        
        if(keccak256(abi.encode(_detail)) != keccak256(abi.encode(""))){
            Detail = _detail;
        }
    }
    
    
    
    
    function addDepartmentByH(address _department) public {
        departmentList.push(_department);
        departmentMapping[_department] = true;
    }
    
    function getDepartmentListByH() public view returns(address[]){
        return departmentList;
    }
    
    function hasDepartmentByH(address _department) public  view returns(bool){
        return departmentMapping[_department];
        
    }
    
    function removeDepartmentByH(address _department) public {
        departmentMapping[_department] = false;
        for(uint256 i = 0;i<departmentList.length;i++){
            if(_department == departmentList[i]){
                for(uint256 j = i;j<departmentList.length;j++){
                    departmentList[j] = departmentList[j+1];
                }
                departmentList.length--;
            }
        }
    }
      
}

医院合约里的变量里有 医院id,医院名,医院电话,医院描述 另外还有科室List和科室mapping,当科室添加到医院的时候,需要list 保存其科室地址, 至于mapping ,是方便由于验证科室是否在此医院里【如hasDepartmentByH 方法】

RBAC 合约 【医院部分】

现在看回RBAC 合约,上篇我们讲解了RBAC 合约怎么对病人合约进行操作,现在我们讲解RBAC 合约怎么操作医院

  
    // ----------------------------------医院---------------------------------------------------
    address[] public hospitalList;
    uint256 public hospitaIdAdd;
    mapping(string=>address)  hospitalMapping;
    mapping(address=>bool) hospitalMappingToBool;
    
    function createHospital(string memory _hName,uint256 _hPhone,string memory _hDetail) public onlyAdmin(msg.sender) returns(bool){
        // uint256 id,string _name,uint256 _phone,string _detail
        hospitaIdAdd++;
        Hospital hospital = new Hospital(hospitaIdAdd,_hName,_hPhone,_hDetail);
        hospitalMapping[_hName] = address(hospital);
        hospitalList.push(address(hospital));
        hospitalMappingToBool[address(hospital)] =true;
        return true;
    }
    
    
    function getHospitalList() public view returns(address[]){
        return hospitalList;
    }
    
    function searchHospital(string memory _hName) public view returns(uint256,string,uint256,string){
        address hospitalA = hospitalMapping[_hName] ;
   
        require(hospitalA!=address(0),"该医院不存在");
        Hospital    hospital  = Hospital(hospitalA);
        return    hospital.getHospitalDetialByH();
    }
    
    function getHospitalDetail(uint256 _hNumberByList) public view returns(address,uint256,string,uint256,string){
        address hospitalA =  hospitalList[_hNumberByList];
             require(hospitalA!=address(0),"该医院不存在");
         Hospital    hospital  = Hospital(hospitalA);
         
         uint256  id;
         string  memory name;
         uint256 phone;
         string memory detail;
         (id,name,phone,detail)  = hospital.getHospitalDetialByH();
         return (address(hospital),id,name,phone,detail);
    }
    
    
    function hasHospital(address _hospitalA) public view returns(bool){
        return hospitalMappingToBool[_hospitalA] ;
    }
    
    
    function updateByHospitalMsg(address _hospitalA,string _name,uint256 _phone,string _detail) public onlyAdmin(msg.sender)  returns(bool){
            require(hasHospital(_hospitalA),"该医院不存在");
             Hospital    hospital  = Hospital(_hospitalA);
             hospital.updateByHospitalMsgByH(_name,_phone,_detail);
             
             return true;
    }
    modifier onlyAdmin(address amount){
        require(amount ==admin,"Access Control:admin only");
        _;
    }

讲解一下上面代码用到的变量

  • address[] public hospitalList;
    用来将系统的医院存储起来

  • uint256 public hospitaIdAdd;
    这个是医院的自增id

  • mapping(string=>address) hospitalMapping;
    这个是医院名字与医院合约地址的映射,此可以作为搜索searchHospital功能,比如搜索名字可以返回医生信息

  • mapping(address=>bool) hospitalMappingToBool;
    这个是医院的状态证明,方便多个方法的 权限校验【需要验证医院是否存在,才能更好的进行操作】,如hasHospital

方法我就不多介绍了,都是增删改查,而onlyAdmin(msg.sender) ,这个msg.sender,就是之前说的部署合约那个人将会是管理员,只有管理员才能新建医院等方法使用。

RBAC合约【科室部分】

  // ----------------------------------科室---------------------------------------------------
   
    
    function addDepartment(address _hospitalA,string _name,uint256 _phone,string _detail) public onlyAdmin(msg.sender) returns(bool){
               require(hasHospital(_hospitalA),"该医院不存在");
         Hospital hospital = Hospital(_hospitalA);
         
         Department department = new Department(_name,_phone,_detail);
         hospital.addDepartmentByH(address(department));
         return true;
    }  
    
    function hasDepartment(address _hospitalA,address _departmentA) public view returns(bool){
               require(hasHospital(_hospitalA),"该医院不存在");
       Hospital hospital = Hospital(_hospitalA);
       return hospital.hasDepartmentByH(_departmentA);
        
    }
    
    
    function removeDepartment(address _hospitalA,address _departmentA) public onlyAdmin(msg.sender) returns(bool){
               require(hasHospital(_hospitalA),"该医院不存在");
        require(hasDepartment(_hospitalA,_departmentA),"该部门不存在");
        Hospital hospital = Hospital(_hospitalA);
        hospital.removeDepartmentByH(_departmentA);
        return true;
    }
    
    function updateByDepartment(address _hospitalA,address _departmentA,string _name,uint256 _phone,string _detail) public onlyAdmin(msg.sender) returns(bool){
       
        Department department = Department(_departmentA);
        department.updateByDepartmentByD(_name,_phone,_detail);
        
        return true;
    }
    
    function getDepartmentDetail(address _hospitalA,address _departmentA) public view returns(string,uint256,string){
        require(hasDepartment(_hospitalA,_departmentA),"该部门不存在");
        Department department = Department(_departmentA);
        return department.getDepartmentDetailByD();
    }
    
    
    function getDepartmentList(address _hospitalA) public view returns(address[]){
          require(hasHospital(_hospitalA),"该医院不存在");
          Hospital hospital =Hospital(_hospitalA);
          return hospital.getDepartmentListByH();
    }

科室的部分,因为是和医院有一对多的关系,所以在增删改的时候,都会与医院产生关系,并且还需要调用医院的方法,如 hospital.addDepartmentByH(address(department)); 就需要调用医院的addDepartmentByH 方法,将其科室加入其医院中

RBAC合约 【医生部分】

终于到了医生部分,医院科室都有了,接下来就是让医生加入到科室医院里

// ----------------------------------医生---------------------------------------------------
    
    event EventDoctorAdd(address role,address doctorA);
    
    function addDoctor(address _hospitalA,address _departmentA,string _dName,uint256 _phone,string _pTitle)  
       public  returns(bool){
        require(hasDepartment(_hospitalA,_departmentA),"该部门或者医院不存在");
        Doctor doctor = new Doctor(_dName,_phone,_pTitle);
        Department department = Department(_departmentA);
        department.addDoctorByD(address(doctor));
         addRole(msg.sender,"DO",address(doctor));
        emit EventDoctorAdd(msg.sender,address(doctor));
        return true;
    }
    
    function hasDoctor(address _hospitalA,address _departmentA,address _doctorA) public view returns(bool){
        require(hasDepartment(_hospitalA,_departmentA),"该部门或者医院不存在");
       Department department = Department(_departmentA);
       return department.hasDoctorByD(_doctorA);
    }
    
   function removeDoctor(string _role,address _hospitalA,address _departmentA)   public  onlyDoctor(msg.sender) returns(bool){
         require(hasDepartment(_hospitalA,_departmentA),"该部门或者医院不存在");
         address _doctorA = roles[_role].getRoleDetail(msg.sender);
       Department department = Department(_departmentA);
       department.removeDoctorByD(_doctorA);
       removeRole(msg.sender,"DO");
       
       return true;
   }
   
   
   
// 工具类,获取该医生的合约地址
    function getDoctorAddress() public view onlyDoctor(tx.origin) returns(address){
          return roles["DO"].getRoleDetail(tx.origin);
    }
   
//   获取医生细节  需要变换
     function getDocotrDetail(string _role,address amount ) public onlyDoctor(amount)  view returns(string,uint256,string,uint256,uint8,uint256){
          
        address _doctorA = roles[_role].getRoleDetail(amount);
          Doctor doctor = Doctor(_doctorA);
          return doctor.getDoctorDetailByD();
     }
     
     
     //   获取医生细节  需要变换
     function getDocotrDetail2(address amount ) public   view returns(string,uint256,string,uint256,uint8,uint256){
          Doctor doctor = Doctor(amount);
          return doctor.getDoctorDetailByD();
     }
// 获取医生列表
    function getDoctorList(address _hospitalA,address _departmentA) public view returns(address[]){
            require(hasDepartment(_hospitalA,_departmentA),"该部门不存在");
               Department department = Department(_departmentA);
        return department.getDoctorListByD();
            
    }
// 更新医生数据
    function updateDoctorMsg(string _role,string _name,uint256 _phone,string _pTitle,uint256 _age,uint8 _gendor)  public onlyDoctor(msg.sender) returns(bool){
        
        
            address _doctorA = roles[_role].getRoleDetail(msg.sender);
            
          Doctor doctor = Doctor(_doctorA);
          doctor.updateDoctorDetailByD(_name,_phone,_pTitle,_age,_gendor);
          return true;
    }

除了需要将其加入到roles 里面,还需要将其加入到科室医院里

     require(hasDepartment(_hospitalA,_departmentA),"该部门或者医院不存在");//判断科室医院是否存在
        Doctor doctor = new Doctor(_dName,_phone,_pTitle); //生成医生合约地址
        Department department = Department(_departmentA);//  根据地址还原科室对象,
        department.addDoctorByD(address(doctor));  //调用添加医院方法
         addRole(msg.sender,"DO",address(doctor));// 增加医生到roles 里面,角色标识为 DO

其他方法就不解释了,大家自行阅读

结语

RBAC 合约已经讲解完毕,对于医生,医院,科室和病人的各种操作增删改查,基本体现在RBAC合约,接下来将讲解最后部署的合约 SyStem,它需要集成这个RBAC合约,在SyStem合约,医生和病人可以进行操作预约挂号,接诊,填写病历等操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

已久依依

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值