Browse Source

feat:画像

zhangxinlei1996 3 năm trước cách đây
mục cha
commit
2f6369eb2d

+ 1 - 0
api/medical/etc/medical-api.yaml

@@ -12,3 +12,4 @@ Gateway:
   ServerCode: medical
   Etcd:
     - 127.0.0.1:2379
+Timeout:  5000

+ 28 - 0
api/medical/internal/handler/institution/getnewmsglisthandler.go

@@ -0,0 +1,28 @@
+package institution
+
+import (
+	"net/http"
+
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/api/medical/internal/logic/institution"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/api/medical/internal/svc"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/api/medical/internal/types"
+	"github.com/zeromicro/go-zero/rest/httpx"
+)
+
+func GetNewMsgListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.GetNewMsgListReq
+		if err := httpx.Parse(r, &req); err != nil {
+			httpx.Error(w, err)
+			return
+		}
+
+		l := institution.NewGetNewMsgListLogic(r.Context(), svcCtx)
+		resp, err := l.GetNewMsgList(&req)
+		if err != nil {
+			httpx.Error(w, err)
+		} else {
+			httpx.OkJson(w, resp)
+		}
+	}
+}

+ 5 - 0
api/medical/internal/handler/routes.go

@@ -36,6 +36,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 				Path:    "/claim/institution",
 				Handler: institution.ClaimInstitutionHandler(serverCtx),
 			},
+			{
+				Method:  http.MethodPost,
+				Path:    "/portrait/getNewMsgList",
+				Handler: institution.GetNewMsgListHandler(serverCtx),
+			},
 		},
 		rest.WithPrefix("/domain"),
 	)

+ 47 - 0
api/medical/internal/logic/institution/getnewmsglistlogic.go

@@ -0,0 +1,47 @@
+package institution
+
+import (
+	"context"
+	"fmt"
+
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/rpc/medical/medical"
+
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/api/medical/internal/svc"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/api/medical/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetNewMsgListLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewGetNewMsgListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetNewMsgListLogic {
+	return &GetNewMsgListLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx,
+	}
+}
+
+func (l *GetNewMsgListLogic) GetNewMsgList(req *types.GetNewMsgListReq) (resp *types.CommonRes, err error) {
+	// todo: add your logic here and delete this line
+	resp = &types.CommonRes{}
+	ret, err := l.svcCtx.Medical.GetNewMsg(l.ctx, &medical.GetNewMsgReq{
+		CompanyName: req.CompanyName,
+		PageNum:     req.PageNum,
+		PageSize:    req.PageSize,
+	})
+	if err != nil || ret == nil {
+		l.Error(fmt.Sprintf("%+v", req), resp.Error_msg)
+		resp.Error_code, resp.Error_msg = -1, "查看失败"
+	} else {
+		resp.Data = map[string]interface{}{
+			"count": ret.Count,
+			"list":  ret.List,
+		}
+	}
+	return
+}

+ 32 - 1
api/medical/internal/logic/institution/portraitinstitutionlogic.go

@@ -2,9 +2,11 @@ package institution
 
 import (
 	"context"
+	"fmt"
 
 	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/api/medical/internal/svc"
 	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/api/medical/internal/types"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/rpc/medical/medical"
 
 	"github.com/zeromicro/go-zero/core/logx"
 )
@@ -23,8 +25,37 @@ func NewPortraitInstitutionLogic(ctx context.Context, svcCtx *svc.ServiceContext
 	}
 }
 
+// 医疗机构画像-医院信息
 func (l *PortraitInstitutionLogic) PortraitInstitution(req *types.PortraitReq) (resp *types.CommonRes, err error) {
 	// todo: add your logic here and delete this line
-
+	resp = &types.CommonRes{}
+	ret, err := l.svcCtx.Medical.Portrait(l.ctx, &medical.PortraitReq{
+		AppId:     req.AppId,
+		CompanyId: req.CompanyId,
+		UserId:    int64(req.UserId),
+	})
+	if err != nil || ret == nil {
+		l.Error(fmt.Sprintf("%+v", req), resp.Error_msg)
+		resp.Error_code, resp.Error_msg = -1, "查看失败"
+	} else {
+		resp.Data = map[string]interface{}{
+			"beds":           ret.Beds,
+			"visit_perday":   ret.VisitPerday,
+			"doctorsnum":     ret.Doctorsnum,
+			"address":        ret.Address,
+			"website":        ret.Website,
+			"area":           ret.Area,
+			"city":           ret.City,
+			"district":       ret.District,
+			"business_type":  ret.BusinessType,
+			"level":          ret.Level,
+			"mi_type":        ret.MiType,
+			"equipment":      ret.Equipment,
+			"departnames":    ret.Departnames,
+			"follow":         ret.Follow,
+			"company_name":   ret.CompanyName,
+			"establish_date": ret.EstablishDate,
+		}
+	}
 	return
 }

+ 11 - 1
api/medical/internal/types/types.go

@@ -39,7 +39,9 @@ type SearchDistributorReq struct {
 }
 
 type PortraitReq struct {
-	CompanyId string `json:"company_id"` // 机构唯一标识
+	CompanyId string `json:"company_id"`           // 机构唯一标识
+	UserId    int    `header:"newUserId,optional"` //session中的用户base_user_id
+	AppId     string `header:"appId,default=10000"`
 }
 
 type ClaimInstitutionReq struct {
@@ -80,6 +82,14 @@ type IsClaimedReq struct {
 	Type      int    `json:"type"`        // 1 医疗机构 2 经销商
 }
 
+type GetNewMsgListReq struct {
+	CompanyName string `json:"companyName"`          // 机构唯一标识
+	UserId      int    `header:"newUserId,optional"` //session中的用户base_user_id
+	AppId       string `header:"appId,default=10000"`
+	PageSize    int64  `json:"pageSize"`
+	PageNum     int64  `json:"pageNum"`
+}
+
 type UserInfoReq struct {
 	Name          string `json:"name"`             // 姓名
 	Phone         string `json:"phone"`            // 手机号

+ 14 - 1
api/medical/medical.api

@@ -37,7 +37,9 @@ type SearchDistributorReq {
 
 // 获取机构信息请求
 type PortraitReq {
-	CompanyId string `json:"company_id"` // 机构唯一标识
+	CompanyId string `json:"company_id"`           // 机构唯一标识
+	UserId    int    `header:"newUserId,optional"` //session中的用户base_user_id
+	AppId     string `header:"appId,default=10000"`
 }
 // 我认领的医疗机构请求
 type ClaimInstitutionReq {
@@ -82,6 +84,15 @@ type IsClaimedReq {
 	CompanyId string `json:"company_id"`  // 机构id
 	Type      int    `json:"type"`        // 1 医疗机构 2 经销商
 }
+
+// 获取机构信息请求
+type GetNewMsgListReq {
+	CompanyName string `json:"companyName"`          // 机构唯一标识
+	UserId      int    `header:"newUserId,optional"` //session中的用户base_user_id
+	AppId       string `header:"appId,default=10000"`
+	PageSize    int64  `json:"pageSize"`
+	PageNum     int64  `json:"pageNum"`
+}
 // 医疗机构
 @server(
 	group : institution
@@ -96,6 +107,8 @@ service medical-api {
 	post /portrait/institution (PortraitReq) returns (CommonRes); 	// 医疗机构画像-医院信息 不确定是否需要
 	@handler claimInstitution
 	post /claim/institution (ClaimInstitutionReq) returns (CommonRes); 	    // 我关注的医疗机构
+	@handler getNewMsgList
+	post /portrait/getNewMsgList(GetNewMsgListReq)returns(CommonRes);	//医疗机构画像标讯信息
 }
 
 // 经销商

BIN
api/medical/medical.exe


+ 1 - 0
entity/coverage

@@ -0,0 +1 @@
+mode: set

+ 7 - 4
entity/db.go

@@ -12,6 +12,7 @@ type MysqlMainStruct struct {
 	MaxOpenConns int    `json:"maxOpenConns"`
 	MaxIdleConns int    `json:"maxIdleConns"`
 }
+
 type EsStruct struct {
 	Addr  string `json:"addr"`
 	Size  int    `json:"size"`
@@ -20,11 +21,13 @@ type EsStruct struct {
 }
 
 var (
-	Mysql     *mysql.Mysql
-	BaseMysql *mysql.Mysql
+	Mysql       *mysql.Mysql
+	BaseMysql   *mysql.Mysql
+	CommonMysql *mysql.Mysql
 )
 
 type Conn struct {
-	Mysql     *mysql.Mysql
-	BaseMysql *mysql.Mysql
+	Mysql       *mysql.Mysql
+	BaseMysql   *mysql.Mysql
+	CommonMysql *mysql.Mysql
 }

+ 51 - 0
entity/portrait.go

@@ -0,0 +1,51 @@
+package entity
+
+const (
+	Institution_baseinfo   = "institution_baseinfo"   //机构信息表
+	Institution_department = "institution_department" //机构科室表
+	Code_level             = "code_level"             //医院等级表
+	Code_type              = "code_type"              //医疗类型表
+	Code_sdleveltypeequip  = "code_sdleveltypeequip"  //医疗器械表
+	Code_area              = "code_area"              //地区表
+	Domain_ent_claim       = "domain_ent_claim"
+
+	BidField = "0101"
+
+	NO_DATA_ERROR_MSG = "暂无数据"
+
+	NewMustSearch   = `{"query":{"bool":{"must":[%s]}}%s}`
+	ListSearchLimit = `,"_source":[%s],"sort":[{"%s":{"order":"desc"}}],"from":%d,"size":%d`
+
+	BiddingIndex, BiddingType        = "bidding", "bidding"
+	TableShowNumLimit                = 40
+	DataExportBatchSearchLimit int64 = 500
+)
+
+//医疗机构画像
+type PortraitInfo struct {
+	Beds          int64  //床位数
+	VisitPerday   int64  // 门诊量/日
+	Doctorsnum    int64  //医生人数
+	Address       string //医疗机构地址
+	Website       string //医疗机构网站
+	Area          string //区域省份
+	City          string //城市
+	District      string //区县
+	BusinessType  int64  //医疗机构经营方式(0:公立、1:民营、2:其它)
+	Level         string //医疗机构等级
+	MiType        string //医疗机构类型
+	Equipment     string //医院设备
+	Departnames   string //医院科室
+	Follow        int64  //是否关注 0-未关注 1已关注
+	CompanyName   string //医疗机构名称
+	EstablishDate string //成立日期
+}
+
+//医疗画像-招标动态
+type GetNewMsgList struct {
+	Area      string //地区
+	Bidstatus string //信息类型
+	Firsttime int64  //时间
+	Id        string //加密信息id
+	Title     string //标题
+}

+ 14 - 6
rpc/medical/etc/medical.yaml

@@ -5,21 +5,29 @@ Etcd:
   - 127.0.0.1:2379
   Key: medical.rpc
 MysqlMain:
-  dbName: field_medical_data
+  dbName: medical_fileld_data
   address: 192.168.3.217:4000
   userName: root
-  passWord: =PDT49#80Z!RVv52_z
+  passWord: '=PDT49#80Z!RVv52_z'
   maxOpenConns: 5
   maxIdleConns: 5
 BaseMysqlMain:
   dbName: base_service
   address: 192.168.3.217:4000
   userName: root
-  passWord: =PDT49#80Z!RVv52_z
+  passWord: '=PDT49#80Z!RVv52_z'
+  maxOpenConns: 5
+  maxIdleConns: 5
+MysqlCommon:
+  dbName: global_common_data
+  address: 192.168.3.217:4000
+  userName: root
+  passWord: '=PDT49#80Z!RVv52_z'
   maxOpenConns: 5
   maxIdleConns: 5
 Es:
-  addr: http://192.168.3.204:1500
+  addr: http://192.168.3.206:9800
   size: 5
-  index: smart_new
-  type: smart
+  index: bidding
+  type: bidding
+Timeout:  5000

+ 43 - 24
rpc/medical/init/init.go

@@ -1,14 +1,15 @@
 package init
 
 import (
+	"flag"
+	"log"
+
+	elastic "app.yhyue.com/moapp/jybase/esv1"
 	"app.yhyue.com/moapp/jybase/mysql"
 	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/entity"
 	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/rpc/medical/internal/config"
-	"flag"
-	"fmt"
 	_ "github.com/go-sql-driver/mysql"
 	"github.com/zeromicro/go-zero/core/conf"
-	"log"
 )
 
 var configF = flag.String("ff", "etc/medical.yaml", "the config file")
@@ -33,6 +34,9 @@ func init() {
 			MaxIdleConns: mm.MaxIdleConns,
 		}
 		entity.Mysql.Init()
+		//medical_fileld_data
+		qwe := entity.Mysql.SelectBySql("select * from code_level limit 1")
+		log.Println("~~~~", qwe)
 	}
 	nn := C.BaseMysqlMain
 	if nn.Address != "" {
@@ -46,28 +50,43 @@ func init() {
 			MaxIdleConns: nn.MaxIdleConns,
 		}
 		entity.BaseMysql.Init()
+		qwe := entity.BaseMysql.SelectBySql("select * from appointment limit 1")
+		log.Println("~~~~", qwe)
 	}
 
-	fmt.Println()
+	if C.MysqlCommon.Address != "" {
+		log.Println("--初始化 mysql--")
+		entity.CommonMysql = &mysql.Mysql{
+			Address:      C.MysqlCommon.Address,
+			UserName:     C.MysqlCommon.UserName,
+			PassWord:     C.MysqlCommon.PassWord,
+			DBName:       C.MysqlCommon.DbName,
+			MaxOpenConns: C.MysqlCommon.MaxOpenConns,
+			MaxIdleConns: C.MysqlCommon.MaxIdleConns,
+		}
+		entity.CommonMysql.Init()
+		qwe := entity.CommonMysql.SelectBySql("select * from code_area limit 1")
+		log.Println("~~~~", qwe)
+	}
 	//初始化 elasticsearch
-	//es := C.Es
-	//if es.Addr != "" {
-	//	log.Println("--初始化 elasticsearch--")
-	//	log.Println(es.Addr, es.Size)
-	//	elastic.InitElasticSize(es.Addr, es.Size)
-	//
-	//	//初始化日志信息
-	//	conf.MustLoad(*logFile, &logc)
-	//	if len(logc.Level) > 0 {
-	//		for _, v := range logc.Level {
-	//			logx.MustSetup(logx.LogConf{
-	//				Mode:     logc.Mode,
-	//				Path:     logc.Path,
-	//				Level:    v,
-	//				KeepDays: logc.KeepDays,
-	//			})
-	//			logx.Info(v, "--日志记录")
-	//		}
-	//	}
-	//}
+	es := C.Es
+	if es.Addr != "" {
+		log.Println("--初始化 elasticsearch--")
+		log.Println(es.Addr, es.Size)
+		elastic.InitElasticSize(es.Addr, es.Size)
+
+		// //初始化日志信息
+		// conf.MustLoad(*logFile, &logc)
+		// if len(logc.Level) > 0 {
+		// 	for _, v := range logc.Level {
+		// 		logx.MustSetup(logx.LogConf{
+		// 			Mode:     logc.Mode,
+		// 			Path:     logc.Path,
+		// 			Level:    v,
+		// 			KeepDays: logc.KeepDays,
+		// 		})
+		// 		logx.Info(v, "--日志记录")
+		// 	}
+		// }
+	}
 }

+ 2 - 1
rpc/medical/internal/config/config.go

@@ -9,5 +9,6 @@ type Config struct {
 	zrpc.RpcServerConf
 	MysqlMain     entity.MysqlMainStruct
 	BaseMysqlMain entity.MysqlMainStruct
-	//Es            entity.EsStruct
+	Es            entity.EsStruct
+	MysqlCommon   entity.MysqlMainStruct
 }

+ 56 - 0
rpc/medical/internal/logic/getnewmsglogic.go

@@ -0,0 +1,56 @@
+package logic
+
+import (
+	"context"
+	"fmt"
+
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/entity"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/rpc/medical/internal/svc"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/rpc/medical/medical"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type GetNewMsgLogic struct {
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+	logx.Logger
+}
+
+func NewGetNewMsgLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetNewMsgLogic {
+	return &GetNewMsgLogic{
+		ctx:    ctx,
+		svcCtx: svcCtx,
+		Logger: logx.WithContext(ctx),
+	}
+}
+
+//  招标动态
+func (l *GetNewMsgLogic) GetNewMsg(in *medical.GetNewMsgReq) (*medical.GetNewMsgResp, error) {
+	resp := &medical.GetNewMsgResp{}
+	portrait := service.NewPortrait(&entity.Conn{
+		Mysql:       entity.Mysql,
+		BaseMysql:   entity.BaseMysql,
+		CommonMysql: entity.CommonMysql,
+	})
+	info, count, err := portrait.List(in.CompanyName, in.PageSize, in.PageNum)
+	if err != nil || info == nil {
+		l.Error(fmt.Sprintf("%+v", in), err.Error())
+		resp.ErrorMsg = err.Error()
+		resp.ErrorCode = -1
+	} else {
+		resp.Count = count
+		for _, v := range *info {
+			resp.List = append(resp.List, &medical.NewMsgList{
+				Area:      v.Area,
+				Bidstatus: v.Bidstatus,
+				Firsttime: v.Firsttime,
+				Id:        v.Id,
+				Title:     v.Title,
+			})
+		}
+	}
+
+	return resp, nil
+}

+ 33 - 1
rpc/medical/internal/logic/portraitlogic.go

@@ -2,9 +2,12 @@ package logic
 
 import (
 	"context"
+	"fmt"
 
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/entity"
 	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/rpc/medical/internal/svc"
 	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/rpc/medical/medical"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service"
 
 	"github.com/zeromicro/go-zero/core/logx"
 )
@@ -26,6 +29,35 @@ func NewPortraitLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Portrait
 // 医疗机构画像
 func (l *PortraitLogic) Portrait(in *medical.PortraitReq) (*medical.PortraitResp, error) {
 	// todo: add your logic here and delete this line
+	resp := &medical.PortraitResp{}
+	portrait := service.NewPortrait(&entity.Conn{
+		Mysql:       entity.Mysql,
+		BaseMysql:   entity.BaseMysql,
+		CommonMysql: entity.CommonMysql,
+	})
+	info, err := portrait.Info(in.CompanyId, in.UserId)
+	if err != nil || info == nil {
+		l.Error(fmt.Sprintf("%+v", in), err.Error())
+		resp.ErrorMsg = err.Error()
+		resp.ErrorCode = -1
+	} else {
+		resp.Address = info.Address
+		resp.Area = info.Area
+		resp.Beds = info.Beds
+		resp.BusinessType = info.BusinessType
+		resp.CompanyName = info.CompanyName
+		resp.Departnames = info.Departnames
+		resp.Doctorsnum = info.Doctorsnum
+		resp.Equipment = info.Equipment
+		resp.EstablishDate = info.EstablishDate
+		resp.Follow = info.Follow
+		resp.Level = info.Level
+		resp.MiType = info.MiType
+		resp.VisitPerday = info.VisitPerday
+		resp.Website = info.Website
+		resp.City = info.City
+		resp.District = info.District
+	}
 
-	return &medical.PortraitResp{}, nil
+	return resp, nil
 }

+ 6 - 0
rpc/medical/internal/server/medicalserver.go

@@ -87,3 +87,9 @@ func (s *MedicalServer) ClaimedInstitutionList(ctx context.Context, in *medical.
 	l := logic.NewClaimedInstitutionListLogic(ctx, s.svcCtx)
 	return l.ClaimedInstitutionList(in)
 }
+
+//  招标动态
+func (s *MedicalServer) GetNewMsg(ctx context.Context, in *medical.GetNewMsgReq) (*medical.GetNewMsgResp, error) {
+	l := logic.NewGetNewMsgLogic(ctx, s.svcCtx)
+	return l.GetNewMsg(in)
+}

BIN
rpc/medical/medical.exe


BIN
rpc/medical/medical.exe~


+ 35 - 1
rpc/medical/medical.proto

@@ -112,6 +112,7 @@ message UserInfoResp{
 message PortraitReq{
 	string appId =1;
 	string companyId =2;
+	int64 userId=3;
 }
 //医疗机构画像出参
 message PortraitResp{
@@ -120,7 +121,7 @@ message PortraitResp{
 	int64 doctorsnum=3;//医生人数
 	string address=4; //医疗机构地址
 	string website=5; //医疗机构网站
-	string area=6; //区域
+	string area=6; //
 	int64 business_type=7; //医疗机构经营方式(0:公立、1:民营、2:其它)
 	string level=8; //医疗机构等级
 	string miType=9; //医疗机构类型
@@ -129,6 +130,10 @@ message PortraitResp{
 	int64 follow=12; //是否关注 0-未关注 1已关注
 	string companyName=13;//医疗机构名称
 	string establish_date=14;//成立日期
+	string error_msg =15;
+	int64 error_code=16;
+	string city=17;//城市
+	string district=18;//区县
 }
 // 认领
 message ClaimReq{
@@ -162,6 +167,33 @@ message ClaimedReq{
   int64  Page = 3; // 认领记录id
   int64 PageSize = 4 ;//appid
 }
+
+//医疗机构画像招标动态入参
+message GetNewMsgReq{
+	string companyName =1;//机构名称
+	int64 pageNum=2;//页码
+	int64 pageSize=3;//条数
+}
+
+//医疗机构画像招标动态出参数
+message GetNewMsgResp{
+	repeated NewMsgList list=1; //招标动态
+	int64 count =2;//招标动态数量
+	string error_msg =3;
+	int64 error_code=4;
+}
+
+//招标动态列表
+message NewMsgList{
+	string area =1;//地区
+	string bidstatus =2;//信息类型
+	string bidamount=3;//金额
+	int64 firsttime=4;//时间
+	string id =5;//加密信息id
+	string title=6;//标题
+	repeated string winner=7;//中标单位
+}
+
 service Medical {
       //搜索医疗机构
       rpc Institution(SearchInstitutionReq) returns(CompanyResp);
@@ -185,4 +217,6 @@ service Medical {
       rpc ClaimedDistributorList(ClaimedReq) returns(CommonResp);
       // 我认领的医疗机构列表
       rpc ClaimedInstitutionList(ClaimedReq) returns(CommonResp);
+      // 招标动态
+      rpc GetNewMsg(GetNewMsgReq) returns (GetNewMsgResp);
 }

+ 8 - 0
rpc/medical/medical/medical.go

@@ -34,6 +34,8 @@ type (
 		ClaimedDistributorList(ctx context.Context, in *ClaimedReq, opts ...grpc.CallOption) (*CommonResp, error)
 		//  我认领的医疗机构列表
 		ClaimedInstitutionList(ctx context.Context, in *ClaimedReq, opts ...grpc.CallOption) (*CommonResp, error)
+		//  招标动态
+		GetNewMsg(ctx context.Context, in *GetNewMsgReq, opts ...grpc.CallOption) (*GetNewMsgResp, error)
 	}
 
 	defaultMedical struct {
@@ -112,3 +114,9 @@ func (m *defaultMedical) ClaimedInstitutionList(ctx context.Context, in *Claimed
 	client := NewMedicalClient(m.cli.Conn())
 	return client.ClaimedInstitutionList(ctx, in, opts...)
 }
+
+//  招标动态
+func (m *defaultMedical) GetNewMsg(ctx context.Context, in *GetNewMsgReq, opts ...grpc.CallOption) (*GetNewMsgResp, error) {
+	client := NewMedicalClient(m.cli.Conn())
+	return client.GetNewMsg(ctx, in, opts...)
+}

+ 485 - 132
rpc/medical/medical/medical.pb.go

@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.28.0
-// 	protoc        v3.15.1
+// 	protoc-gen-go v1.27.1
+// 	protoc        v3.19.4
 // source: medical.proto
 
 package medical
@@ -1168,6 +1168,7 @@ type PortraitReq struct {
 
 	AppId     string `protobuf:"bytes,1,opt,name=appId,proto3" json:"appId,omitempty"`
 	CompanyId string `protobuf:"bytes,2,opt,name=companyId,proto3" json:"companyId,omitempty"`
+	UserId    int64  `protobuf:"varint,3,opt,name=userId,proto3" json:"userId,omitempty"`
 }
 
 func (x *PortraitReq) Reset() {
@@ -1216,6 +1217,13 @@ func (x *PortraitReq) GetCompanyId() string {
 	return ""
 }
 
+func (x *PortraitReq) GetUserId() int64 {
+	if x != nil {
+		return x.UserId
+	}
+	return 0
+}
+
 //医疗机构画像出参
 type PortraitResp struct {
 	state         protoimpl.MessageState
@@ -1227,7 +1235,7 @@ type PortraitResp struct {
 	Doctorsnum    int64  `protobuf:"varint,3,opt,name=doctorsnum,proto3" json:"doctorsnum,omitempty"`                            //医生人数
 	Address       string `protobuf:"bytes,4,opt,name=address,proto3" json:"address,omitempty"`                                   //医疗机构地址
 	Website       string `protobuf:"bytes,5,opt,name=website,proto3" json:"website,omitempty"`                                   //医疗机构网站
-	Area          string `protobuf:"bytes,6,opt,name=area,proto3" json:"area,omitempty"`                                         //区域
+	Area          string `protobuf:"bytes,6,opt,name=area,proto3" json:"area,omitempty"`                                         //
 	BusinessType  int64  `protobuf:"varint,7,opt,name=business_type,json=businessType,proto3" json:"business_type,omitempty"`    //医疗机构经营方式(0:公立、1:民营、2:其它)
 	Level         string `protobuf:"bytes,8,opt,name=level,proto3" json:"level,omitempty"`                                       //医疗机构等级
 	MiType        string `protobuf:"bytes,9,opt,name=miType,proto3" json:"miType,omitempty"`                                     //医疗机构类型
@@ -1236,6 +1244,10 @@ type PortraitResp struct {
 	Follow        int64  `protobuf:"varint,12,opt,name=follow,proto3" json:"follow,omitempty"`                                   //是否关注 0-未关注 1已关注
 	CompanyName   string `protobuf:"bytes,13,opt,name=companyName,proto3" json:"companyName,omitempty"`                          //医疗机构名称
 	EstablishDate string `protobuf:"bytes,14,opt,name=establish_date,json=establishDate,proto3" json:"establish_date,omitempty"` //成立日期
+	ErrorMsg      string `protobuf:"bytes,15,opt,name=error_msg,json=errorMsg,proto3" json:"error_msg,omitempty"`
+	ErrorCode     int64  `protobuf:"varint,16,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"`
+	City          string `protobuf:"bytes,17,opt,name=city,proto3" json:"city,omitempty"`         //城市
+	District      string `protobuf:"bytes,18,opt,name=district,proto3" json:"district,omitempty"` //区县
 }
 
 func (x *PortraitResp) Reset() {
@@ -1368,6 +1380,34 @@ func (x *PortraitResp) GetEstablishDate() string {
 	return ""
 }
 
+func (x *PortraitResp) GetErrorMsg() string {
+	if x != nil {
+		return x.ErrorMsg
+	}
+	return ""
+}
+
+func (x *PortraitResp) GetErrorCode() int64 {
+	if x != nil {
+		return x.ErrorCode
+	}
+	return 0
+}
+
+func (x *PortraitResp) GetCity() string {
+	if x != nil {
+		return x.City
+	}
+	return ""
+}
+
+func (x *PortraitResp) GetDistrict() string {
+	if x != nil {
+		return x.District
+	}
+	return ""
+}
+
 // 认领
 type ClaimReq struct {
 	state         protoimpl.MessageState
@@ -1688,6 +1728,238 @@ func (x *ClaimedReq) GetPageSize() int64 {
 	return 0
 }
 
+//医疗机构画像招标动态入参
+type GetNewMsgReq struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	CompanyName string `protobuf:"bytes,1,opt,name=companyName,proto3" json:"companyName,omitempty"` //机构名称
+	PageNum     int64  `protobuf:"varint,2,opt,name=pageNum,proto3" json:"pageNum,omitempty"`        //页码
+	PageSize    int64  `protobuf:"varint,3,opt,name=pageSize,proto3" json:"pageSize,omitempty"`      //条数
+}
+
+func (x *GetNewMsgReq) Reset() {
+	*x = GetNewMsgReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_medical_proto_msgTypes[22]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetNewMsgReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetNewMsgReq) ProtoMessage() {}
+
+func (x *GetNewMsgReq) ProtoReflect() protoreflect.Message {
+	mi := &file_medical_proto_msgTypes[22]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetNewMsgReq.ProtoReflect.Descriptor instead.
+func (*GetNewMsgReq) Descriptor() ([]byte, []int) {
+	return file_medical_proto_rawDescGZIP(), []int{22}
+}
+
+func (x *GetNewMsgReq) GetCompanyName() string {
+	if x != nil {
+		return x.CompanyName
+	}
+	return ""
+}
+
+func (x *GetNewMsgReq) GetPageNum() int64 {
+	if x != nil {
+		return x.PageNum
+	}
+	return 0
+}
+
+func (x *GetNewMsgReq) GetPageSize() int64 {
+	if x != nil {
+		return x.PageSize
+	}
+	return 0
+}
+
+//医疗机构画像招标动态出参数
+type GetNewMsgResp struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	List      []*NewMsgList `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty"`    //招标动态
+	Count     int64         `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` //招标动态数量
+	ErrorMsg  string        `protobuf:"bytes,3,opt,name=error_msg,json=errorMsg,proto3" json:"error_msg,omitempty"`
+	ErrorCode int64         `protobuf:"varint,4,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"`
+}
+
+func (x *GetNewMsgResp) Reset() {
+	*x = GetNewMsgResp{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_medical_proto_msgTypes[23]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetNewMsgResp) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetNewMsgResp) ProtoMessage() {}
+
+func (x *GetNewMsgResp) ProtoReflect() protoreflect.Message {
+	mi := &file_medical_proto_msgTypes[23]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetNewMsgResp.ProtoReflect.Descriptor instead.
+func (*GetNewMsgResp) Descriptor() ([]byte, []int) {
+	return file_medical_proto_rawDescGZIP(), []int{23}
+}
+
+func (x *GetNewMsgResp) GetList() []*NewMsgList {
+	if x != nil {
+		return x.List
+	}
+	return nil
+}
+
+func (x *GetNewMsgResp) GetCount() int64 {
+	if x != nil {
+		return x.Count
+	}
+	return 0
+}
+
+func (x *GetNewMsgResp) GetErrorMsg() string {
+	if x != nil {
+		return x.ErrorMsg
+	}
+	return ""
+}
+
+func (x *GetNewMsgResp) GetErrorCode() int64 {
+	if x != nil {
+		return x.ErrorCode
+	}
+	return 0
+}
+
+//招标动态列表
+type NewMsgList struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Area      string   `protobuf:"bytes,1,opt,name=area,proto3" json:"area,omitempty"`            //地区
+	Bidstatus string   `protobuf:"bytes,2,opt,name=bidstatus,proto3" json:"bidstatus,omitempty"`  //信息类型
+	Bidamount string   `protobuf:"bytes,3,opt,name=bidamount,proto3" json:"bidamount,omitempty"`  //金额
+	Firsttime int64    `protobuf:"varint,4,opt,name=firsttime,proto3" json:"firsttime,omitempty"` //时间
+	Id        string   `protobuf:"bytes,5,opt,name=id,proto3" json:"id,omitempty"`                //加密信息id
+	Title     string   `protobuf:"bytes,6,opt,name=title,proto3" json:"title,omitempty"`          //标题
+	Winner    []string `protobuf:"bytes,7,rep,name=winner,proto3" json:"winner,omitempty"`        //中标单位
+}
+
+func (x *NewMsgList) Reset() {
+	*x = NewMsgList{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_medical_proto_msgTypes[24]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *NewMsgList) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*NewMsgList) ProtoMessage() {}
+
+func (x *NewMsgList) ProtoReflect() protoreflect.Message {
+	mi := &file_medical_proto_msgTypes[24]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use NewMsgList.ProtoReflect.Descriptor instead.
+func (*NewMsgList) Descriptor() ([]byte, []int) {
+	return file_medical_proto_rawDescGZIP(), []int{24}
+}
+
+func (x *NewMsgList) GetArea() string {
+	if x != nil {
+		return x.Area
+	}
+	return ""
+}
+
+func (x *NewMsgList) GetBidstatus() string {
+	if x != nil {
+		return x.Bidstatus
+	}
+	return ""
+}
+
+func (x *NewMsgList) GetBidamount() string {
+	if x != nil {
+		return x.Bidamount
+	}
+	return ""
+}
+
+func (x *NewMsgList) GetFirsttime() int64 {
+	if x != nil {
+		return x.Firsttime
+	}
+	return 0
+}
+
+func (x *NewMsgList) GetId() string {
+	if x != nil {
+		return x.Id
+	}
+	return ""
+}
+
+func (x *NewMsgList) GetTitle() string {
+	if x != nil {
+		return x.Title
+	}
+	return ""
+}
+
+func (x *NewMsgList) GetWinner() []string {
+	if x != nil {
+		return x.Winner
+	}
+	return nil
+}
+
 var File_medical_proto protoreflect.FileDescriptor
 
 var file_medical_proto_rawDesc = []byte{
@@ -1827,113 +2099,152 @@ var file_medical_proto_rawDesc = []byte{
 	0x25, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e,
 	0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f,
 	0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
-	0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x41,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x59,
 	0x0a, 0x0b, 0x50, 0x6f, 0x72, 0x74, 0x72, 0x61, 0x69, 0x74, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a,
 	0x05, 0x61, 0x70, 0x70, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70,
 	0x70, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x49, 0x64,
 	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x49,
-	0x64, 0x22, 0xa0, 0x03, 0x0a, 0x0c, 0x50, 0x6f, 0x72, 0x74, 0x72, 0x61, 0x69, 0x74, 0x52, 0x65,
-	0x73, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x65, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
-	0x52, 0x04, 0x62, 0x65, 0x64, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x76, 0x69, 0x73, 0x69, 0x74, 0x50,
-	0x65, 0x72, 0x64, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x76, 0x69, 0x73,
-	0x69, 0x74, 0x50, 0x65, 0x72, 0x64, 0x61, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x6f, 0x63, 0x74,
-	0x6f, 0x72, 0x73, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x6f,
-	0x63, 0x74, 0x6f, 0x72, 0x73, 0x6e, 0x75, 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72,
-	0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
-	0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x18, 0x05, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04,
-	0x61, 0x72, 0x65, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x65, 0x61,
-	0x12, 0x23, 0x0a, 0x0d, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x79, 0x70,
-	0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73,
-	0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x08,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d,
-	0x69, 0x54, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x69, 0x54,
-	0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74,
-	0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e,
-	0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73,
-	0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x6e, 0x61,
-	0x6d, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x0c, 0x20,
-	0x01, 0x28, 0x03, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x20, 0x0a, 0x0b, 0x63,
-	0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a,
-	0x0e, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18,
-	0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68,
-	0x44, 0x61, 0x74, 0x65, 0x22, 0x8c, 0x02, 0x0a, 0x08, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52, 0x65,
-	0x71, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x49,
-	0x64, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x03, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x6e, 0x74,
-	0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x6e, 0x74, 0x49, 0x64, 0x12,
-	0x18, 0x0a, 0x07, 0x45, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x07, 0x45, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70,
-	0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a,
-	0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
-	0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x45, 0x73, 0x74, 0x61, 0x62,
-	0x6c, 0x69, 0x73, 0x68, 0x44, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
-	0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x61, 0x74, 0x65, 0x12, 0x28, 0x0a,
-	0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x61, 0x70, 0x69, 0x74, 0x61, 0x6c,
-	0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
-	0x43, 0x61, 0x70, 0x69, 0x74, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65,
-	0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x14, 0x0a,
-	0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x70,
-	0x70, 0x49, 0x64, 0x22, 0x4c, 0x0a, 0x0c, 0x55, 0x6e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64,
-	0x52, 0x65, 0x71, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x03, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x49,
-	0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x41,
-	0x70, 0x70, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x70, 0x70, 0x49,
-	0x64, 0x22, 0x4c, 0x0a, 0x0c, 0x49, 0x73, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x52, 0x65,
+	0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x8c, 0x04, 0x0a, 0x0c, 0x50, 0x6f,
+	0x72, 0x74, 0x72, 0x61, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x65,
+	0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x62, 0x65, 0x64, 0x73, 0x12, 0x20,
+	0x0a, 0x0b, 0x76, 0x69, 0x73, 0x69, 0x74, 0x50, 0x65, 0x72, 0x64, 0x61, 0x79, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x03, 0x52, 0x0b, 0x76, 0x69, 0x73, 0x69, 0x74, 0x50, 0x65, 0x72, 0x64, 0x61, 0x79,
+	0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x6e, 0x75, 0x6d, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x6e, 0x75, 0x6d,
+	0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65,
+	0x62, 0x73, 0x69, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62,
+	0x73, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x65, 0x61, 0x18, 0x06, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x65, 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x75, 0x73, 0x69,
+	0x6e, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52,
+	0x0c, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a,
+	0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x65,
+	0x76, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x54, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x69, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x65,
+	0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+	0x65, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x70,
+	0x61, 0x72, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+	0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66,
+	0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x66, 0x6f, 0x6c,
+	0x6c, 0x6f, 0x77, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x4e, 0x61,
+	0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
+	0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69,
+	0x73, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65,
+	0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09,
+	0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72,
+	0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x65,
+	0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x74, 0x79,
+	0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08,
+	0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+	0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x22, 0x8c, 0x02, 0x0a, 0x08, 0x43, 0x6c, 0x61,
+	0x69, 0x6d, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28,
+	0x03, 0x52, 0x02, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a,
+	0x05, 0x45, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x6e,
+	0x74, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x45, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a,
+	0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x54, 0x79, 0x70,
+	0x65, 0x12, 0x18, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x45,
+	0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0d, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x61, 0x74,
+	0x65, 0x12, 0x28, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x61, 0x70,
+	0x69, 0x74, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x52, 0x65, 0x67, 0x69,
+	0x73, 0x74, 0x65, 0x72, 0x43, 0x61, 0x70, 0x69, 0x74, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x50,
+	0x68, 0x6f, 0x6e, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x50, 0x68, 0x6f, 0x6e,
+	0x65, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x22, 0x4c, 0x0a, 0x0c, 0x55, 0x6e, 0x63, 0x6c, 0x61,
+	0x69, 0x6d, 0x65, 0x64, 0x52, 0x65, 0x71, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12,
+	0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x49, 0x64, 0x12,
+	0x14, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
+	0x41, 0x70, 0x70, 0x49, 0x64, 0x22, 0x4c, 0x0a, 0x0c, 0x49, 0x73, 0x43, 0x6c, 0x61, 0x69, 0x6d,
+	0x65, 0x64, 0x52, 0x65, 0x71, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x0e, 0x0a,
+	0x02, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x49, 0x64, 0x12, 0x14, 0x0a,
+	0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x70,
+	0x70, 0x49, 0x64, 0x22, 0x6a, 0x0a, 0x0a, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x52, 0x65,
 	0x71, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x03, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x70, 0x70,
-	0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x22,
-	0x6a, 0x0a, 0x0a, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x52, 0x65, 0x71, 0x12, 0x16, 0x0a,
-	0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x55,
-	0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x50,
-	0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x50, 0x61, 0x67, 0x65, 0x12,
-	0x1a, 0x0a, 0x08, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
-	0x03, 0x52, 0x08, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x32, 0xa5, 0x05, 0x0a, 0x07,
-	0x4d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x42, 0x0a, 0x0b, 0x49, 0x6e, 0x73, 0x74, 0x69,
-	0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c,
-	0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69,
-	0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e,
-	0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x73, 0x70, 0x12, 0x37, 0x0a, 0x0d, 0x47,
-	0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0d, 0x2e, 0x6d,
-	0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x5a, 0x65, 0x72, 0x6f, 0x1a, 0x17, 0x2e, 0x6d, 0x65,
-	0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x74, 0x65, 0x6d,
-	0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x0b, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
-	0x74, 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x53, 0x65,
-	0x61, 0x72, 0x63, 0x68, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x52,
-	0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d,
-	0x70, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3a, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72,
-	0x41, 0x75, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x61, 0x76, 0x65, 0x12, 0x11, 0x2e, 0x6d,
-	0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x1a,
-	0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
-	0x52, 0x65, 0x73, 0x70, 0x12, 0x39, 0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x41, 0x75, 0x74, 0x68,
-	0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43,
-	0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63,
-	0x61, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12,
-	0x37, 0x0a, 0x08, 0x50, 0x6f, 0x72, 0x74, 0x72, 0x61, 0x69, 0x74, 0x12, 0x14, 0x2e, 0x6d, 0x65,
-	0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x72, 0x61, 0x69, 0x74, 0x52, 0x65,
-	0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x50, 0x6f, 0x72, 0x74,
-	0x72, 0x61, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2f, 0x0a, 0x05, 0x43, 0x6c, 0x61, 0x69,
-	0x6d, 0x12, 0x11, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6c, 0x61, 0x69,
-	0x6d, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43,
-	0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x37, 0x0a, 0x09, 0x55, 0x6e, 0x43,
-	0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x12, 0x15, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c,
-	0x2e, 0x55, 0x6e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e,
-	0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65,
-	0x73, 0x70, 0x12, 0x37, 0x0a, 0x09, 0x49, 0x73, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x12,
-	0x15, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x49, 0x73, 0x43, 0x6c, 0x61, 0x69,
-	0x6d, 0x65, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c,
-	0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x16, 0x43,
-	0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f,
-	0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e,
+	0x03, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x70, 0x70,
+	0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x70, 0x70, 0x49, 0x64, 0x12,
+	0x12, 0x0a, 0x04, 0x50, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x50,
+	0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18,
+	0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22,
+	0x66, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x12,
+	0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x4e, 0x61, 0x6d,
+	0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x03, 0x52, 0x07, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x70,
+	0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70,
+	0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x8a, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4e,
+	0x65, 0x77, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x73, 0x70, 0x12, 0x27, 0x0a, 0x04, 0x6c, 0x69, 0x73,
+	0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61,
+	0x6c, 0x2e, 0x4e, 0x65, 0x77, 0x4d, 0x73, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x04, 0x6c, 0x69,
+	0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x72, 0x72, 0x6f,
+	0x72, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, 0x72,
+	0x6f, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63,
+	0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72,
+	0x43, 0x6f, 0x64, 0x65, 0x22, 0xb8, 0x01, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x4d, 0x73, 0x67, 0x4c,
+	0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x65, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x61, 0x72, 0x65, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x69, 0x64, 0x73, 0x74,
+	0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x69, 0x64, 0x73,
+	0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x69, 0x64, 0x61, 0x6d, 0x6f, 0x75,
+	0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x69, 0x64, 0x61, 0x6d, 0x6f,
+	0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x74, 0x69, 0x6d, 0x65,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x74, 0x69, 0x6d,
+	0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
+	0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x69, 0x6e, 0x6e, 0x65,
+	0x72, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x32,
+	0xe1, 0x05, 0x0a, 0x07, 0x4d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x42, 0x0a, 0x0b, 0x49,
+	0x6e, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x6d, 0x65, 0x64,
+	0x69, 0x63, 0x61, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x49, 0x6e, 0x73, 0x74, 0x69,
+	0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, 0x65, 0x64, 0x69,
+	0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x73, 0x70, 0x12,
+	0x37, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x74, 0x65, 0x6d,
+	0x12, 0x0d, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x5a, 0x65, 0x72, 0x6f, 0x1a,
+	0x17, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72,
+	0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x0b, 0x44, 0x69, 0x73, 0x74,
+	0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61,
+	0x6c, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
+	0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c,
+	0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3a, 0x0a, 0x10,
+	0x75, 0x73, 0x65, 0x72, 0x41, 0x75, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x61, 0x76, 0x65,
+	0x12, 0x11, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49,
+	0x6e, 0x66, 0x6f, 0x1a, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6f,
+	0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x39, 0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72,
+	0x41, 0x75, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63,
+	0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x6d,
+	0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+	0x65, 0x73, 0x70, 0x12, 0x37, 0x0a, 0x08, 0x50, 0x6f, 0x72, 0x74, 0x72, 0x61, 0x69, 0x74, 0x12,
+	0x14, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x72, 0x61,
+	0x69, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e,
+	0x50, 0x6f, 0x72, 0x74, 0x72, 0x61, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2f, 0x0a, 0x05,
+	0x43, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x11, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e,
+	0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63,
+	0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x37, 0x0a,
+	0x09, 0x55, 0x6e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x12, 0x15, 0x2e, 0x6d, 0x65, 0x64,
+	0x69, 0x63, 0x61, 0x6c, 0x2e, 0x55, 0x6e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x52, 0x65,
+	0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
+	0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x37, 0x0a, 0x09, 0x49, 0x73, 0x43, 0x6c, 0x61, 0x69,
+	0x6d, 0x65, 0x64, 0x12, 0x15, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x49, 0x73,
 	0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x65, 0x64,
 	0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12,
-	0x42, 0x0a, 0x16, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x49, 0x6e, 0x73, 0x74, 0x69, 0x74,
-	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69,
+	0x42, 0x0a, 0x16, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69,
+	0x62, 0x75, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69,
 	0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x13,
 	0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52,
+	0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x16, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x49, 0x6e,
+	0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e,
+	0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x52,
+	0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d,
+	0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4e, 0x65,
+	0x77, 0x4d, 0x73, 0x67, 0x12, 0x15, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x47,
+	0x65, 0x74, 0x4e, 0x65, 0x77, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x6d, 0x65,
+	0x64, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x4d, 0x73, 0x67, 0x52,
 	0x65, 0x73, 0x70, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x6d, 0x65, 0x64, 0x69, 0x63, 0x61, 0x6c,
 	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
@@ -1950,7 +2261,7 @@ func file_medical_proto_rawDescGZIP() []byte {
 	return file_medical_proto_rawDescData
 }
 
-var file_medical_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
+var file_medical_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
 var file_medical_proto_goTypes = []interface{}{
 	(*Request)(nil),              // 0: medical.Request
 	(*Response)(nil),             // 1: medical.Response
@@ -1974,43 +2285,49 @@ var file_medical_proto_goTypes = []interface{}{
 	(*UnclaimedReq)(nil),         // 19: medical.UnclaimedReq
 	(*IsClaimedReq)(nil),         // 20: medical.IsClaimedReq
 	(*ClaimedReq)(nil),           // 21: medical.ClaimedReq
-	(*anypb.Any)(nil),            // 22: google.protobuf.Any
+	(*GetNewMsgReq)(nil),         // 22: medical.GetNewMsgReq
+	(*GetNewMsgResp)(nil),        // 23: medical.GetNewMsgResp
+	(*NewMsgList)(nil),           // 24: medical.NewMsgList
+	(*anypb.Any)(nil),            // 25: google.protobuf.Any
 }
 var file_medical_proto_depIdxs = []int32{
-	22, // 0: medical.CommonResp.Data:type_name -> google.protobuf.Any
+	25, // 0: medical.CommonResp.Data:type_name -> google.protobuf.Any
 	7,  // 1: medical.CompanyDataList.list:type_name -> medical.CompanyData
 	8,  // 2: medical.CompanyResp.data:type_name -> medical.CompanyDataList
 	10, // 3: medical.FilterItem.level_code:type_name -> medical.LevelCode
 	11, // 4: medical.FilterItem.mi_type_code:type_name -> medical.MiTypeCode
 	12, // 5: medical.FilterItemResp.data:type_name -> medical.FilterItem
 	14, // 6: medical.UserInfoResp.data:type_name -> medical.UserInfo
-	5,  // 7: medical.Medical.Institution:input_type -> medical.SearchInstitutionReq
-	4,  // 8: medical.Medical.GetFilterItem:input_type -> medical.Zero
-	6,  // 9: medical.Medical.Distributor:input_type -> medical.SearchDistributorReq
-	14, // 10: medical.Medical.userAuthInfoSave:input_type -> medical.UserInfo
-	3,  // 11: medical.Medical.userAuthInfo:input_type -> medical.CommonReq
-	16, // 12: medical.Medical.Portrait:input_type -> medical.PortraitReq
-	18, // 13: medical.Medical.Claim:input_type -> medical.ClaimReq
-	19, // 14: medical.Medical.UnClaimed:input_type -> medical.UnclaimedReq
-	20, // 15: medical.Medical.IsClaimed:input_type -> medical.IsClaimedReq
-	21, // 16: medical.Medical.ClaimedDistributorList:input_type -> medical.ClaimedReq
-	21, // 17: medical.Medical.ClaimedInstitutionList:input_type -> medical.ClaimedReq
-	9,  // 18: medical.Medical.Institution:output_type -> medical.CompanyResp
-	13, // 19: medical.Medical.GetFilterItem:output_type -> medical.FilterItemResp
-	9,  // 20: medical.Medical.Distributor:output_type -> medical.CompanyResp
-	2,  // 21: medical.Medical.userAuthInfoSave:output_type -> medical.CommonResp
-	15, // 22: medical.Medical.userAuthInfo:output_type -> medical.UserInfoResp
-	17, // 23: medical.Medical.Portrait:output_type -> medical.PortraitResp
-	2,  // 24: medical.Medical.Claim:output_type -> medical.CommonResp
-	2,  // 25: medical.Medical.UnClaimed:output_type -> medical.CommonResp
-	2,  // 26: medical.Medical.IsClaimed:output_type -> medical.CommonResp
-	2,  // 27: medical.Medical.ClaimedDistributorList:output_type -> medical.CommonResp
-	2,  // 28: medical.Medical.ClaimedInstitutionList:output_type -> medical.CommonResp
-	18, // [18:29] is the sub-list for method output_type
-	7,  // [7:18] is the sub-list for method input_type
-	7,  // [7:7] is the sub-list for extension type_name
-	7,  // [7:7] is the sub-list for extension extendee
-	0,  // [0:7] is the sub-list for field type_name
+	24, // 7: medical.GetNewMsgResp.list:type_name -> medical.NewMsgList
+	5,  // 8: medical.Medical.Institution:input_type -> medical.SearchInstitutionReq
+	4,  // 9: medical.Medical.GetFilterItem:input_type -> medical.Zero
+	6,  // 10: medical.Medical.Distributor:input_type -> medical.SearchDistributorReq
+	14, // 11: medical.Medical.userAuthInfoSave:input_type -> medical.UserInfo
+	3,  // 12: medical.Medical.userAuthInfo:input_type -> medical.CommonReq
+	16, // 13: medical.Medical.Portrait:input_type -> medical.PortraitReq
+	18, // 14: medical.Medical.Claim:input_type -> medical.ClaimReq
+	19, // 15: medical.Medical.UnClaimed:input_type -> medical.UnclaimedReq
+	20, // 16: medical.Medical.IsClaimed:input_type -> medical.IsClaimedReq
+	21, // 17: medical.Medical.ClaimedDistributorList:input_type -> medical.ClaimedReq
+	21, // 18: medical.Medical.ClaimedInstitutionList:input_type -> medical.ClaimedReq
+	22, // 19: medical.Medical.GetNewMsg:input_type -> medical.GetNewMsgReq
+	9,  // 20: medical.Medical.Institution:output_type -> medical.CompanyResp
+	13, // 21: medical.Medical.GetFilterItem:output_type -> medical.FilterItemResp
+	9,  // 22: medical.Medical.Distributor:output_type -> medical.CompanyResp
+	2,  // 23: medical.Medical.userAuthInfoSave:output_type -> medical.CommonResp
+	15, // 24: medical.Medical.userAuthInfo:output_type -> medical.UserInfoResp
+	17, // 25: medical.Medical.Portrait:output_type -> medical.PortraitResp
+	2,  // 26: medical.Medical.Claim:output_type -> medical.CommonResp
+	2,  // 27: medical.Medical.UnClaimed:output_type -> medical.CommonResp
+	2,  // 28: medical.Medical.IsClaimed:output_type -> medical.CommonResp
+	2,  // 29: medical.Medical.ClaimedDistributorList:output_type -> medical.CommonResp
+	2,  // 30: medical.Medical.ClaimedInstitutionList:output_type -> medical.CommonResp
+	23, // 31: medical.Medical.GetNewMsg:output_type -> medical.GetNewMsgResp
+	20, // [20:32] is the sub-list for method output_type
+	8,  // [8:20] is the sub-list for method input_type
+	8,  // [8:8] is the sub-list for extension type_name
+	8,  // [8:8] is the sub-list for extension extendee
+	0,  // [0:8] is the sub-list for field type_name
 }
 
 func init() { file_medical_proto_init() }
@@ -2283,6 +2600,42 @@ func file_medical_proto_init() {
 				return nil
 			}
 		}
+		file_medical_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetNewMsgReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_medical_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetNewMsgResp); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_medical_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*NewMsgList); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
@@ -2290,7 +2643,7 @@ func file_medical_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_medical_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   22,
+			NumMessages:   25,
 			NumExtensions: 0,
 			NumServices:   1,
 		},

+ 39 - 1
rpc/medical/medical/medical_grpc.pb.go

@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
 // versions:
 // - protoc-gen-go-grpc v1.2.0
-// - protoc             v3.15.1
+// - protoc             v3.19.4
 // source: medical.proto
 
 package medical
@@ -44,6 +44,8 @@ type MedicalClient interface {
 	ClaimedDistributorList(ctx context.Context, in *ClaimedReq, opts ...grpc.CallOption) (*CommonResp, error)
 	// 我认领的医疗机构列表
 	ClaimedInstitutionList(ctx context.Context, in *ClaimedReq, opts ...grpc.CallOption) (*CommonResp, error)
+	// 招标动态
+	GetNewMsg(ctx context.Context, in *GetNewMsgReq, opts ...grpc.CallOption) (*GetNewMsgResp, error)
 }
 
 type medicalClient struct {
@@ -153,6 +155,15 @@ func (c *medicalClient) ClaimedInstitutionList(ctx context.Context, in *ClaimedR
 	return out, nil
 }
 
+func (c *medicalClient) GetNewMsg(ctx context.Context, in *GetNewMsgReq, opts ...grpc.CallOption) (*GetNewMsgResp, error) {
+	out := new(GetNewMsgResp)
+	err := c.cc.Invoke(ctx, "/medical.Medical/GetNewMsg", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // MedicalServer is the server API for Medical service.
 // All implementations must embed UnimplementedMedicalServer
 // for forward compatibility
@@ -179,6 +190,8 @@ type MedicalServer interface {
 	ClaimedDistributorList(context.Context, *ClaimedReq) (*CommonResp, error)
 	// 我认领的医疗机构列表
 	ClaimedInstitutionList(context.Context, *ClaimedReq) (*CommonResp, error)
+	// 招标动态
+	GetNewMsg(context.Context, *GetNewMsgReq) (*GetNewMsgResp, error)
 	mustEmbedUnimplementedMedicalServer()
 }
 
@@ -219,6 +232,9 @@ func (UnimplementedMedicalServer) ClaimedDistributorList(context.Context, *Claim
 func (UnimplementedMedicalServer) ClaimedInstitutionList(context.Context, *ClaimedReq) (*CommonResp, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method ClaimedInstitutionList not implemented")
 }
+func (UnimplementedMedicalServer) GetNewMsg(context.Context, *GetNewMsgReq) (*GetNewMsgResp, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetNewMsg not implemented")
+}
 func (UnimplementedMedicalServer) mustEmbedUnimplementedMedicalServer() {}
 
 // UnsafeMedicalServer may be embedded to opt out of forward compatibility for this service.
@@ -430,6 +446,24 @@ func _Medical_ClaimedInstitutionList_Handler(srv interface{}, ctx context.Contex
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Medical_GetNewMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetNewMsgReq)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(MedicalServer).GetNewMsg(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/medical.Medical/GetNewMsg",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(MedicalServer).GetNewMsg(ctx, req.(*GetNewMsgReq))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 // Medical_ServiceDesc is the grpc.ServiceDesc for Medical service.
 // It's only intended for direct use with grpc.RegisterService,
 // and not to be introspected or modified (even as a copy)
@@ -481,6 +515,10 @@ var Medical_ServiceDesc = grpc.ServiceDesc{
 			MethodName: "ClaimedInstitutionList",
 			Handler:    _Medical_ClaimedInstitutionList_Handler,
 		},
+		{
+			MethodName: "GetNewMsg",
+			Handler:    _Medical_GetNewMsg_Handler,
+		},
 	},
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "medical.proto",

+ 64 - 0
service/coverage

@@ -0,0 +1,64 @@
+mode: set
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:14.76,19.17 2 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:29.2,29.34 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:19.17,20.32 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:20.32,22.4 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:23.8,24.35 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:24.35,26.4 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:29.34,41.10 3 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:41.10,43.4 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:43.9,46.4 2 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:47.8,62.13 3 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:62.13,64.4 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:64.9,67.4 2 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/AuthService.go:72.82,78.2 2 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/InstitutionService.go:10.93,16.2 3 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:16.57,20.2 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:23.61,25.2 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:28.58,34.32 3 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:39.2,40.23 2 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:45.2,49.70 2 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:34.32,37.3 2 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:40.23,43.3 2 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:53.93,61.2 2 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:64.126,75.16 5 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:78.2,78.115 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:75.16,77.3 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:82.126,92.16 5 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:95.2,95.115 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go:92.16,94.3 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:28.54,32.2 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:38.83,40.21 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:44.2,50.36 2 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:54.2,57.37 4 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:63.2,65.47 3 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:69.2,88.26 3 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:40.21,42.3 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:50.36,52.3 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:57.37,61.3 3 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:65.47,67.3 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:98.119,100.21 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:103.2,107.18 4 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:113.2,117.48 4 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:148.2,148.53 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:100.21,102.3 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:107.18,109.17 2 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:109.17,111.4 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:117.48,121.43 4 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:124.3,125.30 2 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:146.3,146.26 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:121.43,123.4 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:125.30,126.18 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:137.4,144.32 2 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:126.18,127.24 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:131.5,132.20 2 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:135.5,135.67 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:127.24,130.6 2 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:132.20,134.6 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:152.83,160.2 4 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:163.66,170.25 6 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:173.2,173.31 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:170.25,172.3 1 1
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:175.34,176.29 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:179.2,179.45 1 0
+bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go:176.29,178.3 1 0

+ 306 - 31
service/coverage.html

@@ -59,22 +59,17 @@
 				
 				<option value="file1">bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/InstitutionService.go (100.0%)</option>
 				
+				<option value="file2">bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/claim.go (27.6%)</option>
+				
+				<option value="file3">bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/service/portrait.go (88.1%)</option>
+				
 				</select>
 			</div>
 			<div id="legend">
 				<span>not tracked</span>
 			
-				<span class="cov0">no coverage</span>
-				<span class="cov1">low coverage</span>
-				<span class="cov2">*</span>
-				<span class="cov3">*</span>
-				<span class="cov4">*</span>
-				<span class="cov5">*</span>
-				<span class="cov6">*</span>
-				<span class="cov7">*</span>
-				<span class="cov8">*</span>
-				<span class="cov9">*</span>
-				<span class="cov10">high coverage</span>
+				<span class="cov0">not covered</span>
+				<span class="cov8">covered</span>
 			
 			</div>
 		</div>
@@ -93,55 +88,55 @@ import (
 type AuthService struct{}
 
 //认证信息保存
-func (b AuthService) UserAuthInfoSave(in *medical.UserInfo) (bool, string) <span class="cov10" title="4">{
+func (b AuthService) UserAuthInfoSave(in *medical.UserInfo) (bool, string) <span class="cov8" title="1">{
         //先判断用户是否存在
         user := entity.BaseMysql.FindOne(entity.DOMAIN_CAPITAL_RETENTION, map[string]interface{}{
-                "user_id": in.UserId,"appid":in.Appid,
+                "user_id": in.UserId, "appid": in.Appid,
         }, "id", "")
-        if user != nil </span><span class="cov5" title="2">{
-                if in.OperationType == "add" </span><span class="cov1" title="1">{
+        if user != nil </span><span class="cov8" title="1">{
+                if in.OperationType == "add" </span><span class="cov8" title="1">{
                         return false, "用户已验证"
                 }</span>
-        } else<span class="cov5" title="2"> {
-                if in.OperationType == "update" </span><span class="cov1" title="1">{
+        } else<span class="cov8" title="1"> {
+                if in.OperationType == "update" </span><span class="cov8" title="1">{
                         return false, "用户未认证,不可修改"
                 }</span>
         }
 
-        <span class="cov5" title="2">if in.OperationType == "update" </span><span class="cov1" title="1">{
+        <span class="cov8" title="1">if in.OperationType == "update" </span><span class="cov8" title="1">{
                 //修改处理
                 data := map[string]interface{}{
-                        "name":  in.Name,
-                        "phone": in.Phone,
+                        "name":       in.Name,
+                        "phone":      in.Phone,
                         "position":   in.Position,
                         "department": in.Department,
-                        "mail":  in.Mail,
+                        "mail":       in.Mail,
                         "ent_code":   in.EntCode,
                         "ent_name":   in.EntName,
                 }
-                ok1 := entity.BaseMysql.Update(entity.DOMAIN_CAPITAL_RETENTION, map[string]interface{}{"user_id": in.UserId,"appid":in.Appid}, data)
-                if ok1 </span><span class="cov1" title="1">{
+                ok1 := entity.BaseMysql.Update(entity.DOMAIN_CAPITAL_RETENTION, map[string]interface{}{"user_id": in.UserId, "appid": in.Appid}, data)
+                if ok1 </span><span class="cov8" title="1">{
                         return true, ""
                 }</span> else<span class="cov0" title="0"> {
                         log.Println(fmt.Sprintf("认证修改失败:入参:%v:%v,", in.UserId, data))
                         return false, "修改失败"
                 }</span>
-        } else<span class="cov1" title="1"> {
+        } else<span class="cov8" title="1"> {
                 //新增处理
                 data := map[string]interface{}{
-                        "name":   in.Name,
-                        "phone":  in.Phone,
+                        "name":        in.Name,
+                        "phone":       in.Phone,
                         "position":    in.Position,
                         "department":  in.Department,
-                        "mail":   in.Mail,
+                        "mail":        in.Mail,
                         "ent_code":    in.EntCode,
                         "ent_name":    in.EntName,
                         "user_id":     in.UserId,
                         "create_time": time.Now().Local(),
-                        "appid":in.Appid,
+                        "appid":       in.Appid,
                 }
                 ok := entity.BaseMysql.Insert(entity.DOMAIN_CAPITAL_RETENTION, data)
-                if ok &gt; 0 </span><span class="cov1" title="1">{
+                if ok &gt; 0 </span><span class="cov8" title="1">{
                         return true, ""
                 }</span> else<span class="cov0" title="0"> {
                         log.Println(fmt.Sprintf("认证失败:参数:%v", data))
@@ -151,10 +146,10 @@ func (b AuthService) UserAuthInfoSave(in *medical.UserInfo) (bool, string) <span
 }
 
 //认证信息查询
-func (b AuthService) UserAuthInfo(in *medical.CommonReq) *map[string]interface{} <span class="cov5" title="2">{
+func (b AuthService) UserAuthInfo(in *medical.CommonReq) *map[string]interface{} <span class="cov8" title="1">{
         //先判断用户是否存在
         user := entity.BaseMysql.FindOne(entity.DOMAIN_CAPITAL_RETENTION, map[string]interface{}{
-                "user_id": in.UserId,"appid":in.Appid,
+                "user_id": in.UserId, "appid": in.Appid,
         }, "id", "")
         return user
 }</span>
@@ -176,6 +171,286 @@ func (b InstitutionService) GetFilterItem() (levelList, typeList *[]map[string]i
         typeList = entity.Mysql.Find(entity.CODE_MEDICAL_INSTITUTION_TYPE, nil, "*", "", -1, -1)
         return
 }</span>
+</pre>
+		
+		<pre class="file" id="file2" style="display: none">package service
+
+import (
+        "app.yhyue.com/moapp/jybase/common"
+        "app.yhyue.com/moapp/jybase/date"
+        "bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/entity"
+        "github.com/zeromicro/go-zero/core/logx"
+)
+
+// EntClaimService 企业认领
+type EntClaimService struct {
+        *entity.Conn
+}
+
+// NewEntClaimSrv 创建一个EntClaimSrv实例
+func NewEntClaimSrv(conn *entity.Conn) *EntClaimService <span class="cov8" title="1">{
+        return &amp;EntClaimService{
+                conn,
+        }
+}</span>
+
+// Claim 认领
+func (e *EntClaimService) Claim(data *entity.EntClaim) bool <span class="cov8" title="1">{
+        return e.BaseMysql.Insert(entity.TableDomainEntClaim, common.StructToMapMore(data)) &gt; 0
+}</span>
+
+// Unclaimed // 取消认领
+func (e *EntClaimService) Unclaimed(id, userId int) bool <span class="cov0" title="0">{
+        query := map[string]interface{}{
+                "id": id,
+        }
+        // 1. 查询该条数据
+        rs := e.BaseMysql.FindOne(entity.TableDomainEntClaim, query, "user_id", "")
+        if rs == nil || len(*rs) == 0 </span><span class="cov0" title="0">{
+                logx.Errorf("取消认领:无效的id %v", id)
+                return false
+        }</span>
+        // 2. 存在则判断是否是该用户的
+        <span class="cov0" title="0">rsUerId := common.IntAll((*rs)["user_id"])
+        if rsUerId != userId </span><span class="cov0" title="0">{
+                logx.Errorf("取消认领:id[%v]与用户id[%v]不匹配 ", id, userId)
+                return false
+        }</span>
+        // 3. 取消认领
+        <span class="cov0" title="0">update := map[string]interface{}{
+                "status":      entity.StatusUnClaimed,
+                "update_time": date.NowFormat(date.Date_Full_Layout),
+        }
+        return e.BaseMysql.Update(entity.TableDomainEntClaim, query, update)</span>
+}
+
+// IsClaimed 是否认领
+func (e *EntClaimService) IsClaimed(userId int, appId string, entId int, typeCode int) bool <span class="cov0" title="0">{
+        query := map[string]interface{}{
+                "user_id": userId,
+                "type":    typeCode,
+                "ent_id":  entId,
+                "status":  entity.StatusClaimed,
+        }
+        return e.BaseMysql.Count(entity.TableDomainEntClaim, query) &gt; 0
+}</span>
+
+// DistributorList 关注的经销商列表
+func (e *EntClaimService) DistributorList(userId int, appId string, page int, pageSize int) (*[]map[string]interface{}, int) <span class="cov8" title="1">{
+
+        query := map[string]interface{}{
+                "user_id": userId,
+                "appid":   appId,
+                "type":    entity.TypeDistributor,
+                "status":  entity.StatusClaimed,
+        }
+        field := "id,appid,user_id,ent_id,ent_name,address,create_time"
+        order := "create_time desc"
+        total := e.BaseMysql.Count(entity.TableDomainEntClaim, query)
+        if total == 0 </span><span class="cov8" title="1">{
+                return nil, 0
+        }</span>
+        <span class="cov0" title="0">return e.BaseMysql.Find(entity.TableDomainEntClaim, query, field, order, (page-1)*pageSize, pageSize), int(total)</span>
+}
+
+// InstitutionList  我关注的医疗机构列表
+func (e *EntClaimService) InstitutionList(userId int, appId string, page int, pageSize int) (*[]map[string]interface{}, int) <span class="cov0" title="0">{
+        query := map[string]interface{}{
+                "user_id": userId,
+                "appid":   appId,
+                "type":    entity.TypeInstitution,
+                "status":  entity.StatusClaimed,
+        }
+        field := "id,appid,user_id,ent_id,ent_name,address,create_time"
+        order := "create_time desc"
+        total := e.BaseMysql.Count(entity.TableDomainEntClaim, query)
+        if total == 0 </span><span class="cov0" title="0">{
+                return nil, 0
+        }</span>
+        <span class="cov0" title="0">return e.BaseMysql.Find(entity.TableDomainEntClaim, query, field, order, (page-1)*pageSize, pageSize), int(total)</span>
+}
+</pre>
+		
+		<pre class="file" id="file3" style="display: none">// @Description   画像相关
+package service
+
+import (
+        "errors"
+        "fmt"
+        "log"
+        "regexp"
+        "strings"
+        "time"
+
+        . "app.yhyue.com/moapp/jybase/common"
+        "app.yhyue.com/moapp/jybase/encrypt"
+        elastic "app.yhyue.com/moapp/jybase/esv1"
+        "bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/entity"
+)
+
+//画像
+type PortraitService struct {
+        *entity.Conn
+}
+
+var ClearHtml = regexp.MustCompile("&lt;[^&gt;]*&gt;")
+
+// @description           生成结构体
+// @param                     conn 数据库实例
+// @return                    Portrait 画像实例
+func NewPortrait(conn *entity.Conn) *PortraitService <span class="cov8" title="1">{
+        return &amp;PortraitService{
+                conn,
+        }
+}</span>
+
+// @description           获取画像内容
+// @param                     companyId 机构id
+// @return                    PortraitInfo 画像信息
+// @return                    error 错误信息
+func (this *PortraitService) Info(companyId string) (*entity.PortraitInfo, error) <span class="cov8" title="1">{
+        //判断是否存在companyid
+        if companyId == "" </span><span class="cov8" title="1">{
+                return nil, errors.New(entity.NO_DATA_ERROR_MSG)
+        }</span>
+        //获取信息
+        <span class="cov8" title="1">data := this.Mysql.SelectBySql(fmt.Sprintf(`SELECT a.sdequipment_code,a.area_code,a.beds,a.visit_perday,a.doctorsnum,a.address,a.website,a.business_type,a.equipment, e.equipment sdleveltypeequip ,a.mi_name,a.establish_date,b.name LEVEL,c.name miType,d.class FROM %s a 
+                                                                                                        LEFT JOIN %s b ON a.level_code=b.code 
+                                                                                                        LEFT JOIN %s c ON c.code =a.mi_type_code
+                                                                                                        LEFT JOIN (SELECT GROUP_CONCAT(DISTINCT departname_class1 SEPARATOR  '、') class,company_id FROM %s WHERE company_id=?)  AS d ON d.company_id =a.company_id
+                                                                                                        left join %s e on e.code =a.sdequipment_code
+                                                                                                        WHERE  a.company_id=?`, entity.Institution_baseinfo, entity.Code_level, entity.Code_type, entity.Institution_department, entity.Code_sdleveltypeequip), companyId, companyId)
+        if data == nil || len(*data) == 0 </span><span class="cov8" title="1">{
+                return nil, errors.New(entity.NO_DATA_ERROR_MSG)
+        }</span>
+        //获取area_code 省份,城市,区县
+        <span class="cov8" title="1">area, city, district := "", "", ""
+        rdata := (*data)[0]
+        adata := this.CommonMysql.SelectBySql(fmt.Sprintf(`select area,city,district from %s where code =? limit 1`, entity.Code_area), ObjToString(rdata["area_code"]))
+        if adata != nil &amp;&amp; len(*adata) &gt; 0 </span><span class="cov8" title="1">{
+                area = ObjToString((*adata)[0]["area"])
+                city = ObjToString((*adata)[0]["city"])
+                district = ObjToString((*adata)[0]["district"])
+        }</span>
+        //医疗设备如果基本信息表中没有,则根据sdequipment_code、code联合查询得到equipment
+        <span class="cov8" title="1">equipment := ObjToString(rdata["equipment"])
+        sdleveltypeequip := ObjToString(rdata["sdleveltypeequip"])
+        if equipment == "" &amp;&amp; sdleveltypeequip != "" </span><span class="cov8" title="1">{
+                equipment = ObjToString(rdata["sdleveltypeequip"])
+        }</span>
+        //TODO 是否关注还没搞呢
+        <span class="cov8" title="1">isFollow := 0
+        portraitInfo := &amp;entity.PortraitInfo{
+                Beds:          Int64All(rdata["beds"]),
+                VisitPerday:   Int64All(rdata["visit_perday"]),      // 门诊量/日
+                Doctorsnum:    Int64All(rdata["doctorsnum"]),        //医生人数
+                Address:       ObjToString(rdata["address"]),        //医疗机构地址
+                Website:       ObjToString(rdata["website"]),        //医疗机构网站
+                Area:          area,                                 //省
+                City:          city,                                 //市
+                District:      district,                             //区
+                BusinessType:  Int64All(rdata["business_type"]),     //医疗机构经营方式(0:公立、1:民营、2:其它)
+                Level:         ObjToString(rdata["level"]),          //医疗机构等级
+                MiType:        ObjToString(rdata["miType"]),         //医疗机构类型
+                Equipment:     equipment,                            //医院设备
+                Departnames:   ObjToString(rdata["class"]),          //医院科室
+                Follow:        int64(isFollow),                      //是否关注 0-未关注 1已关注
+                CompanyName:   ObjToString(rdata["mi_name"]),        //医疗机构名称
+                EstablishDate: ObjToString(rdata["establish_date"]), //成立日期
+        }
+        return portraitInfo, nil</span>
+}
+
+// @description           获取医疗机构画像相关招标动态
+// @param                     companyId 机构id
+// @param                     pageSize 条数
+// @param                     pageNum 页码
+// @return                    GetNewMsgList 招标动态
+// @return                    count 招标数量
+// @return                    error 错误信息
+func (this *PortraitService) List(companyId string, pageSize, pageNum int64) (*[]*entity.GetNewMsgList, int64, error) <span class="cov8" title="1">{
+        //判断是否存在companyid
+        if companyId == "" </span><span class="cov0" title="0">{
+                return nil, 0, errors.New(entity.NO_DATA_ERROR_MSG)
+        }</span>
+        <span class="cov8" title="1">var total int64
+        mustQueryArr := this.CommonPare(companyId)
+        log.Println("~~~~,", mustQueryArr)
+        //仅第一页查询总量(非数据导出)
+        if pageNum == 1 </span><span class="cov8" title="1">{
+                total = elastic.Count(entity.BiddingIndex, entity.BiddingIndex, fmt.Sprintf(entity.NewMustSearch, strings.Join(mustQueryArr, ","), ""))
+                if total &lt;= 0 </span><span class="cov0" title="0">{
+                        return nil, 0, errors.New(entity.NO_DATA_ERROR_MSG)
+                }</span>
+        }
+        <span class="cov8" title="1">start, limit := (pageNum-1)*pageSize, pageSize
+        fields := `"title","area","subtype","_id","projectname","publishtime"`
+        list := &amp;[]*entity.GetNewMsgList{}
+        //列表查询
+        if total &lt;= entity.DataExportBatchSearchLimit </span><span class="cov8" title="1">{
+                listQuery := fmt.Sprintf(entity.NewMustSearch, strings.Join(mustQueryArr, ","), fmt.Sprintf(entity.ListSearchLimit, fields, "publishtime", start, limit))
+                log.Printf("PortraitWinnerProject GetList Sql %s\n", listQuery)
+                newData := elastic.Get(entity.BiddingIndex, entity.BiddingType, listQuery)
+                if newData == nil || len(*newData) == 0 </span><span class="cov0" title="0">{
+                        return nil, 0, errors.New(entity.NO_DATA_ERROR_MSG)
+                }</span>
+                <span class="cov8" title="1">log.Println("newdata:", newData)
+                for k, v := range *newData </span><span class="cov8" title="1">{
+                        if len(v) &gt; 0 </span><span class="cov8" title="1">{
+                                if v["_id"] != nil </span><span class="cov8" title="1">{
+                                        (*newData)[k]["id"] = encrypt.EncodeArticleId2ByCheck(v["_id"].(string))
+                                        delete((*newData)[k], "_id") //删除未加密id
+                                }</span>
+                                <span class="cov8" title="1">title := ObjToString(ObjToString(v["title"]))
+                                if title == "" </span><span class="cov0" title="0">{
+                                        title = ObjToString(v["projectname"])
+                                }</span>
+                                <span class="cov8" title="1">(*newData)[k]["title"] = ClearHtml.ReplaceAllString(title, "")</span>
+                        }
+                        <span class="cov8" title="1">*list = append(*list, &amp;entity.GetNewMsgList{
+                                Area:      ObjToString(v["area"]),
+                                Bidstatus: ObjToString(v["subtype"]),           //信息类型
+                                Firsttime: Int64All(v["publishtime"]),          //时间
+                                Id:        ObjToString((*newData)[k]["id"]),    //加密信息id
+                                Title:     ObjToString((*newData)[k]["title"]), //标题
+                        })
+                        log.Println("~~list:", list)</span>
+                }
+                <span class="cov8" title="1">return list, total, nil</span>
+        }
+        <span class="cov0" title="0">return nil, 0, errors.New(entity.NO_DATA_ERROR_MSG)</span>
+}
+
+//医疗机构画像查询语句拼接
+func (this *PortraitService) CommonPare(companyId string) (mustQueryArr []string) <span class="cov8" title="1">{
+        //按照当前年份,往前推4年,共5个年份可选
+        sTime, eTime := this.PareTimeSelect() //采购单位不校验权限
+
+        mustQueryArr = append(mustQueryArr, fmt.Sprintf(`{"term":{"buyer":"%s"}}`, companyId))
+        mustQueryArr = append(mustQueryArr, fmt.Sprintf(`{"range":{"publishtime":{"gte":"%d","lte":"%d"}}}`, sTime.Unix(), eTime.Unix()))
+
+        return
+}</span>
+
+//PareTimeSelect 格式筛选时间,默认2年
+func (this *PortraitService) PareTimeSelect() (st, et time.Time) <span class="cov8" title="1">{
+        now := time.Now()
+        sYear := now.Year() - 4
+        eYear := now.Year()
+        //返回默认时间
+        sTimeStamp := time.Date(sYear, 1, 1, 0, 0, 0, 0, time.Local)
+        eTimeStamp := time.Date(eYear+1, 1, 1, 0, 0, -1, 0, time.Local)
+        if eYear == now.Year() </span><span class="cov8" title="1">{
+                eTimeStamp = time.Date(eYear, now.Month(), now.Day(), now.Hour(), now.Minute(), 0, 0, time.Local)
+        }</span>
+        <span class="cov8" title="1">return sTimeStamp, eTimeStamp</span>
+}
+func EncodeId(sid string) string <span class="cov0" title="0">{
+        if sid == "" || sid == "-" </span><span class="cov0" title="0">{ //不存在的id为-
+                return ""
+        }</span>
+        <span class="cov0" title="0">return encrypt.EncodeArticleId2ByCheck(sid)</span>
+}
 </pre>
 		
 		</div>

+ 195 - 0
service/portrait.go

@@ -0,0 +1,195 @@
+// @Description   画像相关
+package service
+
+import (
+	"errors"
+	"fmt"
+	"log"
+	"regexp"
+	"strings"
+	"time"
+
+	. "app.yhyue.com/moapp/jybase/common"
+	"app.yhyue.com/moapp/jybase/encrypt"
+	elastic "app.yhyue.com/moapp/jybase/esv1"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/entity"
+)
+
+//画像
+type PortraitService struct {
+	*entity.Conn
+}
+
+var ClearHtml = regexp.MustCompile("<[^>]*>")
+
+// @description   	生成结构体
+// @param     		conn 数据库实例
+// @return    		Portrait 画像实例
+func NewPortrait(conn *entity.Conn) *PortraitService {
+	return &PortraitService{
+		conn,
+	}
+}
+
+// @description   	获取画像内容
+// @param     		companyId 机构id
+// @param     		user_id   base_user_id
+// @return    		PortraitInfo 画像信息
+// @return    		error 错误信息
+func (this *PortraitService) Info(companyId string, user_id int64) (*entity.PortraitInfo, error) {
+	//判断是否存在companyid
+	// if companyId == "" || user_id == 0 {
+	// 	return nil, errors.New(entity.NO_DATA_ERROR_MSG)
+	// }
+	//获取信息
+	data := this.Mysql.SelectBySql(fmt.Sprintf(`SELECT a.sdequipment_code,a.area_code,a.beds,a.visit_perday,a.doctorsnum,a.address,a.website,a.business_type,replace(a.equipment,",","、") equipment, replace(e.equipment,",","、") sdleveltypeequip ,a.mi_name,a.establish_date,b.name LEVEL,c.name miType,d.class FROM %s a 
+													LEFT JOIN %s b ON a.level_code=b.code 
+													LEFT JOIN %s c ON c.code =a.mi_type_code
+													LEFT JOIN (SELECT GROUP_CONCAT(DISTINCT departname_class1 SEPARATOR  '、') class,company_id FROM %s WHERE company_id=?)  AS d ON d.company_id =a.company_id
+													left join %s e on e.code =a.sdequipment_code
+													WHERE  a.company_id=?`, entity.Institution_baseinfo, entity.Code_level, entity.Code_type, entity.Institution_department, entity.Code_sdleveltypeequip), companyId, companyId)
+	if data == nil || len(*data) == 0 {
+		return nil, errors.New(entity.NO_DATA_ERROR_MSG)
+	}
+	//获取area_code 省份,城市,区县
+	area, city, district := "", "", ""
+	rdata := (*data)[0]
+	adata := this.CommonMysql.SelectBySql(fmt.Sprintf(`select area,city,district from %s where code =? limit 1`, entity.Code_area), ObjToString(rdata["area_code"]))
+	if adata != nil && len(*adata) > 0 {
+		area = ObjToString((*adata)[0]["area"])
+		city = ObjToString((*adata)[0]["city"])
+		district = ObjToString((*adata)[0]["district"])
+	}
+	//医疗设备如果基本信息表中没有,则根据sdequipment_code、code联合查询得到equipment
+	equipment := ObjToString(rdata["equipment"])
+	sdleveltypeequip := ObjToString(rdata["sdleveltypeequip"])
+	if equipment == "" && sdleveltypeequip != "" {
+		equipment = ObjToString(rdata["sdleveltypeequip"])
+	}
+	//判断用户是否关注该机构
+	portraitInfo := &entity.PortraitInfo{
+		Beds:          Int64All(rdata["beds"]),
+		VisitPerday:   Int64All(rdata["visit_perday"]),      // 门诊量/日
+		Doctorsnum:    Int64All(rdata["doctorsnum"]),        //医生人数
+		Address:       ObjToString(rdata["address"]),        //医疗机构地址
+		Website:       ObjToString(rdata["website"]),        //医疗机构网站
+		Area:          area,                                 //省
+		City:          city,                                 //市
+		District:      district,                             //区
+		BusinessType:  Int64All(rdata["business_type"]),     //医疗机构经营方式(0:公立、1:民营、2:其它)
+		Level:         ObjToString(rdata["level"]),          //医疗机构等级
+		MiType:        ObjToString(rdata["miType"]),         //医疗机构类型
+		Equipment:     equipment,                            //医院设备
+		Departnames:   ObjToString(rdata["class"]),          //医院科室
+		Follow:        this.IsFollow(companyId, user_id, 1), //是否关注 0-未关注 1已关注
+		CompanyName:   ObjToString(rdata["mi_name"]),        //医疗机构名称
+		EstablishDate: ObjToString(rdata["establish_date"]), //成立日期
+	}
+	return portraitInfo, nil
+}
+
+// @description   	获取医疗机构画像相关招标动态
+// @param     		companyName 机构名称
+// @param     		pageSize 条数
+// @param     		pageNum 页码
+// @return    		GetNewMsgList 招标动态
+// @return    		count 招标数量
+// @return    		error 错误信息
+func (this *PortraitService) List(companyName string, pageSize, pageNum int64) (*[]*entity.GetNewMsgList, int64, error) {
+	//判断是否存在companyid
+	if companyName == "" {
+		return nil, 0, errors.New(entity.NO_DATA_ERROR_MSG)
+	}
+	var total int64
+	mustQueryArr := this.CommonPare(companyName)
+	log.Println("~~~~,", mustQueryArr)
+	//仅第一页查询总量(非数据导出)
+	if pageNum == 1 {
+		total = elastic.Count(entity.BiddingIndex, entity.BiddingIndex, fmt.Sprintf(entity.NewMustSearch, strings.Join(mustQueryArr, ","), ""))
+		if total <= 0 {
+			return nil, 0, errors.New(entity.NO_DATA_ERROR_MSG)
+		}
+	}
+	start, limit := (pageNum-1)*pageSize, pageSize
+	fields := `"title","area","subtype","_id","projectname","publishtime"`
+	list := &[]*entity.GetNewMsgList{}
+	//列表查询
+	if total <= entity.DataExportBatchSearchLimit {
+		listQuery := fmt.Sprintf(entity.NewMustSearch, strings.Join(mustQueryArr, ","), fmt.Sprintf(entity.ListSearchLimit, fields, "publishtime", start, limit))
+		log.Printf("PortraitWinnerProject GetList Sql %s\n", listQuery)
+		newData := elastic.Get(entity.BiddingIndex, entity.BiddingType, listQuery)
+		if newData == nil || len(*newData) == 0 {
+			return nil, 0, errors.New(entity.NO_DATA_ERROR_MSG)
+		}
+		log.Println("newdata:", newData)
+		for k, v := range *newData {
+			if len(v) > 0 {
+				if v["_id"] != nil {
+					(*newData)[k]["id"] = encrypt.EncodeArticleId2ByCheck(v["_id"].(string))
+					delete((*newData)[k], "_id") //删除未加密id
+				}
+				title := ObjToString(ObjToString(v["title"]))
+				if title == "" {
+					title = ObjToString(v["projectname"])
+				}
+				(*newData)[k]["title"] = ClearHtml.ReplaceAllString(title, "")
+			}
+			*list = append(*list, &entity.GetNewMsgList{
+				Area:      ObjToString(v["area"]),
+				Bidstatus: ObjToString(v["subtype"]),           //信息类型
+				Firsttime: Int64All(v["publishtime"]),          //时间
+				Id:        ObjToString((*newData)[k]["id"]),    //加密信息id
+				Title:     ObjToString((*newData)[k]["title"]), //标题
+			})
+			log.Println("~~list:", list)
+		}
+		return list, total, nil
+	}
+	return nil, 0, errors.New(entity.NO_DATA_ERROR_MSG)
+}
+
+//医疗机构画像查询语句拼接
+func (this *PortraitService) CommonPare(companyName string) (mustQueryArr []string) {
+	//按照当前年份,往前推4年,共5个年份可选
+	sTime, eTime := this.PareTimeSelect() //采购单位不校验权限
+
+	mustQueryArr = append(mustQueryArr, fmt.Sprintf(`{"term":{"buyer":"%s"}}`, companyName))
+	mustQueryArr = append(mustQueryArr, fmt.Sprintf(`{"term":{"bid_field":"%s"}}`, entity.BidField))
+	mustQueryArr = append(mustQueryArr, fmt.Sprintf(`{"range":{"publishtime":{"gte":"%d","lte":"%d"}}}`, sTime.Unix(), eTime.Unix()))
+
+	return
+}
+
+//PareTimeSelect 格式筛选时间,默认5年
+func (this *PortraitService) PareTimeSelect() (st, et time.Time) {
+	now := time.Now()
+	sYear := now.Year() - 4
+	eYear := now.Year()
+	//返回默认时间
+	sTimeStamp := time.Date(sYear, 1, 1, 0, 0, 0, 0, time.Local)
+	eTimeStamp := time.Date(eYear+1, 1, 1, 0, 0, -1, 0, time.Local)
+	if eYear == now.Year() {
+		eTimeStamp = time.Date(eYear, now.Month(), now.Day(), now.Hour(), now.Minute(), 0, 0, time.Local)
+	}
+	return sTimeStamp, eTimeStamp
+}
+
+//短地址加密
+func EncodeId(sid string) string {
+	if sid == "" || sid == "-" { //不存在的id为-
+		return ""
+	}
+	return encrypt.EncodeArticleId2ByCheck(sid)
+}
+
+// @description   	判断用户是否关注该项目
+// @param     		companyId 机构id
+// @param     		user_id base_user_id
+// @param     		types 类型 1医疗机构 2经销商
+// @return    		int64 是否关注 1关注 0未关注
+func (this *PortraitService) IsFollow(companyId string, user_id, types int64) int64 {
+	if this.BaseMysql.CountBySql(fmt.Sprintf(`select count(1) from %s where user_id =? and ent_id =? and type =?`, entity.Domain_ent_claim), user_id, companyId, types) > 0 {
+		return 1
+	}
+	return 0
+}

+ 157 - 0
service/portrait_test.go

@@ -0,0 +1,157 @@
+package service
+
+import (
+	"reflect"
+	"testing"
+
+	elastic "app.yhyue.com/moapp/jybase/esv1"
+	"app.yhyue.com/moapp/jybase/mysql"
+	"bp.jydev.jianyu360.cn/ApplicationCenter/medicalField/entity"
+)
+
+var PortService PortraitService
+var MyConn *entity.Conn
+
+func init() {
+	entity.Mysql = &mysql.Mysql{
+		Address:      "192.168.3.217:4000",
+		UserName:     "root",
+		PassWord:     "=PDT49#80Z!RVv52_z",
+		DBName:       "medical_fileld_data",
+		MaxOpenConns: 5,
+		MaxIdleConns: 5,
+	}
+	entity.Mysql.Init()
+	BaseMysqlConn := &mysql.Mysql{
+		Address:      "192.168.3.217:4000",
+		UserName:     "root",
+		PassWord:     "=PDT49#80Z!RVv52_z",
+		DBName:       "base_service",
+		MaxOpenConns: 5,
+		MaxIdleConns: 5,
+	}
+	BaseMysqlConn.Init()
+	CommonMysql := &mysql.Mysql{
+		Address:      "192.168.3.217:4000",
+		UserName:     "root",
+		PassWord:     "=PDT49#80Z!RVv52_z",
+		DBName:       "global_common_data",
+		MaxOpenConns: 5,
+		MaxIdleConns: 5,
+	}
+	CommonMysql.Init()
+	MyConn = &entity.Conn{
+		Mysql:       entity.Mysql,
+		BaseMysql:   BaseMysqlConn,
+		CommonMysql: CommonMysql,
+	}
+	elastic.InitElasticSize("http://192.168.3.206:9800", 30)
+
+	PortService = *NewPortrait(MyConn)
+}
+
+func TestPortraitService_Info(t *testing.T) {
+	type fields struct {
+		Conn *entity.Conn
+	}
+	type args struct {
+		companyId string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    *entity.PortraitInfo
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+		{
+			name: "查询画像",
+			fields: fields{
+				Conn: MyConn,
+			},
+			args: args{
+				companyId: "25caa43ce64036dfd1f55635e06394a6",
+			},
+		},
+		{
+			name: "无参数查看画像",
+			fields: fields{
+				Conn: MyConn,
+			},
+			args: args{
+				companyId: "",
+			},
+		},
+		{
+			name: "错误参数查看画像",
+			fields: fields{
+				Conn: MyConn,
+			},
+			args: args{
+				companyId: "错的",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			this := &PortraitService{
+				Conn: tt.fields.Conn,
+			}
+			got, err := this.Info(tt.args.companyId)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Info() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Info() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestPortraitService_List(t *testing.T) {
+	type fields struct {
+		Conn *entity.Conn
+	}
+	type args struct {
+		companyId string
+		pagesize  int64
+		pagenum   int64
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    *entity.PortraitInfo
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+		{
+			name: "招标动态",
+			fields: fields{
+				Conn: MyConn,
+			},
+			args: args{
+				companyId: "张家港市凤凰镇人民政府",
+				pagesize:  5,
+				pagenum:   1,
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			this := &PortraitService{
+				Conn: tt.fields.Conn,
+			}
+			got, _, err := this.List(tt.args.companyId, tt.args.pagesize, tt.args.pagenum)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Info() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Info() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}