From 5d54d8ca56c486afd3f22f119dc270b84db46b06 Mon Sep 17 00:00:00 2001 From: MXWXZ Date: Tue, 30 Jul 2019 23:00:34 +0800 Subject: [PATCH 01/17] alf done --- backend/stresstest/boom.go | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/backend/stresstest/boom.go b/backend/stresstest/boom.go index f550a82..8b3e1cb 100644 --- a/backend/stresstest/boom.go +++ b/backend/stresstest/boom.go @@ -2,11 +2,11 @@ package main import ( "bufio" + "fmt" "io" "io/ioutil" "math/rand" "net/http" - "net/url" "os" "time" @@ -15,35 +15,34 @@ import ( var names []string var rnd *rand.Rand +var t *http.Transport +var c *http.Client func goodSearch() { - httpClient := &http.Client{ - Timeout: 10 * time.Second, - } - start := time.Now() - res, err := httpClient.Get("http://202.120.40.8:30711/v1/sellInfo?" + url.Values{ - "limit": {"20"}, - "goodName": {names[rnd.Intn(len(names))]}, - }.Encode()) + //res, err := httpClient.Get("http://202.120.40.8:30711/v1/sellInfo?" + url.Values{ + // "limit": {"20"}, + // "goodName": {names[rnd.Intn(len(names))]}, + //}.Encode()) + res, err := c.Get("http://202.120.40.8:30711/v1/user/" + fmt.Sprintf("%v", rnd.Intn(9999)+1)) if err != nil { boomer.RecordFailure("http", "goodSearch", time.Since(start).Nanoseconds()/int64(time.Millisecond), err.Error()) return } - body, err := ioutil.ReadAll(res.Body) + length, _ := io.Copy(ioutil.Discard, res.Body) + err = res.Body.Close() elapsed := time.Since(start) if err != nil { boomer.RecordFailure("http", "goodSearch", elapsed.Nanoseconds()/int64(time.Millisecond), err.Error()) return } - defer res.Body.Close() if res.StatusCode != 200 { boomer.RecordFailure("http", "goodSearch", elapsed.Nanoseconds()/int64(time.Millisecond), res.Status) return } - boomer.RecordSuccess("http", "goodSearch", elapsed.Nanoseconds()/int64(time.Millisecond), int64(len(body))) + boomer.RecordSuccess("http", "goodSearch", elapsed.Nanoseconds()/int64(time.Millisecond), length) } func main() { @@ -68,6 +67,15 @@ func main() { } } + t = &http.Transport{ + MaxIdleConns: 10240, + MaxIdleConnsPerHost: 10240, + } + c = &http.Client{ + Timeout: 10 * time.Second, + Transport: t, + } + task1 := &boomer.Task{ Name: "goodSearch", Weight: 10, From cf22c630c7a82fd6d21fc67656387b41966d65fc Mon Sep 17 00:00:00 2001 From: MXWXZ Date: Tue, 30 Jul 2019 23:02:22 +0800 Subject: [PATCH 02/17] add service --- backend/.realize.yaml | 41 +++++++++++++++++++++++ backend/api/message/Dockerfile | 6 ++++ backend/api/message/main.go | 43 +++++++++++++++++++++++++ backend/api/message/main_test.go | 18 +++++++++++ backend/srv/message/Dockerfile | 6 ++++ backend/srv/message/main.go | 30 +++++++++++++++++ backend/srv/message/main_test.go | 20 ++++++++++++ backend/srv/message/mock/mock.go | 19 +++++++++++ backend/srv/message/proto/message.proto | 14 ++++++++ backend/srvlist.list | 1 + 10 files changed, 198 insertions(+) create mode 100644 backend/api/message/Dockerfile create mode 100644 backend/api/message/main.go create mode 100644 backend/api/message/main_test.go create mode 100644 backend/srv/message/Dockerfile create mode 100644 backend/srv/message/main.go create mode 100644 backend/srv/message/main_test.go create mode 100644 backend/srv/message/mock/mock.go create mode 100644 backend/srv/message/proto/message.proto diff --git a/backend/.realize.yaml b/backend/.realize.yaml index f2716eb..b011512 100755 --- a/backend/.realize.yaml +++ b/backend/.realize.yaml @@ -346,3 +346,44 @@ schema: type: after path: ../../ output: true +- name: api-message + path: api/message + args: + - --registry=consul + commands: + run: + status: true + watcher: + extensions: + - go + paths: + - / + - ../../utils + scripts: + - command: make doc + type: after + path: ../../ + output: true +- name: srv-message + path: srv/message + args: + - --registry=consul + commands: + run: + status: true + watcher: + extensions: + - proto + - go + paths: + - / + - ../../utils + scripts: + - command: make proto SRV=message + type: before + path: ../../ + output: true + - command: make doc + type: after + path: ../../ + output: true diff --git a/backend/api/message/Dockerfile b/backend/api/message/Dockerfile new file mode 100644 index 0000000..3ff1c71 --- /dev/null +++ b/backend/api/message/Dockerfile @@ -0,0 +1,6 @@ +FROM sjtujj:latest AS build +FROM scratch AS prod +COPY --from=build /build/api-message . +COPY --from=build /config.json . + +CMD ["./api-message","--registry=consul"] \ No newline at end of file diff --git a/backend/api/message/main.go b/backend/api/message/main.go new file mode 100644 index 0000000..9dd0882 --- /dev/null +++ b/backend/api/message/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "jiaojiao/utils" + + "github.com/gin-gonic/gin" +) + +func setupRouter() *gin.Engine { + router, rg := utils.CreateAPIGroup() + rg.GET("/message", ) + return router +} + +/** + * @apiIgnore + * @api {} /message + * @apiVersion 1.0.0 + * @apiGroup + * @apiPermission + * @apiName + * @apiDescription + * + * @apiParam + * @apiSuccess + * @apiError (Error 500) + */ +func (c *gin.Context) { + type param struct { + string `form:""` + } + var p param + + if !utils.LogContinue(c.ShouldBindQuery(&p), utils.Warning) { + + } else { + c.AbortWithStatus(400) + } +} + +func main() { + utils.RunWebService("message", setupRouter()) +} diff --git a/backend/api/message/main_test.go b/backend/api/message/main_test.go new file mode 100644 index 0000000..044ddc1 --- /dev/null +++ b/backend/api/message/main_test.go @@ -0,0 +1,18 @@ +package main + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func Test_(t *testing.T) { + Convey("test", t, func() { + + }) +} + +func TestMain(m *testing.M) { + main() + m.Run() +} diff --git a/backend/srv/message/Dockerfile b/backend/srv/message/Dockerfile new file mode 100644 index 0000000..b5a834a --- /dev/null +++ b/backend/srv/message/Dockerfile @@ -0,0 +1,6 @@ +FROM sjtujj:latest AS build +FROM scratch AS prod +COPY --from=build /build/srv-message . +COPY --from=build /config.json . + +CMD ["./srv-message","--registry=consul"] \ No newline at end of file diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go new file mode 100644 index 0000000..7e91fef --- /dev/null +++ b/backend/srv/message/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "context" + "jiaojiao/utils" +) + +type srv struct{} + +/** + * @apiIgnore + * @api {rpc} /rpc + * @apiVersion 1.0.0 + * @apiGroup Service + * @apiName + * @apiDescription + * + * @apiParam {} + * @apiSuccess {} status -1 for invalid param
1 for success + * @apiUse DBServerDown + */ +func (a *srv) (ctx context.Context, req *, rsp *) error { + return nil +} + +func main() { + service := utils.InitMicroService("message") + utils.LogPanic(.Register(service.Server(), new(srv))) + utils.RunMicroService(service) +} diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go new file mode 100644 index 0000000..8e41320 --- /dev/null +++ b/backend/srv/message/main_test.go @@ -0,0 +1,20 @@ +package main + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func Test(t *testing.T) { + var s srv + var req + Convey("Test", t, func() { + + }) +} + +func TestMain(m *testing.M) { + main() + m.Run() +} diff --git a/backend/srv/message/mock/mock.go b/backend/srv/message/mock/mock.go new file mode 100644 index 0000000..93d187b --- /dev/null +++ b/backend/srv/message/mock/mock.go @@ -0,0 +1,19 @@ +package mock + +import ( + "github.com/micro/go-micro/client" +) + +type mockSrv struct{} + +// is mock +func (a *mockSrv) (ctx context.Context, req *, opts ...client.CallOption) (*, error) { + var ret + + return &ret, nil +} + +// is service mock +func New Service() . Service { + return new(mockSrv) +} diff --git a/backend/srv/message/proto/message.proto b/backend/srv/message/proto/message.proto new file mode 100644 index 0000000..f12808b --- /dev/null +++ b/backend/srv/message/proto/message.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +service { + rpc () returns (); +} + +message { + enum Status { + UNKNOWN = 0; + INVALID_PARAM = -1; + SUCCESS = 1; + } + Status status = 1; +} \ No newline at end of file diff --git a/backend/srvlist.list b/backend/srvlist.list index 52f811a..5558bf3 100644 --- a/backend/srvlist.list +++ b/backend/srvlist.list @@ -6,3 +6,4 @@ sellinfo user buyinfo transaction +message From 92f3e4a331b475f3484e3fa5d30b912edee82979 Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Wed, 31 Jul 2019 10:03:02 +0800 Subject: [PATCH 03/17] create chat message --- backend/srv/message/main.go | 142 ++++++++- backend/srv/message/proto/message.micro.go | 91 ++++++ backend/srv/message/proto/message.pb.go | 330 +++++++++++++++++++++ backend/srv/message/proto/message.proto | 34 ++- 4 files changed, 587 insertions(+), 10 deletions(-) create mode 100644 backend/srv/message/proto/message.micro.go create mode 100644 backend/srv/message/proto/message.pb.go diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index 7e91fef..2a67bb0 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -2,29 +2,157 @@ package main import ( "context" + db "jiaojiao/database" + "jiaojiao/srv/file/mock" + file "jiaojiao/srv/file/proto" + message "jiaojiao/srv/message/proto" "jiaojiao/utils" + "time" + + "go.mongodb.org/mongo-driver/bson" + + "github.com/micro/go-micro/client" ) type srv struct{} /** - * @apiIgnore - * @api {rpc} /rpc + * @api {rpc} /rpc Message.Create * @apiVersion 1.0.0 * @apiGroup Service - * @apiName - * @apiDescription + * @apiName Message.Create + * @apiDescription Create Message * - * @apiParam {} + * @apiParam {int32} fromUser user who launch the chat at first time + * @apiParam {int32} toUser user who accept the chat at first time + * @apiParam {int32} badge count of message still unread + * @apiParam {int64} time message create time + * @apiParam {bool} forward false for chat from toUser to fromUser
true for chat from fromUser to toUser + * @apiParam {int32} type 1 for text
2 for picture
3 for video + * @apiParam {string} text plain message text if type is text
fileID if type is picture or video + * @apiParam {bool} unread false for having read
true for not having read * @apiSuccess {} status -1 for invalid param
1 for success * @apiUse DBServerDown */ -func (a *srv) (ctx context.Context, req *, rsp *) error { +func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp *message.MessageCreateResponse) error { + if !utils.RequireParam(req.FromUser, req.ToUser, req.Type) { + rsp.Status = message.MessageCreateResponse_INVALID_PARAM + return nil + } + + if req.Type == message.MessageCreateRequest_PICTURE || req.Type == message.MessageCreateRequest_VIDEO { + srv := utils.CallMicroService("file", func(name string, c client.Client) interface{} { return file.NewFileService(name, c) }, + func() interface{} { return mock.NewFileService() }).(file.FileService) + microRsp, err := srv.Create(context.TODO(), &file.FileCreateRequest{ + File: req.File, + }) + + if err != nil || microRsp.Status != file.FileCreateResponse_SUCCESS { + rsp.Status = message.MessageCreateResponse_INVALID_PARAM + return nil + } + req.Text = microRsp.FileID + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + collection := db.MongoDatabase.Collection("sellinfo") + res1, err1 := collection.Find(ctx, bson.M{ + "fromUser": req.FromUser, + "toUser": req.ToUser, + }) + res2, err2 := collection.Find(ctx, bson.M{ + "fromUser": req.ToUser, + "toUser": req.FromUser, + }) + + if err1 == nil && err2 != nil { //fromUser to toUser + _, err := collection.UpdateOne(ctx, bson.M{ + "fromUser": req.FromUser, + "toUser": req.ToUser, + }, bson.M{"$push": bson.M{ + "infos": bson.M{ + "time": time.Now(), + "forward": true, + "type": req.Type, + "text": req.Text, + "unread": true, + }, + }}) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageCreateResponse_UNKNOWN + return nil + } + + _, err = collection.UpdateOne(ctx, bson.M{ + "fromUser": req.FromUser, + "toUser": req.ToUser, + }, bson.M{"$set": bson.M{ + "badge": res1.Current.Lookup("badge").Int32() + 1, + }}) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageCreateResponse_UNKNOWN + return nil + } + rsp.Status = message.MessageCreateResponse_SUCCESS + return nil + } else if err1 != nil && err2 == nil { //toUser to fromUser + _, err := collection.UpdateOne(ctx, bson.M{ + "fromUser": req.ToUser, + "toUser": req.FromUser, + }, bson.M{"$push": bson.M{ + "infos": bson.M{ + "time": time.Now(), + "forward": false, + "type": req.Type, + "text": req.Text, + "unread": true, + }, + }}) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageCreateResponse_UNKNOWN + return nil + } + + _, err = collection.UpdateOne(ctx, bson.M{ + "fromUser": req.ToUser, + "toUser": req.FromUser, + }, bson.M{"$set": bson.M{ + "badge": res2.Current.Lookup("badge").Int32() + 1, + }}) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageCreateResponse_UNKNOWN + return nil + } + rsp.Status = message.MessageCreateResponse_SUCCESS + return nil + } else if err1 != nil && err2 != nil { //new chat + _, err := collection.InsertOne(ctx, bson.M{ + "fromUser": req.FromUser, + "toUser": req.ToUser, + "badge": 1, + "infos": bson.A{bson.M{ + "time": time.Now(), + "forward": true, + "type": req.Type, + "text": req.Text, + "unread": true, + }}, + }) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageCreateResponse_UNKNOWN + return nil + } + rsp.Status = message.MessageCreateResponse_SUCCESS + return nil + } else { + rsp.Status = message.MessageCreateResponse_INVALID_PARAM + } return nil } func main() { service := utils.InitMicroService("message") - utils.LogPanic(.Register(service.Server(), new(srv))) + utils.LogPanic(message.RegisterMessageHandler(service.Server(), new(srv))) utils.RunMicroService(service) } diff --git a/backend/srv/message/proto/message.micro.go b/backend/srv/message/proto/message.micro.go new file mode 100644 index 0000000..d4f7790 --- /dev/null +++ b/backend/srv/message/proto/message.micro.go @@ -0,0 +1,91 @@ +// Code generated by protoc-gen-micro. DO NOT EDIT. +// source: message.proto + +package message + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +import ( + context "context" + client "github.com/micro/go-micro/client" + server "github.com/micro/go-micro/server" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ client.Option +var _ server.Option + +// Client API for Message service + +type MessageService interface { + Create(ctx context.Context, in *MessageCreateRequest, opts ...client.CallOption) (*MessageCreateResponse, error) +} + +type messageService struct { + c client.Client + name string +} + +func NewMessageService(name string, c client.Client) MessageService { + if c == nil { + c = client.NewClient() + } + if len(name) == 0 { + name = "message" + } + return &messageService{ + c: c, + name: name, + } +} + +func (c *messageService) Create(ctx context.Context, in *MessageCreateRequest, opts ...client.CallOption) (*MessageCreateResponse, error) { + req := c.c.NewRequest(c.name, "Message.Create", in) + out := new(MessageCreateResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Message service + +type MessageHandler interface { + Create(context.Context, *MessageCreateRequest, *MessageCreateResponse) error +} + +func RegisterMessageHandler(s server.Server, hdlr MessageHandler, opts ...server.HandlerOption) error { + type message interface { + Create(ctx context.Context, in *MessageCreateRequest, out *MessageCreateResponse) error + } + type Message struct { + message + } + h := &messageHandler{hdlr} + return s.Handle(s.NewHandler(&Message{h}, opts...)) +} + +type messageHandler struct { + MessageHandler +} + +func (h *messageHandler) Create(ctx context.Context, in *MessageCreateRequest, out *MessageCreateResponse) error { + return h.MessageHandler.Create(ctx, in, out) +} diff --git a/backend/srv/message/proto/message.pb.go b/backend/srv/message/proto/message.pb.go new file mode 100644 index 0000000..970646d --- /dev/null +++ b/backend/srv/message/proto/message.pb.go @@ -0,0 +1,330 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: message.proto + +package message + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type MessageInfo_Type int32 + +const ( + MessageInfo_UNKNOWN MessageInfo_Type = 0 + MessageInfo_TEXT MessageInfo_Type = 1 + MessageInfo_PICTURE MessageInfo_Type = 2 + MessageInfo_VIDEO MessageInfo_Type = 3 +) + +var MessageInfo_Type_name = map[int32]string{ + 0: "UNKNOWN", + 1: "TEXT", + 2: "PICTURE", + 3: "VIDEO", +} + +var MessageInfo_Type_value = map[string]int32{ + "UNKNOWN": 0, + "TEXT": 1, + "PICTURE": 2, + "VIDEO": 3, +} + +func (x MessageInfo_Type) String() string { + return proto.EnumName(MessageInfo_Type_name, int32(x)) +} + +func (MessageInfo_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{0, 0} +} + +type MessageCreateRequest_Type int32 + +const ( + MessageCreateRequest_UNKNOWN MessageCreateRequest_Type = 0 + MessageCreateRequest_TEXT MessageCreateRequest_Type = 1 + MessageCreateRequest_PICTURE MessageCreateRequest_Type = 2 + MessageCreateRequest_VIDEO MessageCreateRequest_Type = 3 +) + +var MessageCreateRequest_Type_name = map[int32]string{ + 0: "UNKNOWN", + 1: "TEXT", + 2: "PICTURE", + 3: "VIDEO", +} + +var MessageCreateRequest_Type_value = map[string]int32{ + "UNKNOWN": 0, + "TEXT": 1, + "PICTURE": 2, + "VIDEO": 3, +} + +func (x MessageCreateRequest_Type) String() string { + return proto.EnumName(MessageCreateRequest_Type_name, int32(x)) +} + +func (MessageCreateRequest_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{1, 0} +} + +type MessageCreateResponse_Status int32 + +const ( + MessageCreateResponse_UNKNOWN MessageCreateResponse_Status = 0 + MessageCreateResponse_INVALID_PARAM MessageCreateResponse_Status = -1 + MessageCreateResponse_SUCCESS MessageCreateResponse_Status = 1 +) + +var MessageCreateResponse_Status_name = map[int32]string{ + 0: "UNKNOWN", + -1: "INVALID_PARAM", + 1: "SUCCESS", +} + +var MessageCreateResponse_Status_value = map[string]int32{ + "UNKNOWN": 0, + "INVALID_PARAM": -1, + "SUCCESS": 1, +} + +func (x MessageCreateResponse_Status) String() string { + return proto.EnumName(MessageCreateResponse_Status_name, int32(x)) +} + +func (MessageCreateResponse_Status) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{2, 0} +} + +type MessageInfo struct { + Time int64 `protobuf:"varint,1,opt,name=time,proto3" json:"time,omitempty"` + Forward bool `protobuf:"varint,2,opt,name=forward,proto3" json:"forward,omitempty"` + Type MessageInfo_Type `protobuf:"varint,3,opt,name=type,proto3,enum=MessageInfo_Type" json:"type,omitempty"` + Text string `protobuf:"bytes,4,opt,name=text,proto3" json:"text,omitempty"` + Unread bool `protobuf:"varint,5,opt,name=unread,proto3" json:"unread,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MessageInfo) Reset() { *m = MessageInfo{} } +func (m *MessageInfo) String() string { return proto.CompactTextString(m) } +func (*MessageInfo) ProtoMessage() {} +func (*MessageInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{0} +} + +func (m *MessageInfo) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageInfo.Unmarshal(m, b) +} +func (m *MessageInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageInfo.Marshal(b, m, deterministic) +} +func (m *MessageInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageInfo.Merge(m, src) +} +func (m *MessageInfo) XXX_Size() int { + return xxx_messageInfo_MessageInfo.Size(m) +} +func (m *MessageInfo) XXX_DiscardUnknown() { + xxx_messageInfo_MessageInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageInfo proto.InternalMessageInfo + +func (m *MessageInfo) GetTime() int64 { + if m != nil { + return m.Time + } + return 0 +} + +func (m *MessageInfo) GetForward() bool { + if m != nil { + return m.Forward + } + return false +} + +func (m *MessageInfo) GetType() MessageInfo_Type { + if m != nil { + return m.Type + } + return MessageInfo_UNKNOWN +} + +func (m *MessageInfo) GetText() string { + if m != nil { + return m.Text + } + return "" +} + +func (m *MessageInfo) GetUnread() bool { + if m != nil { + return m.Unread + } + return false +} + +type MessageCreateRequest struct { + FromUser int32 `protobuf:"varint,1,opt,name=fromUser,proto3" json:"fromUser,omitempty"` + ToUser int32 `protobuf:"varint,2,opt,name=toUser,proto3" json:"toUser,omitempty"` + Type MessageCreateRequest_Type `protobuf:"varint,3,opt,name=type,proto3,enum=MessageCreateRequest_Type" json:"type,omitempty"` + Text string `protobuf:"bytes,4,opt,name=text,proto3" json:"text,omitempty"` + File []byte `protobuf:"bytes,5,opt,name=file,proto3" json:"file,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MessageCreateRequest) Reset() { *m = MessageCreateRequest{} } +func (m *MessageCreateRequest) String() string { return proto.CompactTextString(m) } +func (*MessageCreateRequest) ProtoMessage() {} +func (*MessageCreateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{1} +} + +func (m *MessageCreateRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageCreateRequest.Unmarshal(m, b) +} +func (m *MessageCreateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageCreateRequest.Marshal(b, m, deterministic) +} +func (m *MessageCreateRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageCreateRequest.Merge(m, src) +} +func (m *MessageCreateRequest) XXX_Size() int { + return xxx_messageInfo_MessageCreateRequest.Size(m) +} +func (m *MessageCreateRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MessageCreateRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageCreateRequest proto.InternalMessageInfo + +func (m *MessageCreateRequest) GetFromUser() int32 { + if m != nil { + return m.FromUser + } + return 0 +} + +func (m *MessageCreateRequest) GetToUser() int32 { + if m != nil { + return m.ToUser + } + return 0 +} + +func (m *MessageCreateRequest) GetType() MessageCreateRequest_Type { + if m != nil { + return m.Type + } + return MessageCreateRequest_UNKNOWN +} + +func (m *MessageCreateRequest) GetText() string { + if m != nil { + return m.Text + } + return "" +} + +func (m *MessageCreateRequest) GetFile() []byte { + if m != nil { + return m.File + } + return nil +} + +type MessageCreateResponse struct { + Status MessageCreateResponse_Status `protobuf:"varint,1,opt,name=status,proto3,enum=MessageCreateResponse_Status" json:"status,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MessageCreateResponse) Reset() { *m = MessageCreateResponse{} } +func (m *MessageCreateResponse) String() string { return proto.CompactTextString(m) } +func (*MessageCreateResponse) ProtoMessage() {} +func (*MessageCreateResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{2} +} + +func (m *MessageCreateResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageCreateResponse.Unmarshal(m, b) +} +func (m *MessageCreateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageCreateResponse.Marshal(b, m, deterministic) +} +func (m *MessageCreateResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageCreateResponse.Merge(m, src) +} +func (m *MessageCreateResponse) XXX_Size() int { + return xxx_messageInfo_MessageCreateResponse.Size(m) +} +func (m *MessageCreateResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MessageCreateResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageCreateResponse proto.InternalMessageInfo + +func (m *MessageCreateResponse) GetStatus() MessageCreateResponse_Status { + if m != nil { + return m.Status + } + return MessageCreateResponse_UNKNOWN +} + +func init() { + proto.RegisterEnum("MessageInfo_Type", MessageInfo_Type_name, MessageInfo_Type_value) + proto.RegisterEnum("MessageCreateRequest_Type", MessageCreateRequest_Type_name, MessageCreateRequest_Type_value) + proto.RegisterEnum("MessageCreateResponse_Status", MessageCreateResponse_Status_name, MessageCreateResponse_Status_value) + proto.RegisterType((*MessageInfo)(nil), "MessageInfo") + proto.RegisterType((*MessageCreateRequest)(nil), "MessageCreateRequest") + proto.RegisterType((*MessageCreateResponse)(nil), "MessageCreateResponse") +} + +func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) } + +var fileDescriptor_33c57e4bae7b9afd = []byte{ + // 362 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0xdf, 0x4a, 0xf3, 0x30, + 0x14, 0xff, 0xb2, 0x75, 0xdd, 0x76, 0xf6, 0x6d, 0xd4, 0xe0, 0x46, 0x29, 0x08, 0xa5, 0x20, 0xf4, + 0xaa, 0x17, 0x93, 0xe1, 0x9d, 0x30, 0xbb, 0x5e, 0x14, 0x5d, 0x37, 0xd2, 0x76, 0x7a, 0x27, 0x95, + 0xa5, 0x32, 0x70, 0x6b, 0x4d, 0x32, 0x74, 0x2f, 0xe1, 0x5b, 0xf9, 0x10, 0x3e, 0x8d, 0xb2, 0xac, + 0x13, 0x27, 0x05, 0xc1, 0x5c, 0x9d, 0xdf, 0x39, 0x27, 0xbf, 0x3f, 0x21, 0xd0, 0x5e, 0x52, 0xce, + 0x93, 0x07, 0xea, 0xe4, 0x2c, 0x13, 0x99, 0xf5, 0x86, 0xa0, 0x35, 0xde, 0x75, 0xfc, 0x55, 0x9a, + 0x61, 0x0c, 0x8a, 0x58, 0x2c, 0xa9, 0x8e, 0x4c, 0x64, 0x57, 0x89, 0xac, 0xb1, 0x0e, 0xf5, 0x34, + 0x63, 0xcf, 0x09, 0x9b, 0xeb, 0x15, 0x13, 0xd9, 0x0d, 0xb2, 0x87, 0xf8, 0x14, 0x14, 0xb1, 0xc9, + 0xa9, 0x5e, 0x35, 0x91, 0xdd, 0xe9, 0x1f, 0x39, 0xdf, 0x98, 0x9c, 0x68, 0x93, 0x53, 0x22, 0xc7, + 0x92, 0x94, 0xbe, 0x08, 0x5d, 0x31, 0x91, 0xdd, 0x24, 0xb2, 0xc6, 0x3d, 0x50, 0xd7, 0x2b, 0x46, + 0x93, 0xb9, 0x5e, 0x93, 0x9c, 0x05, 0xb2, 0x06, 0xa0, 0x6c, 0x6f, 0xe2, 0x16, 0xd4, 0xe3, 0xe0, + 0x2a, 0x98, 0xdc, 0x04, 0xda, 0x3f, 0xdc, 0x00, 0x25, 0xf2, 0x6e, 0x23, 0x0d, 0x6d, 0xdb, 0x53, + 0xdf, 0x8d, 0x62, 0xe2, 0x69, 0x15, 0xdc, 0x84, 0xda, 0xcc, 0x1f, 0x79, 0x13, 0xad, 0x6a, 0xbd, + 0x23, 0x38, 0x2e, 0xd4, 0x5d, 0x46, 0x13, 0x41, 0x09, 0x7d, 0x5a, 0x53, 0x2e, 0xb0, 0x01, 0x8d, + 0x94, 0x65, 0xcb, 0x98, 0x53, 0x26, 0x43, 0xd5, 0xc8, 0x17, 0xde, 0x7a, 0x10, 0x99, 0x9c, 0x54, + 0xe4, 0xa4, 0x40, 0xd8, 0x39, 0x88, 0x65, 0x38, 0x65, 0xc4, 0xbf, 0xe5, 0xc3, 0xa0, 0xa4, 0x8b, + 0x47, 0x2a, 0xd3, 0xfd, 0x27, 0xb2, 0xfe, 0x6b, 0xb6, 0x57, 0x04, 0xdd, 0x1f, 0x16, 0x78, 0x9e, + 0xad, 0x38, 0xc5, 0x03, 0x50, 0xb9, 0x48, 0xc4, 0x9a, 0xcb, 0x68, 0x9d, 0xfe, 0x89, 0x53, 0xba, + 0xe7, 0x84, 0x72, 0x89, 0x14, 0xcb, 0xd6, 0x05, 0xa8, 0xbb, 0xce, 0xa1, 0x13, 0x03, 0xda, 0x7e, + 0x30, 0x1b, 0x5e, 0xfb, 0xa3, 0xbb, 0xe9, 0x90, 0x0c, 0xc7, 0xda, 0xc7, 0xfe, 0x48, 0x6f, 0x61, + 0xec, 0xba, 0x5e, 0x18, 0x6a, 0xa8, 0x7f, 0x09, 0xf5, 0x42, 0x07, 0x9f, 0x83, 0xba, 0xd3, 0xc2, + 0xdd, 0xd2, 0x67, 0x32, 0x7a, 0xe5, 0x96, 0xee, 0x55, 0xf9, 0xff, 0xce, 0x3e, 0x03, 0x00, 0x00, + 0xff, 0xff, 0x90, 0x46, 0x83, 0x01, 0x90, 0x02, 0x00, 0x00, +} diff --git a/backend/srv/message/proto/message.proto b/backend/srv/message/proto/message.proto index f12808b..ee25566 100644 --- a/backend/srv/message/proto/message.proto +++ b/backend/srv/message/proto/message.proto @@ -1,10 +1,38 @@ syntax = "proto3"; -service { - rpc () returns (); +service Message { + rpc Create (MessageCreateRequest) returns (MessageCreateResponse); } -message { +message MessageInfo{ + enum Type { + UNKNOWN = 0; + TEXT = 1; + PICTURE = 2; + VIDEO = 3; + } + int64 time = 1; + bool forward = 2; + Type type = 3; + string text = 4; + bool unread = 5; +} + +message MessageCreateRequest{ + enum Type { + UNKNOWN = 0; + TEXT = 1; + PICTURE = 2; + VIDEO = 3; + } + int32 fromUser = 1; + int32 toUser = 2; + Type type = 3; + string text = 4; + bytes file = 5; +} + +message MessageCreateResponse { enum Status { UNKNOWN = 0; INVALID_PARAM = -1; From 1992c7079ef5657a491674f457213ba6288bd544 Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Wed, 31 Jul 2019 13:10:28 +0800 Subject: [PATCH 04/17] query chat message --- backend/srv/message/main.go | 113 +++++++++- backend/srv/message/proto/message.micro.go | 17 ++ backend/srv/message/proto/message.pb.go | 251 +++++++++++++++++++-- backend/srv/message/proto/message.proto | 27 +++ 4 files changed, 378 insertions(+), 30 deletions(-) diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index 2a67bb0..ed1809d 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -25,13 +25,10 @@ type srv struct{} * * @apiParam {int32} fromUser user who launch the chat at first time * @apiParam {int32} toUser user who accept the chat at first time - * @apiParam {int32} badge count of message still unread - * @apiParam {int64} time message create time - * @apiParam {bool} forward false for chat from toUser to fromUser
true for chat from fromUser to toUser * @apiParam {int32} type 1 for text
2 for picture
3 for video - * @apiParam {string} text plain message text if type is text
fileID if type is picture or video - * @apiParam {bool} unread false for having read
true for not having read - * @apiSuccess {} status -1 for invalid param
1 for success + * @apiParam {string} text plain message text if type is text + * @apiParam {bytes} file file stream bytes, valid only if type is picture or video + * @apiSuccess {int32} status -1 for invalid param
1 for success * @apiUse DBServerDown */ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp *message.MessageCreateResponse) error { @@ -151,6 +148,110 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp return nil } +/** + * @api {rpc} /rpc Message.Query + * @apiVersion 1.0.0 + * @apiGroup Service + * @apiName Message.Create + * @apiDescription Create Message + * + * @apiParam {int32} fromUser user who launch the chat at first time + * @apiParam {int32} toUser user who accept the chat at first time + * @apiParam {int32} way 1 for only pull message
2 for read message
3 for query history message + * @apiSuccess {int32} fromUser user who launch the chat at first time + * @apiSuccess {int32} toUser user who accept the chat at first time + * @apiSuccess {int32} badge count of message still unread + * @apiSuccess {int32} status -1 for invalid param
1 for success
2 for not found + * @apiSuccess {list} infos see below MessageInfo + * @apiSuccess (MessageInfo) {int64} time message create time + * @apiSuccess (MessageInfo) {bool} forward false for chat from toUser to fromUser
true for chat from fromUser to toUser + * @apiSuccess (MessageInfo) {int32} type 1 for text
2 for picture
3 for video + * @apiSuccess (MessageInfo) {string} text plain message text if type is text
fileID if type is picture or video + * @apiParam (MessageInfo) {bool} unread false for having read
true for not having read + * @apiUse DBServerDown + */ +func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp *message.MessageQueryResponse) error { + if !utils.RequireParam(req.FromUser, req.ToUser, req.Way) { + rsp.Status = message.MessageQueryResponse_INVALID_PARAM + return nil + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + collection := db.MongoDatabase.Collection("sellinfo") + _, err1 := collection.Find(ctx, bson.M{ + "fromUser": req.FromUser, + "toUser": req.ToUser, + }) + _, err2 := collection.Find(ctx, bson.M{ + "fromUser": req.ToUser, + "toUser": req.FromUser, + }) + + if err1 == nil && err2 != nil { + rsp.FromUser = req.FromUser + rsp.ToUser = req.ToUser + } else if err1 != nil && err2 == nil { + rsp.FromUser = req.ToUser + rsp.ToUser = req.FromUser + } else if err1 != nil && err2 != nil { + rsp.Status = message.MessageQueryResponse_NOT_FOUND + return nil + } else { + rsp.Status = message.MessageQueryResponse_INVALID_PARAM + return nil + } + + if req.Way == message.MessageQueryRequest_ONLY_PULL { + err := collection.FindOne(ctx, bson.M{ + "fromUser": rsp.FromUser, + "toUser": rsp.ToUser, + "infos": bson.M{ + "forward": req.FromUser == rsp.FromUser, + "unread": true, + }, + }).Decode(&rsp) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageQueryResponse_UNKNOWN + return nil + } + rsp.Status = message.MessageQueryResponse_SUCCESS + return nil + } else if req.Way == message.MessageQueryRequest_READ_MESSAGE { + err := collection.FindOneAndUpdate(ctx, bson.M{ + "fromUser": rsp.FromUser, + "toUser": rsp.ToUser, + "infos": bson.M{ + "forward": req.FromUser == rsp.FromUser, + "unread": true, + }, + }, bson.M{ + "$set": bson.M{ + "badge": 0, + "unread": false, + }, + }).Decode(&rsp) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageQueryResponse_UNKNOWN + return nil + } + rsp.Status = message.MessageQueryResponse_SUCCESS + return nil + } else if req.Way == message.MessageQueryRequest_HISTORY { + err := collection.FindOne(ctx, bson.M{ + "fromUser": rsp.FromUser, + "toUser": rsp.ToUser, + }).Decode(&rsp) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageQueryResponse_UNKNOWN + return nil + } + rsp.Status = message.MessageQueryResponse_SUCCESS + return nil + } + return nil +} + func main() { service := utils.InitMicroService("message") utils.LogPanic(message.RegisterMessageHandler(service.Server(), new(srv))) diff --git a/backend/srv/message/proto/message.micro.go b/backend/srv/message/proto/message.micro.go index d4f7790..57b763e 100644 --- a/backend/srv/message/proto/message.micro.go +++ b/backend/srv/message/proto/message.micro.go @@ -35,6 +35,7 @@ var _ server.Option type MessageService interface { Create(ctx context.Context, in *MessageCreateRequest, opts ...client.CallOption) (*MessageCreateResponse, error) + Query(ctx context.Context, in *MessageQueryRequest, opts ...client.CallOption) (*MessageQueryResponse, error) } type messageService struct { @@ -65,15 +66,27 @@ func (c *messageService) Create(ctx context.Context, in *MessageCreateRequest, o return out, nil } +func (c *messageService) Query(ctx context.Context, in *MessageQueryRequest, opts ...client.CallOption) (*MessageQueryResponse, error) { + req := c.c.NewRequest(c.name, "Message.Query", in) + out := new(MessageQueryResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Message service type MessageHandler interface { Create(context.Context, *MessageCreateRequest, *MessageCreateResponse) error + Query(context.Context, *MessageQueryRequest, *MessageQueryResponse) error } func RegisterMessageHandler(s server.Server, hdlr MessageHandler, opts ...server.HandlerOption) error { type message interface { Create(ctx context.Context, in *MessageCreateRequest, out *MessageCreateResponse) error + Query(ctx context.Context, in *MessageQueryRequest, out *MessageQueryResponse) error } type Message struct { message @@ -89,3 +102,7 @@ type messageHandler struct { func (h *messageHandler) Create(ctx context.Context, in *MessageCreateRequest, out *MessageCreateResponse) error { return h.MessageHandler.Create(ctx, in, out) } + +func (h *messageHandler) Query(ctx context.Context, in *MessageQueryRequest, out *MessageQueryResponse) error { + return h.MessageHandler.Query(ctx, in, out) +} diff --git a/backend/srv/message/proto/message.pb.go b/backend/srv/message/proto/message.pb.go index 970646d..7637ac3 100644 --- a/backend/srv/message/proto/message.pb.go +++ b/backend/srv/message/proto/message.pb.go @@ -110,6 +110,68 @@ func (MessageCreateResponse_Status) EnumDescriptor() ([]byte, []int) { return fileDescriptor_33c57e4bae7b9afd, []int{2, 0} } +type MessageQueryRequest_Way int32 + +const ( + MessageQueryRequest_UNKNOWN MessageQueryRequest_Way = 0 + MessageQueryRequest_ONLY_PULL MessageQueryRequest_Way = 1 + MessageQueryRequest_READ_MESSAGE MessageQueryRequest_Way = 2 + MessageQueryRequest_HISTORY MessageQueryRequest_Way = 3 +) + +var MessageQueryRequest_Way_name = map[int32]string{ + 0: "UNKNOWN", + 1: "ONLY_PULL", + 2: "READ_MESSAGE", + 3: "HISTORY", +} + +var MessageQueryRequest_Way_value = map[string]int32{ + "UNKNOWN": 0, + "ONLY_PULL": 1, + "READ_MESSAGE": 2, + "HISTORY": 3, +} + +func (x MessageQueryRequest_Way) String() string { + return proto.EnumName(MessageQueryRequest_Way_name, int32(x)) +} + +func (MessageQueryRequest_Way) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{3, 0} +} + +type MessageQueryResponse_Status int32 + +const ( + MessageQueryResponse_UNKNOWN MessageQueryResponse_Status = 0 + MessageQueryResponse_INVALID_PARAM MessageQueryResponse_Status = -1 + MessageQueryResponse_SUCCESS MessageQueryResponse_Status = 1 + MessageQueryResponse_NOT_FOUND MessageQueryResponse_Status = 2 +) + +var MessageQueryResponse_Status_name = map[int32]string{ + 0: "UNKNOWN", + -1: "INVALID_PARAM", + 1: "SUCCESS", + 2: "NOT_FOUND", +} + +var MessageQueryResponse_Status_value = map[string]int32{ + "UNKNOWN": 0, + "INVALID_PARAM": -1, + "SUCCESS": 1, + "NOT_FOUND": 2, +} + +func (x MessageQueryResponse_Status) String() string { + return proto.EnumName(MessageQueryResponse_Status_name, int32(x)) +} + +func (MessageQueryResponse_Status) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{4, 0} +} + type MessageInfo struct { Time int64 `protobuf:"varint,1,opt,name=time,proto3" json:"time,omitempty"` Forward bool `protobuf:"varint,2,opt,name=forward,proto3" json:"forward,omitempty"` @@ -291,40 +353,181 @@ func (m *MessageCreateResponse) GetStatus() MessageCreateResponse_Status { return MessageCreateResponse_UNKNOWN } +type MessageQueryRequest struct { + FromUser int32 `protobuf:"varint,1,opt,name=fromUser,proto3" json:"fromUser,omitempty"` + ToUser int32 `protobuf:"varint,2,opt,name=toUser,proto3" json:"toUser,omitempty"` + Way MessageQueryRequest_Way `protobuf:"varint,3,opt,name=way,proto3,enum=MessageQueryRequest_Way" json:"way,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MessageQueryRequest) Reset() { *m = MessageQueryRequest{} } +func (m *MessageQueryRequest) String() string { return proto.CompactTextString(m) } +func (*MessageQueryRequest) ProtoMessage() {} +func (*MessageQueryRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{3} +} + +func (m *MessageQueryRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageQueryRequest.Unmarshal(m, b) +} +func (m *MessageQueryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageQueryRequest.Marshal(b, m, deterministic) +} +func (m *MessageQueryRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageQueryRequest.Merge(m, src) +} +func (m *MessageQueryRequest) XXX_Size() int { + return xxx_messageInfo_MessageQueryRequest.Size(m) +} +func (m *MessageQueryRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MessageQueryRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageQueryRequest proto.InternalMessageInfo + +func (m *MessageQueryRequest) GetFromUser() int32 { + if m != nil { + return m.FromUser + } + return 0 +} + +func (m *MessageQueryRequest) GetToUser() int32 { + if m != nil { + return m.ToUser + } + return 0 +} + +func (m *MessageQueryRequest) GetWay() MessageQueryRequest_Way { + if m != nil { + return m.Way + } + return MessageQueryRequest_UNKNOWN +} + +type MessageQueryResponse struct { + Status MessageQueryResponse_Status `protobuf:"varint,1,opt,name=status,proto3,enum=MessageQueryResponse_Status" json:"status,omitempty"` + FromUser int32 `protobuf:"varint,2,opt,name=fromUser,proto3" json:"fromUser,omitempty"` + ToUser int32 `protobuf:"varint,3,opt,name=toUser,proto3" json:"toUser,omitempty"` + Badge int32 `protobuf:"varint,4,opt,name=badge,proto3" json:"badge,omitempty"` + Infos []*MessageInfo `protobuf:"bytes,5,rep,name=infos,proto3" json:"infos,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MessageQueryResponse) Reset() { *m = MessageQueryResponse{} } +func (m *MessageQueryResponse) String() string { return proto.CompactTextString(m) } +func (*MessageQueryResponse) ProtoMessage() {} +func (*MessageQueryResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{4} +} + +func (m *MessageQueryResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageQueryResponse.Unmarshal(m, b) +} +func (m *MessageQueryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageQueryResponse.Marshal(b, m, deterministic) +} +func (m *MessageQueryResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageQueryResponse.Merge(m, src) +} +func (m *MessageQueryResponse) XXX_Size() int { + return xxx_messageInfo_MessageQueryResponse.Size(m) +} +func (m *MessageQueryResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MessageQueryResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageQueryResponse proto.InternalMessageInfo + +func (m *MessageQueryResponse) GetStatus() MessageQueryResponse_Status { + if m != nil { + return m.Status + } + return MessageQueryResponse_UNKNOWN +} + +func (m *MessageQueryResponse) GetFromUser() int32 { + if m != nil { + return m.FromUser + } + return 0 +} + +func (m *MessageQueryResponse) GetToUser() int32 { + if m != nil { + return m.ToUser + } + return 0 +} + +func (m *MessageQueryResponse) GetBadge() int32 { + if m != nil { + return m.Badge + } + return 0 +} + +func (m *MessageQueryResponse) GetInfos() []*MessageInfo { + if m != nil { + return m.Infos + } + return nil +} + func init() { proto.RegisterEnum("MessageInfo_Type", MessageInfo_Type_name, MessageInfo_Type_value) proto.RegisterEnum("MessageCreateRequest_Type", MessageCreateRequest_Type_name, MessageCreateRequest_Type_value) proto.RegisterEnum("MessageCreateResponse_Status", MessageCreateResponse_Status_name, MessageCreateResponse_Status_value) + proto.RegisterEnum("MessageQueryRequest_Way", MessageQueryRequest_Way_name, MessageQueryRequest_Way_value) + proto.RegisterEnum("MessageQueryResponse_Status", MessageQueryResponse_Status_name, MessageQueryResponse_Status_value) proto.RegisterType((*MessageInfo)(nil), "MessageInfo") proto.RegisterType((*MessageCreateRequest)(nil), "MessageCreateRequest") proto.RegisterType((*MessageCreateResponse)(nil), "MessageCreateResponse") + proto.RegisterType((*MessageQueryRequest)(nil), "MessageQueryRequest") + proto.RegisterType((*MessageQueryResponse)(nil), "MessageQueryResponse") } func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) } var fileDescriptor_33c57e4bae7b9afd = []byte{ - // 362 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0xdf, 0x4a, 0xf3, 0x30, - 0x14, 0xff, 0xb2, 0x75, 0xdd, 0x76, 0xf6, 0x6d, 0xd4, 0xe0, 0x46, 0x29, 0x08, 0xa5, 0x20, 0xf4, - 0xaa, 0x17, 0x93, 0xe1, 0x9d, 0x30, 0xbb, 0x5e, 0x14, 0x5d, 0x37, 0xd2, 0x76, 0x7a, 0x27, 0x95, - 0xa5, 0x32, 0x70, 0x6b, 0x4d, 0x32, 0x74, 0x2f, 0xe1, 0x5b, 0xf9, 0x10, 0x3e, 0x8d, 0xb2, 0xac, - 0x13, 0x27, 0x05, 0xc1, 0x5c, 0x9d, 0xdf, 0x39, 0x27, 0xbf, 0x3f, 0x21, 0xd0, 0x5e, 0x52, 0xce, - 0x93, 0x07, 0xea, 0xe4, 0x2c, 0x13, 0x99, 0xf5, 0x86, 0xa0, 0x35, 0xde, 0x75, 0xfc, 0x55, 0x9a, - 0x61, 0x0c, 0x8a, 0x58, 0x2c, 0xa9, 0x8e, 0x4c, 0x64, 0x57, 0x89, 0xac, 0xb1, 0x0e, 0xf5, 0x34, - 0x63, 0xcf, 0x09, 0x9b, 0xeb, 0x15, 0x13, 0xd9, 0x0d, 0xb2, 0x87, 0xf8, 0x14, 0x14, 0xb1, 0xc9, - 0xa9, 0x5e, 0x35, 0x91, 0xdd, 0xe9, 0x1f, 0x39, 0xdf, 0x98, 0x9c, 0x68, 0x93, 0x53, 0x22, 0xc7, - 0x92, 0x94, 0xbe, 0x08, 0x5d, 0x31, 0x91, 0xdd, 0x24, 0xb2, 0xc6, 0x3d, 0x50, 0xd7, 0x2b, 0x46, - 0x93, 0xb9, 0x5e, 0x93, 0x9c, 0x05, 0xb2, 0x06, 0xa0, 0x6c, 0x6f, 0xe2, 0x16, 0xd4, 0xe3, 0xe0, - 0x2a, 0x98, 0xdc, 0x04, 0xda, 0x3f, 0xdc, 0x00, 0x25, 0xf2, 0x6e, 0x23, 0x0d, 0x6d, 0xdb, 0x53, - 0xdf, 0x8d, 0x62, 0xe2, 0x69, 0x15, 0xdc, 0x84, 0xda, 0xcc, 0x1f, 0x79, 0x13, 0xad, 0x6a, 0xbd, - 0x23, 0x38, 0x2e, 0xd4, 0x5d, 0x46, 0x13, 0x41, 0x09, 0x7d, 0x5a, 0x53, 0x2e, 0xb0, 0x01, 0x8d, - 0x94, 0x65, 0xcb, 0x98, 0x53, 0x26, 0x43, 0xd5, 0xc8, 0x17, 0xde, 0x7a, 0x10, 0x99, 0x9c, 0x54, - 0xe4, 0xa4, 0x40, 0xd8, 0x39, 0x88, 0x65, 0x38, 0x65, 0xc4, 0xbf, 0xe5, 0xc3, 0xa0, 0xa4, 0x8b, - 0x47, 0x2a, 0xd3, 0xfd, 0x27, 0xb2, 0xfe, 0x6b, 0xb6, 0x57, 0x04, 0xdd, 0x1f, 0x16, 0x78, 0x9e, - 0xad, 0x38, 0xc5, 0x03, 0x50, 0xb9, 0x48, 0xc4, 0x9a, 0xcb, 0x68, 0x9d, 0xfe, 0x89, 0x53, 0xba, - 0xe7, 0x84, 0x72, 0x89, 0x14, 0xcb, 0xd6, 0x05, 0xa8, 0xbb, 0xce, 0xa1, 0x13, 0x03, 0xda, 0x7e, - 0x30, 0x1b, 0x5e, 0xfb, 0xa3, 0xbb, 0xe9, 0x90, 0x0c, 0xc7, 0xda, 0xc7, 0xfe, 0x48, 0x6f, 0x61, - 0xec, 0xba, 0x5e, 0x18, 0x6a, 0xa8, 0x7f, 0x09, 0xf5, 0x42, 0x07, 0x9f, 0x83, 0xba, 0xd3, 0xc2, - 0xdd, 0xd2, 0x67, 0x32, 0x7a, 0xe5, 0x96, 0xee, 0x55, 0xf9, 0xff, 0xce, 0x3e, 0x03, 0x00, 0x00, - 0xff, 0xff, 0x90, 0x46, 0x83, 0x01, 0x90, 0x02, 0x00, 0x00, + // 533 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcd, 0x6a, 0xdb, 0x4c, + 0x14, 0xfd, 0x46, 0x3f, 0xfe, 0xb9, 0xb6, 0xc3, 0x7c, 0x53, 0x3b, 0x08, 0xd3, 0x82, 0x11, 0x14, + 0x4c, 0x17, 0xb3, 0x70, 0x13, 0xba, 0x2b, 0x35, 0xb6, 0xda, 0x8a, 0xda, 0x92, 0x3b, 0x92, 0xe2, + 0x66, 0x65, 0x14, 0x3c, 0x0a, 0x86, 0xda, 0x72, 0x25, 0x99, 0x44, 0x8f, 0xd0, 0x4d, 0x5f, 0xa7, + 0x4f, 0xd0, 0x87, 0xe8, 0xd3, 0xb4, 0x68, 0xa4, 0x84, 0xc8, 0xa8, 0x14, 0x1a, 0xad, 0xe6, 0xfe, + 0xe8, 0xde, 0x73, 0xce, 0x1c, 0x09, 0x3a, 0x5b, 0x1e, 0xc7, 0xfe, 0x35, 0xa7, 0xfb, 0x28, 0x4c, + 0x42, 0xfd, 0x07, 0x82, 0xd6, 0x3c, 0xcf, 0x98, 0xbb, 0x20, 0x24, 0x04, 0x94, 0x64, 0xb3, 0xe5, + 0x1a, 0x1a, 0xa0, 0xa1, 0xcc, 0xc4, 0x99, 0x68, 0x50, 0x0f, 0xc2, 0xe8, 0xc6, 0x8f, 0xd6, 0x9a, + 0x34, 0x40, 0xc3, 0x06, 0xbb, 0x0b, 0xc9, 0x73, 0x50, 0x92, 0x74, 0xcf, 0x35, 0x79, 0x80, 0x86, + 0x27, 0xa3, 0xff, 0xe9, 0x83, 0x49, 0xd4, 0x4d, 0xf7, 0x9c, 0x89, 0xb2, 0x18, 0xca, 0x6f, 0x13, + 0x4d, 0x19, 0xa0, 0x61, 0x93, 0x89, 0x33, 0x39, 0x85, 0xda, 0x61, 0x17, 0x71, 0x7f, 0xad, 0xa9, + 0x62, 0x66, 0x11, 0xe9, 0xe7, 0xa0, 0x64, 0x6f, 0x92, 0x16, 0xd4, 0x3d, 0xeb, 0x83, 0x65, 0x2f, + 0x2d, 0xfc, 0x1f, 0x69, 0x80, 0xe2, 0x1a, 0x9f, 0x5c, 0x8c, 0xb2, 0xf4, 0xc2, 0x9c, 0xb8, 0x1e, + 0x33, 0xb0, 0x44, 0x9a, 0xa0, 0x5e, 0x98, 0x53, 0xc3, 0xc6, 0xb2, 0xfe, 0x13, 0x41, 0xb7, 0xd8, + 0x3e, 0x89, 0xb8, 0x9f, 0x70, 0xc6, 0xbf, 0x1c, 0x78, 0x9c, 0x90, 0x3e, 0x34, 0x82, 0x28, 0xdc, + 0x7a, 0x31, 0x8f, 0x04, 0x29, 0x95, 0xdd, 0xc7, 0x19, 0x86, 0x24, 0x14, 0x15, 0x49, 0x54, 0x8a, + 0x88, 0xd0, 0x12, 0xad, 0x3e, 0xad, 0x1a, 0xfc, 0x37, 0x7e, 0x04, 0x94, 0x60, 0xf3, 0x99, 0x0b, + 0x76, 0x6d, 0x26, 0xce, 0xff, 0xca, 0xed, 0x1b, 0x82, 0xde, 0x11, 0x84, 0x78, 0x1f, 0xee, 0x62, + 0x4e, 0xce, 0xa1, 0x16, 0x27, 0x7e, 0x72, 0x88, 0x05, 0xb5, 0x93, 0xd1, 0x33, 0x5a, 0xd9, 0x47, + 0x1d, 0xd1, 0xc4, 0x8a, 0x66, 0xfd, 0x35, 0xd4, 0xf2, 0x4c, 0x19, 0x49, 0x1f, 0x3a, 0xa6, 0x75, + 0x31, 0x9e, 0x99, 0xd3, 0xd5, 0x62, 0xcc, 0xc6, 0x73, 0xfc, 0xeb, 0xee, 0x11, 0xd8, 0x1c, 0x6f, + 0x32, 0x31, 0x1c, 0x07, 0x23, 0xfd, 0x3b, 0x82, 0x27, 0xc5, 0xa2, 0x8f, 0x07, 0x1e, 0xa5, 0x8f, + 0xd1, 0xfa, 0x05, 0xc8, 0x37, 0x7e, 0x5a, 0x48, 0xad, 0xd1, 0x8a, 0xb1, 0x74, 0xe9, 0xa7, 0x2c, + 0x6b, 0xd2, 0xdf, 0x80, 0xbc, 0xf4, 0xd3, 0x32, 0xe8, 0x0e, 0x34, 0x6d, 0x6b, 0x76, 0xb9, 0x5a, + 0x78, 0xb3, 0x19, 0x46, 0x04, 0x43, 0x9b, 0x19, 0xe3, 0xe9, 0x6a, 0x6e, 0x38, 0xce, 0xf8, 0x5d, + 0x26, 0x64, 0x0b, 0xea, 0xef, 0x4d, 0xc7, 0xb5, 0xd9, 0x25, 0x96, 0xf5, 0xaf, 0xd2, 0xbd, 0x4d, + 0x8a, 0x15, 0x85, 0x92, 0x67, 0x47, 0x4a, 0x3e, 0xa5, 0x55, 0x6d, 0x47, 0x42, 0x96, 0x08, 0x4b, + 0x7f, 0x24, 0x2c, 0x97, 0x08, 0x77, 0x41, 0xbd, 0xf2, 0xd7, 0xd7, 0x5c, 0xb8, 0x45, 0x65, 0x79, + 0x40, 0x74, 0x50, 0x37, 0xbb, 0x20, 0x8c, 0x35, 0x75, 0x20, 0x0f, 0x5b, 0xa3, 0xf6, 0xc3, 0x4f, + 0x89, 0xe5, 0x25, 0x7d, 0xfe, 0xb8, 0x6b, 0xcb, 0xa4, 0xb2, 0x6c, 0x77, 0xf5, 0xd6, 0xf6, 0xac, + 0x29, 0x96, 0x46, 0xb7, 0x50, 0x2f, 0x96, 0x90, 0x57, 0x50, 0xcb, 0x1d, 0x43, 0x7a, 0x95, 0x66, + 0xef, 0x9f, 0x56, 0x1b, 0x8b, 0x9c, 0x81, 0x2a, 0x04, 0x22, 0xdd, 0xaa, 0x9b, 0xeb, 0xf7, 0x2a, + 0x55, 0xbc, 0xaa, 0x89, 0x7f, 0xcf, 0xcb, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xdd, 0xf9, 0x95, + 0xfc, 0x8c, 0x04, 0x00, 0x00, } diff --git a/backend/srv/message/proto/message.proto b/backend/srv/message/proto/message.proto index ee25566..3e9960d 100644 --- a/backend/srv/message/proto/message.proto +++ b/backend/srv/message/proto/message.proto @@ -2,6 +2,7 @@ syntax = "proto3"; service Message { rpc Create (MessageCreateRequest) returns (MessageCreateResponse); + rpc Query (MessageQueryRequest) returns (MessageQueryResponse); } message MessageInfo{ @@ -39,4 +40,30 @@ message MessageCreateResponse { SUCCESS = 1; } Status status = 1; +} + +message MessageQueryRequest { + enum Way { + UNKNOWN = 0; + ONLY_PULL = 1; + READ_MESSAGE = 2; + HISTORY = 3; + } + int32 fromUser = 1; + int32 toUser = 2; + Way way = 3; +} + +message MessageQueryResponse { + enum Status { + UNKNOWN = 0; + INVALID_PARAM = -1; + SUCCESS = 1; + NOT_FOUND = 2; + } + Status status = 1; + int32 fromUser = 2; + int32 toUser = 3; + int32 badge = 4; + repeated MessageInfo infos = 5; } \ No newline at end of file From 34d7bc56011f3e1f90a92be44040cedf0feb7e73 Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Wed, 31 Jul 2019 14:32:38 +0800 Subject: [PATCH 05/17] chat message api --- backend/api/message/main.go | 121 +++++++++++++++++++++++++++---- backend/srv/message/main_test.go | 21 +++++- backend/srv/message/mock/mock.go | 24 ++++-- 3 files changed, 140 insertions(+), 26 deletions(-) diff --git a/backend/api/message/main.go b/backend/api/message/main.go index 9dd0882..fc51154 100644 --- a/backend/api/message/main.go +++ b/backend/api/message/main.go @@ -1,38 +1,131 @@ package main import ( + "context" + "jiaojiao/srv/message/mock" + message "jiaojiao/srv/message/proto" "jiaojiao/utils" "github.com/gin-gonic/gin" + "github.com/micro/go-micro/client" ) func setupRouter() *gin.Engine { router, rg := utils.CreateAPIGroup() - rg.GET("/message", ) + rg.GET("/message", findMessage) + rg.POST("/message", addMessage) return router } /** - * @apiIgnore - * @api {} /message + * @apiDefine MessageServiceDown + * @apiError (Error 500) MessageServiceDown Message service down + */ + +/** + * @api {post} /message AddMessage + * @apiVersion 1.0.0 + * @apiGroup Message + * @apiPermission self/admin + * @apiName AddMessage + * @apiDescription Add chat message + * + * @apiParam {--} Param see [Message Service](#api-Service-Message_Create) + * @apiSuccess (Success 200) {Response} response see [Message Service](#api-Service-Message_Create) + * @apiUse InvalidParam + * @apiUse MessageServiceDown + */ +func addMessage(c *gin.Context) { + type param struct { + FromUser int32 `form:"fromUser" binding:"required"` + ToUser int32 `form:"toUser" binding:"required"` + Type message.MessageCreateRequest_Type `form:"type" binding:"required"` + Text string `form:"text"` + } + var p param + var data []byte + + if !utils.LogContinue(c.ShouldBind(&p), utils.Warning) { + if p.Type == message.MessageCreateRequest_PICTURE || p.Type == message.MessageCreateRequest_VIDEO { + var code int + var err error + data, code, err = utils.GetQueryFile(c, "file", 1024*1024*50) // 50M + if err != nil { + c.AbortWithStatus(400) + return + } + if code != 200 { + c.AbortWithStatus(code) + return + } + } + role1 := utils.GetRoleID(c, int32(p.FromUser)) + role2 := utils.GetRoleID(c, int32(p.FromUser)) + if !(role1.Self || role1.Admin || role2.Self || role2.Admin) { + c.Status(403) + return + } + + srv := utils.CallMicroService("message", func(name string, c client.Client) interface{} { return message.NewMessageService(name, c) }, + func() interface{} { return mock.NewMessageService() }).(message.MessageService) + rsp, err := srv.Create(context.TODO(), &message.MessageCreateRequest{ + FromUser: p.FromUser, + ToUser: p.ToUser, + Type: p.Type, + Text: p.Text, + File: data, + }) + if utils.LogContinue(err, utils.Warning, "Message service error: %v", err) { + c.JSON(500, err) + return + } + c.JSON(200, rsp) + } else { + c.AbortWithStatus(400) + } +} + +/** + * @api {get} /message FindMessage * @apiVersion 1.0.0 - * @apiGroup - * @apiPermission - * @apiName - * @apiDescription + * @apiGroup Message + * @apiPermission self/admin + * @apiName FindMessage + * @apiDescription Find chat message * - * @apiParam - * @apiSuccess - * @apiError (Error 500) + * @apiParam {--} Param see [Message Service](#api-Service-Message_Query) + * @apiSuccess (Success 200) {Response} response see [Message Service](#api-Service-Message_Query) + * @apiUse InvalidParam + * @apiUse MessageServiceDown */ -func (c *gin.Context) { +func findMessage(c *gin.Context) { type param struct { - string `form:""` + FromUser int32 `form:"fromUser" binding:"required"` + ToUser int32 `form:"toUser" binding:"required"` + Way message.MessageQueryRequest_Way `form:"way" binding:"required"` } var p param - if !utils.LogContinue(c.ShouldBindQuery(&p), utils.Warning) { - + if !utils.LogContinue(c.ShouldBind(&p), utils.Warning) { + role1 := utils.GetRoleID(c, int32(p.FromUser)) + role2 := utils.GetRoleID(c, int32(p.FromUser)) + if !(role1.Self || role1.Admin || role2.Self || role2.Admin) { + c.Status(403) + return + } + + srv := utils.CallMicroService("message", func(name string, c client.Client) interface{} { return message.NewMessageService(name, c) }, + func() interface{} { return mock.NewMessageService() }).(message.MessageService) + rsp, err := srv.Query(context.TODO(), &message.MessageQueryRequest{ + FromUser: p.FromUser, + ToUser: p.ToUser, + Way: p.Way, + }) + if utils.LogContinue(err, utils.Warning, "Message service error: %v", err) { + c.JSON(500, err) + return + } + c.JSON(200, rsp) } else { c.AbortWithStatus(400) } diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index 8e41320..8c3324e 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -1,19 +1,32 @@ package main import ( + "context" + message "jiaojiao/srv/message/proto" "testing" . "github.com/smartystreets/goconvey/convey" ) -func Test(t *testing.T) { +func TestCreate(t *testing.T) { var s srv - var req - Convey("Test", t, func() { - + var req message.MessageCreateRequest + Convey("Test Create Message", t, func() { + err := s.Create(context.TODO(), &req, &message.MessageCreateResponse{}) + ShouldBeNil(err) }) } +func TestQuery(t *testing.T) { + var s srv + var req message.MessageQueryRequest + Convey("Test Query Message", t, func() { + err := s.Query(context.TODO(), &req, &message.MessageQueryResponse{}) + ShouldBeNil(err) + }) + +} + func TestMain(m *testing.M) { main() m.Run() diff --git a/backend/srv/message/mock/mock.go b/backend/srv/message/mock/mock.go index 93d187b..4d02454 100644 --- a/backend/srv/message/mock/mock.go +++ b/backend/srv/message/mock/mock.go @@ -1,19 +1,27 @@ package mock import ( + "context" + message "jiaojiao/srv/message/proto" + "github.com/micro/go-micro/client" ) -type mockSrv struct{} +type mockMessageSrv struct{} + +func (a *mockMessageSrv) Query(ctx context.Context, in *message.MessageQueryRequest, opts ...client.CallOption) (*message.MessageQueryResponse, error) { + var rsp message.MessageQueryResponse + // TODO + return &rsp, nil +} -// is mock -func (a *mockSrv) (ctx context.Context, req *, opts ...client.CallOption) (*, error) { - var ret - - return &ret, nil +func (a *mockMessageSrv) Create(ctx context.Context, in *message.MessageCreateRequest, opts ...client.CallOption) (*message.MessageCreateResponse, error) { + var rsp message.MessageCreateResponse + // TODO + return &rsp, nil } // is service mock -func New Service() . Service { - return new(mockSrv) +func NewMessageService() message.MessageService { + return new(mockMessageSrv) } From 219afd52ec542fb686d73d8cd206a2075a5c92d5 Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Wed, 31 Jul 2019 14:51:17 +0800 Subject: [PATCH 06/17] optimize naming and fix doc --- backend/api/message/main.go | 12 +- backend/apidoc.json | 1 + backend/doc/api_data.js | 336 +++++++++++++++++++++ backend/doc/api_data.json | 336 +++++++++++++++++++++ backend/doc/api_project.js | 3 +- backend/doc/api_project.json | 3 +- backend/srv/message/main.go | 38 +-- backend/srv/message/main_test.go | 8 +- backend/srv/message/proto/message.micro.go | 16 +- backend/srv/message/proto/message.pb.go | 230 +++++++------- backend/srv/message/proto/message.proto | 6 +- 11 files changed, 832 insertions(+), 157 deletions(-) diff --git a/backend/api/message/main.go b/backend/api/message/main.go index fc51154..c3cb2d2 100644 --- a/backend/api/message/main.go +++ b/backend/api/message/main.go @@ -93,16 +93,16 @@ func addMessage(c *gin.Context) { * @apiName FindMessage * @apiDescription Find chat message * - * @apiParam {--} Param see [Message Service](#api-Service-Message_Query) - * @apiSuccess (Success 200) {Response} response see [Message Service](#api-Service-Message_Query) + * @apiParam {--} Param see [Message Service](#api-Service-Message_Find) + * @apiSuccess (Success 200) {Response} response see [Message Service](#api-Service-Message_Find) * @apiUse InvalidParam * @apiUse MessageServiceDown */ func findMessage(c *gin.Context) { type param struct { - FromUser int32 `form:"fromUser" binding:"required"` - ToUser int32 `form:"toUser" binding:"required"` - Way message.MessageQueryRequest_Way `form:"way" binding:"required"` + FromUser int32 `form:"fromUser" binding:"required"` + ToUser int32 `form:"toUser" binding:"required"` + Way message.MessageFindRequest_Way `form:"way" binding:"required"` } var p param @@ -116,7 +116,7 @@ func findMessage(c *gin.Context) { srv := utils.CallMicroService("message", func(name string, c client.Client) interface{} { return message.NewMessageService(name, c) }, func() interface{} { return mock.NewMessageService() }).(message.MessageService) - rsp, err := srv.Query(context.TODO(), &message.MessageQueryRequest{ + rsp, err := srv.Find(context.TODO(), &message.MessageFindRequest{ FromUser: p.FromUser, ToUser: p.ToUser, Way: p.Way, diff --git a/backend/apidoc.json b/backend/apidoc.json index 7250833..69dfdf7 100644 --- a/backend/apidoc.json +++ b/backend/apidoc.json @@ -13,6 +13,7 @@ "Avatar", "File", "Transaction", + "Message", "Service" ] } diff --git a/backend/doc/api_data.js b/backend/doc/api_data.js index 3aba1f0..4992064 100644 --- a/backend/doc/api_data.js +++ b/backend/doc/api_data.js @@ -652,6 +652,130 @@ define({ "api": [ "filename": "api/file/main.go", "groupTitle": "File" }, + { + "type": "post", + "url": "/message", + "title": "AddMessage", + "version": "1.0.0", + "group": "Message", + "permission": [ + { + "name": "self/admin" + } + ], + "name": "AddMessage", + "description": "

Add chat message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "--", + "optional": false, + "field": "Param", + "description": "

see Message Service

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "Response", + "optional": false, + "field": "response", + "description": "

see Message Service

" + } + ] + } + }, + "filename": "api/message/main.go", + "groupTitle": "Message", + "error": { + "fields": { + "Error 400": [ + { + "group": "Error 400", + "optional": false, + "field": "InvalidParam", + "description": "

Invalid param

" + } + ], + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "MessageServiceDown", + "description": "

Message service down

" + } + ] + } + } + }, + { + "type": "get", + "url": "/message", + "title": "FindMessage", + "version": "1.0.0", + "group": "Message", + "permission": [ + { + "name": "self/admin" + } + ], + "name": "FindMessage", + "description": "

Find chat message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "--", + "optional": false, + "field": "Param", + "description": "

see Message Service

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "Response", + "optional": false, + "field": "response", + "description": "

see Message Service

" + } + ] + } + }, + "filename": "api/message/main.go", + "groupTitle": "Message", + "error": { + "fields": { + "Error 400": [ + { + "group": "Error 400", + "optional": false, + "field": "InvalidParam", + "description": "

Invalid param

" + } + ], + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "MessageServiceDown", + "description": "

Message service down

" + } + ] + } + } + }, { "type": "post", "url": "/sellInfo", @@ -1377,6 +1501,13 @@ define({ "api": [ "optional": false, "field": "contentToken", "description": "

random uuid content token

" + }, + { + "group": "Success 200", + "type": "string", + "optional": false, + "field": "fileID", + "description": "

24 bytes fileID

" } ] } @@ -1767,6 +1898,211 @@ define({ "api": [ } } }, + { + "type": "rpc", + "url": "/rpc", + "title": "Message.Create", + "version": "1.0.0", + "group": "Service", + "name": "Message_Create", + "description": "

Create Message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "fromUser", + "description": "

user who launch the chat at first time

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "toUser", + "description": "

user who accept the chat at first time

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "type", + "description": "

1 for text
2 for picture
3 for video

" + }, + { + "group": "Parameter", + "type": "string", + "optional": true, + "field": "text", + "description": "

plain message text if type is text

" + }, + { + "group": "Parameter", + "type": "bytes", + "optional": true, + "field": "file", + "description": "

file stream bytes, valid only if type is picture or video

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "status", + "description": "

-1 for invalid param
1 for success

" + } + ] + } + }, + "filename": "srv/message/main.go", + "groupTitle": "Service", + "error": { + "fields": { + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "DBServerDown", + "description": "

can't connect to database server

" + } + ] + } + } + }, + { + "type": "rpc", + "url": "/rpc", + "title": "Message.Find", + "version": "1.0.0", + "group": "Service", + "name": "Message_Find", + "description": "

Find Message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "fromUser", + "description": "

user who launch the chat at first time

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "toUser", + "description": "

user who accept the chat at first time

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "way", + "description": "

1 for only pull message
2 for read message
3 for query history message

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "fromUser", + "description": "

user who launch the chat at first time

" + }, + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "toUser", + "description": "

user who accept the chat at first time

" + }, + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "badge", + "description": "

count of message still unread

" + }, + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "status", + "description": "

-1 for invalid param
1 for success
2 for not found

" + }, + { + "group": "Success 200", + "type": "list", + "optional": false, + "field": "infos", + "description": "

see below MessageInfo

" + } + ], + "MessageInfo": [ + { + "group": "MessageInfo", + "type": "int64", + "optional": false, + "field": "time", + "description": "

message create time

" + }, + { + "group": "MessageInfo", + "type": "bool", + "optional": false, + "field": "forward", + "description": "

false for chat from toUser to fromUser
true for chat from fromUser to toUser

" + }, + { + "group": "MessageInfo", + "type": "int32", + "optional": false, + "field": "type", + "description": "

1 for text
2 for picture
3 for video

" + }, + { + "group": "MessageInfo", + "type": "string", + "optional": false, + "field": "text", + "description": "

plain message text if type is text
fileID if type is picture or video

" + }, + { + "group": "MessageInfo", + "type": "bool", + "optional": false, + "field": "unread", + "description": "

false for having read
true for not having read

" + } + ] + } + }, + "filename": "srv/message/main.go", + "groupTitle": "Service", + "error": { + "fields": { + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "DBServerDown", + "description": "

can't connect to database server

" + } + ] + } + } + }, { "type": "rpc", "url": "/rpc", diff --git a/backend/doc/api_data.json b/backend/doc/api_data.json index 99f4c37..cfd263a 100644 --- a/backend/doc/api_data.json +++ b/backend/doc/api_data.json @@ -652,6 +652,130 @@ "filename": "api/file/main.go", "groupTitle": "File" }, + { + "type": "post", + "url": "/message", + "title": "AddMessage", + "version": "1.0.0", + "group": "Message", + "permission": [ + { + "name": "self/admin" + } + ], + "name": "AddMessage", + "description": "

Add chat message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "--", + "optional": false, + "field": "Param", + "description": "

see Message Service

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "Response", + "optional": false, + "field": "response", + "description": "

see Message Service

" + } + ] + } + }, + "filename": "api/message/main.go", + "groupTitle": "Message", + "error": { + "fields": { + "Error 400": [ + { + "group": "Error 400", + "optional": false, + "field": "InvalidParam", + "description": "

Invalid param

" + } + ], + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "MessageServiceDown", + "description": "

Message service down

" + } + ] + } + } + }, + { + "type": "get", + "url": "/message", + "title": "FindMessage", + "version": "1.0.0", + "group": "Message", + "permission": [ + { + "name": "self/admin" + } + ], + "name": "FindMessage", + "description": "

Find chat message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "--", + "optional": false, + "field": "Param", + "description": "

see Message Service

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "Response", + "optional": false, + "field": "response", + "description": "

see Message Service

" + } + ] + } + }, + "filename": "api/message/main.go", + "groupTitle": "Message", + "error": { + "fields": { + "Error 400": [ + { + "group": "Error 400", + "optional": false, + "field": "InvalidParam", + "description": "

Invalid param

" + } + ], + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "MessageServiceDown", + "description": "

Message service down

" + } + ] + } + } + }, { "type": "post", "url": "/sellInfo", @@ -1377,6 +1501,13 @@ "optional": false, "field": "contentToken", "description": "

random uuid content token

" + }, + { + "group": "Success 200", + "type": "string", + "optional": false, + "field": "fileID", + "description": "

24 bytes fileID

" } ] } @@ -1767,6 +1898,211 @@ } } }, + { + "type": "rpc", + "url": "/rpc", + "title": "Message.Create", + "version": "1.0.0", + "group": "Service", + "name": "Message_Create", + "description": "

Create Message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "fromUser", + "description": "

user who launch the chat at first time

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "toUser", + "description": "

user who accept the chat at first time

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "type", + "description": "

1 for text
2 for picture
3 for video

" + }, + { + "group": "Parameter", + "type": "string", + "optional": true, + "field": "text", + "description": "

plain message text if type is text

" + }, + { + "group": "Parameter", + "type": "bytes", + "optional": true, + "field": "file", + "description": "

file stream bytes, valid only if type is picture or video

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "status", + "description": "

-1 for invalid param
1 for success

" + } + ] + } + }, + "filename": "srv/message/main.go", + "groupTitle": "Service", + "error": { + "fields": { + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "DBServerDown", + "description": "

can't connect to database server

" + } + ] + } + } + }, + { + "type": "rpc", + "url": "/rpc", + "title": "Message.Find", + "version": "1.0.0", + "group": "Service", + "name": "Message_Find", + "description": "

Find Message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "fromUser", + "description": "

user who launch the chat at first time

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "toUser", + "description": "

user who accept the chat at first time

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "way", + "description": "

1 for only pull message
2 for read message
3 for query history message

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "fromUser", + "description": "

user who launch the chat at first time

" + }, + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "toUser", + "description": "

user who accept the chat at first time

" + }, + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "badge", + "description": "

count of message still unread

" + }, + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "status", + "description": "

-1 for invalid param
1 for success
2 for not found

" + }, + { + "group": "Success 200", + "type": "list", + "optional": false, + "field": "infos", + "description": "

see below MessageInfo

" + } + ], + "MessageInfo": [ + { + "group": "MessageInfo", + "type": "int64", + "optional": false, + "field": "time", + "description": "

message create time

" + }, + { + "group": "MessageInfo", + "type": "bool", + "optional": false, + "field": "forward", + "description": "

false for chat from toUser to fromUser
true for chat from fromUser to toUser

" + }, + { + "group": "MessageInfo", + "type": "int32", + "optional": false, + "field": "type", + "description": "

1 for text
2 for picture
3 for video

" + }, + { + "group": "MessageInfo", + "type": "string", + "optional": false, + "field": "text", + "description": "

plain message text if type is text
fileID if type is picture or video

" + }, + { + "group": "MessageInfo", + "type": "bool", + "optional": false, + "field": "unread", + "description": "

false for having read
true for not having read

" + } + ] + } + }, + "filename": "srv/message/main.go", + "groupTitle": "Service", + "error": { + "fields": { + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "DBServerDown", + "description": "

can't connect to database server

" + } + ] + } + } + }, { "type": "rpc", "url": "/rpc", diff --git a/backend/doc/api_project.js b/backend/doc/api_project.js index 71b19d6..bbc8399 100644 --- a/backend/doc/api_project.js +++ b/backend/doc/api_project.js @@ -13,6 +13,7 @@ define({ "Avatar", "File", "Transaction", + "Message", "Service" ], "sampleUrl": false, @@ -20,7 +21,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-07-29T12:32:59.009Z", + "time": "2019-07-31T06:45:27.228Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/api_project.json b/backend/doc/api_project.json index 9a7ed28..c6e675a 100644 --- a/backend/doc/api_project.json +++ b/backend/doc/api_project.json @@ -13,6 +13,7 @@ "Avatar", "File", "Transaction", + "Message", "Service" ], "sampleUrl": false, @@ -20,7 +21,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-07-29T12:32:59.009Z", + "time": "2019-07-31T06:45:27.228Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index ed1809d..2b4536a 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -26,8 +26,8 @@ type srv struct{} * @apiParam {int32} fromUser user who launch the chat at first time * @apiParam {int32} toUser user who accept the chat at first time * @apiParam {int32} type 1 for text
2 for picture
3 for video - * @apiParam {string} text plain message text if type is text - * @apiParam {bytes} file file stream bytes, valid only if type is picture or video + * @apiParam {string} [text] plain message text if type is text + * @apiParam {bytes} [file] file stream bytes, valid only if type is picture or video * @apiSuccess {int32} status -1 for invalid param
1 for success * @apiUse DBServerDown */ @@ -149,11 +149,11 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp } /** - * @api {rpc} /rpc Message.Query + * @api {rpc} /rpc Message.Find * @apiVersion 1.0.0 * @apiGroup Service - * @apiName Message.Create - * @apiDescription Create Message + * @apiName Message.Find + * @apiDescription Find Message * * @apiParam {int32} fromUser user who launch the chat at first time * @apiParam {int32} toUser user who accept the chat at first time @@ -167,12 +167,12 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp * @apiSuccess (MessageInfo) {bool} forward false for chat from toUser to fromUser
true for chat from fromUser to toUser * @apiSuccess (MessageInfo) {int32} type 1 for text
2 for picture
3 for video * @apiSuccess (MessageInfo) {string} text plain message text if type is text
fileID if type is picture or video - * @apiParam (MessageInfo) {bool} unread false for having read
true for not having read + * @apiSuccess (MessageInfo) {bool} unread false for having read
true for not having read * @apiUse DBServerDown */ -func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp *message.MessageQueryResponse) error { +func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *message.MessageFindResponse) error { if !utils.RequireParam(req.FromUser, req.ToUser, req.Way) { - rsp.Status = message.MessageQueryResponse_INVALID_PARAM + rsp.Status = message.MessageFindResponse_INVALID_PARAM return nil } @@ -195,14 +195,14 @@ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp * rsp.FromUser = req.ToUser rsp.ToUser = req.FromUser } else if err1 != nil && err2 != nil { - rsp.Status = message.MessageQueryResponse_NOT_FOUND + rsp.Status = message.MessageFindResponse_NOT_FOUND return nil } else { - rsp.Status = message.MessageQueryResponse_INVALID_PARAM + rsp.Status = message.MessageFindResponse_INVALID_PARAM return nil } - if req.Way == message.MessageQueryRequest_ONLY_PULL { + if req.Way == message.MessageFindRequest_ONLY_PULL { err := collection.FindOne(ctx, bson.M{ "fromUser": rsp.FromUser, "toUser": rsp.ToUser, @@ -212,12 +212,12 @@ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp * }, }).Decode(&rsp) if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageQueryResponse_UNKNOWN + rsp.Status = message.MessageFindResponse_UNKNOWN return nil } - rsp.Status = message.MessageQueryResponse_SUCCESS + rsp.Status = message.MessageFindResponse_SUCCESS return nil - } else if req.Way == message.MessageQueryRequest_READ_MESSAGE { + } else if req.Way == message.MessageFindRequest_READ_MESSAGE { err := collection.FindOneAndUpdate(ctx, bson.M{ "fromUser": rsp.FromUser, "toUser": rsp.ToUser, @@ -232,21 +232,21 @@ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp * }, }).Decode(&rsp) if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageQueryResponse_UNKNOWN + rsp.Status = message.MessageFindResponse_UNKNOWN return nil } - rsp.Status = message.MessageQueryResponse_SUCCESS + rsp.Status = message.MessageFindResponse_SUCCESS return nil - } else if req.Way == message.MessageQueryRequest_HISTORY { + } else if req.Way == message.MessageFindRequest_HISTORY { err := collection.FindOne(ctx, bson.M{ "fromUser": rsp.FromUser, "toUser": rsp.ToUser, }).Decode(&rsp) if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageQueryResponse_UNKNOWN + rsp.Status = message.MessageFindResponse_UNKNOWN return nil } - rsp.Status = message.MessageQueryResponse_SUCCESS + rsp.Status = message.MessageFindResponse_SUCCESS return nil } return nil diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index 8c3324e..3b45cc6 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -17,11 +17,11 @@ func TestCreate(t *testing.T) { }) } -func TestQuery(t *testing.T) { +func TestFind(t *testing.T) { var s srv - var req message.MessageQueryRequest - Convey("Test Query Message", t, func() { - err := s.Query(context.TODO(), &req, &message.MessageQueryResponse{}) + var req message.MessageFindRequest + Convey("Test Find Message", t, func() { + err := s.Find(context.TODO(), &req, &message.MessageFindResponse{}) ShouldBeNil(err) }) diff --git a/backend/srv/message/proto/message.micro.go b/backend/srv/message/proto/message.micro.go index 57b763e..26e44e2 100644 --- a/backend/srv/message/proto/message.micro.go +++ b/backend/srv/message/proto/message.micro.go @@ -35,7 +35,7 @@ var _ server.Option type MessageService interface { Create(ctx context.Context, in *MessageCreateRequest, opts ...client.CallOption) (*MessageCreateResponse, error) - Query(ctx context.Context, in *MessageQueryRequest, opts ...client.CallOption) (*MessageQueryResponse, error) + Find(ctx context.Context, in *MessageFindRequest, opts ...client.CallOption) (*MessageFindResponse, error) } type messageService struct { @@ -66,9 +66,9 @@ func (c *messageService) Create(ctx context.Context, in *MessageCreateRequest, o return out, nil } -func (c *messageService) Query(ctx context.Context, in *MessageQueryRequest, opts ...client.CallOption) (*MessageQueryResponse, error) { - req := c.c.NewRequest(c.name, "Message.Query", in) - out := new(MessageQueryResponse) +func (c *messageService) Find(ctx context.Context, in *MessageFindRequest, opts ...client.CallOption) (*MessageFindResponse, error) { + req := c.c.NewRequest(c.name, "Message.Find", in) + out := new(MessageFindResponse) err := c.c.Call(ctx, req, out, opts...) if err != nil { return nil, err @@ -80,13 +80,13 @@ func (c *messageService) Query(ctx context.Context, in *MessageQueryRequest, opt type MessageHandler interface { Create(context.Context, *MessageCreateRequest, *MessageCreateResponse) error - Query(context.Context, *MessageQueryRequest, *MessageQueryResponse) error + Find(context.Context, *MessageFindRequest, *MessageFindResponse) error } func RegisterMessageHandler(s server.Server, hdlr MessageHandler, opts ...server.HandlerOption) error { type message interface { Create(ctx context.Context, in *MessageCreateRequest, out *MessageCreateResponse) error - Query(ctx context.Context, in *MessageQueryRequest, out *MessageQueryResponse) error + Find(ctx context.Context, in *MessageFindRequest, out *MessageFindResponse) error } type Message struct { message @@ -103,6 +103,6 @@ func (h *messageHandler) Create(ctx context.Context, in *MessageCreateRequest, o return h.MessageHandler.Create(ctx, in, out) } -func (h *messageHandler) Query(ctx context.Context, in *MessageQueryRequest, out *MessageQueryResponse) error { - return h.MessageHandler.Query(ctx, in, out) +func (h *messageHandler) Find(ctx context.Context, in *MessageFindRequest, out *MessageFindResponse) error { + return h.MessageHandler.Find(ctx, in, out) } diff --git a/backend/srv/message/proto/message.pb.go b/backend/srv/message/proto/message.pb.go index 7637ac3..8edb08b 100644 --- a/backend/srv/message/proto/message.pb.go +++ b/backend/srv/message/proto/message.pb.go @@ -110,65 +110,65 @@ func (MessageCreateResponse_Status) EnumDescriptor() ([]byte, []int) { return fileDescriptor_33c57e4bae7b9afd, []int{2, 0} } -type MessageQueryRequest_Way int32 +type MessageFindRequest_Way int32 const ( - MessageQueryRequest_UNKNOWN MessageQueryRequest_Way = 0 - MessageQueryRequest_ONLY_PULL MessageQueryRequest_Way = 1 - MessageQueryRequest_READ_MESSAGE MessageQueryRequest_Way = 2 - MessageQueryRequest_HISTORY MessageQueryRequest_Way = 3 + MessageFindRequest_UNKNOWN MessageFindRequest_Way = 0 + MessageFindRequest_ONLY_PULL MessageFindRequest_Way = 1 + MessageFindRequest_READ_MESSAGE MessageFindRequest_Way = 2 + MessageFindRequest_HISTORY MessageFindRequest_Way = 3 ) -var MessageQueryRequest_Way_name = map[int32]string{ +var MessageFindRequest_Way_name = map[int32]string{ 0: "UNKNOWN", 1: "ONLY_PULL", 2: "READ_MESSAGE", 3: "HISTORY", } -var MessageQueryRequest_Way_value = map[string]int32{ +var MessageFindRequest_Way_value = map[string]int32{ "UNKNOWN": 0, "ONLY_PULL": 1, "READ_MESSAGE": 2, "HISTORY": 3, } -func (x MessageQueryRequest_Way) String() string { - return proto.EnumName(MessageQueryRequest_Way_name, int32(x)) +func (x MessageFindRequest_Way) String() string { + return proto.EnumName(MessageFindRequest_Way_name, int32(x)) } -func (MessageQueryRequest_Way) EnumDescriptor() ([]byte, []int) { +func (MessageFindRequest_Way) EnumDescriptor() ([]byte, []int) { return fileDescriptor_33c57e4bae7b9afd, []int{3, 0} } -type MessageQueryResponse_Status int32 +type MessageFindResponse_Status int32 const ( - MessageQueryResponse_UNKNOWN MessageQueryResponse_Status = 0 - MessageQueryResponse_INVALID_PARAM MessageQueryResponse_Status = -1 - MessageQueryResponse_SUCCESS MessageQueryResponse_Status = 1 - MessageQueryResponse_NOT_FOUND MessageQueryResponse_Status = 2 + MessageFindResponse_UNKNOWN MessageFindResponse_Status = 0 + MessageFindResponse_INVALID_PARAM MessageFindResponse_Status = -1 + MessageFindResponse_SUCCESS MessageFindResponse_Status = 1 + MessageFindResponse_NOT_FOUND MessageFindResponse_Status = 2 ) -var MessageQueryResponse_Status_name = map[int32]string{ +var MessageFindResponse_Status_name = map[int32]string{ 0: "UNKNOWN", -1: "INVALID_PARAM", 1: "SUCCESS", 2: "NOT_FOUND", } -var MessageQueryResponse_Status_value = map[string]int32{ +var MessageFindResponse_Status_value = map[string]int32{ "UNKNOWN": 0, "INVALID_PARAM": -1, "SUCCESS": 1, "NOT_FOUND": 2, } -func (x MessageQueryResponse_Status) String() string { - return proto.EnumName(MessageQueryResponse_Status_name, int32(x)) +func (x MessageFindResponse_Status) String() string { + return proto.EnumName(MessageFindResponse_Status_name, int32(x)) } -func (MessageQueryResponse_Status) EnumDescriptor() ([]byte, []int) { +func (MessageFindResponse_Status) EnumDescriptor() ([]byte, []int) { return fileDescriptor_33c57e4bae7b9afd, []int{4, 0} } @@ -353,126 +353,126 @@ func (m *MessageCreateResponse) GetStatus() MessageCreateResponse_Status { return MessageCreateResponse_UNKNOWN } -type MessageQueryRequest struct { - FromUser int32 `protobuf:"varint,1,opt,name=fromUser,proto3" json:"fromUser,omitempty"` - ToUser int32 `protobuf:"varint,2,opt,name=toUser,proto3" json:"toUser,omitempty"` - Way MessageQueryRequest_Way `protobuf:"varint,3,opt,name=way,proto3,enum=MessageQueryRequest_Way" json:"way,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type MessageFindRequest struct { + FromUser int32 `protobuf:"varint,1,opt,name=fromUser,proto3" json:"fromUser,omitempty"` + ToUser int32 `protobuf:"varint,2,opt,name=toUser,proto3" json:"toUser,omitempty"` + Way MessageFindRequest_Way `protobuf:"varint,3,opt,name=way,proto3,enum=MessageFindRequest_Way" json:"way,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *MessageQueryRequest) Reset() { *m = MessageQueryRequest{} } -func (m *MessageQueryRequest) String() string { return proto.CompactTextString(m) } -func (*MessageQueryRequest) ProtoMessage() {} -func (*MessageQueryRequest) Descriptor() ([]byte, []int) { +func (m *MessageFindRequest) Reset() { *m = MessageFindRequest{} } +func (m *MessageFindRequest) String() string { return proto.CompactTextString(m) } +func (*MessageFindRequest) ProtoMessage() {} +func (*MessageFindRequest) Descriptor() ([]byte, []int) { return fileDescriptor_33c57e4bae7b9afd, []int{3} } -func (m *MessageQueryRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_MessageQueryRequest.Unmarshal(m, b) +func (m *MessageFindRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageFindRequest.Unmarshal(m, b) } -func (m *MessageQueryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_MessageQueryRequest.Marshal(b, m, deterministic) +func (m *MessageFindRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageFindRequest.Marshal(b, m, deterministic) } -func (m *MessageQueryRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_MessageQueryRequest.Merge(m, src) +func (m *MessageFindRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageFindRequest.Merge(m, src) } -func (m *MessageQueryRequest) XXX_Size() int { - return xxx_messageInfo_MessageQueryRequest.Size(m) +func (m *MessageFindRequest) XXX_Size() int { + return xxx_messageInfo_MessageFindRequest.Size(m) } -func (m *MessageQueryRequest) XXX_DiscardUnknown() { - xxx_messageInfo_MessageQueryRequest.DiscardUnknown(m) +func (m *MessageFindRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MessageFindRequest.DiscardUnknown(m) } -var xxx_messageInfo_MessageQueryRequest proto.InternalMessageInfo +var xxx_messageInfo_MessageFindRequest proto.InternalMessageInfo -func (m *MessageQueryRequest) GetFromUser() int32 { +func (m *MessageFindRequest) GetFromUser() int32 { if m != nil { return m.FromUser } return 0 } -func (m *MessageQueryRequest) GetToUser() int32 { +func (m *MessageFindRequest) GetToUser() int32 { if m != nil { return m.ToUser } return 0 } -func (m *MessageQueryRequest) GetWay() MessageQueryRequest_Way { +func (m *MessageFindRequest) GetWay() MessageFindRequest_Way { if m != nil { return m.Way } - return MessageQueryRequest_UNKNOWN + return MessageFindRequest_UNKNOWN } -type MessageQueryResponse struct { - Status MessageQueryResponse_Status `protobuf:"varint,1,opt,name=status,proto3,enum=MessageQueryResponse_Status" json:"status,omitempty"` - FromUser int32 `protobuf:"varint,2,opt,name=fromUser,proto3" json:"fromUser,omitempty"` - ToUser int32 `protobuf:"varint,3,opt,name=toUser,proto3" json:"toUser,omitempty"` - Badge int32 `protobuf:"varint,4,opt,name=badge,proto3" json:"badge,omitempty"` - Infos []*MessageInfo `protobuf:"bytes,5,rep,name=infos,proto3" json:"infos,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type MessageFindResponse struct { + Status MessageFindResponse_Status `protobuf:"varint,1,opt,name=status,proto3,enum=MessageFindResponse_Status" json:"status,omitempty"` + FromUser int32 `protobuf:"varint,2,opt,name=fromUser,proto3" json:"fromUser,omitempty"` + ToUser int32 `protobuf:"varint,3,opt,name=toUser,proto3" json:"toUser,omitempty"` + Badge int32 `protobuf:"varint,4,opt,name=badge,proto3" json:"badge,omitempty"` + Infos []*MessageInfo `protobuf:"bytes,5,rep,name=infos,proto3" json:"infos,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *MessageQueryResponse) Reset() { *m = MessageQueryResponse{} } -func (m *MessageQueryResponse) String() string { return proto.CompactTextString(m) } -func (*MessageQueryResponse) ProtoMessage() {} -func (*MessageQueryResponse) Descriptor() ([]byte, []int) { +func (m *MessageFindResponse) Reset() { *m = MessageFindResponse{} } +func (m *MessageFindResponse) String() string { return proto.CompactTextString(m) } +func (*MessageFindResponse) ProtoMessage() {} +func (*MessageFindResponse) Descriptor() ([]byte, []int) { return fileDescriptor_33c57e4bae7b9afd, []int{4} } -func (m *MessageQueryResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_MessageQueryResponse.Unmarshal(m, b) +func (m *MessageFindResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageFindResponse.Unmarshal(m, b) } -func (m *MessageQueryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_MessageQueryResponse.Marshal(b, m, deterministic) +func (m *MessageFindResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageFindResponse.Marshal(b, m, deterministic) } -func (m *MessageQueryResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MessageQueryResponse.Merge(m, src) +func (m *MessageFindResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageFindResponse.Merge(m, src) } -func (m *MessageQueryResponse) XXX_Size() int { - return xxx_messageInfo_MessageQueryResponse.Size(m) +func (m *MessageFindResponse) XXX_Size() int { + return xxx_messageInfo_MessageFindResponse.Size(m) } -func (m *MessageQueryResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MessageQueryResponse.DiscardUnknown(m) +func (m *MessageFindResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MessageFindResponse.DiscardUnknown(m) } -var xxx_messageInfo_MessageQueryResponse proto.InternalMessageInfo +var xxx_messageInfo_MessageFindResponse proto.InternalMessageInfo -func (m *MessageQueryResponse) GetStatus() MessageQueryResponse_Status { +func (m *MessageFindResponse) GetStatus() MessageFindResponse_Status { if m != nil { return m.Status } - return MessageQueryResponse_UNKNOWN + return MessageFindResponse_UNKNOWN } -func (m *MessageQueryResponse) GetFromUser() int32 { +func (m *MessageFindResponse) GetFromUser() int32 { if m != nil { return m.FromUser } return 0 } -func (m *MessageQueryResponse) GetToUser() int32 { +func (m *MessageFindResponse) GetToUser() int32 { if m != nil { return m.ToUser } return 0 } -func (m *MessageQueryResponse) GetBadge() int32 { +func (m *MessageFindResponse) GetBadge() int32 { if m != nil { return m.Badge } return 0 } -func (m *MessageQueryResponse) GetInfos() []*MessageInfo { +func (m *MessageFindResponse) GetInfos() []*MessageInfo { if m != nil { return m.Infos } @@ -483,51 +483,51 @@ func init() { proto.RegisterEnum("MessageInfo_Type", MessageInfo_Type_name, MessageInfo_Type_value) proto.RegisterEnum("MessageCreateRequest_Type", MessageCreateRequest_Type_name, MessageCreateRequest_Type_value) proto.RegisterEnum("MessageCreateResponse_Status", MessageCreateResponse_Status_name, MessageCreateResponse_Status_value) - proto.RegisterEnum("MessageQueryRequest_Way", MessageQueryRequest_Way_name, MessageQueryRequest_Way_value) - proto.RegisterEnum("MessageQueryResponse_Status", MessageQueryResponse_Status_name, MessageQueryResponse_Status_value) + proto.RegisterEnum("MessageFindRequest_Way", MessageFindRequest_Way_name, MessageFindRequest_Way_value) + proto.RegisterEnum("MessageFindResponse_Status", MessageFindResponse_Status_name, MessageFindResponse_Status_value) proto.RegisterType((*MessageInfo)(nil), "MessageInfo") proto.RegisterType((*MessageCreateRequest)(nil), "MessageCreateRequest") proto.RegisterType((*MessageCreateResponse)(nil), "MessageCreateResponse") - proto.RegisterType((*MessageQueryRequest)(nil), "MessageQueryRequest") - proto.RegisterType((*MessageQueryResponse)(nil), "MessageQueryResponse") + proto.RegisterType((*MessageFindRequest)(nil), "MessageFindRequest") + proto.RegisterType((*MessageFindResponse)(nil), "MessageFindResponse") } func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) } var fileDescriptor_33c57e4bae7b9afd = []byte{ - // 533 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcd, 0x6a, 0xdb, 0x4c, - 0x14, 0xfd, 0x46, 0x3f, 0xfe, 0xb9, 0xb6, 0xc3, 0x7c, 0x53, 0x3b, 0x08, 0xd3, 0x82, 0x11, 0x14, - 0x4c, 0x17, 0xb3, 0x70, 0x13, 0xba, 0x2b, 0x35, 0xb6, 0xda, 0x8a, 0xda, 0x92, 0x3b, 0x92, 0xe2, - 0x66, 0x65, 0x14, 0x3c, 0x0a, 0x86, 0xda, 0x72, 0x25, 0x99, 0x44, 0x8f, 0xd0, 0x4d, 0x5f, 0xa7, - 0x4f, 0xd0, 0x87, 0xe8, 0xd3, 0xb4, 0x68, 0xa4, 0x84, 0xc8, 0xa8, 0x14, 0x1a, 0xad, 0xe6, 0xfe, - 0xe8, 0xde, 0x73, 0xce, 0x1c, 0x09, 0x3a, 0x5b, 0x1e, 0xc7, 0xfe, 0x35, 0xa7, 0xfb, 0x28, 0x4c, - 0x42, 0xfd, 0x07, 0x82, 0xd6, 0x3c, 0xcf, 0x98, 0xbb, 0x20, 0x24, 0x04, 0x94, 0x64, 0xb3, 0xe5, - 0x1a, 0x1a, 0xa0, 0xa1, 0xcc, 0xc4, 0x99, 0x68, 0x50, 0x0f, 0xc2, 0xe8, 0xc6, 0x8f, 0xd6, 0x9a, - 0x34, 0x40, 0xc3, 0x06, 0xbb, 0x0b, 0xc9, 0x73, 0x50, 0x92, 0x74, 0xcf, 0x35, 0x79, 0x80, 0x86, - 0x27, 0xa3, 0xff, 0xe9, 0x83, 0x49, 0xd4, 0x4d, 0xf7, 0x9c, 0x89, 0xb2, 0x18, 0xca, 0x6f, 0x13, - 0x4d, 0x19, 0xa0, 0x61, 0x93, 0x89, 0x33, 0x39, 0x85, 0xda, 0x61, 0x17, 0x71, 0x7f, 0xad, 0xa9, - 0x62, 0x66, 0x11, 0xe9, 0xe7, 0xa0, 0x64, 0x6f, 0x92, 0x16, 0xd4, 0x3d, 0xeb, 0x83, 0x65, 0x2f, - 0x2d, 0xfc, 0x1f, 0x69, 0x80, 0xe2, 0x1a, 0x9f, 0x5c, 0x8c, 0xb2, 0xf4, 0xc2, 0x9c, 0xb8, 0x1e, - 0x33, 0xb0, 0x44, 0x9a, 0xa0, 0x5e, 0x98, 0x53, 0xc3, 0xc6, 0xb2, 0xfe, 0x13, 0x41, 0xb7, 0xd8, - 0x3e, 0x89, 0xb8, 0x9f, 0x70, 0xc6, 0xbf, 0x1c, 0x78, 0x9c, 0x90, 0x3e, 0x34, 0x82, 0x28, 0xdc, - 0x7a, 0x31, 0x8f, 0x04, 0x29, 0x95, 0xdd, 0xc7, 0x19, 0x86, 0x24, 0x14, 0x15, 0x49, 0x54, 0x8a, - 0x88, 0xd0, 0x12, 0xad, 0x3e, 0xad, 0x1a, 0xfc, 0x37, 0x7e, 0x04, 0x94, 0x60, 0xf3, 0x99, 0x0b, - 0x76, 0x6d, 0x26, 0xce, 0xff, 0xca, 0xed, 0x1b, 0x82, 0xde, 0x11, 0x84, 0x78, 0x1f, 0xee, 0x62, - 0x4e, 0xce, 0xa1, 0x16, 0x27, 0x7e, 0x72, 0x88, 0x05, 0xb5, 0x93, 0xd1, 0x33, 0x5a, 0xd9, 0x47, - 0x1d, 0xd1, 0xc4, 0x8a, 0x66, 0xfd, 0x35, 0xd4, 0xf2, 0x4c, 0x19, 0x49, 0x1f, 0x3a, 0xa6, 0x75, - 0x31, 0x9e, 0x99, 0xd3, 0xd5, 0x62, 0xcc, 0xc6, 0x73, 0xfc, 0xeb, 0xee, 0x11, 0xd8, 0x1c, 0x6f, - 0x32, 0x31, 0x1c, 0x07, 0x23, 0xfd, 0x3b, 0x82, 0x27, 0xc5, 0xa2, 0x8f, 0x07, 0x1e, 0xa5, 0x8f, - 0xd1, 0xfa, 0x05, 0xc8, 0x37, 0x7e, 0x5a, 0x48, 0xad, 0xd1, 0x8a, 0xb1, 0x74, 0xe9, 0xa7, 0x2c, - 0x6b, 0xd2, 0xdf, 0x80, 0xbc, 0xf4, 0xd3, 0x32, 0xe8, 0x0e, 0x34, 0x6d, 0x6b, 0x76, 0xb9, 0x5a, - 0x78, 0xb3, 0x19, 0x46, 0x04, 0x43, 0x9b, 0x19, 0xe3, 0xe9, 0x6a, 0x6e, 0x38, 0xce, 0xf8, 0x5d, - 0x26, 0x64, 0x0b, 0xea, 0xef, 0x4d, 0xc7, 0xb5, 0xd9, 0x25, 0x96, 0xf5, 0xaf, 0xd2, 0xbd, 0x4d, - 0x8a, 0x15, 0x85, 0x92, 0x67, 0x47, 0x4a, 0x3e, 0xa5, 0x55, 0x6d, 0x47, 0x42, 0x96, 0x08, 0x4b, - 0x7f, 0x24, 0x2c, 0x97, 0x08, 0x77, 0x41, 0xbd, 0xf2, 0xd7, 0xd7, 0x5c, 0xb8, 0x45, 0x65, 0x79, - 0x40, 0x74, 0x50, 0x37, 0xbb, 0x20, 0x8c, 0x35, 0x75, 0x20, 0x0f, 0x5b, 0xa3, 0xf6, 0xc3, 0x4f, - 0x89, 0xe5, 0x25, 0x7d, 0xfe, 0xb8, 0x6b, 0xcb, 0xa4, 0xb2, 0x6c, 0x77, 0xf5, 0xd6, 0xf6, 0xac, - 0x29, 0x96, 0x46, 0xb7, 0x50, 0x2f, 0x96, 0x90, 0x57, 0x50, 0xcb, 0x1d, 0x43, 0x7a, 0x95, 0x66, - 0xef, 0x9f, 0x56, 0x1b, 0x8b, 0x9c, 0x81, 0x2a, 0x04, 0x22, 0xdd, 0xaa, 0x9b, 0xeb, 0xf7, 0x2a, - 0x55, 0xbc, 0xaa, 0x89, 0x7f, 0xcf, 0xcb, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xdd, 0xf9, 0x95, - 0xfc, 0x8c, 0x04, 0x00, 0x00, + // 530 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xdd, 0x8a, 0xd3, 0x40, + 0x14, 0x76, 0xf2, 0xd3, 0x9f, 0xd3, 0x76, 0x19, 0x67, 0xbb, 0x6b, 0xa8, 0x08, 0x25, 0x20, 0xd4, + 0x9b, 0x01, 0xbb, 0x2c, 0xde, 0x89, 0xa5, 0xcd, 0x6a, 0xb0, 0x4d, 0xca, 0x24, 0xd9, 0xba, 0x57, + 0x25, 0x4b, 0xa7, 0x4b, 0xc1, 0x26, 0x35, 0x49, 0x59, 0xf3, 0x04, 0xde, 0xf9, 0x36, 0x3e, 0x82, + 0x0f, 0xe1, 0xd3, 0x28, 0x99, 0x64, 0x65, 0x53, 0x23, 0x82, 0x9b, 0xab, 0x39, 0x3f, 0xf9, 0xce, + 0xf7, 0x7d, 0x73, 0x12, 0xe8, 0x6c, 0x79, 0x1c, 0xfb, 0x37, 0x9c, 0xee, 0xa2, 0x30, 0x09, 0xf5, + 0xef, 0x08, 0x5a, 0xb3, 0x3c, 0x63, 0x06, 0xeb, 0x90, 0x10, 0x50, 0x92, 0xcd, 0x96, 0x6b, 0xa8, + 0x8f, 0x06, 0x32, 0x13, 0x67, 0xa2, 0x41, 0x7d, 0x1d, 0x46, 0xb7, 0x7e, 0xb4, 0xd2, 0xa4, 0x3e, + 0x1a, 0x34, 0xd8, 0x5d, 0x48, 0x9e, 0x83, 0x92, 0xa4, 0x3b, 0xae, 0xc9, 0x7d, 0x34, 0x38, 0x1a, + 0x3e, 0xa6, 0xf7, 0x90, 0xa8, 0x9b, 0xee, 0x38, 0x13, 0x65, 0x01, 0xca, 0x3f, 0x27, 0x9a, 0xd2, + 0x47, 0x83, 0x26, 0x13, 0x67, 0x72, 0x0a, 0xb5, 0x7d, 0x10, 0x71, 0x7f, 0xa5, 0xa9, 0x02, 0xb3, + 0x88, 0xf4, 0x73, 0x50, 0xb2, 0x37, 0x49, 0x0b, 0xea, 0x9e, 0xf5, 0xde, 0xb2, 0x17, 0x16, 0x7e, + 0x44, 0x1a, 0xa0, 0xb8, 0xc6, 0x07, 0x17, 0xa3, 0x2c, 0x3d, 0x37, 0xc7, 0xae, 0xc7, 0x0c, 0x2c, + 0x91, 0x26, 0xa8, 0x97, 0xe6, 0xc4, 0xb0, 0xb1, 0xac, 0xff, 0x40, 0xd0, 0x2d, 0xa6, 0x8f, 0x23, + 0xee, 0x27, 0x9c, 0xf1, 0x4f, 0x7b, 0x1e, 0x27, 0xa4, 0x07, 0x8d, 0x75, 0x14, 0x6e, 0xbd, 0x98, + 0x47, 0x42, 0x94, 0xca, 0x7e, 0xc7, 0x19, 0x87, 0x24, 0x14, 0x15, 0x49, 0x54, 0x8a, 0x88, 0xd0, + 0x92, 0xac, 0x1e, 0xad, 0x02, 0xfe, 0x97, 0x3e, 0x02, 0xca, 0x7a, 0xf3, 0x91, 0x0b, 0x75, 0x6d, + 0x26, 0xce, 0xff, 0xab, 0xed, 0x2b, 0x82, 0x93, 0x03, 0x0a, 0xf1, 0x2e, 0x0c, 0x62, 0x4e, 0xce, + 0xa1, 0x16, 0x27, 0x7e, 0xb2, 0x8f, 0x85, 0xb4, 0xa3, 0xe1, 0x33, 0x5a, 0xd9, 0x47, 0x1d, 0xd1, + 0xc4, 0x8a, 0x66, 0xfd, 0x35, 0xd4, 0xf2, 0x4c, 0x99, 0x49, 0x0f, 0x3a, 0xa6, 0x75, 0x39, 0x9a, + 0x9a, 0x93, 0xe5, 0x7c, 0xc4, 0x46, 0x33, 0xfc, 0xf3, 0xee, 0x11, 0xdc, 0x1c, 0x6f, 0x3c, 0x36, + 0x1c, 0x07, 0x23, 0xfd, 0x1b, 0x02, 0x52, 0x0c, 0xba, 0xd8, 0x04, 0xab, 0x87, 0x58, 0xfd, 0x02, + 0xe4, 0x5b, 0x3f, 0x2d, 0x9c, 0x7e, 0x42, 0xff, 0x44, 0xa5, 0x0b, 0x3f, 0x65, 0x59, 0x8f, 0xfe, + 0x06, 0xe4, 0x85, 0x9f, 0x96, 0x29, 0x77, 0xa0, 0x69, 0x5b, 0xd3, 0xab, 0xe5, 0xdc, 0x9b, 0x4e, + 0x31, 0x22, 0x18, 0xda, 0xcc, 0x18, 0x4d, 0x96, 0x33, 0xc3, 0x71, 0x46, 0x6f, 0x33, 0x1b, 0x5b, + 0x50, 0x7f, 0x67, 0x3a, 0xae, 0xcd, 0xae, 0xb0, 0xac, 0x7f, 0x91, 0xe0, 0xb8, 0x34, 0xa1, 0xb0, + 0xf1, 0xec, 0xc0, 0xc6, 0xa7, 0xb4, 0xa2, 0xeb, 0xc0, 0xc4, 0x92, 0x5a, 0xe9, 0xaf, 0x6a, 0xe5, + 0x92, 0xda, 0x2e, 0xa8, 0xd7, 0xfe, 0xea, 0x86, 0x8b, 0x4d, 0x51, 0x59, 0x1e, 0x10, 0x1d, 0xd4, + 0x4d, 0xb0, 0x0e, 0x63, 0x4d, 0xed, 0xcb, 0x83, 0xd6, 0xb0, 0x7d, 0xff, 0x33, 0x62, 0x79, 0x49, + 0x9f, 0x3d, 0xec, 0xca, 0x32, 0xa3, 0x2c, 0xdb, 0x5d, 0x5e, 0xd8, 0x9e, 0x35, 0xc1, 0xd2, 0x70, + 0x0f, 0xf5, 0x62, 0x08, 0x79, 0x05, 0xb5, 0x7c, 0x5b, 0xc8, 0x49, 0xe5, 0xa2, 0xf7, 0x4e, 0xab, + 0x97, 0x8a, 0xbc, 0x04, 0x25, 0xf3, 0x87, 0x1c, 0x57, 0xdc, 0x5a, 0xaf, 0x5b, 0x65, 0xe1, 0x75, + 0x4d, 0xfc, 0x74, 0xce, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x4c, 0x58, 0xf9, 0x5f, 0x85, 0x04, + 0x00, 0x00, } diff --git a/backend/srv/message/proto/message.proto b/backend/srv/message/proto/message.proto index 3e9960d..13c8fa1 100644 --- a/backend/srv/message/proto/message.proto +++ b/backend/srv/message/proto/message.proto @@ -2,7 +2,7 @@ syntax = "proto3"; service Message { rpc Create (MessageCreateRequest) returns (MessageCreateResponse); - rpc Query (MessageQueryRequest) returns (MessageQueryResponse); + rpc Find (MessageFindRequest) returns (MessageFindResponse); } message MessageInfo{ @@ -42,7 +42,7 @@ message MessageCreateResponse { Status status = 1; } -message MessageQueryRequest { +message MessageFindRequest { enum Way { UNKNOWN = 0; ONLY_PULL = 1; @@ -54,7 +54,7 @@ message MessageQueryRequest { Way way = 3; } -message MessageQueryResponse { +message MessageFindResponse { enum Status { UNKNOWN = 0; INVALID_PARAM = -1; From 35bd4e21dd6964487f83d051449aeebe83b6c41f Mon Sep 17 00:00:00 2001 From: MXWXZ Date: Wed, 31 Jul 2019 15:36:05 +0800 Subject: [PATCH 07/17] fix stress --- backend/.gitignore | 1 + backend/database/orm.go | 4 ++-- .../stresstest/__pycache__/dummy.cpython-37.pyc | Bin 654 -> 0 bytes backend/stresstest/boom.go | 11 ++++++++--- backend/utils/service.go | 4 ++-- 5 files changed, 13 insertions(+), 7 deletions(-) delete mode 100644 backend/stresstest/__pycache__/dummy.cpython-37.pyc diff --git a/backend/.gitignore b/backend/.gitignore index a61e474..a5cecdd 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -3,3 +3,4 @@ go.sum .idea/ build/ *.coverprofile +__pycache__/ \ No newline at end of file diff --git a/backend/database/orm.go b/backend/database/orm.go index 3cf1695..5578925 100644 --- a/backend/database/orm.go +++ b/backend/database/orm.go @@ -24,9 +24,9 @@ func InitORM(dbName string, m ...interface{}) { Ormer.AutoMigrate(m...) - Ormer.DB().SetMaxIdleConns(10) + Ormer.DB().SetMaxIdleConns(0) Ormer.DB().SetMaxOpenConns(256) - Ormer.DB().SetConnMaxLifetime(time.Hour) + Ormer.DB().SetConnMaxLifetime(time.Second * 16) } // CloseORM close orm object diff --git a/backend/stresstest/__pycache__/dummy.cpython-37.pyc b/backend/stresstest/__pycache__/dummy.cpython-37.pyc deleted file mode 100644 index bae785a28ac5308c464fbe6b73c5423e2bdfb615..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 654 zcmZuu!A`?43{9H0>&6B(1U1-#AP`SS?*P^{GJViB zxGmvp5Kc2C!aI7~#%0Nc%L4a-|v=A_}4R9aa$b4t+#BoK^!k!w=<_I;`z~1J2=tQUCw| diff --git a/backend/stresstest/boom.go b/backend/stresstest/boom.go index 8b3e1cb..0c96584 100644 --- a/backend/stresstest/boom.go +++ b/backend/stresstest/boom.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "crypto/tls" "fmt" "io" "io/ioutil" @@ -29,14 +30,14 @@ func goodSearch() { boomer.RecordFailure("http", "goodSearch", time.Since(start).Nanoseconds()/int64(time.Millisecond), err.Error()) return } - length, _ := io.Copy(ioutil.Discard, res.Body) - err = res.Body.Close() + length, err := io.Copy(ioutil.Discard, res.Body) elapsed := time.Since(start) if err != nil { boomer.RecordFailure("http", "goodSearch", elapsed.Nanoseconds()/int64(time.Millisecond), err.Error()) return } + defer res.Body.Close() if res.StatusCode != 200 { boomer.RecordFailure("http", "goodSearch", elapsed.Nanoseconds()/int64(time.Millisecond), res.Status) @@ -68,11 +69,15 @@ func main() { } t = &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, MaxIdleConns: 10240, MaxIdleConnsPerHost: 10240, + DisableKeepAlives: true, } c = &http.Client{ - Timeout: 10 * time.Second, + Timeout: 40 * time.Second, Transport: t, } diff --git a/backend/utils/service.go b/backend/utils/service.go index 9183101..081ad99 100644 --- a/backend/utils/service.go +++ b/backend/utils/service.go @@ -56,7 +56,7 @@ func InitMicroService(name string) micro.Service { // RunMicroService run a micro service func RunMicroService(service micro.Service) { if !CheckInTest() { - Info("Running micro service \"%s\"", service.String()) + Info("Running micro service \"%s\"", service.Options().Server.Options().Name) LogPanic(service.Run()) } } @@ -74,7 +74,7 @@ func CallMicroService(name string, f func(name string, c client.Client) interfac } Info("Calling micro service \"%s\"", name) c := client.NewClient( - client.RequestTimeout(time.Second*10), + client.RequestTimeout(time.Second*30), client.Selector(selector.DefaultSelector), ) return f(GetServiceName(name), c) From 60c13017ffbbeb43d2111ec4d75081e7dec808d9 Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Wed, 31 Jul 2019 16:56:31 +0800 Subject: [PATCH 08/17] test messageCreate and fix bug --- backend/consul.json | 2 +- backend/doc/api_project.js | 2 +- backend/doc/api_project.json | 2 +- backend/srv/file/mock/mock.go | 8 +++-- backend/srv/message/main.go | 40 +++++++++++++++++----- backend/srv/message/main_test.go | 59 ++++++++++++++++++++++++++++++-- 6 files changed, 98 insertions(+), 15 deletions(-) diff --git a/backend/consul.json b/backend/consul.json index 924ac6a..ce92625 100644 --- a/backend/consul.json +++ b/backend/consul.json @@ -7,7 +7,7 @@ { "key": "srv_config", "flags": 0, - "value": "ewogICJuYW1lc3BhY2UiOiAiZ28ubWljcm8uc3J2IiwKICAidHRsIjogNjAsCiAgImludGVydmFsIjogMjAsCiAgImRlZmF1bHRfYXZhdGFyIiA6ICJ0b19iZV9jaGFuZ2VkIiwKICAidGVzdGRiIiA6IHsKICAgICJkZXZlbG9wIjogIi9zanR1amoiLAogICAgInN1ZmZpeCI6ICI/Y2hhcnNldD11dGY4bWI0LHV0ZjgmcGFyc2VUaW1lPVRydWUiCiAgfSwKICAidGVzdG1vbmdvIjogewogICAgImRibmFtZSI6ICJzanR1amoiLAogICAgImRldmVsb3AiOiAibG9jYWxob3N0OjI3MDE3IgogIH0sCiAgInVzZXJkYiI6IHsKICAgICJkZXZlbG9wIjogIi9zanR1amoiLAogICAgInByb2R1Y3QiOiAidGNwKDEwLjAuMC4yODozMzA2KS9zanR1amoiLAogICAgInN1ZmZpeCI6ICI/Y2hhcnNldD11dGY4bWI0LHV0ZjgmcGFyc2VUaW1lPVRydWUiCiAgfSwKICAic2VsbGluZm9kYiI6IHsKICAgICJkZXZlbG9wIjogIi9zanR1amoiLAogICAgInByb2R1Y3QiOiAidGNwKDEwLjAuMC4yODozMzA2KS9zanR1amoiLAogICAgInN1ZmZpeCI6ICI/Y2hhcnNldD11dGY4bWI0LHV0ZjgmcGFyc2VUaW1lPVRydWUiCiAgfSwgIAogICJidXlpbmZvZGIiOiB7CiAgICAiZGV2ZWxvcCI6ICIvc2p0dWpqIiwKICAgICJwcm9kdWN0IjogInRjcCgxMC4wLjAuMjg6MzMwNykvc2p0dWpqIiwKICAgICJzdWZmaXgiOiAiP2NoYXJzZXQ9dXRmOG1iNCx1dGY4JnBhcnNlVGltZT1UcnVlIgogIH0sCiAgInRyYW5zYWN0aW9uZGIiOiB7CiAgICAiZGV2ZWxvcCI6ICIvc2p0dWpqIiwKICAgICJwcm9kdWN0IjogInRjcCgxMC4wLjAuMjg6MzMwNykvc2p0dWpqIiwKICAgICJzdWZmaXgiOiAiP2NoYXJzZXQ9dXRmOG1iNCx1dGY4JnBhcnNlVGltZT1UcnVlIgogIH0sCiAgImNvbnRlbnRtb25nbyI6IHsKICAgICJkYm5hbWUiOiAic2p0dWpqIiwKICAgICJkZXZlbG9wIjogImxvY2FsaG9zdDoyNzAxNyIsCiAgICAicHJvZHVjdCI6ICIxMC4wLjAuMjg6MjcwMTciCiAgfSwKICAiZmlsZW1vbmdvIjogewogICAgImRibmFtZSI6ICJzanR1amoiLAogICAgImRldmVsb3AiOiAibG9jYWxob3N0OjI3MDE3IiwKICAgICJwcm9kdWN0IjogIjEwLjAuMC4yODoyNzAxNyIKICB9Cn0=" + "value": "ewogICJuYW1lc3BhY2UiOiAiZ28ubWljcm8uc3J2IiwKICAidHRsIjogNjAsCiAgImludGVydmFsIjogMjAsCiAgImRlZmF1bHRfYXZhdGFyIiA6ICJ0b19iZV9jaGFuZ2VkIiwKICAidGVzdGRiIiA6IHsKICAgICJkZXZlbG9wIjogIi9zanR1amoiLAogICAgInN1ZmZpeCI6ICI/Y2hhcnNldD11dGY4bWI0LHV0ZjgmcGFyc2VUaW1lPVRydWUiCiAgfSwKICAidGVzdG1vbmdvIjogewogICAgImRibmFtZSI6ICJzanR1amoiLAogICAgImRldmVsb3AiOiAibG9jYWxob3N0OjI3MDE3IgogIH0sCiAgInVzZXJkYiI6IHsKICAgICJkZXZlbG9wIjogIi9zanR1amoiLAogICAgInByb2R1Y3QiOiAidGNwKDEwLjAuMC4yODozMzA2KS9zanR1amoiLAogICAgInN1ZmZpeCI6ICI/Y2hhcnNldD11dGY4bWI0LHV0ZjgmcGFyc2VUaW1lPVRydWUiCiAgfSwKICAic2VsbGluZm9kYiI6IHsKICAgICJkZXZlbG9wIjogIi9zanR1amoiLAogICAgInByb2R1Y3QiOiAidGNwKDEwLjAuMC4yODozMzA2KS9zanR1amoiLAogICAgInN1ZmZpeCI6ICI/Y2hhcnNldD11dGY4bWI0LHV0ZjgmcGFyc2VUaW1lPVRydWUiCiAgfSwgIAogICJidXlpbmZvZGIiOiB7CiAgICAiZGV2ZWxvcCI6ICIvc2p0dWpqIiwKICAgICJwcm9kdWN0IjogInRjcCgxMC4wLjAuMjg6MzMwNykvc2p0dWpqIiwKICAgICJzdWZmaXgiOiAiP2NoYXJzZXQ9dXRmOG1iNCx1dGY4JnBhcnNlVGltZT1UcnVlIgogIH0sCiAgInRyYW5zYWN0aW9uZGIiOiB7CiAgICAiZGV2ZWxvcCI6ICIvc2p0dWpqIiwKICAgICJwcm9kdWN0IjogInRjcCgxMC4wLjAuMjg6MzMwNykvc2p0dWpqIiwKICAgICJzdWZmaXgiOiAiP2NoYXJzZXQ9dXRmOG1iNCx1dGY4JnBhcnNlVGltZT1UcnVlIgogIH0sCiAgImNvbnRlbnRtb25nbyI6IHsKICAgICJkYm5hbWUiOiAic2p0dWpqIiwKICAgICJkZXZlbG9wIjogImxvY2FsaG9zdDoyNzAxNyIsCiAgICAicHJvZHVjdCI6ICIxMC4wLjAuMjg6MjcwMTciCiAgfSwKICAiZmlsZW1vbmdvIjogewogICAgImRibmFtZSI6ICJzanR1amoiLAogICAgImRldmVsb3AiOiAibG9jYWxob3N0OjI3MDE3IiwKICAgICJwcm9kdWN0IjogIjEwLjAuMC4yODoyNzAxNyIKICB9LAogICJtZXNzYWdlbW9uZ28iOnsKICAgICJkYm5hbWUiOiAic2p0dWpqIiwKICAgICJkZXZlbG9wIjogImxvY2FsaG9zdDoyNzAxNyIsCiAgICAicHJvZHVjdCI6ICIxMC4wLjAuMjg6MjcwMTciCiAgfQp9" }, { "key": "sys_config", diff --git a/backend/doc/api_project.js b/backend/doc/api_project.js index bbc8399..2cff4eb 100644 --- a/backend/doc/api_project.js +++ b/backend/doc/api_project.js @@ -21,7 +21,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-07-31T06:45:27.228Z", + "time": "2019-07-31T08:45:37.153Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/api_project.json b/backend/doc/api_project.json index c6e675a..4f1cd62 100644 --- a/backend/doc/api_project.json +++ b/backend/doc/api_project.json @@ -21,7 +21,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-07-31T06:45:27.228Z", + "time": "2019-07-31T08:45:37.153Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/srv/file/mock/mock.go b/backend/srv/file/mock/mock.go index 19d8362..687fd25 100644 --- a/backend/srv/file/mock/mock.go +++ b/backend/srv/file/mock/mock.go @@ -1,6 +1,7 @@ package mock import ( + "bytes" "context" file "jiaojiao/srv/file/proto" @@ -10,9 +11,12 @@ import ( type mockFileSrv struct{} // Create is file create mock -func (a *mockFileSrv) Create(ctx context.Context, in *file.FileCreateRequest, opts ...client.CallOption) (*file.FileCreateResponse, error) { +func (a *mockFileSrv) Create(ctx context.Context, req *file.FileCreateRequest, opts ...client.CallOption) (*file.FileCreateResponse, error) { var rsp file.FileCreateResponse - // TODO + if bytes.Equal(req.File, []byte{0, 1, 2, 3, 4, 5}) { + rsp.Status = file.FileCreateResponse_SUCCESS + rsp.FileID = "1234567890abcdef12345678" + } return &rsp, nil } diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index 2b4536a..b0c05e9 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -9,6 +9,8 @@ import ( "jiaojiao/utils" "time" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/bson" "github.com/micro/go-micro/client" @@ -16,6 +18,22 @@ import ( type srv struct{} +type MsgInfo struct { + Time time.Time `bson:"time"` + Forward bool `bson:"forward"` + Type message.MessageInfo_Type `bson:"type"` + Text string `bson:"text"` + Unread bool `bson:"unread"` +} + +type ChatLog struct { + ID primitive.ObjectID `bson:"_id"` + FromUser int32 `bson:"fromUser"` + ToUser int32 `bson:"toUser"` + Badge int32 `bson:"badge"` + Infos []MsgInfo `bson:"infos"` +} + /** * @api {rpc} /rpc Message.Create * @apiVersion 1.0.0 @@ -37,6 +55,10 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp return nil } + if req.Type == message.MessageCreateRequest_TEXT && !utils.RequireParam(req.Text) { + rsp.Status = message.MessageCreateResponse_INVALID_PARAM + return nil + } if req.Type == message.MessageCreateRequest_PICTURE || req.Type == message.MessageCreateRequest_VIDEO { srv := utils.CallMicroService("file", func(name string, c client.Client) interface{} { return file.NewFileService(name, c) }, func() interface{} { return mock.NewFileService() }).(file.FileService) @@ -53,15 +75,16 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") - res1, err1 := collection.Find(ctx, bson.M{ + collection := db.MongoDatabase.Collection("message") + var res1, res2 ChatLog + err1 := collection.FindOne(ctx, bson.M{ "fromUser": req.FromUser, "toUser": req.ToUser, - }) - res2, err2 := collection.Find(ctx, bson.M{ + }).Decode(&res1) + err2 := collection.FindOne(ctx, bson.M{ "fromUser": req.ToUser, "toUser": req.FromUser, - }) + }).Decode(&res2) if err1 == nil && err2 != nil { //fromUser to toUser _, err := collection.UpdateOne(ctx, bson.M{ @@ -85,7 +108,7 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp "fromUser": req.FromUser, "toUser": req.ToUser, }, bson.M{"$set": bson.M{ - "badge": res1.Current.Lookup("badge").Int32() + 1, + "badge": res1.Badge + 1, }}) if utils.LogContinue(err, utils.Warning) { rsp.Status = message.MessageCreateResponse_UNKNOWN @@ -115,7 +138,7 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp "fromUser": req.ToUser, "toUser": req.FromUser, }, bson.M{"$set": bson.M{ - "badge": res2.Current.Lookup("badge").Int32() + 1, + "badge": res2.Badge + 1, }}) if utils.LogContinue(err, utils.Warning) { rsp.Status = message.MessageCreateResponse_UNKNOWN @@ -178,7 +201,7 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") + collection := db.MongoDatabase.Collection("message") _, err1 := collection.Find(ctx, bson.M{ "fromUser": req.FromUser, "toUser": req.ToUser, @@ -253,6 +276,7 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me } func main() { + db.InitMongoDB("messagemongo") service := utils.InitMicroService("message") utils.LogPanic(message.RegisterMessageHandler(service.Server(), new(srv))) utils.RunMicroService(service) diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index 3b45cc6..368c15e 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -2,8 +2,12 @@ package main import ( "context" + db "jiaojiao/database" message "jiaojiao/srv/message/proto" "testing" + "time" + + "go.mongodb.org/mongo-driver/bson/primitive" . "github.com/smartystreets/goconvey/convey" ) @@ -11,9 +15,60 @@ import ( func TestCreate(t *testing.T) { var s srv var req message.MessageCreateRequest + var rsp message.MessageCreateResponse + filter := primitive.M{ + "fromUser": 1001, + "toUser": 2001, + } Convey("Test Create Message", t, func() { - err := s.Create(context.TODO(), &req, &message.MessageCreateResponse{}) - ShouldBeNil(err) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + collection := db.MongoDatabase.Collection("message") + + _, err := collection.DeleteOne(ctx, filter) + So(err, ShouldBeNil) + + So(s.Create(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_INVALID_PARAM) + + req.FromUser = 1001 + req.ToUser = 2001 + So(s.Create(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_INVALID_PARAM) + + req.Type = message.MessageCreateRequest_TEXT + So(s.Create(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_INVALID_PARAM) + + req.Text = "你好,我是小明(⊙﹏⊙),🔺" + So(s.Create(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) + + req.Type = message.MessageCreateRequest_PICTURE + req.File = []byte{0, 1, 2, 3, 4, 5} + So(s.Create(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) + + req.FromUser = 2001 + req.ToUser = 1001 + So(s.Create(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) + + count, err := collection.CountDocuments(ctx, filter) + So(count, ShouldEqual, 1) + So(err, ShouldBeNil) + + var chat ChatLog + So(collection.FindOne(ctx, filter).Decode(&chat), ShouldBeNil) + So(chat.Badge, ShouldEqual, 3) + So(len(chat.Infos), ShouldEqual, 3) + So(chat.Infos[2].Forward, ShouldEqual, false) + So(chat.Infos[1].Text, ShouldEqual, "1234567890abcdef12345678") + + defer func() { + _, err = collection.DeleteOne(ctx, filter) + So(err, ShouldBeNil) + }() }) } From 06c4f058e7bec62f50fc5c477feed99e2059a86e Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Thu, 1 Aug 2019 11:35:14 +0800 Subject: [PATCH 09/17] test messageFind and fix bug --- backend/doc/api_project.js | 2 +- backend/doc/api_project.json | 2 +- backend/doc/css/style.css | 569 ------------------------------- backend/srv/message/main.go | 137 +++++--- backend/srv/message/main_test.go | 133 +++++++- 5 files changed, 218 insertions(+), 625 deletions(-) delete mode 100644 backend/doc/css/style.css diff --git a/backend/doc/api_project.js b/backend/doc/api_project.js index 2cff4eb..b444d53 100644 --- a/backend/doc/api_project.js +++ b/backend/doc/api_project.js @@ -21,7 +21,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-07-31T08:45:37.153Z", + "time": "2019-08-01T03:01:03.620Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/api_project.json b/backend/doc/api_project.json index 4f1cd62..21f95fe 100644 --- a/backend/doc/api_project.json +++ b/backend/doc/api_project.json @@ -21,7 +21,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-07-31T08:45:37.153Z", + "time": "2019-08-01T03:01:03.620Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/css/style.css b/backend/doc/css/style.css deleted file mode 100644 index 6468b2b..0000000 --- a/backend/doc/css/style.css +++ /dev/null @@ -1,569 +0,0 @@ -/* ------------------------------------------------------------------------------------------ - * Content - * ------------------------------------------------------------------------------------------ */ -body { - min-width: 980px; - max-width: 1280px; -} - -body, p, a, div, th, td { - font-family: "Source Sans Pro", sans-serif; - font-weight: 400; - font-size: 16px; -} - -td.code { - font-size: 14px; - font-family: "Source Code Pro", monospace; - font-style: normal; - font-weight: 400; -} - -#content { - padding-top: 16px; - z-Index: -1; - margin-left: 270px; -} - -p { - color: #808080; -} - -h1 { - font-family: "Source Sans Pro Semibold", sans-serif; - font-weight: normal; - font-size: 44px; - line-height: 50px; - margin: 0 0 10px 0; - padding: 0; -} - -h2 { - font-family: "Source Sans Pro", sans-serif; - font-weight: normal; - font-size: 24px; - line-height: 40px; - margin: 0 0 20px 0; - padding: 0; -} - -section { - border-top: 1px solid #ebebeb; - padding: 30px 0; -} - -section h1 { - font-family: "Source Sans Pro", sans-serif; - font-weight: 700; - font-size: 32px; - line-height: 40px; - padding-bottom: 14px; - margin: 0 0 20px 0; - padding: 0; -} - -article { - padding: 14px 0 30px 0; -} - -article h1 { - font-family: "Source Sans Pro Bold", sans-serif; - font-weight: 600; - font-size: 24px; - line-height: 26px; -} - -article h2 { - font-family: "Source Sans Pro", sans-serif; - font-weight: 600; - font-size: 18px; - line-height: 24px; - margin: 0 0 10px 0; -} - -article h3 { - font-family: "Source Sans Pro", sans-serif; - font-weight: 600; - font-size: 16px; - line-height: 18px; - margin: 0 0 10px 0; -} - -article h4 { - font-family: "Source Sans Pro", sans-serif; - font-weight: 600; - font-size: 14px; - line-height: 16px; - margin: 0 0 8px 0; -} - -table { - border-collapse: collapse; - width: 100%; - margin: 0 0 20px 0; -} - -th { - background-color: #f5f5f5; - text-align: left; - font-family: "Source Sans Pro", sans-serif; - font-weight: 700; - padding: 4px 8px; - border: #e0e0e0 1px solid; -} - -td { - vertical-align: top; - padding: 10px 8px 0 8px; - border: #e0e0e0 1px solid; -} - -#generator .content { - color: #b0b0b0; - border-top: 1px solid #ebebeb; - padding: 10px 0; -} - -.label-optional { - float: right; - background-color: grey; - margin-top: 4px; -} - -.open-left { - right: 0; - left: auto; -} - -/* ------------------------------------------------------------------------------------------ - * apidoc - intro - * ------------------------------------------------------------------------------------------ */ - -#apidoc .apidoc { - border-top: 1px solid #ebebeb; - padding: 30px 0; -} - -#apidoc h1 { - font-family: "Source Sans Pro", sans-serif; - font-weight: 700; - font-size: 32px; - line-height: 40px; - padding-bottom: 14px; - margin: 0 0 20px 0; - padding: 0; -} - -#apidoc h2 { - font-family: "Source Sans Pro Bold", sans-serif; - font-weight: 600; - font-size: 22px; - line-height: 26px; - padding-top: 14px; -} - -/* ------------------------------------------------------------------------------------------ - * pre / code - * ------------------------------------------------------------------------------------------ */ -pre { - background-color: #292b36; - color: #ffffff; - padding: 10px; - border-radius: 6px; - position: relative; - margin: 10px 0 20px 0; - overflow-x: auto; -} - -pre.prettyprint { - width: 100%; -} - -code.language-text { - word-wrap: break-word; -} - -pre.language-json { - overflow: auto; -} - -pre.language-html { - margin: 0 0 20px 0; -} - -.type { - font-family: "Source Sans Pro", sans-serif; - font-weight: 600; - font-size: 15px; - display: inline-block; - margin: 0 0 5px 0; - padding: 4px 5px; - border-radius: 6px; - text-transform: uppercase; - background-color: #3387CC; - color: #ffffff; -} - -.type__get { - background-color: green; -} - -.type__put { - background-color: #e5c500; -} - -.type__post { - background-color: #4070ec; -} - -.type__delete { - background-color: #ed0039; -} - -pre.language-api .str { - color: #ffffff; -} - -pre.language-api .pln, -pre.language-api .pun { - color: #65B042; -} - -pre code { - display: block; - font-size: 14px; - font-family: "Source Code Pro", monospace; - font-style: normal; - font-weight: 400; - word-wrap: normal; - white-space: pre; -} - -pre code.sample-request-response-json { - white-space: pre-wrap; - max-height: 500px; - overflow: auto; -} - -/* ------------------------------------------------------------------------------------------ - * Sidenav - * ------------------------------------------------------------------------------------------ */ -.sidenav { - width: 228px; - margin: 0; - padding: 0 20px 20px 20px; - position: fixed; - top: 50px; - left: 0; - bottom: 0; - overflow-x: hidden; - overflow-y: auto; - background-color: #f5f5f5; - z-index: 10; -} - -.sidenav > li > a { - display: block; - width: 192px; - margin: 0; - padding: 2px 11px; - border: 0; - border-left: transparent 4px solid; - border-right: transparent 4px solid; - font-family: "Source Sans Pro", sans-serif; - font-weight: 400; - font-size: 14px; -} - -.sidenav > li.nav-header { - margin-top: 8px; - margin-bottom: 8px; -} - -.sidenav > li.nav-header > a { - padding: 5px 15px; - border: 1px solid #e5e5e5; - width: 190px; - font-family: "Source Sans Pro", sans-serif; - font-weight: 700; - font-size: 16px; - background-color: #ffffff; -} - -.sidenav > li.active > a { - position: relative; - z-index: 2; - background-color: #0088cc; - color: #ffffff; -} - -.sidenav > li.has-modifications a { - border-right: #60d060 4px solid; -} - -.sidenav > li.is-new a { - border-left: #e5e5e5 4px solid; -} - -/* ------------------------------------------------------------------------------------------ - * Side nav search - * ------------------------------------------------------------------------------------------ */ -.sidenav-search { - width: 228px; - left: 0px; - position: fixed; - padding: 16px 20px 10px 20px; - background-color: #F5F5F5; - z-index: 11; -} - -.sidenav-search .search { - height: 26px; -} - -.search-reset { - position: absolute; - display: block; - cursor: pointer; - width: 20px; - height: 20px; - text-align: center; - right: 28px; - top: 17px; - background-color: #fff; -} - -/* ------------------------------------------------------------------------------------------ - * Compare - * ------------------------------------------------------------------------------------------ */ - -ins { - background: #60d060; - text-decoration: none; - color: #000000; -} - -del { - background: #f05050; - color: #000000; -} - -.label-ins { - background-color: #60d060; -} - -.label-del { - background-color: #f05050; - text-decoration: line-through; -} - -pre.ins { - background-color: #60d060; -} - -pre.del { - background-color: #f05050; - text-decoration: line-through; -} - -table.ins th, -table.ins td { - background-color: #60d060; -} - -table.del th, -table.del td { - background-color: #f05050; - text-decoration: line-through; -} - -tr.ins td { - background-color: #60d060; -} - -tr.del td { - background-color: #f05050; - text-decoration: line-through; -} - -/* ------------------------------------------------------------------------------------------ - * Spinner - * ------------------------------------------------------------------------------------------ */ - -#loader { - position: absolute; - width: 100%; -} - -#loader p { - padding-top: 80px; - margin-left: -4px; -} - -.spinner { - margin: 200px auto; - width: 60px; - height: 60px; - position: relative; -} - -.container1 > div, .container2 > div, .container3 > div { - width: 14px; - height: 14px; - background-color: #0088cc; - - border-radius: 100%; - position: absolute; - -webkit-animation: bouncedelay 1.2s infinite ease-in-out; - animation: bouncedelay 1.2s infinite ease-in-out; - /* Prevent first frame from flickering when animation starts */ - -webkit-animation-fill-mode: both; - animation-fill-mode: both; -} - -.spinner .spinner-container { - position: absolute; - width: 100%; - height: 100%; -} - -.container2 { - -webkit-transform: rotateZ(45deg); - transform: rotateZ(45deg); -} - -.container3 { - -webkit-transform: rotateZ(90deg); - transform: rotateZ(90deg); -} - -.circle1 { top: 0; left: 0; } -.circle2 { top: 0; right: 0; } -.circle3 { right: 0; bottom: 0; } -.circle4 { left: 0; bottom: 0; } - -.container2 .circle1 { - -webkit-animation-delay: -1.1s; - animation-delay: -1.1s; -} - -.container3 .circle1 { - -webkit-animation-delay: -1.0s; - animation-delay: -1.0s; -} - -.container1 .circle2 { - -webkit-animation-delay: -0.9s; - animation-delay: -0.9s; -} - -.container2 .circle2 { - -webkit-animation-delay: -0.8s; - animation-delay: -0.8s; -} - -.container3 .circle2 { - -webkit-animation-delay: -0.7s; - animation-delay: -0.7s; -} - -.container1 .circle3 { - -webkit-animation-delay: -0.6s; - animation-delay: -0.6s; -} - -.container2 .circle3 { - -webkit-animation-delay: -0.5s; - animation-delay: -0.5s; -} - -.container3 .circle3 { - -webkit-animation-delay: -0.4s; - animation-delay: -0.4s; -} - -.container1 .circle4 { - -webkit-animation-delay: -0.3s; - animation-delay: -0.3s; -} - -.container2 .circle4 { - -webkit-animation-delay: -0.2s; - animation-delay: -0.2s; -} - -.container3 .circle4 { - -webkit-animation-delay: -0.1s; - animation-delay: -0.1s; -} - -@-webkit-keyframes bouncedelay { - 0%, 80%, 100% { -webkit-transform: scale(0.0) } - 40% { -webkit-transform: scale(1.0) } -} - -@keyframes bouncedelay { - 0%, 80%, 100% { - transform: scale(0.0); - -webkit-transform: scale(0.0); - } 40% { - transform: scale(1.0); - -webkit-transform: scale(1.0); - } -} - -/* ------------------------------------------------------------------------------------------ - * Tabs - * ------------------------------------------------------------------------------------------ */ -ul.nav-tabs { - margin: 0; -} - -p.deprecated span{ - color: #ff0000; - font-weight: bold; - text-decoration: underline; -} - -/* ------------------------------------------------------------------------------------------ - * Print - * ------------------------------------------------------------------------------------------ */ - -@media print { - - #sidenav, - #version, - #versions, - section .version, - section .versions { - display: none; - } - - #content { - margin-left: 0; - } - - a { - text-decoration: none; - color: inherit; - } - - a:after { - content: " [" attr(href) "] "; - } - - p { - color: #000000 - } - - pre { - background-color: #ffffff; - color: #000000; - padding: 10px; - border: #808080 1px solid; - border-radius: 6px; - position: relative; - margin: 10px 0 20px 0; - } - -} /* /@media print */ diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index b0c05e9..3c65d88 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -9,6 +9,8 @@ import ( "jiaojiao/utils" "time" + "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson" @@ -92,11 +94,16 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp "toUser": req.ToUser, }, bson.M{"$push": bson.M{ "infos": bson.M{ - "time": time.Now(), - "forward": true, - "type": req.Type, - "text": req.Text, - "unread": true, + "$each": bson.A{ + bson.M{ + "time": time.Now(), + "forward": true, + "type": req.Type, + "text": req.Text, + "unread": true, + }, + }, + "$position": 0, }, }}) if utils.LogContinue(err, utils.Warning) { @@ -122,11 +129,16 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp "toUser": req.FromUser, }, bson.M{"$push": bson.M{ "infos": bson.M{ - "time": time.Now(), - "forward": false, - "type": req.Type, - "text": req.Text, - "unread": true, + "$each": bson.A{ + bson.M{ + "time": time.Now(), + "forward": false, + "type": req.Type, + "text": req.Text, + "unread": true, + }, + }, + "$position": 0, }, }}) if utils.LogContinue(err, utils.Warning) { @@ -199,17 +211,33 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me return nil } + decodeRes := func(src *ChatLog, dest *message.MessageFindResponse) { + dest.FromUser = src.FromUser + dest.ToUser = src.ToUser + dest.Badge = src.Badge + for _, v := range src.Infos { + dest.Infos = append(dest.Infos, &message.MessageInfo{ + Time: v.Time.Unix(), + Forward: v.Forward, + Type: v.Type, + Text: v.Text, + Unread: v.Unread, + }) + } + } + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() collection := db.MongoDatabase.Collection("message") - _, err1 := collection.Find(ctx, bson.M{ + var res1, res2 ChatLog + err1 := collection.FindOne(ctx, bson.M{ "fromUser": req.FromUser, "toUser": req.ToUser, - }) - _, err2 := collection.Find(ctx, bson.M{ + }).Decode(&res1) + err2 := collection.FindOne(ctx, bson.M{ "fromUser": req.ToUser, "toUser": req.FromUser, - }) + }).Decode(&res2) if err1 == nil && err2 != nil { rsp.FromUser = req.FromUser @@ -225,39 +253,72 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me return nil } - if req.Way == message.MessageFindRequest_ONLY_PULL { - err := collection.FindOne(ctx, bson.M{ - "fromUser": rsp.FromUser, - "toUser": rsp.ToUser, - "infos": bson.M{ - "forward": req.FromUser == rsp.FromUser, - "unread": true, + if req.Way == message.MessageFindRequest_ONLY_PULL || req.Way == message.MessageFindRequest_READ_MESSAGE { + var res ChatLog + cur, err := collection.Aggregate(ctx, bson.A{ + bson.M{ + "$match": bson.M{ + "fromUser": rsp.FromUser, + "toUser": rsp.ToUser, + }, }, - }).Decode(&rsp) + bson.M{ + "$project": bson.M{ + "fromUser": 1, + "toUser": 1, + "badge": 1, + "infos": bson.M{ + "$filter": bson.M{ + "input": "$infos", + "as": "item", + "cond": bson.M{ + "$and": bson.A{ + bson.M{"$eq": bson.A{"$$item.forward", req.FromUser == rsp.FromUser}}, + bson.M{"$eq": bson.A{"$$item.unread", true}}, + }, + }, + }, + }, + }, + }, + }) if utils.LogContinue(err, utils.Warning) { rsp.Status = message.MessageFindResponse_UNKNOWN return nil } - rsp.Status = message.MessageFindResponse_SUCCESS - return nil - } else if req.Way == message.MessageFindRequest_READ_MESSAGE { - err := collection.FindOneAndUpdate(ctx, bson.M{ - "fromUser": rsp.FromUser, - "toUser": rsp.ToUser, - "infos": bson.M{ - "forward": req.FromUser == rsp.FromUser, - "unread": true, - }, - }, bson.M{ - "$set": bson.M{ - "badge": 0, - "unread": false, - }, - }).Decode(&rsp) + cur.Next(ctx) + err = cur.Decode(&res) if utils.LogContinue(err, utils.Warning) { rsp.Status = message.MessageFindResponse_UNKNOWN return nil } + + decodeRes(&res, rsp) + + if req.Way == message.MessageFindRequest_READ_MESSAGE { + _, err := collection.UpdateMany(ctx, bson.M{ + "fromUser": rsp.FromUser, + "toUser": rsp.ToUser, + "infos.forward": req.FromUser == rsp.FromUser, + "infos.unread": true, + }, bson.M{ + "$set": bson.M{ + "badge": 0, + "infos.$[elem].unread": false, + }, + }, &options.UpdateOptions{ + ArrayFilters: &options.ArrayFilters{ + Filters: bson.A{bson.M{ + "elem.forward": req.FromUser == rsp.FromUser, + "elem.unread": true, + }}, + }, + }) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageFindResponse_UNKNOWN + return nil + } + } rsp.Status = message.MessageFindResponse_SUCCESS return nil } else if req.Way == message.MessageFindRequest_HISTORY { diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index 368c15e..c014d22 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" . "github.com/smartystreets/goconvey/convey" @@ -20,11 +22,24 @@ func TestCreate(t *testing.T) { "fromUser": 1001, "toUser": 2001, } - Convey("Test Create Message", t, func() { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - collection := db.MongoDatabase.Collection("message") + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + collection := db.MongoDatabase.Collection("message") + + checkResult := func() { + count, err := collection.CountDocuments(ctx, filter) + So(count, ShouldEqual, 1) + So(err, ShouldBeNil) + + var chat ChatLog + So(collection.FindOne(ctx, filter).Decode(&chat), ShouldBeNil) + So(chat.Badge, ShouldEqual, 3) + So(len(chat.Infos), ShouldEqual, 3) + So(chat.Infos[0].Forward, ShouldEqual, false) + So(chat.Infos[1].Text, ShouldEqual, "1234567890abcdef12345678") + } + Convey("Test Create Message", t, func() { _, err := collection.DeleteOne(ctx, filter) So(err, ShouldBeNil) @@ -54,16 +69,7 @@ func TestCreate(t *testing.T) { So(s.Create(context.TODO(), &req, &rsp), ShouldBeNil) So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) - count, err := collection.CountDocuments(ctx, filter) - So(count, ShouldEqual, 1) - So(err, ShouldBeNil) - - var chat ChatLog - So(collection.FindOne(ctx, filter).Decode(&chat), ShouldBeNil) - So(chat.Badge, ShouldEqual, 3) - So(len(chat.Infos), ShouldEqual, 3) - So(chat.Infos[2].Forward, ShouldEqual, false) - So(chat.Infos[1].Text, ShouldEqual, "1234567890abcdef12345678") + checkResult() defer func() { _, err = collection.DeleteOne(ctx, filter) @@ -75,9 +81,104 @@ func TestCreate(t *testing.T) { func TestFind(t *testing.T) { var s srv var req message.MessageFindRequest + var rsp message.MessageFindResponse + filter := primitive.M{ + "fromUser": 1001, + "toUser": 2001, + } + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + collection := db.MongoDatabase.Collection("message") + + prepareData := func() { + _, err := collection.DeleteOne(ctx, filter) + So(err, ShouldBeNil) + + _, err = collection.InsertOne(ctx, bson.M{ + "fromUser": 1001, + "toUser": 2001, + "badge": 3, + "infos": bson.A{bson.M{ + "time": time.Now(), + "forward": true, + "type": message.MessageInfo_TEXT, + "text": "你好,我是小明1(⊙﹏⊙),🔺", + "unread": false, + }, bson.M{ + "time": time.Now(), + "forward": false, + "type": message.MessageInfo_TEXT, + "text": "你好,我是小明2(⊙﹏⊙),🔺", + "unread": false, + }, bson.M{ + "time": time.Now(), + "forward": true, + "type": message.MessageInfo_TEXT, + "text": "你好,我是小明3(⊙﹏⊙),🔺", + "unread": true, + }, bson.M{ + "time": time.Now(), + "forward": false, + "type": message.MessageInfo_TEXT, + "text": "你好,我是小明4(⊙﹏⊙),🔺", + "unread": true, + }, bson.M{ + "time": time.Now(), + "forward": true, + "type": message.MessageCreateRequest_PICTURE, + "text": "1234567890abcdef12345678", + "unread": true, + }}, + }) + So(err, ShouldBeNil) + } Convey("Test Find Message", t, func() { - err := s.Find(context.TODO(), &req, &message.MessageFindResponse{}) - ShouldBeNil(err) + prepareData() + + req.FromUser = 1001 + req.ToUser = 2001 + So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_INVALID_PARAM) + + req.Way = message.MessageFindRequest_ONLY_PULL + So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) + So(rsp.Badge, ShouldEqual, 3) + So(len(rsp.Infos), ShouldEqual, 2) + So(rsp.Infos[1].Text, ShouldEqual, "1234567890abcdef12345678") + + rsp.Infos = nil + req.Way = message.MessageFindRequest_READ_MESSAGE + So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) + So(rsp.Badge, ShouldEqual, 3) + So(len(rsp.Infos), ShouldEqual, 2) + So(rsp.Infos[1].Text, ShouldEqual, "1234567890abcdef12345678") + + rsp.Infos = nil + So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) + So(rsp.Badge, ShouldEqual, 0) + So(len(rsp.Infos), ShouldEqual, 0) + + rsp.Infos = nil + req.FromUser = 2001 + req.Way = message.MessageFindRequest_ONLY_PULL + So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageFindResponse_NOT_FOUND) + + rsp.Infos = nil + req.ToUser = 1001 + So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) + So(rsp.Badge, ShouldEqual, 0) + So(len(rsp.Infos), ShouldEqual, 1) + So(rsp.Infos[0].Text, ShouldEqual, "你好,我是小明4(⊙﹏⊙),🔺") + + defer func() { + _, err := collection.DeleteOne(ctx, filter) + So(err, ShouldBeNil) + }() }) } From 22353189f2c3cce61753e0b2b250180513a07d0a Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Thu, 1 Aug 2019 13:11:25 +0800 Subject: [PATCH 10/17] add message query pageable --- backend/api/message/main.go | 2 + backend/doc/api_data.js | 16 +++++ backend/doc/api_data.json | 16 +++++ backend/doc/api_project.js | 2 +- backend/doc/api_project.json | 2 +- backend/srv/message/main.go | 16 ++++- backend/srv/message/main_test.go | 40 ++++++------ backend/srv/message/proto/message.pb.go | 87 +++++++++++++++---------- backend/srv/message/proto/message.proto | 2 + 9 files changed, 124 insertions(+), 59 deletions(-) diff --git a/backend/api/message/main.go b/backend/api/message/main.go index c3cb2d2..69a9bfe 100644 --- a/backend/api/message/main.go +++ b/backend/api/message/main.go @@ -103,6 +103,8 @@ func findMessage(c *gin.Context) { FromUser int32 `form:"fromUser" binding:"required"` ToUser int32 `form:"toUser" binding:"required"` Way message.MessageFindRequest_Way `form:"way" binding:"required"` + Limit int32 `form:"limit"` + Offset int32 `form:"offset"` } var p param diff --git a/backend/doc/api_data.js b/backend/doc/api_data.js index 4992064..2d8035e 100644 --- a/backend/doc/api_data.js +++ b/backend/doc/api_data.js @@ -2006,6 +2006,22 @@ define({ "api": [ "optional": false, "field": "way", "description": "

1 for only pull message
2 for read message
3 for query history message

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "limit", + "defaultValue": "20", + "description": "

limit of return message infos, only for history query

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "offset", + "defaultValue": "0", + "description": "

offset from the latest message info, only for history query

" } ] } diff --git a/backend/doc/api_data.json b/backend/doc/api_data.json index cfd263a..65546de 100644 --- a/backend/doc/api_data.json +++ b/backend/doc/api_data.json @@ -2006,6 +2006,22 @@ "optional": false, "field": "way", "description": "

1 for only pull message
2 for read message
3 for query history message

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "limit", + "defaultValue": "20", + "description": "

limit of return message infos, only for history query

" + }, + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "offset", + "defaultValue": "0", + "description": "

offset from the latest message info, only for history query

" } ] } diff --git a/backend/doc/api_project.js b/backend/doc/api_project.js index b444d53..7922e5c 100644 --- a/backend/doc/api_project.js +++ b/backend/doc/api_project.js @@ -21,7 +21,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T03:01:03.620Z", + "time": "2019-08-01T05:10:06.467Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/api_project.json b/backend/doc/api_project.json index 21f95fe..b895704 100644 --- a/backend/doc/api_project.json +++ b/backend/doc/api_project.json @@ -21,7 +21,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T03:01:03.620Z", + "time": "2019-08-01T05:10:06.467Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index 3c65d88..19afe41 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -193,6 +193,8 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp * @apiParam {int32} fromUser user who launch the chat at first time * @apiParam {int32} toUser user who accept the chat at first time * @apiParam {int32} way 1 for only pull message
2 for read message
3 for query history message + * @apiParam {int32} limit=20 limit of return message infos, only for history query + * @apiParam {int32} offset=0 offset from the latest message info, only for history query * @apiSuccess {int32} fromUser user who launch the chat at first time * @apiSuccess {int32} toUser user who accept the chat at first time * @apiSuccess {int32} badge count of message still unread @@ -210,6 +212,9 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me rsp.Status = message.MessageFindResponse_INVALID_PARAM return nil } + if req.Limit == 0 { + req.Limit = 20 + } decodeRes := func(src *ChatLog, dest *message.MessageFindResponse) { dest.FromUser = src.FromUser @@ -322,14 +327,23 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me rsp.Status = message.MessageFindResponse_SUCCESS return nil } else if req.Way == message.MessageFindRequest_HISTORY { + var res ChatLog err := collection.FindOne(ctx, bson.M{ "fromUser": rsp.FromUser, "toUser": rsp.ToUser, - }).Decode(&rsp) + }, &options.FindOneOptions{ + Projection: bson.M{ + "infos": bson.M{ + "$slice": bson.A{req.Offset, req.Limit}, + }, + }, + }).Decode(&res) if utils.LogContinue(err, utils.Warning) { rsp.Status = message.MessageFindResponse_UNKNOWN return nil } + + decodeRes(&res, rsp) rsp.Status = message.MessageFindResponse_SUCCESS return nil } diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index c014d22..cd52ba3 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -132,47 +132,45 @@ func TestFind(t *testing.T) { }) So(err, ShouldBeNil) } + + testBase := func(infoLen int, badge int, status message.MessageFindResponse_Status) { + rsp.Reset() + So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, status) + So(rsp.Badge, ShouldEqual, badge) + So(len(rsp.Infos), ShouldEqual, infoLen) + } Convey("Test Find Message", t, func() { prepareData() req.FromUser = 1001 req.ToUser = 2001 So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) - So(rsp.Status, ShouldEqual, message.MessageCreateResponse_INVALID_PARAM) + So(rsp.Status, ShouldEqual, message.MessageFindResponse_INVALID_PARAM) req.Way = message.MessageFindRequest_ONLY_PULL - So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) - So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) - So(rsp.Badge, ShouldEqual, 3) - So(len(rsp.Infos), ShouldEqual, 2) + testBase(2, 3, message.MessageFindResponse_SUCCESS) So(rsp.Infos[1].Text, ShouldEqual, "1234567890abcdef12345678") - rsp.Infos = nil req.Way = message.MessageFindRequest_READ_MESSAGE - So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) - So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) - So(rsp.Badge, ShouldEqual, 3) - So(len(rsp.Infos), ShouldEqual, 2) + testBase(2, 3, message.MessageFindResponse_SUCCESS) So(rsp.Infos[1].Text, ShouldEqual, "1234567890abcdef12345678") - rsp.Infos = nil - So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) - So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) - So(rsp.Badge, ShouldEqual, 0) - So(len(rsp.Infos), ShouldEqual, 0) + testBase(0, 0, message.MessageFindResponse_SUCCESS) + + req.Way = message.MessageFindRequest_HISTORY + testBase(5, 0, message.MessageFindResponse_SUCCESS) + + req.Limit = 3 + testBase(3, 0, message.MessageFindResponse_SUCCESS) - rsp.Infos = nil req.FromUser = 2001 req.Way = message.MessageFindRequest_ONLY_PULL So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) So(rsp.Status, ShouldEqual, message.MessageFindResponse_NOT_FOUND) - rsp.Infos = nil req.ToUser = 1001 - So(s.Find(context.TODO(), &req, &rsp), ShouldBeNil) - So(rsp.Status, ShouldEqual, message.MessageCreateResponse_SUCCESS) - So(rsp.Badge, ShouldEqual, 0) - So(len(rsp.Infos), ShouldEqual, 1) + testBase(1, 0, message.MessageFindResponse_SUCCESS) So(rsp.Infos[0].Text, ShouldEqual, "你好,我是小明4(⊙﹏⊙),🔺") defer func() { diff --git a/backend/srv/message/proto/message.pb.go b/backend/srv/message/proto/message.pb.go index 8edb08b..5e1646c 100644 --- a/backend/srv/message/proto/message.pb.go +++ b/backend/srv/message/proto/message.pb.go @@ -357,6 +357,8 @@ type MessageFindRequest struct { FromUser int32 `protobuf:"varint,1,opt,name=fromUser,proto3" json:"fromUser,omitempty"` ToUser int32 `protobuf:"varint,2,opt,name=toUser,proto3" json:"toUser,omitempty"` Way MessageFindRequest_Way `protobuf:"varint,3,opt,name=way,proto3,enum=MessageFindRequest_Way" json:"way,omitempty"` + Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` + Offset int32 `protobuf:"varint,5,opt,name=offset,proto3" json:"offset,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -408,6 +410,20 @@ func (m *MessageFindRequest) GetWay() MessageFindRequest_Way { return MessageFindRequest_UNKNOWN } +func (m *MessageFindRequest) GetLimit() int32 { + if m != nil { + return m.Limit + } + return 0 +} + +func (m *MessageFindRequest) GetOffset() int32 { + if m != nil { + return m.Offset + } + return 0 +} + type MessageFindResponse struct { Status MessageFindResponse_Status `protobuf:"varint,1,opt,name=status,proto3,enum=MessageFindResponse_Status" json:"status,omitempty"` FromUser int32 `protobuf:"varint,2,opt,name=fromUser,proto3" json:"fromUser,omitempty"` @@ -495,39 +511,40 @@ func init() { func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) } var fileDescriptor_33c57e4bae7b9afd = []byte{ - // 530 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xdd, 0x8a, 0xd3, 0x40, - 0x14, 0x76, 0xf2, 0xd3, 0x9f, 0xd3, 0x76, 0x19, 0x67, 0xbb, 0x6b, 0xa8, 0x08, 0x25, 0x20, 0xd4, - 0x9b, 0x01, 0xbb, 0x2c, 0xde, 0x89, 0xa5, 0xcd, 0x6a, 0xb0, 0x4d, 0xca, 0x24, 0xd9, 0xba, 0x57, - 0x25, 0x4b, 0xa7, 0x4b, 0xc1, 0x26, 0x35, 0x49, 0x59, 0xf3, 0x04, 0xde, 0xf9, 0x36, 0x3e, 0x82, - 0x0f, 0xe1, 0xd3, 0x28, 0x99, 0x64, 0x65, 0x53, 0x23, 0x82, 0x9b, 0xab, 0x39, 0x3f, 0xf9, 0xce, - 0xf7, 0x7d, 0x73, 0x12, 0xe8, 0x6c, 0x79, 0x1c, 0xfb, 0x37, 0x9c, 0xee, 0xa2, 0x30, 0x09, 0xf5, - 0xef, 0x08, 0x5a, 0xb3, 0x3c, 0x63, 0x06, 0xeb, 0x90, 0x10, 0x50, 0x92, 0xcd, 0x96, 0x6b, 0xa8, - 0x8f, 0x06, 0x32, 0x13, 0x67, 0xa2, 0x41, 0x7d, 0x1d, 0x46, 0xb7, 0x7e, 0xb4, 0xd2, 0xa4, 0x3e, - 0x1a, 0x34, 0xd8, 0x5d, 0x48, 0x9e, 0x83, 0x92, 0xa4, 0x3b, 0xae, 0xc9, 0x7d, 0x34, 0x38, 0x1a, - 0x3e, 0xa6, 0xf7, 0x90, 0xa8, 0x9b, 0xee, 0x38, 0x13, 0x65, 0x01, 0xca, 0x3f, 0x27, 0x9a, 0xd2, - 0x47, 0x83, 0x26, 0x13, 0x67, 0x72, 0x0a, 0xb5, 0x7d, 0x10, 0x71, 0x7f, 0xa5, 0xa9, 0x02, 0xb3, - 0x88, 0xf4, 0x73, 0x50, 0xb2, 0x37, 0x49, 0x0b, 0xea, 0x9e, 0xf5, 0xde, 0xb2, 0x17, 0x16, 0x7e, - 0x44, 0x1a, 0xa0, 0xb8, 0xc6, 0x07, 0x17, 0xa3, 0x2c, 0x3d, 0x37, 0xc7, 0xae, 0xc7, 0x0c, 0x2c, - 0x91, 0x26, 0xa8, 0x97, 0xe6, 0xc4, 0xb0, 0xb1, 0xac, 0xff, 0x40, 0xd0, 0x2d, 0xa6, 0x8f, 0x23, - 0xee, 0x27, 0x9c, 0xf1, 0x4f, 0x7b, 0x1e, 0x27, 0xa4, 0x07, 0x8d, 0x75, 0x14, 0x6e, 0xbd, 0x98, - 0x47, 0x42, 0x94, 0xca, 0x7e, 0xc7, 0x19, 0x87, 0x24, 0x14, 0x15, 0x49, 0x54, 0x8a, 0x88, 0xd0, - 0x92, 0xac, 0x1e, 0xad, 0x02, 0xfe, 0x97, 0x3e, 0x02, 0xca, 0x7a, 0xf3, 0x91, 0x0b, 0x75, 0x6d, - 0x26, 0xce, 0xff, 0xab, 0xed, 0x2b, 0x82, 0x93, 0x03, 0x0a, 0xf1, 0x2e, 0x0c, 0x62, 0x4e, 0xce, - 0xa1, 0x16, 0x27, 0x7e, 0xb2, 0x8f, 0x85, 0xb4, 0xa3, 0xe1, 0x33, 0x5a, 0xd9, 0x47, 0x1d, 0xd1, - 0xc4, 0x8a, 0x66, 0xfd, 0x35, 0xd4, 0xf2, 0x4c, 0x99, 0x49, 0x0f, 0x3a, 0xa6, 0x75, 0x39, 0x9a, - 0x9a, 0x93, 0xe5, 0x7c, 0xc4, 0x46, 0x33, 0xfc, 0xf3, 0xee, 0x11, 0xdc, 0x1c, 0x6f, 0x3c, 0x36, - 0x1c, 0x07, 0x23, 0xfd, 0x1b, 0x02, 0x52, 0x0c, 0xba, 0xd8, 0x04, 0xab, 0x87, 0x58, 0xfd, 0x02, - 0xe4, 0x5b, 0x3f, 0x2d, 0x9c, 0x7e, 0x42, 0xff, 0x44, 0xa5, 0x0b, 0x3f, 0x65, 0x59, 0x8f, 0xfe, - 0x06, 0xe4, 0x85, 0x9f, 0x96, 0x29, 0x77, 0xa0, 0x69, 0x5b, 0xd3, 0xab, 0xe5, 0xdc, 0x9b, 0x4e, - 0x31, 0x22, 0x18, 0xda, 0xcc, 0x18, 0x4d, 0x96, 0x33, 0xc3, 0x71, 0x46, 0x6f, 0x33, 0x1b, 0x5b, - 0x50, 0x7f, 0x67, 0x3a, 0xae, 0xcd, 0xae, 0xb0, 0xac, 0x7f, 0x91, 0xe0, 0xb8, 0x34, 0xa1, 0xb0, - 0xf1, 0xec, 0xc0, 0xc6, 0xa7, 0xb4, 0xa2, 0xeb, 0xc0, 0xc4, 0x92, 0x5a, 0xe9, 0xaf, 0x6a, 0xe5, - 0x92, 0xda, 0x2e, 0xa8, 0xd7, 0xfe, 0xea, 0x86, 0x8b, 0x4d, 0x51, 0x59, 0x1e, 0x10, 0x1d, 0xd4, - 0x4d, 0xb0, 0x0e, 0x63, 0x4d, 0xed, 0xcb, 0x83, 0xd6, 0xb0, 0x7d, 0xff, 0x33, 0x62, 0x79, 0x49, - 0x9f, 0x3d, 0xec, 0xca, 0x32, 0xa3, 0x2c, 0xdb, 0x5d, 0x5e, 0xd8, 0x9e, 0x35, 0xc1, 0xd2, 0x70, - 0x0f, 0xf5, 0x62, 0x08, 0x79, 0x05, 0xb5, 0x7c, 0x5b, 0xc8, 0x49, 0xe5, 0xa2, 0xf7, 0x4e, 0xab, - 0x97, 0x8a, 0xbc, 0x04, 0x25, 0xf3, 0x87, 0x1c, 0x57, 0xdc, 0x5a, 0xaf, 0x5b, 0x65, 0xe1, 0x75, - 0x4d, 0xfc, 0x74, 0xce, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x4c, 0x58, 0xf9, 0x5f, 0x85, 0x04, - 0x00, 0x00, + // 552 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0xdd, 0x8a, 0xd3, 0x40, + 0x14, 0xc7, 0x9d, 0x7c, 0xf4, 0xe3, 0xb4, 0x5d, 0xe2, 0x6c, 0x77, 0x0d, 0x15, 0xa1, 0x04, 0x84, + 0x7a, 0x13, 0xb0, 0xcb, 0xe2, 0x9d, 0x58, 0xda, 0xac, 0x06, 0xdb, 0xa4, 0x4c, 0x92, 0xad, 0x7b, + 0x55, 0xb2, 0x74, 0xb2, 0x04, 0xb6, 0x4d, 0x4d, 0xa6, 0xac, 0x79, 0x02, 0xef, 0x7c, 0x2b, 0x1f, + 0xc2, 0x6b, 0x1f, 0x44, 0xc9, 0x24, 0x95, 0x4d, 0x8d, 0x08, 0xbb, 0xbd, 0x9a, 0xff, 0x9c, 0xd3, + 0x73, 0xce, 0xff, 0x37, 0x33, 0x81, 0xce, 0x9a, 0x26, 0x89, 0x7f, 0x43, 0xf5, 0x6d, 0x1c, 0xb1, + 0x48, 0xfb, 0x8e, 0xa0, 0x35, 0xcb, 0x77, 0xcc, 0x4d, 0x10, 0x61, 0x0c, 0x12, 0x0b, 0xd7, 0x54, + 0x45, 0x7d, 0x34, 0x10, 0x09, 0x5f, 0x63, 0x15, 0xea, 0x41, 0x14, 0xdf, 0xf9, 0xf1, 0x4a, 0x15, + 0xfa, 0x68, 0xd0, 0x20, 0x7b, 0x89, 0x5f, 0x82, 0xc4, 0xd2, 0x2d, 0x55, 0xc5, 0x3e, 0x1a, 0x1c, + 0x0d, 0x9f, 0xea, 0xf7, 0x2a, 0xe9, 0x6e, 0xba, 0xa5, 0x84, 0x87, 0x79, 0x51, 0xfa, 0x85, 0xa9, + 0x52, 0x1f, 0x0d, 0x9a, 0x84, 0xaf, 0xf1, 0x29, 0xd4, 0x76, 0x9b, 0x98, 0xfa, 0x2b, 0x55, 0xe6, + 0x35, 0x0b, 0xa5, 0x9d, 0x83, 0x94, 0xfd, 0x13, 0xb7, 0xa0, 0xee, 0x59, 0x1f, 0x2d, 0x7b, 0x61, + 0x29, 0x4f, 0x70, 0x03, 0x24, 0xd7, 0xf8, 0xe4, 0x2a, 0x28, 0xdb, 0x9e, 0x9b, 0x63, 0xd7, 0x23, + 0x86, 0x22, 0xe0, 0x26, 0xc8, 0x97, 0xe6, 0xc4, 0xb0, 0x15, 0x51, 0xfb, 0x81, 0xa0, 0x5b, 0x74, + 0x1f, 0xc7, 0xd4, 0x67, 0x94, 0xd0, 0xcf, 0x3b, 0x9a, 0x30, 0xdc, 0x83, 0x46, 0x10, 0x47, 0x6b, + 0x2f, 0xa1, 0x31, 0x37, 0x25, 0x93, 0x3f, 0x3a, 0x9b, 0x81, 0x45, 0x3c, 0x22, 0xf0, 0x48, 0xa1, + 0xb0, 0x5e, 0xb2, 0xd5, 0xd3, 0xab, 0x0a, 0xff, 0xcf, 0x1f, 0x06, 0x29, 0x08, 0x6f, 0x29, 0x77, + 0xd7, 0x26, 0x7c, 0xfd, 0x50, 0x6f, 0xdf, 0x10, 0x9c, 0x1c, 0x8c, 0x90, 0x6c, 0xa3, 0x4d, 0x42, + 0xf1, 0x39, 0xd4, 0x12, 0xe6, 0xb3, 0x5d, 0xc2, 0xad, 0x1d, 0x0d, 0x5f, 0xe8, 0x95, 0x79, 0xba, + 0xc3, 0x93, 0x48, 0x91, 0xac, 0xbd, 0x85, 0x5a, 0xbe, 0x53, 0x9e, 0xa4, 0x07, 0x1d, 0xd3, 0xba, + 0x1c, 0x4d, 0xcd, 0xc9, 0x72, 0x3e, 0x22, 0xa3, 0x99, 0xf2, 0x6b, 0xff, 0xe3, 0xb3, 0x39, 0xde, + 0x78, 0x6c, 0x38, 0x8e, 0x82, 0xb4, 0x9f, 0x08, 0x70, 0xd1, 0xe8, 0x22, 0xdc, 0xac, 0x1e, 0x83, + 0xfa, 0x15, 0x88, 0x77, 0x7e, 0x5a, 0x90, 0x7e, 0xa6, 0xff, 0x5d, 0x55, 0x5f, 0xf8, 0x29, 0xc9, + 0x72, 0x70, 0x17, 0xe4, 0xdb, 0x70, 0x1d, 0xe6, 0x98, 0x65, 0x92, 0x8b, 0xac, 0x70, 0x14, 0x04, + 0x09, 0x65, 0x9c, 0xb4, 0x4c, 0x0a, 0xa5, 0xbd, 0x03, 0x71, 0xe1, 0xa7, 0x65, 0x83, 0x1d, 0x68, + 0xda, 0xd6, 0xf4, 0x6a, 0x39, 0xf7, 0xa6, 0x53, 0x05, 0x61, 0x05, 0xda, 0xc4, 0x18, 0x4d, 0x96, + 0x33, 0xc3, 0x71, 0x46, 0xef, 0x33, 0xe8, 0x2d, 0xa8, 0x7f, 0x30, 0x1d, 0xd7, 0x26, 0x57, 0x8a, + 0xa8, 0x7d, 0x15, 0xe0, 0xb8, 0x34, 0x4f, 0x01, 0xfd, 0xec, 0x00, 0xfa, 0x73, 0xbd, 0x22, 0xeb, + 0x00, 0x79, 0x89, 0x8d, 0xf0, 0x4f, 0x36, 0x62, 0x89, 0x4d, 0x17, 0xe4, 0x6b, 0x7f, 0x75, 0x43, + 0xf7, 0x86, 0xb9, 0xc0, 0x1a, 0xc8, 0xe1, 0x26, 0x88, 0x12, 0x55, 0xee, 0x8b, 0x83, 0xd6, 0xb0, + 0x7d, 0xff, 0xd1, 0x91, 0x3c, 0xa4, 0xcd, 0x1e, 0x77, 0xc0, 0x19, 0x28, 0xcb, 0x76, 0x97, 0x17, + 0xb6, 0x67, 0x4d, 0x14, 0x61, 0xb8, 0x83, 0x7a, 0xd1, 0x04, 0xbf, 0x81, 0x5a, 0x7e, 0xb7, 0xf0, + 0x49, 0xe5, 0xb3, 0xe8, 0x9d, 0x56, 0x5f, 0x41, 0xfc, 0x1a, 0xa4, 0x8c, 0x0f, 0x3e, 0xae, 0x38, + 0xe3, 0x5e, 0xb7, 0x0a, 0xe1, 0x75, 0x8d, 0x7f, 0xa2, 0xce, 0x7e, 0x07, 0x00, 0x00, 0xff, 0xff, + 0x21, 0x81, 0x12, 0x81, 0xb3, 0x04, 0x00, 0x00, } diff --git a/backend/srv/message/proto/message.proto b/backend/srv/message/proto/message.proto index 13c8fa1..2c9d3fa 100644 --- a/backend/srv/message/proto/message.proto +++ b/backend/srv/message/proto/message.proto @@ -52,6 +52,8 @@ message MessageFindRequest { int32 fromUser = 1; int32 toUser = 2; Way way = 3; + int32 limit = 4; + int32 offset = 5; } message MessageFindResponse { From ad70b5c1a8dc457197fded0dc599c0f5da8b17bf Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Thu, 1 Aug 2019 13:38:52 +0800 Subject: [PATCH 11/17] add test --- backend/doc/api_project.js | 2 +- backend/doc/api_project.json | 2 +- backend/srv/message/main_test.go | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/backend/doc/api_project.js b/backend/doc/api_project.js index 7922e5c..38b443d 100644 --- a/backend/doc/api_project.js +++ b/backend/doc/api_project.js @@ -21,7 +21,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T05:10:06.467Z", + "time": "2019-08-01T05:35:19.268Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/api_project.json b/backend/doc/api_project.json index b895704..ed771d9 100644 --- a/backend/doc/api_project.json +++ b/backend/doc/api_project.json @@ -21,7 +21,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T05:10:06.467Z", + "time": "2019-08-01T05:35:19.268Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index cd52ba3..3d8c198 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -163,6 +163,11 @@ func TestFind(t *testing.T) { req.Limit = 3 testBase(3, 0, message.MessageFindResponse_SUCCESS) + rsp.Infos[0].Text = "你好,我是小明1(⊙﹏⊙),🔺" + + req.Offset = 1 + testBase(3, 0, message.MessageFindResponse_SUCCESS) + rsp.Infos[0].Text = "你好,我是小明2(⊙﹏⊙),🔺" req.FromUser = 2001 req.Way = message.MessageFindRequest_ONLY_PULL @@ -173,6 +178,12 @@ func TestFind(t *testing.T) { testBase(1, 0, message.MessageFindResponse_SUCCESS) So(rsp.Infos[0].Text, ShouldEqual, "你好,我是小明4(⊙﹏⊙),🔺") + req.Way = message.MessageFindRequest_HISTORY + testBase(3, 0, message.MessageFindResponse_SUCCESS) + + req.Way = message.MessageFindRequest_READ_MESSAGE + testBase(1, 0, message.MessageFindResponse_SUCCESS) + defer func() { _, err := collection.DeleteOne(ctx, filter) So(err, ShouldBeNil) From 82018738dd76ecfa2f6d60b633f8ab4ee7deb34f Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Thu, 1 Aug 2019 15:11:20 +0800 Subject: [PATCH 12/17] query all new message --- backend/doc/api_data.js | 123 +++++++++++ backend/doc/api_data.json | 123 +++++++++++ backend/doc/api_project.js | 2 +- backend/doc/api_project.json | 2 +- backend/srv/message/main.go | 98 +++++++++ backend/srv/message/main_test.go | 99 +++++++++ backend/srv/message/proto/message.pb.go | 261 ++++++++++++++++++++---- backend/srv/message/proto/message.proto | 22 ++ 8 files changed, 692 insertions(+), 38 deletions(-) diff --git a/backend/doc/api_data.js b/backend/doc/api_data.js index 2d8035e..4d3f923 100644 --- a/backend/doc/api_data.js +++ b/backend/doc/api_data.js @@ -2119,6 +2119,129 @@ define({ "api": [ } } }, + { + "type": "rpc", + "url": "/rpc", + "title": "Message.Query", + "version": "1.0.0", + "group": "Service", + "name": "Message_Query", + "description": "

Query New Message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "user", + "description": "

user who wants to pull new message

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "status", + "description": "

-1 for invalid param
1 for success
2 for not found

" + }, + { + "group": "Success 200", + "type": "list", + "optional": false, + "field": "news", + "description": "

see below NewMessage

" + } + ], + "NewMessage": [ + { + "group": "NewMessage", + "type": "int32", + "optional": false, + "field": "fromUser", + "description": "

user who launch the chat at first time

" + }, + { + "group": "NewMessage", + "type": "int32", + "optional": false, + "field": "toUser", + "description": "

user who accept the chat at first time

" + }, + { + "group": "NewMessage", + "type": "int32", + "optional": false, + "field": "badge", + "description": "

count of message still unread

" + }, + { + "group": "NewMessage", + "type": "MessageInfo", + "optional": false, + "field": "info", + "description": "

see below MessageInfo

" + } + ], + "MessageInfo": [ + { + "group": "MessageInfo", + "type": "int64", + "optional": false, + "field": "time", + "description": "

message create time

" + }, + { + "group": "MessageInfo", + "type": "bool", + "optional": false, + "field": "forward", + "description": "

false for chat from toUser to fromUser
true for chat from fromUser to toUser

" + }, + { + "group": "MessageInfo", + "type": "int32", + "optional": false, + "field": "type", + "description": "

1 for text
2 for picture
3 for video

" + }, + { + "group": "MessageInfo", + "type": "string", + "optional": false, + "field": "text", + "description": "

plain message text if type is text
fileID if type is picture or video

" + }, + { + "group": "MessageInfo", + "type": "bool", + "optional": false, + "field": "unread", + "description": "

false for having read
true for not having read

" + } + ] + } + }, + "filename": "srv/message/main.go", + "groupTitle": "Service", + "error": { + "fields": { + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "DBServerDown", + "description": "

can't connect to database server

" + } + ] + } + } + }, { "type": "rpc", "url": "/rpc", diff --git a/backend/doc/api_data.json b/backend/doc/api_data.json index 65546de..6c54378 100644 --- a/backend/doc/api_data.json +++ b/backend/doc/api_data.json @@ -2119,6 +2119,129 @@ } } }, + { + "type": "rpc", + "url": "/rpc", + "title": "Message.Query", + "version": "1.0.0", + "group": "Service", + "name": "Message_Query", + "description": "

Query New Message

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "int32", + "optional": false, + "field": "user", + "description": "

user who wants to pull new message

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "int32", + "optional": false, + "field": "status", + "description": "

-1 for invalid param
1 for success
2 for not found

" + }, + { + "group": "Success 200", + "type": "list", + "optional": false, + "field": "news", + "description": "

see below NewMessage

" + } + ], + "NewMessage": [ + { + "group": "NewMessage", + "type": "int32", + "optional": false, + "field": "fromUser", + "description": "

user who launch the chat at first time

" + }, + { + "group": "NewMessage", + "type": "int32", + "optional": false, + "field": "toUser", + "description": "

user who accept the chat at first time

" + }, + { + "group": "NewMessage", + "type": "int32", + "optional": false, + "field": "badge", + "description": "

count of message still unread

" + }, + { + "group": "NewMessage", + "type": "MessageInfo", + "optional": false, + "field": "info", + "description": "

see below MessageInfo

" + } + ], + "MessageInfo": [ + { + "group": "MessageInfo", + "type": "int64", + "optional": false, + "field": "time", + "description": "

message create time

" + }, + { + "group": "MessageInfo", + "type": "bool", + "optional": false, + "field": "forward", + "description": "

false for chat from toUser to fromUser
true for chat from fromUser to toUser

" + }, + { + "group": "MessageInfo", + "type": "int32", + "optional": false, + "field": "type", + "description": "

1 for text
2 for picture
3 for video

" + }, + { + "group": "MessageInfo", + "type": "string", + "optional": false, + "field": "text", + "description": "

plain message text if type is text
fileID if type is picture or video

" + }, + { + "group": "MessageInfo", + "type": "bool", + "optional": false, + "field": "unread", + "description": "

false for having read
true for not having read

" + } + ] + } + }, + "filename": "srv/message/main.go", + "groupTitle": "Service", + "error": { + "fields": { + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "DBServerDown", + "description": "

can't connect to database server

" + } + ] + } + } + }, { "type": "rpc", "url": "/rpc", diff --git a/backend/doc/api_project.js b/backend/doc/api_project.js index 38b443d..ecdaf9c 100644 --- a/backend/doc/api_project.js +++ b/backend/doc/api_project.js @@ -21,7 +21,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T05:35:19.268Z", + "time": "2019-08-01T06:58:03.812Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/api_project.json b/backend/doc/api_project.json index ed771d9..3abc9af 100644 --- a/backend/doc/api_project.json +++ b/backend/doc/api_project.json @@ -21,7 +21,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T05:35:19.268Z", + "time": "2019-08-01T06:58:03.812Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index 19afe41..2be7458 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -350,6 +350,104 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me return nil } +/** + * @api {rpc} /rpc Message.Query + * @apiVersion 1.0.0 + * @apiGroup Service + * @apiName Message.Query + * @apiDescription Query New Message + * + * @apiParam {int32} user user who wants to pull new message + * @apiSuccess {int32} status -1 for invalid param
1 for success
2 for not found + * @apiSuccess {list} news see below NewMessage + * @apiSuccess (NewMessage) {int32} fromUser user who launch the chat at first time + * @apiSuccess (NewMessage) {int32} toUser user who accept the chat at first time + * @apiSuccess (NewMessage) {int32} badge count of message still unread + * @apiSuccess (NewMessage) {MessageInfo} info see below MessageInfo + * @apiSuccess (MessageInfo) {int64} time message create time + * @apiSuccess (MessageInfo) {bool} forward false for chat from toUser to fromUser
true for chat from fromUser to toUser + * @apiSuccess (MessageInfo) {int32} type 1 for text
2 for picture
3 for video + * @apiSuccess (MessageInfo) {string} text plain message text if type is text
fileID if type is picture or video + * @apiSuccess (MessageInfo) {bool} unread false for having read
true for not having read + * @apiUse DBServerDown + */ +func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp *message.MessageQueryResponse) error { + if !utils.RequireParam(req.User) { + rsp.Status = message.MessageQueryResponse_INVALID_PARAM + return nil + } + + decodeRes := func(src *ChatLog, dest *message.NewMessage) { + dest.FromUser = src.FromUser + dest.ToUser = src.ToUser + dest.Badge = src.Badge + dest.Info = &message.MessageInfo{ + Time: src.Infos[0].Time.Unix(), + Forward: src.Infos[0].Forward, + Type: src.Infos[0].Type, + Text: src.Infos[0].Text, + Unread: src.Infos[0].Unread, + } + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + collection := db.MongoDatabase.Collection("message") + + cur, err := collection.Find(ctx, bson.M{ + "$or": bson.A{ + bson.M{ + "fromUser": req.User, + "badge": bson.M{"$gt": 0}, + "infos": bson.M{ + "$elemMatch": bson.M{ + "forward": false, + "unread": true, + }, + }, + }, + bson.M{ + "toUser": req.User, + "badge": bson.M{"$gt": 0}, + "infos": bson.M{ + "$elemMatch": bson.M{ + "forward": true, + "unread": true, + }, + }, + }, + }, + }, &options.FindOptions{Projection: bson.M{ + "infos": bson.M{ + "$slice": 1, + }, + }}) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageQueryResponse_NOT_FOUND + return nil + } + + for cur.Next(ctx) { + var res ChatLog + var newMessage message.NewMessage + err = cur.Decode(&res) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = message.MessageQueryResponse_UNKNOWN + return nil + } + + decodeRes(&res, &newMessage) + rsp.News = append(rsp.News, &newMessage) + } + + if rsp.News == nil || len(rsp.News) == 0 { + rsp.Status = message.MessageQueryResponse_NOT_FOUND + return nil + } + rsp.Status = message.MessageQueryResponse_SUCCESS + return nil +} + func main() { db.InitMongoDB("messagemongo") service := utils.InitMicroService("message") diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index 3d8c198..9c7e86e 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -192,6 +192,105 @@ func TestFind(t *testing.T) { } +func TestQuery(t *testing.T) { + var s srv + var req message.MessageQueryRequest + var rsp message.MessageQueryResponse + filter1 := primitive.M{ + "fromUser": 1001, + "toUser": 2001, + } + filter2 := primitive.M{ + "fromUser": 1001, + "toUser": 2002, + } + filter3 := primitive.M{ + "fromUser": 2003, + "toUser": 1001, + } + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + collection := db.MongoDatabase.Collection("message") + + prepareData := func() { + _, err := collection.DeleteOne(ctx, filter1) + So(err, ShouldBeNil) + _, err = collection.DeleteOne(ctx, filter2) + So(err, ShouldBeNil) + _, err = collection.DeleteOne(ctx, filter3) + So(err, ShouldBeNil) + + _, err = collection.InsertMany(ctx, bson.A{ + bson.M{ + "fromUser": 1001, + "toUser": 2001, + "badge": 1, + "infos": bson.A{ + bson.M{"time": time.Now(), "forward": false, "type": message.MessageInfo_TEXT, "text": "你好,我是小明1(⊙﹏⊙),🔺", "unread": true}, + bson.M{"time": time.Now(), "forward": false, "type": message.MessageInfo_TEXT, "text": "你好,我是小明2(⊙﹏⊙),🔺", "unread": false}, + }, + }, + bson.M{ + "fromUser": 1001, + "toUser": 2002, + "badge": 1, + "infos": bson.A{ + bson.M{"time": time.Now(), "forward": true, "type": message.MessageInfo_TEXT, "text": "你好,我是小明3(⊙﹏⊙),🔺", "unread": true}, + bson.M{"time": time.Now(), "forward": false, "type": message.MessageInfo_TEXT, "text": "你好,我是小明4(⊙﹏⊙),🔺", "unread": false}, + }, + }, + bson.M{ + "fromUser": 2003, + "toUser": 1001, + "badge": 2, + "infos": bson.A{ + bson.M{"time": time.Now(), "forward": true, "type": message.MessageInfo_TEXT, "text": "你好,我是小明5(⊙﹏⊙),🔺", "unread": true}, + bson.M{"time": time.Now(), "forward": true, "type": message.MessageInfo_TEXT, "text": "你好,我是小明6(⊙﹏⊙),🔺", "unread": true}, + }, + }, + }) + So(err, ShouldBeNil) + } + + testBase := func(newsLen int, status message.MessageQueryResponse_Status) { + rsp.Reset() + So(s.Query(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, status) + So(len(rsp.News), ShouldEqual, newsLen) + } + Convey("Test Find Message", t, func() { + prepareData() + + So(s.Query(context.TODO(), &req, &rsp), ShouldBeNil) + So(rsp.Status, ShouldEqual, message.MessageQueryResponse_INVALID_PARAM) + + req.User = 1001 + testBase(2, message.MessageQueryResponse_SUCCESS) + So(rsp.News[0].Badge, ShouldEqual, 1) + So(rsp.News[1].Badge, ShouldEqual, 2) + So(rsp.News[1].Info.Text, ShouldEqual, "你好,我是小明5(⊙﹏⊙),🔺") + + req.User = 2001 + testBase(0, message.MessageQueryResponse_NOT_FOUND) + + req.User = 2002 + testBase(1, message.MessageQueryResponse_SUCCESS) + So(rsp.News[0].Info.Text, ShouldEqual, "你好,我是小明3(⊙﹏⊙),🔺") + + req.User = 2003 + testBase(0, message.MessageQueryResponse_NOT_FOUND) + + defer func() { + _, err := collection.DeleteOne(ctx, filter1) + So(err, ShouldBeNil) + _, err = collection.DeleteOne(ctx, filter2) + So(err, ShouldBeNil) + _, err = collection.DeleteOne(ctx, filter3) + So(err, ShouldBeNil) + }() + }) +} + func TestMain(m *testing.M) { main() m.Run() diff --git a/backend/srv/message/proto/message.pb.go b/backend/srv/message/proto/message.pb.go index 5e1646c..14c49eb 100644 --- a/backend/srv/message/proto/message.pb.go +++ b/backend/srv/message/proto/message.pb.go @@ -172,6 +172,37 @@ func (MessageFindResponse_Status) EnumDescriptor() ([]byte, []int) { return fileDescriptor_33c57e4bae7b9afd, []int{4, 0} } +type MessageQueryResponse_Status int32 + +const ( + MessageQueryResponse_UNKNOWN MessageQueryResponse_Status = 0 + MessageQueryResponse_INVALID_PARAM MessageQueryResponse_Status = -1 + MessageQueryResponse_SUCCESS MessageQueryResponse_Status = 1 + MessageQueryResponse_NOT_FOUND MessageQueryResponse_Status = 2 +) + +var MessageQueryResponse_Status_name = map[int32]string{ + 0: "UNKNOWN", + -1: "INVALID_PARAM", + 1: "SUCCESS", + 2: "NOT_FOUND", +} + +var MessageQueryResponse_Status_value = map[string]int32{ + "UNKNOWN": 0, + "INVALID_PARAM": -1, + "SUCCESS": 1, + "NOT_FOUND": 2, +} + +func (x MessageQueryResponse_Status) String() string { + return proto.EnumName(MessageQueryResponse_Status_name, int32(x)) +} + +func (MessageQueryResponse_Status) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{7, 0} +} + type MessageInfo struct { Time int64 `protobuf:"varint,1,opt,name=time,proto3" json:"time,omitempty"` Forward bool `protobuf:"varint,2,opt,name=forward,proto3" json:"forward,omitempty"` @@ -495,56 +526,214 @@ func (m *MessageFindResponse) GetInfos() []*MessageInfo { return nil } +type NewMessage struct { + FromUser int32 `protobuf:"varint,1,opt,name=fromUser,proto3" json:"fromUser,omitempty"` + ToUser int32 `protobuf:"varint,2,opt,name=toUser,proto3" json:"toUser,omitempty"` + Badge int32 `protobuf:"varint,3,opt,name=badge,proto3" json:"badge,omitempty"` + Info *MessageInfo `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NewMessage) Reset() { *m = NewMessage{} } +func (m *NewMessage) String() string { return proto.CompactTextString(m) } +func (*NewMessage) ProtoMessage() {} +func (*NewMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{5} +} + +func (m *NewMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NewMessage.Unmarshal(m, b) +} +func (m *NewMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NewMessage.Marshal(b, m, deterministic) +} +func (m *NewMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_NewMessage.Merge(m, src) +} +func (m *NewMessage) XXX_Size() int { + return xxx_messageInfo_NewMessage.Size(m) +} +func (m *NewMessage) XXX_DiscardUnknown() { + xxx_messageInfo_NewMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_NewMessage proto.InternalMessageInfo + +func (m *NewMessage) GetFromUser() int32 { + if m != nil { + return m.FromUser + } + return 0 +} + +func (m *NewMessage) GetToUser() int32 { + if m != nil { + return m.ToUser + } + return 0 +} + +func (m *NewMessage) GetBadge() int32 { + if m != nil { + return m.Badge + } + return 0 +} + +func (m *NewMessage) GetInfo() *MessageInfo { + if m != nil { + return m.Info + } + return nil +} + +type MessageQueryRequest struct { + User int32 `protobuf:"varint,1,opt,name=user,proto3" json:"user,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MessageQueryRequest) Reset() { *m = MessageQueryRequest{} } +func (m *MessageQueryRequest) String() string { return proto.CompactTextString(m) } +func (*MessageQueryRequest) ProtoMessage() {} +func (*MessageQueryRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{6} +} + +func (m *MessageQueryRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageQueryRequest.Unmarshal(m, b) +} +func (m *MessageQueryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageQueryRequest.Marshal(b, m, deterministic) +} +func (m *MessageQueryRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageQueryRequest.Merge(m, src) +} +func (m *MessageQueryRequest) XXX_Size() int { + return xxx_messageInfo_MessageQueryRequest.Size(m) +} +func (m *MessageQueryRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MessageQueryRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageQueryRequest proto.InternalMessageInfo + +func (m *MessageQueryRequest) GetUser() int32 { + if m != nil { + return m.User + } + return 0 +} + +type MessageQueryResponse struct { + Status MessageQueryResponse_Status `protobuf:"varint,1,opt,name=status,proto3,enum=MessageQueryResponse_Status" json:"status,omitempty"` + News []*NewMessage `protobuf:"bytes,2,rep,name=news,proto3" json:"news,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MessageQueryResponse) Reset() { *m = MessageQueryResponse{} } +func (m *MessageQueryResponse) String() string { return proto.CompactTextString(m) } +func (*MessageQueryResponse) ProtoMessage() {} +func (*MessageQueryResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{7} +} + +func (m *MessageQueryResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MessageQueryResponse.Unmarshal(m, b) +} +func (m *MessageQueryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MessageQueryResponse.Marshal(b, m, deterministic) +} +func (m *MessageQueryResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MessageQueryResponse.Merge(m, src) +} +func (m *MessageQueryResponse) XXX_Size() int { + return xxx_messageInfo_MessageQueryResponse.Size(m) +} +func (m *MessageQueryResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MessageQueryResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MessageQueryResponse proto.InternalMessageInfo + +func (m *MessageQueryResponse) GetStatus() MessageQueryResponse_Status { + if m != nil { + return m.Status + } + return MessageQueryResponse_UNKNOWN +} + +func (m *MessageQueryResponse) GetNews() []*NewMessage { + if m != nil { + return m.News + } + return nil +} + func init() { proto.RegisterEnum("MessageInfo_Type", MessageInfo_Type_name, MessageInfo_Type_value) proto.RegisterEnum("MessageCreateRequest_Type", MessageCreateRequest_Type_name, MessageCreateRequest_Type_value) proto.RegisterEnum("MessageCreateResponse_Status", MessageCreateResponse_Status_name, MessageCreateResponse_Status_value) proto.RegisterEnum("MessageFindRequest_Way", MessageFindRequest_Way_name, MessageFindRequest_Way_value) proto.RegisterEnum("MessageFindResponse_Status", MessageFindResponse_Status_name, MessageFindResponse_Status_value) + proto.RegisterEnum("MessageQueryResponse_Status", MessageQueryResponse_Status_name, MessageQueryResponse_Status_value) proto.RegisterType((*MessageInfo)(nil), "MessageInfo") proto.RegisterType((*MessageCreateRequest)(nil), "MessageCreateRequest") proto.RegisterType((*MessageCreateResponse)(nil), "MessageCreateResponse") proto.RegisterType((*MessageFindRequest)(nil), "MessageFindRequest") proto.RegisterType((*MessageFindResponse)(nil), "MessageFindResponse") + proto.RegisterType((*NewMessage)(nil), "NewMessage") + proto.RegisterType((*MessageQueryRequest)(nil), "MessageQueryRequest") + proto.RegisterType((*MessageQueryResponse)(nil), "MessageQueryResponse") } func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) } var fileDescriptor_33c57e4bae7b9afd = []byte{ - // 552 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0xdd, 0x8a, 0xd3, 0x40, - 0x14, 0xc7, 0x9d, 0x7c, 0xf4, 0xe3, 0xb4, 0x5d, 0xe2, 0x6c, 0x77, 0x0d, 0x15, 0xa1, 0x04, 0x84, - 0x7a, 0x13, 0xb0, 0xcb, 0xe2, 0x9d, 0x58, 0xda, 0xac, 0x06, 0xdb, 0xa4, 0x4c, 0x92, 0xad, 0x7b, - 0x55, 0xb2, 0x74, 0xb2, 0x04, 0xb6, 0x4d, 0x4d, 0xa6, 0xac, 0x79, 0x02, 0xef, 0x7c, 0x2b, 0x1f, - 0xc2, 0x6b, 0x1f, 0x44, 0xc9, 0x24, 0x95, 0x4d, 0x8d, 0x08, 0xbb, 0xbd, 0x9a, 0xff, 0x9c, 0xd3, - 0x73, 0xce, 0xff, 0x37, 0x33, 0x81, 0xce, 0x9a, 0x26, 0x89, 0x7f, 0x43, 0xf5, 0x6d, 0x1c, 0xb1, - 0x48, 0xfb, 0x8e, 0xa0, 0x35, 0xcb, 0x77, 0xcc, 0x4d, 0x10, 0x61, 0x0c, 0x12, 0x0b, 0xd7, 0x54, - 0x45, 0x7d, 0x34, 0x10, 0x09, 0x5f, 0x63, 0x15, 0xea, 0x41, 0x14, 0xdf, 0xf9, 0xf1, 0x4a, 0x15, - 0xfa, 0x68, 0xd0, 0x20, 0x7b, 0x89, 0x5f, 0x82, 0xc4, 0xd2, 0x2d, 0x55, 0xc5, 0x3e, 0x1a, 0x1c, - 0x0d, 0x9f, 0xea, 0xf7, 0x2a, 0xe9, 0x6e, 0xba, 0xa5, 0x84, 0x87, 0x79, 0x51, 0xfa, 0x85, 0xa9, - 0x52, 0x1f, 0x0d, 0x9a, 0x84, 0xaf, 0xf1, 0x29, 0xd4, 0x76, 0x9b, 0x98, 0xfa, 0x2b, 0x55, 0xe6, - 0x35, 0x0b, 0xa5, 0x9d, 0x83, 0x94, 0xfd, 0x13, 0xb7, 0xa0, 0xee, 0x59, 0x1f, 0x2d, 0x7b, 0x61, - 0x29, 0x4f, 0x70, 0x03, 0x24, 0xd7, 0xf8, 0xe4, 0x2a, 0x28, 0xdb, 0x9e, 0x9b, 0x63, 0xd7, 0x23, - 0x86, 0x22, 0xe0, 0x26, 0xc8, 0x97, 0xe6, 0xc4, 0xb0, 0x15, 0x51, 0xfb, 0x81, 0xa0, 0x5b, 0x74, - 0x1f, 0xc7, 0xd4, 0x67, 0x94, 0xd0, 0xcf, 0x3b, 0x9a, 0x30, 0xdc, 0x83, 0x46, 0x10, 0x47, 0x6b, - 0x2f, 0xa1, 0x31, 0x37, 0x25, 0x93, 0x3f, 0x3a, 0x9b, 0x81, 0x45, 0x3c, 0x22, 0xf0, 0x48, 0xa1, - 0xb0, 0x5e, 0xb2, 0xd5, 0xd3, 0xab, 0x0a, 0xff, 0xcf, 0x1f, 0x06, 0x29, 0x08, 0x6f, 0x29, 0x77, - 0xd7, 0x26, 0x7c, 0xfd, 0x50, 0x6f, 0xdf, 0x10, 0x9c, 0x1c, 0x8c, 0x90, 0x6c, 0xa3, 0x4d, 0x42, - 0xf1, 0x39, 0xd4, 0x12, 0xe6, 0xb3, 0x5d, 0xc2, 0xad, 0x1d, 0x0d, 0x5f, 0xe8, 0x95, 0x79, 0xba, - 0xc3, 0x93, 0x48, 0x91, 0xac, 0xbd, 0x85, 0x5a, 0xbe, 0x53, 0x9e, 0xa4, 0x07, 0x1d, 0xd3, 0xba, - 0x1c, 0x4d, 0xcd, 0xc9, 0x72, 0x3e, 0x22, 0xa3, 0x99, 0xf2, 0x6b, 0xff, 0xe3, 0xb3, 0x39, 0xde, - 0x78, 0x6c, 0x38, 0x8e, 0x82, 0xb4, 0x9f, 0x08, 0x70, 0xd1, 0xe8, 0x22, 0xdc, 0xac, 0x1e, 0x83, - 0xfa, 0x15, 0x88, 0x77, 0x7e, 0x5a, 0x90, 0x7e, 0xa6, 0xff, 0x5d, 0x55, 0x5f, 0xf8, 0x29, 0xc9, - 0x72, 0x70, 0x17, 0xe4, 0xdb, 0x70, 0x1d, 0xe6, 0x98, 0x65, 0x92, 0x8b, 0xac, 0x70, 0x14, 0x04, - 0x09, 0x65, 0x9c, 0xb4, 0x4c, 0x0a, 0xa5, 0xbd, 0x03, 0x71, 0xe1, 0xa7, 0x65, 0x83, 0x1d, 0x68, - 0xda, 0xd6, 0xf4, 0x6a, 0x39, 0xf7, 0xa6, 0x53, 0x05, 0x61, 0x05, 0xda, 0xc4, 0x18, 0x4d, 0x96, - 0x33, 0xc3, 0x71, 0x46, 0xef, 0x33, 0xe8, 0x2d, 0xa8, 0x7f, 0x30, 0x1d, 0xd7, 0x26, 0x57, 0x8a, - 0xa8, 0x7d, 0x15, 0xe0, 0xb8, 0x34, 0x4f, 0x01, 0xfd, 0xec, 0x00, 0xfa, 0x73, 0xbd, 0x22, 0xeb, - 0x00, 0x79, 0x89, 0x8d, 0xf0, 0x4f, 0x36, 0x62, 0x89, 0x4d, 0x17, 0xe4, 0x6b, 0x7f, 0x75, 0x43, - 0xf7, 0x86, 0xb9, 0xc0, 0x1a, 0xc8, 0xe1, 0x26, 0x88, 0x12, 0x55, 0xee, 0x8b, 0x83, 0xd6, 0xb0, - 0x7d, 0xff, 0xd1, 0x91, 0x3c, 0xa4, 0xcd, 0x1e, 0x77, 0xc0, 0x19, 0x28, 0xcb, 0x76, 0x97, 0x17, - 0xb6, 0x67, 0x4d, 0x14, 0x61, 0xb8, 0x83, 0x7a, 0xd1, 0x04, 0xbf, 0x81, 0x5a, 0x7e, 0xb7, 0xf0, - 0x49, 0xe5, 0xb3, 0xe8, 0x9d, 0x56, 0x5f, 0x41, 0xfc, 0x1a, 0xa4, 0x8c, 0x0f, 0x3e, 0xae, 0x38, - 0xe3, 0x5e, 0xb7, 0x0a, 0xe1, 0x75, 0x8d, 0x7f, 0xa2, 0xce, 0x7e, 0x07, 0x00, 0x00, 0xff, 0xff, - 0x21, 0x81, 0x12, 0x81, 0xb3, 0x04, 0x00, 0x00, + // 635 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xcf, 0x6e, 0xd3, 0x4e, + 0x10, 0xc7, 0x7f, 0xeb, 0x3f, 0x49, 0x3b, 0x69, 0x2b, 0xff, 0xb6, 0x69, 0xb1, 0x02, 0x88, 0x68, + 0x25, 0xa4, 0xf4, 0xb2, 0x12, 0x29, 0x15, 0x37, 0x44, 0x94, 0xa4, 0x10, 0x91, 0x38, 0x65, 0x9d, + 0xb4, 0xf4, 0x14, 0xb9, 0xca, 0xba, 0xb2, 0xd4, 0xd8, 0xc1, 0x7f, 0x94, 0xfa, 0x09, 0xb8, 0xf1, + 0x44, 0x5c, 0x79, 0x08, 0xce, 0x3c, 0x08, 0xc8, 0x6b, 0xa7, 0xad, 0x8d, 0x11, 0x52, 0x4b, 0x4e, + 0x3b, 0x3b, 0x93, 0xd9, 0xf9, 0x7e, 0x66, 0x67, 0x0d, 0xdb, 0x0b, 0x1e, 0x04, 0xd6, 0x25, 0xa7, + 0x4b, 0xdf, 0x0b, 0x3d, 0xf2, 0x0d, 0x41, 0x6d, 0x94, 0xee, 0x0c, 0x5c, 0xdb, 0xc3, 0x18, 0x94, + 0xd0, 0x59, 0x70, 0x1d, 0x35, 0x51, 0x4b, 0x66, 0x62, 0x8d, 0x75, 0xa8, 0xda, 0x9e, 0xbf, 0xb2, + 0xfc, 0xb9, 0x2e, 0x35, 0x51, 0x6b, 0x83, 0xad, 0x4d, 0xfc, 0x1c, 0x94, 0x30, 0x5e, 0x72, 0x5d, + 0x6e, 0xa2, 0xd6, 0x4e, 0xfb, 0x7f, 0x7a, 0x27, 0x13, 0x9d, 0xc4, 0x4b, 0xce, 0x84, 0x5b, 0x24, + 0xe5, 0xd7, 0xa1, 0xae, 0x34, 0x51, 0x6b, 0x93, 0x89, 0x35, 0xde, 0x87, 0x4a, 0xe4, 0xfa, 0xdc, + 0x9a, 0xeb, 0xaa, 0xc8, 0x99, 0x59, 0xe4, 0x08, 0x94, 0xe4, 0x9f, 0xb8, 0x06, 0xd5, 0xa9, 0xf1, + 0xde, 0x18, 0x9f, 0x19, 0xda, 0x7f, 0x78, 0x03, 0x94, 0x49, 0xff, 0xe3, 0x44, 0x43, 0xc9, 0xf6, + 0xc9, 0xa0, 0x3b, 0x99, 0xb2, 0xbe, 0x26, 0xe1, 0x4d, 0x50, 0x4f, 0x07, 0xbd, 0xfe, 0x58, 0x93, + 0xc9, 0x77, 0x04, 0xf5, 0xec, 0xf4, 0xae, 0xcf, 0xad, 0x90, 0x33, 0xfe, 0x29, 0xe2, 0x41, 0x88, + 0x1b, 0xb0, 0x61, 0xfb, 0xde, 0x62, 0x1a, 0x70, 0x5f, 0x88, 0x52, 0xd9, 0x8d, 0x9d, 0xd4, 0x10, + 0x7a, 0xc2, 0x23, 0x09, 0x4f, 0x66, 0x61, 0x9a, 0x93, 0xd5, 0xa0, 0x65, 0x89, 0xff, 0xa6, 0x0f, + 0x83, 0x62, 0x3b, 0x57, 0x5c, 0xa8, 0xdb, 0x62, 0x62, 0x7d, 0x5f, 0x6d, 0x5f, 0x10, 0xec, 0x15, + 0x4a, 0x08, 0x96, 0x9e, 0x1b, 0x70, 0x7c, 0x04, 0x95, 0x20, 0xb4, 0xc2, 0x28, 0x10, 0xd2, 0x76, + 0xda, 0x4f, 0x69, 0x69, 0x1c, 0x35, 0x45, 0x10, 0xcb, 0x82, 0xc9, 0x6b, 0xa8, 0xa4, 0x3b, 0xf9, + 0x4a, 0x1a, 0xb0, 0x3d, 0x30, 0x4e, 0x3b, 0xc3, 0x41, 0x6f, 0x76, 0xd2, 0x61, 0x9d, 0x91, 0xf6, + 0x73, 0xfd, 0x13, 0xb5, 0x99, 0xd3, 0x6e, 0xb7, 0x6f, 0x9a, 0x1a, 0x22, 0x3f, 0x10, 0xe0, 0xec, + 0xa0, 0x63, 0xc7, 0x9d, 0x3f, 0x04, 0xf5, 0x01, 0xc8, 0x2b, 0x2b, 0xce, 0x48, 0x3f, 0xa2, 0xbf, + 0x67, 0xa5, 0x67, 0x56, 0xcc, 0x92, 0x18, 0x5c, 0x07, 0xf5, 0xca, 0x59, 0x38, 0x29, 0x66, 0x95, + 0xa5, 0x46, 0x92, 0xd8, 0xb3, 0xed, 0x80, 0x87, 0x82, 0xb4, 0xca, 0x32, 0x8b, 0xbc, 0x01, 0xf9, + 0xcc, 0x8a, 0xf3, 0x02, 0xb7, 0x61, 0x73, 0x6c, 0x0c, 0xcf, 0x67, 0x27, 0xd3, 0xe1, 0x50, 0x43, + 0x58, 0x83, 0x2d, 0xd6, 0xef, 0xf4, 0x66, 0xa3, 0xbe, 0x69, 0x76, 0xde, 0x26, 0xd0, 0x6b, 0x50, + 0x7d, 0x37, 0x30, 0x27, 0x63, 0x76, 0xae, 0xc9, 0xe4, 0xb3, 0x04, 0xbb, 0xb9, 0x7a, 0x32, 0xe8, + 0x87, 0x05, 0xe8, 0x8f, 0x69, 0x49, 0x54, 0x01, 0x79, 0x8e, 0x8d, 0xf4, 0x47, 0x36, 0x72, 0x8e, + 0x4d, 0x1d, 0xd4, 0x0b, 0x6b, 0x7e, 0xc9, 0xd7, 0x82, 0x85, 0x81, 0x09, 0xa8, 0x8e, 0x6b, 0x7b, + 0x81, 0xae, 0x36, 0xe5, 0x56, 0xad, 0xbd, 0x75, 0x77, 0xe8, 0x58, 0xea, 0x22, 0xa3, 0x87, 0x35, + 0x38, 0x01, 0x65, 0x8c, 0x27, 0xb3, 0xe3, 0xf1, 0xd4, 0xe8, 0x69, 0x12, 0xb9, 0x06, 0x30, 0xf8, + 0x2a, 0x3b, 0xe7, 0x5e, 0x6d, 0xbe, 0x91, 0x22, 0xdf, 0x95, 0xd2, 0x04, 0x25, 0xa9, 0x57, 0xe8, + 0x2b, 0x2a, 0x11, 0x1e, 0x72, 0x70, 0xd3, 0x82, 0x0f, 0x11, 0xf7, 0xe3, 0xf5, 0x4d, 0xc3, 0xa0, + 0x44, 0xb7, 0xc7, 0x8b, 0x35, 0xf9, 0x7a, 0xfb, 0x02, 0x64, 0xb1, 0x59, 0xbf, 0x5e, 0x16, 0xfa, + 0xf5, 0x84, 0x96, 0x85, 0x15, 0x1b, 0xf6, 0x0c, 0x14, 0x97, 0xaf, 0x02, 0x5d, 0x12, 0x94, 0x6b, + 0xf4, 0x16, 0x00, 0x13, 0x8e, 0x7f, 0xcc, 0xb8, 0x1d, 0x41, 0x75, 0x0d, 0xf8, 0x15, 0x54, 0xd2, + 0xf9, 0xc5, 0x7b, 0xa5, 0x4f, 0x4f, 0x63, 0xbf, 0x7c, 0xcc, 0xf1, 0x0b, 0x50, 0x92, 0x3b, 0x88, + 0x77, 0x4b, 0xe6, 0xa8, 0x51, 0x2f, 0xbb, 0xa6, 0x17, 0x15, 0xf1, 0x19, 0x38, 0xfc, 0x15, 0x00, + 0x00, 0xff, 0xff, 0xcd, 0xe9, 0x64, 0x7c, 0x17, 0x06, 0x00, 0x00, } diff --git a/backend/srv/message/proto/message.proto b/backend/srv/message/proto/message.proto index 2c9d3fa..e77323b 100644 --- a/backend/srv/message/proto/message.proto +++ b/backend/srv/message/proto/message.proto @@ -68,4 +68,26 @@ message MessageFindResponse { int32 toUser = 3; int32 badge = 4; repeated MessageInfo infos = 5; +} + +message NewMessage{ + int32 fromUser = 1; + int32 toUser = 2; + int32 badge = 3; + MessageInfo info = 4; +} + +message MessageQueryRequest{ + int32 user = 1; +} + +message MessageQueryResponse{ + enum Status { + UNKNOWN = 0; + INVALID_PARAM = -1; + SUCCESS = 1; + NOT_FOUND = 2; + } + Status status = 1; + repeated NewMessage news = 2; } \ No newline at end of file From 2cbf0df686e817a59d69743d79a6e74012b8a34e Mon Sep 17 00:00:00 2001 From: Kang Huquan <799385272@qq.com> Date: Thu, 1 Aug 2019 15:23:43 +0800 Subject: [PATCH 13/17] message api(final) --- backend/api/message/main.go | 42 ++++++++++ backend/doc/api_data.js | 64 +++++++++++++++- backend/doc/api_data.json | 64 +++++++++++++++- backend/doc/api_project.js | 2 +- backend/doc/api_project.json | 2 +- backend/srv/message/main.go | 8 +- backend/srv/message/main_test.go | 8 +- backend/srv/message/mock/mock.go | 6 ++ backend/srv/message/proto/message.micro.go | 17 +++++ backend/srv/message/proto/message.pb.go | 89 +++++++++++----------- backend/srv/message/proto/message.proto | 3 +- 11 files changed, 248 insertions(+), 57 deletions(-) diff --git a/backend/api/message/main.go b/backend/api/message/main.go index 69a9bfe..378bef1 100644 --- a/backend/api/message/main.go +++ b/backend/api/message/main.go @@ -14,6 +14,7 @@ func setupRouter() *gin.Engine { router, rg := utils.CreateAPIGroup() rg.GET("/message", findMessage) rg.POST("/message", addMessage) + rg.GET("/message/:userID", getMessage) return router } @@ -133,6 +134,47 @@ func findMessage(c *gin.Context) { } } +/** + * @api {get} /message/:userID GetMessage + * @apiVersion 1.0.0 + * @apiGroup Message + * @apiPermission self/admin + * @apiName GetMessage + * @apiDescription Get all new message about user + * + * @apiParam {--} Param see [Message Service](#api-Service-Message_Query) + * @apiSuccess (Success 200) {Response} response see [Message Service](#api-Service-Message_Query) + * @apiUse InvalidParam + * @apiUse MessageServiceDown + */ +func getMessage(c *gin.Context) { + type param struct { + UserID int32 `uri:"userID" binding:"required,min=1"` + } + var p param + + if !utils.LogContinue(c.ShouldBindUri(&p), utils.Warning) { + role := utils.GetRoleID(c, int32(p.UserID)) + if !(role.Self || role.Admin) { + c.Status(403) + return + } + + srv := utils.CallMicroService("message", func(name string, c client.Client) interface{} { return message.NewMessageService(name, c) }, + func() interface{} { return mock.NewMessageService() }).(message.MessageService) + rsp, err := srv.Query(context.TODO(), &message.MessageQueryRequest{ + UserID: p.UserID, + }) + if utils.LogContinue(err, utils.Warning, "Message service error: %v", err) { + c.JSON(500, err) + return + } + c.JSON(200, rsp) + } else { + c.AbortWithStatus(400) + } +} + func main() { utils.RunWebService("message", setupRouter()) } diff --git a/backend/doc/api_data.js b/backend/doc/api_data.js index 4d3f923..0a7fab3 100644 --- a/backend/doc/api_data.js +++ b/backend/doc/api_data.js @@ -776,6 +776,68 @@ define({ "api": [ } } }, + { + "type": "get", + "url": "/message/:userID", + "title": "GetMessage", + "version": "1.0.0", + "group": "Message", + "permission": [ + { + "name": "self/admin" + } + ], + "name": "GetMessage", + "description": "

Get all new message about user

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "--", + "optional": false, + "field": "Param", + "description": "

see Message Service

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "Response", + "optional": false, + "field": "response", + "description": "

see Message Service

" + } + ] + } + }, + "filename": "api/message/main.go", + "groupTitle": "Message", + "error": { + "fields": { + "Error 400": [ + { + "group": "Error 400", + "optional": false, + "field": "InvalidParam", + "description": "

Invalid param

" + } + ], + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "MessageServiceDown", + "description": "

Message service down

" + } + ] + } + } + }, { "type": "post", "url": "/sellInfo", @@ -2134,7 +2196,7 @@ define({ "api": [ "group": "Parameter", "type": "int32", "optional": false, - "field": "user", + "field": "userID", "description": "

user who wants to pull new message

" } ] diff --git a/backend/doc/api_data.json b/backend/doc/api_data.json index 6c54378..857103e 100644 --- a/backend/doc/api_data.json +++ b/backend/doc/api_data.json @@ -776,6 +776,68 @@ } } }, + { + "type": "get", + "url": "/message/:userID", + "title": "GetMessage", + "version": "1.0.0", + "group": "Message", + "permission": [ + { + "name": "self/admin" + } + ], + "name": "GetMessage", + "description": "

Get all new message about user

", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "--", + "optional": false, + "field": "Param", + "description": "

see Message Service

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "Response", + "optional": false, + "field": "response", + "description": "

see Message Service

" + } + ] + } + }, + "filename": "api/message/main.go", + "groupTitle": "Message", + "error": { + "fields": { + "Error 400": [ + { + "group": "Error 400", + "optional": false, + "field": "InvalidParam", + "description": "

Invalid param

" + } + ], + "Error 500": [ + { + "group": "Error 500", + "optional": false, + "field": "MessageServiceDown", + "description": "

Message service down

" + } + ] + } + } + }, { "type": "post", "url": "/sellInfo", @@ -2134,7 +2196,7 @@ "group": "Parameter", "type": "int32", "optional": false, - "field": "user", + "field": "userID", "description": "

user who wants to pull new message

" } ] diff --git a/backend/doc/api_project.js b/backend/doc/api_project.js index ecdaf9c..5abf99e 100644 --- a/backend/doc/api_project.js +++ b/backend/doc/api_project.js @@ -21,7 +21,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T06:58:03.812Z", + "time": "2019-08-01T07:21:44.261Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/api_project.json b/backend/doc/api_project.json index 3abc9af..e51fe52 100644 --- a/backend/doc/api_project.json +++ b/backend/doc/api_project.json @@ -21,7 +21,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T06:58:03.812Z", + "time": "2019-08-01T07:21:44.261Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index 2be7458..f0855c2 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -357,7 +357,7 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me * @apiName Message.Query * @apiDescription Query New Message * - * @apiParam {int32} user user who wants to pull new message + * @apiParam {int32} userID user who wants to pull new message * @apiSuccess {int32} status -1 for invalid param
1 for success
2 for not found * @apiSuccess {list} news see below NewMessage * @apiSuccess (NewMessage) {int32} fromUser user who launch the chat at first time @@ -372,7 +372,7 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me * @apiUse DBServerDown */ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp *message.MessageQueryResponse) error { - if !utils.RequireParam(req.User) { + if !utils.RequireParam(req.UserID) { rsp.Status = message.MessageQueryResponse_INVALID_PARAM return nil } @@ -397,7 +397,7 @@ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp * cur, err := collection.Find(ctx, bson.M{ "$or": bson.A{ bson.M{ - "fromUser": req.User, + "fromUser": req.UserID, "badge": bson.M{"$gt": 0}, "infos": bson.M{ "$elemMatch": bson.M{ @@ -407,7 +407,7 @@ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp * }, }, bson.M{ - "toUser": req.User, + "toUser": req.UserID, "badge": bson.M{"$gt": 0}, "infos": bson.M{ "$elemMatch": bson.M{ diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index 9c7e86e..d1f6cc5 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -264,20 +264,20 @@ func TestQuery(t *testing.T) { So(s.Query(context.TODO(), &req, &rsp), ShouldBeNil) So(rsp.Status, ShouldEqual, message.MessageQueryResponse_INVALID_PARAM) - req.User = 1001 + req.UserID = 1001 testBase(2, message.MessageQueryResponse_SUCCESS) So(rsp.News[0].Badge, ShouldEqual, 1) So(rsp.News[1].Badge, ShouldEqual, 2) So(rsp.News[1].Info.Text, ShouldEqual, "你好,我是小明5(⊙﹏⊙),🔺") - req.User = 2001 + req.UserID = 2001 testBase(0, message.MessageQueryResponse_NOT_FOUND) - req.User = 2002 + req.UserID = 2002 testBase(1, message.MessageQueryResponse_SUCCESS) So(rsp.News[0].Info.Text, ShouldEqual, "你好,我是小明3(⊙﹏⊙),🔺") - req.User = 2003 + req.UserID = 2003 testBase(0, message.MessageQueryResponse_NOT_FOUND) defer func() { diff --git a/backend/srv/message/mock/mock.go b/backend/srv/message/mock/mock.go index 4d02454..f0c6295 100644 --- a/backend/srv/message/mock/mock.go +++ b/backend/srv/message/mock/mock.go @@ -9,6 +9,12 @@ import ( type mockMessageSrv struct{} +func (a *mockMessageSrv) Find(ctx context.Context, in *message.MessageFindRequest, opts ...client.CallOption) (*message.MessageFindResponse, error) { + var rsp message.MessageFindResponse + // TODO + return &rsp, nil +} + func (a *mockMessageSrv) Query(ctx context.Context, in *message.MessageQueryRequest, opts ...client.CallOption) (*message.MessageQueryResponse, error) { var rsp message.MessageQueryResponse // TODO diff --git a/backend/srv/message/proto/message.micro.go b/backend/srv/message/proto/message.micro.go index 26e44e2..1a5be33 100644 --- a/backend/srv/message/proto/message.micro.go +++ b/backend/srv/message/proto/message.micro.go @@ -36,6 +36,7 @@ var _ server.Option type MessageService interface { Create(ctx context.Context, in *MessageCreateRequest, opts ...client.CallOption) (*MessageCreateResponse, error) Find(ctx context.Context, in *MessageFindRequest, opts ...client.CallOption) (*MessageFindResponse, error) + Query(ctx context.Context, in *MessageQueryRequest, opts ...client.CallOption) (*MessageQueryResponse, error) } type messageService struct { @@ -76,17 +77,29 @@ func (c *messageService) Find(ctx context.Context, in *MessageFindRequest, opts return out, nil } +func (c *messageService) Query(ctx context.Context, in *MessageQueryRequest, opts ...client.CallOption) (*MessageQueryResponse, error) { + req := c.c.NewRequest(c.name, "Message.Query", in) + out := new(MessageQueryResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Message service type MessageHandler interface { Create(context.Context, *MessageCreateRequest, *MessageCreateResponse) error Find(context.Context, *MessageFindRequest, *MessageFindResponse) error + Query(context.Context, *MessageQueryRequest, *MessageQueryResponse) error } func RegisterMessageHandler(s server.Server, hdlr MessageHandler, opts ...server.HandlerOption) error { type message interface { Create(ctx context.Context, in *MessageCreateRequest, out *MessageCreateResponse) error Find(ctx context.Context, in *MessageFindRequest, out *MessageFindResponse) error + Query(ctx context.Context, in *MessageQueryRequest, out *MessageQueryResponse) error } type Message struct { message @@ -106,3 +119,7 @@ func (h *messageHandler) Create(ctx context.Context, in *MessageCreateRequest, o func (h *messageHandler) Find(ctx context.Context, in *MessageFindRequest, out *MessageFindResponse) error { return h.MessageHandler.Find(ctx, in, out) } + +func (h *messageHandler) Query(ctx context.Context, in *MessageQueryRequest, out *MessageQueryResponse) error { + return h.MessageHandler.Query(ctx, in, out) +} diff --git a/backend/srv/message/proto/message.pb.go b/backend/srv/message/proto/message.pb.go index 14c49eb..cf30b37 100644 --- a/backend/srv/message/proto/message.pb.go +++ b/backend/srv/message/proto/message.pb.go @@ -590,7 +590,7 @@ func (m *NewMessage) GetInfo() *MessageInfo { } type MessageQueryRequest struct { - User int32 `protobuf:"varint,1,opt,name=user,proto3" json:"user,omitempty"` + UserID int32 `protobuf:"varint,1,opt,name=userID,proto3" json:"userID,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -621,9 +621,9 @@ func (m *MessageQueryRequest) XXX_DiscardUnknown() { var xxx_messageInfo_MessageQueryRequest proto.InternalMessageInfo -func (m *MessageQueryRequest) GetUser() int32 { +func (m *MessageQueryRequest) GetUserID() int32 { if m != nil { - return m.User + return m.UserID } return 0 } @@ -695,45 +695,46 @@ func init() { func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) } var fileDescriptor_33c57e4bae7b9afd = []byte{ - // 635 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xcf, 0x6e, 0xd3, 0x4e, - 0x10, 0xc7, 0x7f, 0xeb, 0x3f, 0x49, 0x3b, 0x69, 0x2b, 0xff, 0xb6, 0x69, 0xb1, 0x02, 0x88, 0x68, - 0x25, 0xa4, 0xf4, 0xb2, 0x12, 0x29, 0x15, 0x37, 0x44, 0x94, 0xa4, 0x10, 0x91, 0x38, 0x65, 0x9d, - 0xb4, 0xf4, 0x14, 0xb9, 0xca, 0xba, 0xb2, 0xd4, 0xd8, 0xc1, 0x7f, 0x94, 0xfa, 0x09, 0xb8, 0xf1, - 0x44, 0x5c, 0x79, 0x08, 0xce, 0x3c, 0x08, 0xc8, 0x6b, 0xa7, 0xad, 0x8d, 0x11, 0x52, 0x4b, 0x4e, - 0x3b, 0x3b, 0x93, 0xd9, 0xf9, 0x7e, 0x66, 0x67, 0x0d, 0xdb, 0x0b, 0x1e, 0x04, 0xd6, 0x25, 0xa7, - 0x4b, 0xdf, 0x0b, 0x3d, 0xf2, 0x0d, 0x41, 0x6d, 0x94, 0xee, 0x0c, 0x5c, 0xdb, 0xc3, 0x18, 0x94, - 0xd0, 0x59, 0x70, 0x1d, 0x35, 0x51, 0x4b, 0x66, 0x62, 0x8d, 0x75, 0xa8, 0xda, 0x9e, 0xbf, 0xb2, - 0xfc, 0xb9, 0x2e, 0x35, 0x51, 0x6b, 0x83, 0xad, 0x4d, 0xfc, 0x1c, 0x94, 0x30, 0x5e, 0x72, 0x5d, - 0x6e, 0xa2, 0xd6, 0x4e, 0xfb, 0x7f, 0x7a, 0x27, 0x13, 0x9d, 0xc4, 0x4b, 0xce, 0x84, 0x5b, 0x24, - 0xe5, 0xd7, 0xa1, 0xae, 0x34, 0x51, 0x6b, 0x93, 0x89, 0x35, 0xde, 0x87, 0x4a, 0xe4, 0xfa, 0xdc, - 0x9a, 0xeb, 0xaa, 0xc8, 0x99, 0x59, 0xe4, 0x08, 0x94, 0xe4, 0x9f, 0xb8, 0x06, 0xd5, 0xa9, 0xf1, - 0xde, 0x18, 0x9f, 0x19, 0xda, 0x7f, 0x78, 0x03, 0x94, 0x49, 0xff, 0xe3, 0x44, 0x43, 0xc9, 0xf6, - 0xc9, 0xa0, 0x3b, 0x99, 0xb2, 0xbe, 0x26, 0xe1, 0x4d, 0x50, 0x4f, 0x07, 0xbd, 0xfe, 0x58, 0x93, - 0xc9, 0x77, 0x04, 0xf5, 0xec, 0xf4, 0xae, 0xcf, 0xad, 0x90, 0x33, 0xfe, 0x29, 0xe2, 0x41, 0x88, - 0x1b, 0xb0, 0x61, 0xfb, 0xde, 0x62, 0x1a, 0x70, 0x5f, 0x88, 0x52, 0xd9, 0x8d, 0x9d, 0xd4, 0x10, - 0x7a, 0xc2, 0x23, 0x09, 0x4f, 0x66, 0x61, 0x9a, 0x93, 0xd5, 0xa0, 0x65, 0x89, 0xff, 0xa6, 0x0f, - 0x83, 0x62, 0x3b, 0x57, 0x5c, 0xa8, 0xdb, 0x62, 0x62, 0x7d, 0x5f, 0x6d, 0x5f, 0x10, 0xec, 0x15, - 0x4a, 0x08, 0x96, 0x9e, 0x1b, 0x70, 0x7c, 0x04, 0x95, 0x20, 0xb4, 0xc2, 0x28, 0x10, 0xd2, 0x76, - 0xda, 0x4f, 0x69, 0x69, 0x1c, 0x35, 0x45, 0x10, 0xcb, 0x82, 0xc9, 0x6b, 0xa8, 0xa4, 0x3b, 0xf9, - 0x4a, 0x1a, 0xb0, 0x3d, 0x30, 0x4e, 0x3b, 0xc3, 0x41, 0x6f, 0x76, 0xd2, 0x61, 0x9d, 0x91, 0xf6, - 0x73, 0xfd, 0x13, 0xb5, 0x99, 0xd3, 0x6e, 0xb7, 0x6f, 0x9a, 0x1a, 0x22, 0x3f, 0x10, 0xe0, 0xec, - 0xa0, 0x63, 0xc7, 0x9d, 0x3f, 0x04, 0xf5, 0x01, 0xc8, 0x2b, 0x2b, 0xce, 0x48, 0x3f, 0xa2, 0xbf, - 0x67, 0xa5, 0x67, 0x56, 0xcc, 0x92, 0x18, 0x5c, 0x07, 0xf5, 0xca, 0x59, 0x38, 0x29, 0x66, 0x95, - 0xa5, 0x46, 0x92, 0xd8, 0xb3, 0xed, 0x80, 0x87, 0x82, 0xb4, 0xca, 0x32, 0x8b, 0xbc, 0x01, 0xf9, - 0xcc, 0x8a, 0xf3, 0x02, 0xb7, 0x61, 0x73, 0x6c, 0x0c, 0xcf, 0x67, 0x27, 0xd3, 0xe1, 0x50, 0x43, - 0x58, 0x83, 0x2d, 0xd6, 0xef, 0xf4, 0x66, 0xa3, 0xbe, 0x69, 0x76, 0xde, 0x26, 0xd0, 0x6b, 0x50, - 0x7d, 0x37, 0x30, 0x27, 0x63, 0x76, 0xae, 0xc9, 0xe4, 0xb3, 0x04, 0xbb, 0xb9, 0x7a, 0x32, 0xe8, - 0x87, 0x05, 0xe8, 0x8f, 0x69, 0x49, 0x54, 0x01, 0x79, 0x8e, 0x8d, 0xf4, 0x47, 0x36, 0x72, 0x8e, - 0x4d, 0x1d, 0xd4, 0x0b, 0x6b, 0x7e, 0xc9, 0xd7, 0x82, 0x85, 0x81, 0x09, 0xa8, 0x8e, 0x6b, 0x7b, - 0x81, 0xae, 0x36, 0xe5, 0x56, 0xad, 0xbd, 0x75, 0x77, 0xe8, 0x58, 0xea, 0x22, 0xa3, 0x87, 0x35, - 0x38, 0x01, 0x65, 0x8c, 0x27, 0xb3, 0xe3, 0xf1, 0xd4, 0xe8, 0x69, 0x12, 0xb9, 0x06, 0x30, 0xf8, - 0x2a, 0x3b, 0xe7, 0x5e, 0x6d, 0xbe, 0x91, 0x22, 0xdf, 0x95, 0xd2, 0x04, 0x25, 0xa9, 0x57, 0xe8, - 0x2b, 0x2a, 0x11, 0x1e, 0x72, 0x70, 0xd3, 0x82, 0x0f, 0x11, 0xf7, 0xe3, 0xf5, 0x4d, 0xc3, 0xa0, - 0x44, 0xb7, 0xc7, 0x8b, 0x35, 0xf9, 0x7a, 0xfb, 0x02, 0x64, 0xb1, 0x59, 0xbf, 0x5e, 0x16, 0xfa, - 0xf5, 0x84, 0x96, 0x85, 0x15, 0x1b, 0xf6, 0x0c, 0x14, 0x97, 0xaf, 0x02, 0x5d, 0x12, 0x94, 0x6b, - 0xf4, 0x16, 0x00, 0x13, 0x8e, 0x7f, 0xcc, 0xb8, 0x1d, 0x41, 0x75, 0x0d, 0xf8, 0x15, 0x54, 0xd2, - 0xf9, 0xc5, 0x7b, 0xa5, 0x4f, 0x4f, 0x63, 0xbf, 0x7c, 0xcc, 0xf1, 0x0b, 0x50, 0x92, 0x3b, 0x88, - 0x77, 0x4b, 0xe6, 0xa8, 0x51, 0x2f, 0xbb, 0xa6, 0x17, 0x15, 0xf1, 0x19, 0x38, 0xfc, 0x15, 0x00, - 0x00, 0xff, 0xff, 0xcd, 0xe9, 0x64, 0x7c, 0x17, 0x06, 0x00, 0x00, + // 655 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xdf, 0x6e, 0x12, 0x4f, + 0x14, 0xc7, 0x7f, 0xb3, 0x7f, 0xa0, 0x3d, 0xb4, 0xcd, 0xfe, 0xa6, 0xb4, 0x6e, 0x50, 0x23, 0x99, + 0xc4, 0x04, 0x2f, 0x9c, 0x44, 0xda, 0xc6, 0x3b, 0x23, 0x01, 0xaa, 0x1b, 0x61, 0xa9, 0xb3, 0xd0, + 0xda, 0x2b, 0xb2, 0x0d, 0xb3, 0x0d, 0x49, 0x61, 0x71, 0x67, 0x09, 0xe5, 0x09, 0xbc, 0xf3, 0x45, + 0x7c, 0x05, 0x6f, 0x7d, 0x08, 0xaf, 0x7d, 0x10, 0xcd, 0x0e, 0x43, 0x0b, 0xeb, 0x1a, 0x93, 0x56, + 0xae, 0xe6, 0xcc, 0x39, 0x9c, 0x39, 0xdf, 0xcf, 0x99, 0x33, 0x0b, 0xdb, 0x23, 0x2e, 0x84, 0x7f, + 0xc9, 0xe9, 0x24, 0x0a, 0xe3, 0x90, 0x7c, 0x43, 0x50, 0x68, 0x2f, 0x76, 0x9c, 0x71, 0x10, 0x62, + 0x0c, 0x46, 0x3c, 0x1c, 0x71, 0x1b, 0x95, 0x51, 0x45, 0x67, 0x72, 0x8d, 0x6d, 0xc8, 0x07, 0x61, + 0x34, 0xf3, 0xa3, 0x81, 0xad, 0x95, 0x51, 0x65, 0x83, 0x2d, 0x4d, 0xfc, 0x14, 0x8c, 0x78, 0x3e, + 0xe1, 0xb6, 0x5e, 0x46, 0x95, 0x9d, 0xea, 0xff, 0x74, 0x25, 0x13, 0xed, 0xce, 0x27, 0x9c, 0x49, + 0xb7, 0x4c, 0xca, 0xaf, 0x63, 0xdb, 0x28, 0xa3, 0xca, 0x26, 0x93, 0x6b, 0xbc, 0x0f, 0xb9, 0xe9, + 0x38, 0xe2, 0xfe, 0xc0, 0x36, 0x65, 0x4e, 0x65, 0x91, 0x23, 0x30, 0x92, 0x7f, 0xe2, 0x02, 0xe4, + 0x7b, 0xee, 0x3b, 0xb7, 0x73, 0xe6, 0x5a, 0xff, 0xe1, 0x0d, 0x30, 0xba, 0xcd, 0x0f, 0x5d, 0x0b, + 0x25, 0xdb, 0x27, 0x4e, 0xbd, 0xdb, 0x63, 0x4d, 0x4b, 0xc3, 0x9b, 0x60, 0x9e, 0x3a, 0x8d, 0x66, + 0xc7, 0xd2, 0xc9, 0x77, 0x04, 0x45, 0x75, 0x7a, 0x3d, 0xe2, 0x7e, 0xcc, 0x19, 0xff, 0x38, 0xe5, + 0x22, 0xc6, 0x25, 0xd8, 0x08, 0xa2, 0x70, 0xd4, 0x13, 0x3c, 0x92, 0xa2, 0x4c, 0x76, 0x63, 0x27, + 0x35, 0xc4, 0xa1, 0xf4, 0x68, 0xd2, 0xa3, 0x2c, 0x4c, 0xd7, 0x64, 0x95, 0x68, 0x56, 0xe2, 0xbf, + 0xe9, 0xc3, 0x60, 0x04, 0xc3, 0x2b, 0x2e, 0xd5, 0x6d, 0x31, 0xb9, 0xbe, 0xab, 0xb6, 0xcf, 0x08, + 0xf6, 0x52, 0x25, 0x88, 0x49, 0x38, 0x16, 0x1c, 0x1f, 0x41, 0x4e, 0xc4, 0x7e, 0x3c, 0x15, 0x52, + 0xda, 0x4e, 0xf5, 0x31, 0xcd, 0x8c, 0xa3, 0x9e, 0x0c, 0x62, 0x2a, 0x98, 0xbc, 0x82, 0xdc, 0x62, + 0x67, 0xbd, 0x92, 0x12, 0x6c, 0x3b, 0xee, 0x69, 0xad, 0xe5, 0x34, 0xfa, 0x27, 0x35, 0x56, 0x6b, + 0x5b, 0x3f, 0x97, 0x3f, 0x59, 0x9b, 0xd7, 0xab, 0xd7, 0x9b, 0x9e, 0x67, 0x21, 0xf2, 0x03, 0x01, + 0x56, 0x07, 0x1d, 0x0f, 0xc7, 0x83, 0xfb, 0xa0, 0x7e, 0x06, 0xfa, 0xcc, 0x9f, 0x2b, 0xd2, 0x0f, + 0xe8, 0xef, 0x59, 0xe9, 0x99, 0x3f, 0x67, 0x49, 0x0c, 0x2e, 0x82, 0x79, 0x35, 0x1c, 0x0d, 0x17, + 0x98, 0x4d, 0xb6, 0x30, 0x92, 0xc4, 0x61, 0x10, 0x08, 0x1e, 0x4b, 0xd2, 0x26, 0x53, 0x16, 0x79, + 0x0d, 0xfa, 0x99, 0x3f, 0x5f, 0x17, 0xb8, 0x0d, 0x9b, 0x1d, 0xb7, 0x75, 0xde, 0x3f, 0xe9, 0xb5, + 0x5a, 0x16, 0xc2, 0x16, 0x6c, 0xb1, 0x66, 0xad, 0xd1, 0x6f, 0x37, 0x3d, 0xaf, 0xf6, 0x26, 0x81, + 0x5e, 0x80, 0xfc, 0x5b, 0xc7, 0xeb, 0x76, 0xd8, 0xb9, 0xa5, 0x93, 0x4f, 0x1a, 0xec, 0xae, 0xd5, + 0xa3, 0xa0, 0x1f, 0xa4, 0xa0, 0x3f, 0xa4, 0x19, 0x51, 0x29, 0xe4, 0x6b, 0x6c, 0xb4, 0x3f, 0xb2, + 0xd1, 0xd7, 0xd8, 0x14, 0xc1, 0xbc, 0xf0, 0x07, 0x97, 0x7c, 0x29, 0x58, 0x1a, 0x98, 0x80, 0x39, + 0x1c, 0x07, 0xa1, 0xb0, 0xcd, 0xb2, 0x5e, 0x29, 0x54, 0xb7, 0x56, 0x87, 0x8e, 0x2d, 0x5c, 0xa4, + 0x7d, 0xbf, 0x06, 0x27, 0xa0, 0xdc, 0x4e, 0xb7, 0x7f, 0xdc, 0xe9, 0xb9, 0x0d, 0x4b, 0x23, 0xd7, + 0x00, 0x2e, 0x9f, 0xa9, 0x73, 0xee, 0xd4, 0xe6, 0x1b, 0x29, 0xfa, 0xaa, 0x94, 0x32, 0x18, 0x49, + 0xbd, 0x52, 0x5f, 0x5a, 0x89, 0xf4, 0x90, 0xe7, 0x37, 0x2d, 0x78, 0x3f, 0xe5, 0xd1, 0x7c, 0x79, + 0xd3, 0x92, 0xc7, 0x43, 0xf0, 0xc8, 0x69, 0xa8, 0x02, 0x94, 0x45, 0xbe, 0xde, 0xbe, 0x02, 0x2a, + 0x5e, 0xf5, 0xec, 0x30, 0xd5, 0xb3, 0x47, 0x34, 0x2b, 0x2c, 0xdd, 0xb4, 0x27, 0x60, 0x8c, 0xf9, + 0x4c, 0xd8, 0x9a, 0x24, 0x5d, 0xa0, 0xb7, 0x10, 0x98, 0x74, 0xfc, 0x63, 0xce, 0xd5, 0x2f, 0x08, + 0xf2, 0x4b, 0xca, 0x2f, 0x21, 0xb7, 0x18, 0x62, 0xbc, 0x97, 0xf9, 0xfe, 0x94, 0xf6, 0xb3, 0x67, + 0x1d, 0xbf, 0x00, 0x23, 0xb9, 0x88, 0x78, 0x37, 0x63, 0x98, 0x4a, 0xc5, 0xac, 0xbb, 0x8a, 0x0f, + 0xc1, 0x94, 0x1c, 0x70, 0x91, 0x66, 0xd0, 0x2e, 0xed, 0x65, 0xc2, 0xba, 0xc8, 0xc9, 0x2f, 0xc8, + 0xc1, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x2d, 0xd2, 0xc0, 0x52, 0x06, 0x00, 0x00, } diff --git a/backend/srv/message/proto/message.proto b/backend/srv/message/proto/message.proto index e77323b..a6f9434 100644 --- a/backend/srv/message/proto/message.proto +++ b/backend/srv/message/proto/message.proto @@ -3,6 +3,7 @@ syntax = "proto3"; service Message { rpc Create (MessageCreateRequest) returns (MessageCreateResponse); rpc Find (MessageFindRequest) returns (MessageFindResponse); + rpc Query (MessageQueryRequest) returns (MessageQueryResponse); } message MessageInfo{ @@ -78,7 +79,7 @@ message NewMessage{ } message MessageQueryRequest{ - int32 user = 1; + int32 userID = 1; } message MessageQueryResponse{ From e7cf37b5916980796ae454bd26a74a14e06e2eb0 Mon Sep 17 00:00:00 2001 From: sjtuzwj Date: Thu, 1 Aug 2019 22:46:40 +0800 Subject: [PATCH 14/17] feat: transaction + doc: iter 3 --- admin-frontend/src/app/auth.service.ts | 3 +- .../app/dashboard/dashboard.component.html | 7 +- .../src/app/dashboard/dashboard.component.ts | 30 +- admin-frontend/src/app/entity/transaction.ts | 9 + .../info-statistic.component.html | 2 +- .../info-statistic.component.spec.ts | 25 +- .../info-statistic.component.ts | 241 +-- admin-frontend/src/app/info.service.spec.ts | 2 + admin-frontend/src/app/info.service.ts | 34 +- .../app/info/sell-info/sell-info.component.ts | 2 + .../app/infodetail/infodetail.component.html | 2 +- .../infodetail/infodetail.component.spec.ts | 6 +- .../app/infodetail/infodetail.component.ts | 1 - .../src/app/transaction.service.spec.ts | 19 + admin-frontend/src/app/transaction.service.ts | 86 + .../userdetail/userdetail.component.spec.ts | 1 + .../app/userdetail/userdetail.component.ts | 3 +- .../coverage/jiaojiaoadmin/base.css" | 224 +++ .../jiaojiaoadmin/block-navigation.js" | 79 + .../coverage/jiaojiaoadmin/index.html" | 305 +++ .../coverage/jiaojiaoadmin/lcov.info" | 1446 ++++++++++++++ .../coverage/jiaojiaoadmin/prettify.css" | 1 + .../coverage/jiaojiaoadmin/prettify.js" | 2 + .../jiaojiaoadmin/sort-arrow-sprite.png" | Bin 0 -> 209 bytes .../coverage/jiaojiaoadmin/sorter.js" | 170 ++ .../src/app/Formatter/format.ts.html" | 114 ++ .../src/app/Formatter/index.html" | 97 + .../app/activity/activity.component.ts.html" | 126 ++ .../src/app/activity/index.html" | 97 + .../activitydetail.component.ts.html" | 324 ++++ .../src/app/activitydetail/index.html" | 97 + .../src/app/app-routing.module.ts.html" | 174 ++ .../src/app/app.component.ts.html" | 132 ++ .../src/app/auth.service.ts.html" | 159 ++ .../app/callback/callback.component.ts.html" | 150 ++ .../src/app/callback/index.html" | 97 + .../dashboard/dashboard.component.ts.html" | 300 +++ .../src/app/dashboard/index.html" | 97 + .../jiaojiaoadmin/src/app/entity/index.html" | 123 ++ .../src/app/entity/info.ts.html" | 156 ++ .../src/app/entity/transaction.ts.html" | 93 + .../src/app/entity/user.ts.html" | 114 ++ .../src/app/file.service.ts.html" | 189 ++ .../jiaojiaoadmin/src/app/index.html" | 201 ++ .../src/app/info-statistic/index.html" | 97 + .../info-statistic.component.ts.html" | 1716 +++++++++++++++++ .../src/app/info.service.ts.html" | 612 ++++++ .../info/buy-info/buy-info.component.ts.html" | 282 +++ .../src/app/info/buy-info/index.html" | 97 + .../jiaojiaoadmin/src/app/info/index.html" | 110 ++ .../src/app/info/info.component.ts.html" | 243 +++ .../src/app/info/infocom.service.ts.html" | 156 ++ .../src/app/info/sell-info/index.html" | 97 + .../sell-info/sell-info.component.ts.html" | 279 +++ .../src/app/infodetail/index.html" | 97 + .../infodetail/infodetail.component.ts.html" | 501 +++++ .../src/app/inmemory-data.service.ts.html" | 120 ++ .../jiaojiaoadmin/src/app/login/index.html" | 97 + .../src/app/login/login.component.ts.html" | 174 ++ .../src/app/transaction.service.ts.html" | 327 ++++ .../src/app/user.service.ts.html" | 288 +++ .../jiaojiaoadmin/src/app/user/index.html" | 97 + .../src/app/user/user.component.ts.html" | 261 +++ .../src/app/userdetail/index.html" | 97 + .../userdetail/userdetail.component.ts.html" | 534 +++++ .../src/app/website.service.ts.html" | 300 +++ .../jiaojiaoadmin/src/app/website/index.html" | 97 + .../app/website/website.component.ts.html" | 225 +++ .../coverage/jiaojiaoadmin/src/index.html" | 110 ++ .../jiaojiaoadmin/src/polyfills.ts.html" | 258 +++ .../coverage/jiaojiaoadmin/src/test.ts.html" | 129 ++ ...3\350\257\225\347\224\250\344\276\213.xls" | Bin 0 -> 125440 bytes 72 files changed, 12797 insertions(+), 144 deletions(-) create mode 100644 admin-frontend/src/app/entity/transaction.ts create mode 100644 admin-frontend/src/app/transaction.service.spec.ts create mode 100644 admin-frontend/src/app/transaction.service.ts create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/base.css" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/block-navigation.js" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/lcov.info" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/prettify.css" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/prettify.js" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/sort-arrow-sprite.png" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/sorter.js" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/Formatter/format.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/Formatter/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activity/activity.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activity/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activitydetail/activitydetail.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activitydetail/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/app-routing.module.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/app.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/auth.service.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/callback/callback.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/callback/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/dashboard/dashboard.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/dashboard/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/info.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/transaction.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/user.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/file.service.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info-statistic/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info-statistic/info-statistic.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info.service.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/buy-info/buy-info.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/buy-info/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/info.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/infocom.service.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/sell-info/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/sell-info/sell-info.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/infodetail/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/infodetail/infodetail.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/inmemory-data.service.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/login/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/login/login.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/transaction.service.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user.service.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user/user.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/userdetail/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/userdetail/userdetail.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website.service.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website/website.component.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/index.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/polyfills.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/test.ts.html" create mode 100644 "docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web\345\211\215\347\253\257\346\265\213\350\257\225\347\224\250\344\276\213.xls" diff --git a/admin-frontend/src/app/auth.service.ts b/admin-frontend/src/app/auth.service.ts index 55d38b0..c6df69f 100644 --- a/admin-frontend/src/app/auth.service.ts +++ b/admin-frontend/src/app/auth.service.ts @@ -18,10 +18,9 @@ export class AuthService { //JWTTokenModely this.tokenService.set(res); const jwt :JWTTokenModel = this.tokenService.get(JWTTokenModel); - console.log(jwt); if(jwt.payload.role !== 10) { this.logout(); - console.log( 'not admin'); + console.log('error! not admin'); } } diff --git a/admin-frontend/src/app/dashboard/dashboard.component.html b/admin-frontend/src/app/dashboard/dashboard.component.html index 7ab487b..288f97f 100644 --- a/admin-frontend/src/app/dashboard/dashboard.component.html +++ b/admin-frontend/src/app/dashboard/dashboard.component.html @@ -1,8 +1,8 @@ - diff --git a/admin-frontend/src/app/dashboard/dashboard.component.ts b/admin-frontend/src/app/dashboard/dashboard.component.ts index 8ac875e..55352e4 100644 --- a/admin-frontend/src/app/dashboard/dashboard.component.ts +++ b/admin-frontend/src/app/dashboard/dashboard.component.ts @@ -5,6 +5,7 @@ import { InfoService } from '../info.service'; import { sellInfo } from './../entity/info'; import { getCurrencySymbol } from '@angular/common'; import { trigger, transition, style, state, animate } from '@angular/animations'; +import { Route } from '@angular/compiler/src/core'; @Component({ selector: 'app-dashboard', @@ -12,24 +13,33 @@ import { trigger, transition, style, state, animate } from '@angular/animations' styleUrls: ['./dashboard.component.css'] }) export class DashboardComponent implements OnInit { - constructor(private ifService: InfoService, private wbService: WebsiteService,private usService: UserService) { } + constructor( + private ifService: InfoService, private wbService: WebsiteService,private usService: UserService) { } site : any; hst: any[]; - /* - userNum: number; + + rsInfoNum: number; infoNum: number; acInfoNum: number; - */ + ngOnInit() { this.getHistory(); this.wbService.getSite().subscribe(s => this.site= s); - //this.usService.getUsers().subscribe( e =>this.userNum = e.user.length); - //this.ifService.getSellInfos().subscribe( e => { - // this.infoNum = e.sellInfo.length; - //this.acInfoNum = e.sellInfo.filter( e => e.status < 3).length; - //} - // ); + this.ifService.getAllBuyInfo(); + this.ifService.getAllSellInfo(); + this.infoNum = this.ifService.getInfoNum() + this.acInfoNum = this.ifService.getAcInfo(); + this.rsInfoNum = this.ifService.getReserveInfoNum(); + this.getInfo(); + } + getInfo(){ + setTimeout(() => { + this.infoNum = this.ifService.getInfoNum() + this.acInfoNum = this.ifService.getAcInfo(); + this.rsInfoNum = this.ifService.getReserveInfoNum(); + this.getInfo(); + },10000); } getHistory(){ this.wbService.getSiteHistory().subscribe( s =>this.hst =s.sort((a,b)=> a.time-b.time)); diff --git a/admin-frontend/src/app/entity/transaction.ts b/admin-frontend/src/app/entity/transaction.ts new file mode 100644 index 0000000..47c100e --- /dev/null +++ b/admin-frontend/src/app/entity/transaction.ts @@ -0,0 +1,9 @@ +export class Transaction{ + public transactionID:number; + public infoID: number; + public category:number; + public fromUserID: number; + public toUserID: number; + public createTime: number; + public status: number; +} \ No newline at end of file diff --git a/admin-frontend/src/app/info-statistic/info-statistic.component.html b/admin-frontend/src/app/info-statistic/info-statistic.component.html index 1874670..a80ac2f 100644 --- a/admin-frontend/src/app/info-statistic/info-statistic.component.html +++ b/admin-frontend/src/app/info-statistic/info-statistic.component.html @@ -1,6 +1,6 @@
-
+
diff --git a/admin-frontend/src/app/info-statistic/info-statistic.component.spec.ts b/admin-frontend/src/app/info-statistic/info-statistic.component.spec.ts index 3f6b7ad..b58a22a 100644 --- a/admin-frontend/src/app/info-statistic/info-statistic.component.spec.ts +++ b/admin-frontend/src/app/info-statistic/info-statistic.component.spec.ts @@ -13,7 +13,7 @@ import { LoginComponent } from '../login/login.component'; import { InfoDetailComponent } from '../infodetail/infodetail.component'; import { WebsiteComponent } from '../website/website.component'; import { ActivityComponent } from '../activity/activity.component'; -import { InfoStatisticComponent } from './info-statistic.component'; +import { InfoStatisticComponent, fdgFormatter } from './info-statistic.component'; import { NgxEchartsModule } from 'ngx-echarts'; import { HttpClientModule } from '@angular/common/http'; import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api'; @@ -25,6 +25,7 @@ import { CallbackComponent } from '../callback/callback.component'; import { SellInfoComponent } from '../info/sell-info/sell-info.component'; import { BuyInfoComponent } from '../info/buy-info/buy-info.component'; import { buyInfo, sellInfo } from '../entity/info'; +import { Transaction } from '../entity/transaction'; describe('InfoStatisticComponent', () => { let component: InfoStatisticComponent; let fixture: ComponentFixture; @@ -75,5 +76,27 @@ describe('InfoStatisticComponent', () => { component.bi = [ new buyInfo()]; component.si = [ new sellInfo()]; expect(component.fmt(new Date(1563134054000))).toEqual('2019/7/15'); + component.pl=false; + component.pauseLine(); + expect(component.pl).toEqual(true); + component.clickForce({dataType: 'node', data:{name: '1'}}); + component.tr= [new Transaction()]; + component.bi = [new buyInfo()]; + component.si = [new sellInfo()]; + expect(fdgFormatter({dataType: 'node',data:{name: '1', value: '2'}})).toEqual('1 has completed 2 transaction'); + expect(fdgFormatter({dataType: 'edge',data:{source: '1', target: '2', value: '2'}})). + toEqual('1 has selled 2 goods to 2'); + component.tr= [ + {transactionID: 2, infoID: 1, category: 2, fromUserID: 10003, toUserID: 3,createTime :1 ,status:6}, + {transactionID: 3, infoID: 1, category: 3, fromUserID: 10003, toUserID: 3,createTime :1 ,status:6}, + {transactionID: 4, infoID: 2, category: 2, fromUserID: 10003, toUserID: 3,createTime :1 ,status:6}, + {transactionID: 5, infoID: 6, category: 2, fromUserID: 10003, toUserID: 10002,createTime :1 ,status:6}, + {transactionID: 6, infoID: 6, category: 1, fromUserID: 10003, toUserID: 1366,createTime :1 ,status:6}, + {transactionID: 7, infoID: 200001, category: 1, fromUserID: 3, toUserID: 10003,createTime :1 ,status:6}, + {transactionID: 8, infoID: 200002, category: 1, fromUserID: 10002, toUserID: 10003,createTime :1 ,status:6}, + {transactionID: 9, infoID: 200003, category: 1, fromUserID: 1366, toUserID: 10003,createTime :1 ,status:6}, + {transactionID: 10, infoID: 16473, category: 1, fromUserID: 1366, toUserID: 9368,createTime :1 ,status:6}] + component.forceGraph(); + }); }); diff --git a/admin-frontend/src/app/info-statistic/info-statistic.component.ts b/admin-frontend/src/app/info-statistic/info-statistic.component.ts index 01994b5..0fd4016 100644 --- a/admin-frontend/src/app/info-statistic/info-statistic.component.ts +++ b/admin-frontend/src/app/info-statistic/info-statistic.component.ts @@ -7,9 +7,17 @@ import {prepareBoxplotData} from 'echarts/extension/dataTool'; import { Transaction } from '../entity/transaction'; import { TransactionService } from '../transaction.service'; import { Format } from '../Formatter/format'; +import { Router } from '@angular/router'; const name = ['LJH', 'WXZ', 'ZWJ', 'KHQ', 'MZD', 'ZEL', 'JZM', 'HJT', 'TRUMP', 'LJH2', 'WXZ2', 'ZWJ2', 'KHQ2', 'MZD2', 'ZEL2', 'JZM2', 'HJT2', 'TRUMP2', 'LJH3', 'WXZ3', 'ZWJ3', 'KHQ3', 'MZD3', 'ZEL3', 'JZM3', 'HJT3', 'TRUMP3']; +export function fdgFormatter + (p) { + if(p.dataType=='node') + return p.data.name + ' has completed '+ p.data.value + ' transaction'; + if(p.dataType=='edge') + return p.data.source + ' has selled '+ p.data.value + ' goods to '+ p.data.target; + } @Component({ selector: 'app-info-statistic', templateUrl: './info-statistic.component.html', @@ -25,48 +33,39 @@ export class InfoStatisticComponent implements OnInit { si: sellInfo[]=[]; tr: Transaction[]=[]; pl: boolean = false; - constructor(private trs: TransactionService, private is: InfoService) { } + constructor(private router: Router, private trs: TransactionService, private is: InfoService) { } ngOnInit() { - this.is.getBuyInfos().subscribe( - e => {this.bi = e.buyInfo; - this.is.getSellInfos().subscribe( - e => { - this.si = e.sellInfo; - this.cloudGrpah(); - this.forceGraph(); - this.calenderGraph(); - this.lineGraph(); - this.boxGraph(); - const now = new Date().getFullYear() - this.tr = this.trs.getAllTR(6,new Date(now,1,1).getTime()/1000, new Date(now+1,1,1).getTime()/1000); - this.bi = this.is.getAllBuyInfo(); - this.si = this.is.getAllSellInfo(); - this.getAllInfo(); - this.getAllTR(new Date(now,1,1).getTime()/1000, new Date(now+1,1,1).getTime()/1000); - } - );}) + const now = new Date().getFullYear(); + this.getAllInfo(); + this.getAllTR(new Date(now,1,1).getTime()/1000, new Date(now+1,1,1).getTime()/1000); + this.cloudGrpah(); + this.forceGraph(); + this.calenderGraph(); + this.lineGraph(); + this.boxGraph(); + } pauseLine(){ this.pl=!this.pl; } getAllTR(beg, end){ + this.tr = this.trs.getAllTR(6,beg,end); + if(!this.pl){ + this.calenderGraph(); + this.forceGraph(); + } setTimeout(() => { - this.tr = this.trs.getAllTR(6,beg,end); - if(!this.pl){ - this.calenderGraph(); - this.forceGraph(); - } this.getAllTR(beg,end); }, 10000); } getAllInfo(){ + this.bi = this.is.getAllBuyInfo(); + this.bi = this.bi.sort( (a,b) => a.releaseTime - b.releaseTime); + this.si = this.is.getAllSellInfo(); + this.si = this.si.sort( (a,b) => a.releaseTime - b.releaseTime); + if(!this.pl)this.lineGraph(); setTimeout(() => { - this.bi = this.is.getAllBuyInfo(); - this.bi = this.bi.sort( (a,b) => a.releaseTime - b.releaseTime); - this.si = this.is.getAllSellInfo(); - this.si = this.si.sort( (a,b) => a.releaseTime - b.releaseTime); - if(!this.pl)this.lineGraph(); this.getAllInfo(); }, 10000); } @@ -83,7 +82,7 @@ this.goodoption = { backgroundColor: '#01193d', title: [ { - text: 'Price Trend', + text: '交易价格分布', left: 'center', } ], @@ -162,7 +161,7 @@ this.goodoption = { this.cldoption = { backgroundColor: '#01193d', title: { - text: 'Label WordCloud', + text: '标签热度', left: 'center', }, tooltip: {}, @@ -223,7 +222,7 @@ this.goodoption = { this.tsoption = { backgroundColor: '#01193d', title: { - text: 'Transaction Calendar', + text: '活跃度日历', left: 'center' }, tooltip : { @@ -295,94 +294,114 @@ this.goodoption = { } forceGraph() { let td =new Map(); + let join = []; this.tr.forEach( e => { if(!e)return; - if(e.category==2) - this.is.getBuyInfo(e.infoID).subscribe(info => { - const other = info.userID; - if(e.userID in td) - if(other in td[e.userID]) - td[e.userID][td] +=1; - else td[e.userID][td] =1; + if(e&&e.category==2){ + const other = e.toUserID; + if(e.fromUserID in td) + if(other in td[e.fromUserID]) + td[e.fromUserID][other] +=1; + else td[e.fromUserID][other] =1; else { - td[e.userID] = new Map(); - td[e.userID][td] = 1; + td[e.fromUserID] = new Map(); + td[e.fromUserID][other] = 1; } - }); - if(e.category==1) - this.is.getSellInfo(e.infoID).subscribe(info => { - const other = info.userID; - if(other in td) - if(e.userID in td[other]) - td[other][e.userID] +=1; - else td[other][e.userID] =1; - else { - td[other] = new Map(); - td[other][e.userID] = 1; - } - }); - }); - setTimeout(( )=> { - const E = []; - const V = []; - for( let i in td){ - let sum = 0; - for( let j in td[i]){ - E.push( - {source: i, target: j - , value: td[i][j], lineStyle: { - width: td[i][j] - }}); - sum += td[i][j]; - } - V.push({name: i, itemStyle: { - color: '#60acfc' - }, value : sum, symbolSize: sum*5, - draggable: true}) } - this.fdgoption = { - backgroundColor: '#01193d', - title: { - text: 'Transaction Network', - left: 'center', - }, - tooltip: {}, - animationDurationUpdate: 1500, - animationEasingUpdate: 'quinticInOut', - series : [ - { - type: 'graph', - layout: 'force', - data: V, edges: E, - label: { - emphasis: { - position: 'right', - show: true - } - }, - force: { - repulsion : 100 - }, - roam: true, - focusNodeAdjacency: true, - lineStyle: { - normal: { - color :'source', - type : 'solid', - width: 0.5, - curveness: 0.2, - opacity: 0.7 - } - } + else if(e&& e.category==1){ + const other = e.toUserID; + if(other in td) + if(e.fromUserID in td[other]) + td[other][e.fromUserID] +=1; + else td[other][e.fromUserID] =1; + else { + td[other] = new Map(); + td[other][e.fromUserID] = 1; + } + } +}); +const VMAP= {}; +const E = []; +const V = []; +for( let i in td){ + let sum = 0; + for( let j in td[i]){ + E.push( + {source: i, target: j + , value: td[i][j], lineStyle: { + width: td[i][j] + }}); + sum += td[i][j]; + if(j in VMAP) + VMAP[j]+=td[i][j]; + else + VMAP[j]= td[i][j]; + } + if(i in VMAP) + VMAP[i]+=sum; + else + VMAP[i]=sum; +} +for( let i in VMAP){ + V.push({name: i, value : VMAP[i], symbolSize: VMAP[i]*5, + draggable: true}) +} +this.fdgoption = { +backgroundColor: '#01193d', + title: { + text: '交易网络', + left: 'center', + }, + tooltip: { + formatter: fdgFormatter + }, + visualMap: { + type: 'continuous', + min: 1, + max: 10, + text:['Active','Lazy'], + realtime: false, + calculable : true, + color: ['orangered','yellow','lightskyblue'] + }, + animationDurationUpdate: 1500, + animationEasingUpdate: 'quinticInOut', + series : [ + { + type: 'graph', + layout: 'force', + data: V, edges: E, + label: { + emphasis: { + position: 'right', + show: true } - ] - }; - - },1000) + }, + force: { + repulsion : 100 + }, + roam: true, + focusNodeAdjacency: true, + lineStyle: { + normal: { + color :'source', + type : 'solid', + width: 0.5, + curveness: 0.2, + opacity: 0.7 + } + } +} + ] + }; } fmt(t: Date) { return [t.getFullYear(), t.getMonth() + 1, t.getDate()].join('/'); } + clickForce(param){ + if(param.dataType=='node') + this.router.navigateByUrl('/user/'+param.data.name); + } lineGraph() { let bd =new Map(); this.bi.forEach( e => { @@ -414,7 +433,7 @@ this.goodoption = { this.lqoption = { backgroundColor: '#01193d', title : { - text: 'Transaction Trend', + text: '新增交易趋势', x: 'center', align: 'right' }, diff --git a/admin-frontend/src/app/info.service.spec.ts b/admin-frontend/src/app/info.service.spec.ts index e341155..347cba0 100644 --- a/admin-frontend/src/app/info.service.spec.ts +++ b/admin-frontend/src/app/info.service.spec.ts @@ -2,6 +2,7 @@ import { TestBed } from '@angular/core/testing'; import { InfoService } from './info.service'; import { HttpClient } from '@angular/common/http'; +import { sellInfo, buyInfo } from './entity/info'; describe('InfoService', () => { let service: InfoService; @@ -16,5 +17,6 @@ describe('InfoService', () => { it('should be created', () => { service = TestBed.get(InfoService); expect(service).toBeTruthy(); + }); }); diff --git a/admin-frontend/src/app/info.service.ts b/admin-frontend/src/app/info.service.ts index 95b9cc9..1d653ba 100644 --- a/admin-frontend/src/app/info.service.ts +++ b/admin-frontend/src/app/info.service.ts @@ -18,11 +18,20 @@ export class InfoService { private sellinfoUrl = 'api/sellInfo'; // URL to web api private buyinfoUrl = 'api/buyInfo'; constructor(private http: HttpClient) { } - bi: buyInfo[]; - si: sellInfo[]; + bi: buyInfo[] = []; + si: sellInfo[] = []; + getAcInfo(){ + return this.bi.filter( a => a.status<3).length+ this.si.filter(a =>a.status<3).length; + } + getInfoNum(){ + return this.bi.length + this.si.length; + } + getReserveInfoNum(){ + return this.bi.filter( a=> a.status ==2).length+ this.si.filter(a=> a.status ==2).length; + } getAllSellInfo(): sellInfo[]{ - if(!this.si) + if(this.si.length==0) { this.getSellInfos().subscribe(e=> { @@ -34,7 +43,7 @@ export class InfoService { } getAllBuyInfo(): buyInfo[]{ - if(!this.bi) + if(this.bi.length==0) { this.getBuyInfos().subscribe(e=> { @@ -49,7 +58,7 @@ export class InfoService { if(!(this.bi.length%100) && !dynamic) this.getBuyInfos(null,null,null,null,offset).subscribe( e => { - if(e){ + if(e&&Object.keys(e).length!=0){ this.bi=this.bi.concat(e.buyInfo); if(e.buyInfo.length!=100) dynamic =! dynamic; @@ -61,10 +70,9 @@ export class InfoService { setTimeout(() => { this.getBuyInfos(null,null,null,null,offset).subscribe( e => { - if(e) + if(e&&Object.keys(e).length!=0) this.bi=this.bi.concat(e.buyInfo); this.getMoreBuy(this.bi.length-1, true); - console.log(this.bi); } );}, 5000 ); } @@ -74,7 +82,7 @@ getMoreSell(offset, dynamic){ if(!(this.si.length%100) && !dynamic) this.getSellInfos(null,null,null,null,offset).subscribe( e => { - if(e){ + if(e&&Object.keys(e).length!=0){ this.si= this.si.concat(e.sellInfo); if(e.sellInfo.length!=100) dynamic=!dynamic; @@ -86,7 +94,7 @@ getMoreSell(offset, dynamic){ setTimeout(() => { this.getSellInfos(null,null,null,null,offset).subscribe( e => { - if(e) + if(e&&Object.keys(e).length!=0) this.si=this.si.concat(e.sellInfo); this.getMoreSell(this.si.length-1,true); } @@ -105,15 +113,18 @@ getMoreSell(offset, dynamic){ getSellInfos(userID: string = null, status: number = null, goodName: string = null,limit:number=null, offset: number=null): Observable { let url = `${this.sellinfoUrl}?`; if(userID && userID.trim()) url += `userID=${userID}&`; + if(status) url+= `status=${status}&`; if(goodName && goodName.trim()) url+=`goodName=${goodName}&`; if(limit) url+= `limit=${limit}&`; if(offset) url+=`offset=${offset}&`; + return this.http.get(url) .pipe( catchError(this.handleError('getSellInfos')) ); - } + + } /** PUT: update the info on the server */ updateSellInfo(info: any): Observable { @@ -123,7 +134,8 @@ getMoreSell(offset, dynamic){ } /** GET infos from the server */ - getBuyInfos(userID: string = null, status: number = null, goodName: string = null,limit:number=null, offset: number=null): Observable { + getBuyInfos(userID: string = null, status: number = null, goodName: string = null,limit:number=null, offset: number=null): + Observable { let url = `${this.buyinfoUrl}?`; if(userID && userID.trim()) url += `userID=${userID}&`; if(status) url+= `status=${status}&`; diff --git a/admin-frontend/src/app/info/sell-info/sell-info.component.ts b/admin-frontend/src/app/info/sell-info/sell-info.component.ts index fea3c97..143b244 100644 --- a/admin-frontend/src/app/info/sell-info/sell-info.component.ts +++ b/admin-frontend/src/app/info/sell-info/sell-info.component.ts @@ -39,6 +39,8 @@ export class SellInfoComponent implements OnInit { return '完成'; case 4: return '失效'; + case 5: + return '关闭'; } } getinfos(): void { diff --git a/admin-frontend/src/app/infodetail/infodetail.component.html b/admin-frontend/src/app/infodetail/infodetail.component.html index cc25772..a88546f 100644 --- a/admin-frontend/src/app/infodetail/infodetail.component.html +++ b/admin-frontend/src/app/infodetail/infodetail.component.html @@ -8,7 +8,7 @@
- 交易ID{{info.sellInfoID}} + 交易ID{{type=='sellInfo'?info.sellInfoID:info.buyInfoID}}
交易类型{{type=='sellInfo'?'出售':'求购'}} diff --git a/admin-frontend/src/app/infodetail/infodetail.component.spec.ts b/admin-frontend/src/app/infodetail/infodetail.component.spec.ts index bf38280..de42162 100644 --- a/admin-frontend/src/app/infodetail/infodetail.component.spec.ts +++ b/admin-frontend/src/app/infodetail/infodetail.component.spec.ts @@ -80,7 +80,6 @@ describe('InfodetailComponent', () => { expect(component).toBeTruthy(); //create setInterval(()=> {},1000); - component.save(); component.goBack(); expect(component.stringToDate(1563134054)).toEqual('2019-07-15 03:54:14'); component.type = 'sellInfo'; @@ -90,5 +89,10 @@ describe('InfodetailComponent', () => { component.info = new sellInfo(); component.info.contentID= '1'; component.getContent(); + component.deadLine=new Date(1563134051000); + component.save(); + component.type = 'sellInfo'; + component.save(); + }); }); diff --git a/admin-frontend/src/app/infodetail/infodetail.component.ts b/admin-frontend/src/app/infodetail/infodetail.component.ts index 0b9f46a..6cdb937 100644 --- a/admin-frontend/src/app/infodetail/infodetail.component.ts +++ b/admin-frontend/src/app/infodetail/infodetail.component.ts @@ -44,7 +44,6 @@ stringToDate(params) { getContent(): void { this.fileService.getContent(this.info.contentID).subscribe( e => { - console.log(e); if(e) this.contents = e.files; } diff --git a/admin-frontend/src/app/transaction.service.spec.ts b/admin-frontend/src/app/transaction.service.spec.ts new file mode 100644 index 0000000..c1bb1f3 --- /dev/null +++ b/admin-frontend/src/app/transaction.service.spec.ts @@ -0,0 +1,19 @@ +import { TestBed } from '@angular/core/testing'; + +import { TransactionService } from './transaction.service'; +import { HttpClient } from '@angular/common/http'; +import { Transaction } from './entity/transaction'; + +describe('TransactionService', () => { + beforeEach(() => { + const httpClientSpy = jasmine.createSpyObj('HttpClient', ['get','put','post','delete']); + TestBed.configureTestingModule({ + providers: [{provide: HttpClient, useValue: httpClientSpy} ] + }); +}); + + it('should be created', () => { + const service: TransactionService = TestBed.get(TransactionService); + expect(service).toBeTruthy(); + }); +}); diff --git a/admin-frontend/src/app/transaction.service.ts b/admin-frontend/src/app/transaction.service.ts new file mode 100644 index 0000000..6a46b55 --- /dev/null +++ b/admin-frontend/src/app/transaction.service.ts @@ -0,0 +1,86 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Transaction } from './entity/transaction'; +import { Observable, of } from 'rxjs'; +import { catchError } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class TransactionService { + + private trUrl = 'api/transaction'; // URL to web api + tr: Transaction[]=[]; + constructor(private http: HttpClient) { } + + getAllTR(status,lowCreateTime,highCreateTime): Transaction[]{ + if(this.tr.length==0) + { + this.getTransactions(null,status,null,lowCreateTime,highCreateTime).subscribe(e=> + { + this.tr = e.transactions; + this.getMoreTransaction(100,false,status,lowCreateTime,highCreateTime); + }) + } + return this.tr; + } + + getMoreTransaction(offset, dynamic,status,lowCreateTime,highCreateTime){ + if(!(this.tr.length%100) && !dynamic) + this.getTransactions(null,null,null,lowCreateTime,highCreateTime, null,offset).subscribe( + e => { + if(e&&Object.keys(e).length!=0){ + this.tr=this.tr.concat(e.transactions); + if(e.buyInfo.length!=100) + dynamic =! dynamic; + } + this.getMoreTransaction(offset+100, dynamic,status,lowCreateTime,highCreateTime); + } + ); + else{ + setTimeout(() => { + this.getTransactions(null,null,null,lowCreateTime,highCreateTime, null,offset).subscribe( + e => { + if(e&&Object.keys(e).length!=0) + this.tr=this.tr.concat(e.buyInfo); + this.getMoreTransaction(this.tr.length-1, true,status,lowCreateTime,highCreateTime); + } + );}, 5000 ); + } +} + + /** GET infos from the server */ + getTransactions(userID: string = null, status: number = null, infoID: number = null, + lowCreateTime :number = null, highCreateTime: number =null, limit:number=null, offset: number=null): + Observable + { + let url = `${this.trUrl}?`; + if(userID && userID.trim()) url += `userID=${userID}&`; + if(status) url+= `status=${status}&`; + if(infoID) url+=`goodName=${infoID}&`; + if(limit) url+= `limit=${limit}&`; + if(lowCreateTime) url+=`lowCreateTime=${lowCreateTime}&`; + if(highCreateTime) url+=`highCreateTime=${highCreateTime}&`; + if(offset) url+=`offset=${offset}&`; + return this.http.get(url).pipe( + catchError(this.handleError('getTransactions')) + ); + } + + /** + * Handle Http operation that failed. + * Let the app continue. + * @param operation - name of the operation that failed + * @param result - optional value to return as the observable result + * + */ + + private handleError(operation, result?: T) { + return (error: any): Observable => { + // TODO: send the error to remote logging infrastructure + console.error(error); // log to console instead + // Let the app keep running by returning an empty result. + return of(result as T); + }; + } +} diff --git a/admin-frontend/src/app/userdetail/userdetail.component.spec.ts b/admin-frontend/src/app/userdetail/userdetail.component.spec.ts index 89444fd..cb462a6 100644 --- a/admin-frontend/src/app/userdetail/userdetail.component.spec.ts +++ b/admin-frontend/src/app/userdetail/userdetail.component.spec.ts @@ -89,6 +89,7 @@ describe('UserdetailComponent', () => { expect(component.getstate(2)).toEqual('预约'); expect(component.getstate(3)).toEqual('完成'); expect(component.getstate(4)).toEqual('失效'); + expect(component.getstate(5)).toEqual('关闭'); expect(fFormatter({value: 5, name: 'Jan'})).toEqual('5 activities in Jan'); expect(component.stringToDate(1563134054)).toEqual('2019-07-15 03:54:14'); const sI = new sellInfo; diff --git a/admin-frontend/src/app/userdetail/userdetail.component.ts b/admin-frontend/src/app/userdetail/userdetail.component.ts index 1b466e2..5ad0d0f 100644 --- a/admin-frontend/src/app/userdetail/userdetail.component.ts +++ b/admin-frontend/src/app/userdetail/userdetail.component.ts @@ -87,6 +87,8 @@ stringToDate(params) { return '完成'; case 4: return '失效'; + case 5: + return '关闭'; } } @@ -107,7 +109,6 @@ this.infos.forEach(element => { else buyData[m-1] +=1; }); - console.log(sellData) this.option = { title: { }, diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/base.css" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/base.css" new file mode 100644 index 0000000..f418035 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/base.css" @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/block-navigation.js" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/block-navigation.js" new file mode 100644 index 0000000..c7ff5a5 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/block-navigation.js" @@ -0,0 +1,79 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selecter that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/index.html" new file mode 100644 index 0000000..b4823eb --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/index.html" @@ -0,0 +1,305 @@ + + + + Code coverage report for All files + + + + + + + +
+
+

+ All files +

+
+
+ 80.6% + Statements + 507/629 +
+
+ 55.73% + Branches + 141/253 +
+
+ 82.81% + Functions + 159/192 +
+
+ 81.93% + Lines + 449/548 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src
100%3/3100%0/0100%0/0100%3/3
src/app
72.36%144/19941.12%44/10773.85%48/6575.3%125/166
src/app/Formatter
100%7/766.67%4/6100%1/1100%5/5
src/app/activity
100%3/3100%0/0100%2/2100%2/2
src/app/activitydetail
100%4/4100%0/0100%3/3100%3/3
src/app/callback
100%9/9100%2/2100%3/3100%8/8
src/app/dashboard
90.24%37/41100%5/594.12%16/1787.88%29/33
src/app/entity
0%0/00%0/00%0/00%0/0
src/app/info
96.77%30/3150%5/10100%12/1296.43%27/28
src/app/info-statistic
76.98%97/12656.25%27/4864.29%18/2880.17%93/116
src/app/info/buy-info
93.55%29/3190.91%10/11100%7/792.86%26/28
src/app/info/sell-info
93.33%28/3090.91%10/11100%7/792.59%25/27
src/app/infodetail
82.61%38/4668.75%11/16100%13/1383.33%35/42
src/app/login
100%8/8100%0/080%4/5100%6/6
src/app/user
78.26%18/2375%9/12100%8/875%15/20
src/app/userdetail
68.63%35/5157.89%11/1975%12/1670.83%34/48
src/app/website
100%17/1750%3/6100%5/5100%13/13
+
+
+ +
+ + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/lcov.info" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/lcov.info" new file mode 100644 index 0000000..07fbecb --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/lcov.info" @@ -0,0 +1,1446 @@ +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\polyfills.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\test.ts +FNF:0 +FNH:0 +DA:13,1 +DA:18,1 +DA:20,1 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\app-routing.module.ts +FNF:0 +FNH:0 +DA:16,1 +DA:35,1 +LF:2 +LH:2 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\app.component.ts +FN:14,(anonymous_0) +FN:15,(anonymous_1) +FNF:2 +FNH:2 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +DA:11,1 +DA:12,1 +DA:13,1 +DA:14,1 +DA:16,1 +DA:17,1 +DA:19,1 +LF:7 +LH:7 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\auth.service.ts +FN:14,(anonymous_0) +FN:17,(anonymous_1) +FN:27,(anonymous_2) +FNF:3 +FNH:3 +FNDA:13,(anonymous_0) +FNDA:11,(anonymous_1) +FNDA:13,(anonymous_2) +DA:13,1 +DA:14,13 +DA:19,11 +DA:20,11 +DA:21,11 +DA:22,11 +DA:23,11 +DA:28,13 +LF:8 +LH:8 +BRDA:21,0,0,11 +BRDA:21,0,1,0 +BRF:2 +BRH:1 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\file.service.ts +FN:17,(anonymous_0) +FN:19,(anonymous_1) +FN:32,(anonymous_2) +FN:33,(anonymous_3) +FNF:4 +FNH:4 +FNDA:2,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:1,(anonymous_3) +DA:7,1 +DA:14,1 +DA:16,2 +DA:17,2 +DA:20,1 +DA:21,1 +DA:33,1 +DA:35,1 +DA:37,1 +LF:9 +LH:9 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\info.service.ts +FN:20,(anonymous_0) +FN:24,(anonymous_1) +FN:25,(anonymous_2) +FN:25,(anonymous_3) +FN:27,(anonymous_4) +FN:30,(anonymous_5) +FN:31,(anonymous_6) +FN:31,(anonymous_7) +FN:33,(anonymous_8) +FN:36,(anonymous_9) +FN:45,(anonymous_10) +FN:48,(anonymous_11) +FN:57,(anonymous_12) +FN:60,(anonymous_13) +FN:70,(anonymous_14) +FN:72,(anonymous_15) +FN:81,(anonymous_16) +FN:84,(anonymous_17) +FN:94,(anonymous_18) +FN:96,(anonymous_19) +FN:105,(anonymous_20) +FN:113,(anonymous_21) +FN:130,(anonymous_22) +FN:137,(anonymous_23) +FN:152,(anonymous_24) +FN:160,(anonymous_25) +FN:172,(anonymous_26) +FN:173,(anonymous_27) +FNF:28 +FNH:16 +FNDA:9,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:2,(anonymous_8) +FNDA:2,(anonymous_9) +FNDA:2,(anonymous_10) +FNDA:2,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:0,(anonymous_18) +FNDA:0,(anonymous_19) +FNDA:1,(anonymous_20) +FNDA:8,(anonymous_21) +FNDA:1,(anonymous_22) +FNDA:8,(anonymous_23) +FNDA:1,(anonymous_24) +FNDA:1,(anonymous_25) +FNDA:20,(anonymous_26) +FNDA:20,(anonymous_27) +DA:9,1 +DA:16,1 +DA:18,9 +DA:19,9 +DA:20,9 +DA:21,9 +DA:22,9 +DA:25,1 +DA:28,1 +DA:31,1 +DA:34,2 +DA:36,2 +DA:38,2 +DA:39,0 +DA:42,2 +DA:46,2 +DA:48,2 +DA:50,2 +DA:51,0 +DA:54,2 +DA:58,0 +DA:59,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:66,0 +DA:70,0 +DA:71,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:90,0 +DA:94,0 +DA:95,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:106,1 +DA:107,1 +DA:114,8 +DA:115,8 +DA:117,8 +DA:118,8 +DA:119,8 +DA:120,8 +DA:122,8 +DA:131,1 +DA:139,8 +DA:140,8 +DA:141,8 +DA:142,8 +DA:143,8 +DA:144,8 +DA:145,8 +DA:153,1 +DA:154,1 +DA:161,1 +DA:173,20 +DA:175,20 +DA:177,20 +LF:67 +LH:41 +BRDA:34,0,0,2 +BRDA:34,0,1,0 +BRDA:46,1,0,2 +BRDA:46,1,1,0 +BRDA:58,2,0,0 +BRDA:58,2,1,0 +BRDA:58,3,0,0 +BRDA:58,3,1,0 +BRDA:61,4,0,0 +BRDA:61,4,1,0 +BRDA:61,5,0,0 +BRDA:61,5,1,0 +BRDA:63,6,0,0 +BRDA:63,6,1,0 +BRDA:73,7,0,0 +BRDA:73,7,1,0 +BRDA:73,8,0,0 +BRDA:73,8,1,0 +BRDA:82,9,0,0 +BRDA:82,9,1,0 +BRDA:82,10,0,0 +BRDA:82,10,1,0 +BRDA:85,11,0,0 +BRDA:85,11,1,0 +BRDA:85,12,0,0 +BRDA:85,12,1,0 +BRDA:87,13,0,0 +BRDA:87,13,1,0 +BRDA:97,14,0,0 +BRDA:97,14,1,0 +BRDA:97,15,0,0 +BRDA:97,15,1,0 +BRDA:113,16,0,6 +BRDA:113,17,0,8 +BRDA:113,18,0,8 +BRDA:113,19,0,2 +BRDA:113,20,0,2 +BRDA:115,21,0,2 +BRDA:115,21,1,6 +BRDA:115,22,0,8 +BRDA:115,22,1,2 +BRDA:117,23,0,0 +BRDA:117,23,1,8 +BRDA:118,24,0,0 +BRDA:118,24,1,8 +BRDA:118,25,0,8 +BRDA:118,25,1,0 +BRDA:119,26,0,6 +BRDA:119,26,1,2 +BRDA:120,27,0,0 +BRDA:120,27,1,8 +BRDA:137,28,0,6 +BRDA:137,29,0,8 +BRDA:137,30,0,8 +BRDA:137,31,0,2 +BRDA:137,32,0,2 +BRDA:140,33,0,2 +BRDA:140,33,1,6 +BRDA:140,34,0,8 +BRDA:140,34,1,2 +BRDA:141,35,0,0 +BRDA:141,35,1,8 +BRDA:142,36,0,0 +BRDA:142,36,1,8 +BRDA:142,37,0,8 +BRDA:142,37,1,0 +BRDA:143,38,0,6 +BRDA:143,38,1,2 +BRDA:144,39,0,0 +BRDA:144,39,1,8 +BRF:70 +BRH:32 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\inmemory-data.service.ts +FN:9,(anonymous_0) +FNF:1 +FNH:1 +FNDA:12,(anonymous_0) +DA:8,1 +DA:10,12 +DA:11,12 +DA:16,12 +LF:4 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\transaction.service.ts +FN:14,(anonymous_0) +FN:16,(anonymous_1) +FN:19,(anonymous_2) +FN:28,(anonymous_3) +FN:31,(anonymous_4) +FN:41,(anonymous_5) +FN:43,(anonymous_6) +FN:53,(anonymous_7) +FN:78,(anonymous_8) +FN:79,(anonymous_9) +FNF:10 +FNH:6 +FNDA:2,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:1,(anonymous_7) +FNDA:1,(anonymous_8) +FNDA:1,(anonymous_9) +DA:10,1 +DA:12,2 +DA:13,2 +DA:14,2 +DA:17,1 +DA:19,1 +DA:21,1 +DA:22,0 +DA:25,1 +DA:29,0 +DA:30,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:41,0 +DA:42,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,1 +DA:61,1 +DA:62,1 +DA:63,1 +DA:64,1 +DA:65,1 +DA:79,1 +DA:81,1 +DA:83,1 +LF:33 +LH:20 +BRDA:17,0,0,1 +BRDA:17,0,1,0 +BRDA:29,1,0,0 +BRDA:29,1,1,0 +BRDA:29,2,0,0 +BRDA:29,2,1,0 +BRDA:32,3,0,0 +BRDA:32,3,1,0 +BRDA:34,4,0,0 +BRDA:34,4,1,0 +BRDA:44,5,0,0 +BRDA:44,5,1,0 +BRDA:53,6,0,0 +BRDA:53,7,0,0 +BRDA:53,8,0,0 +BRDA:54,9,0,0 +BRDA:54,10,0,0 +BRDA:54,11,0,1 +BRDA:54,12,0,1 +BRDA:58,13,0,0 +BRDA:58,13,1,1 +BRDA:58,14,0,1 +BRDA:58,14,1,0 +BRDA:59,15,0,1 +BRDA:59,15,1,0 +BRDA:60,16,0,0 +BRDA:60,16,1,1 +BRDA:61,17,0,0 +BRDA:61,17,1,1 +BRDA:62,18,0,1 +BRDA:62,18,1,0 +BRDA:63,19,0,1 +BRDA:63,19,1,0 +BRDA:64,20,0,0 +BRDA:64,20,1,1 +BRF:35 +BRH:11 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\user.service.ts +FN:15,(anonymous_0) +FN:18,(anonymous_1) +FN:26,(anonymous_2) +FN:34,(anonymous_3) +FN:42,(anonymous_4) +FN:51,(anonymous_5) +FN:63,(anonymous_6) +FN:64,(anonymous_7) +FNF:8 +FNH:7 +FNDA:4,(anonymous_0) +FNDA:3,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:2,(anonymous_4) +FNDA:2,(anonymous_5) +FNDA:8,(anonymous_6) +FNDA:7,(anonymous_7) +DA:6,1 +DA:11,1 +DA:13,4 +DA:15,4 +DA:19,3 +DA:20,3 +DA:27,0 +DA:28,0 +DA:35,1 +DA:36,1 +DA:43,2 +DA:44,2 +DA:52,2 +DA:64,8 +DA:67,7 +DA:70,7 +LF:16 +LH:14 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\website.service.ts +FN:17,(anonymous_0) +FN:20,(anonymous_1) +FN:28,(anonymous_2) +FN:36,(anonymous_3) +FN:43,(anonymous_4) +FN:50,(anonymous_5) +FN:57,(anonymous_6) +FN:69,(anonymous_7) +FN:70,(anonymous_8) +FNF:9 +FNH:9 +FNDA:3,(anonymous_0) +FNDA:2,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:4,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +FNDA:1,(anonymous_6) +FNDA:10,(anonymous_7) +FNDA:1,(anonymous_8) +DA:6,1 +DA:13,1 +DA:15,3 +DA:16,3 +DA:17,3 +DA:21,2 +DA:22,2 +DA:29,1 +DA:30,1 +DA:37,4 +DA:38,4 +DA:44,1 +DA:45,1 +DA:51,1 +DA:52,1 +DA:58,1 +DA:59,1 +DA:70,10 +DA:72,1 +DA:74,1 +LF:20 +LH:20 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\Formatter\format.ts +FN:2,Format +FNF:1 +FNH:1 +FNDA:4,Format +DA:3,4 +DA:12,4 +DA:13,4 +DA:14,28 +DA:15,4 +LF:5 +LH:5 +BRDA:12,0,0,4 +BRDA:12,0,1,0 +BRDA:14,1,0,20 +BRDA:14,1,1,8 +BRDA:14,2,0,0 +BRDA:14,2,1,20 +BRF:6 +BRH:4 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\activity\activity.component.ts +FN:10,(anonymous_0) +FN:12,(anonymous_1) +FNF:2 +FNH:2 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +DA:8,1 +DA:13,1 +LF:2 +LH:2 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\activitydetail\activitydetail.component.ts +FN:80,(anonymous_0) +FN:60,(anonymous_1) +FN:82,(anonymous_2) +FNF:3 +FNH:3 +FNDA:1,(anonymous_0) +FNDA:17,(anonymous_1) +FNDA:1,(anonymous_2) +DA:8,1 +DA:9,1 +DA:61,17 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\callback\callback.component.ts +FN:11,(anonymous_0) +FN:16,(anonymous_1) +FN:21,(anonymous_2) +FNF:3 +FNH:3 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:2,(anonymous_2) +DA:10,1 +DA:12,1 +DA:13,1 +DA:17,1 +DA:18,1 +DA:22,2 +DA:25,2 +DA:26,1 +LF:8 +LH:8 +BRDA:25,0,0,1 +BRDA:25,0,1,1 +BRF:2 +BRH:2 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\dashboard\dashboard.component.ts +FN:16,(anonymous_0) +FN:26,(anonymous_1) +FN:28,(anonymous_2) +FN:36,(anonymous_3) +FN:37,(anonymous_4) +FN:44,(anonymous_5) +FN:45,(anonymous_6) +FN:45,(anonymous_7) +FN:47,(anonymous_8) +FN:50,(anonymous_9) +FN:52,(anonymous_10) +FN:54,(anonymous_11) +FN:56,(anonymous_12) +FN:66,(anonymous_13) +FN:67,(anonymous_14) +FN:70,(anonymous_15) +FN:73,(anonymous_16) +FNF:17 +FNH:16 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:4,(anonymous_5) +FNDA:4,(anonymous_6) +FNDA:15,(anonymous_7) +FNDA:1,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:2,(anonymous_10) +FNDA:1,(anonymous_11) +FNDA:3,(anonymous_12) +FNDA:1,(anonymous_13) +FNDA:2,(anonymous_14) +FNDA:1,(anonymous_15) +FNDA:1,(anonymous_16) +DA:15,1 +DA:17,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:37,1 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:45,15 +DA:48,1 +DA:49,1 +DA:50,1 +DA:51,1 +DA:52,2 +DA:53,1 +DA:54,1 +DA:57,3 +DA:59,1 +DA:61,1 +DA:63,1 +DA:67,1 +DA:68,2 +DA:69,1 +DA:70,1 +DA:72,1 +DA:73,1 +LF:33 +LH:29 +BRDA:58,0,0,1 +BRDA:58,0,1,1 +BRDA:58,0,2,1 +BRDA:68,1,0,1 +BRDA:68,1,1,1 +BRF:5 +BRH:5 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\entity\info.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\entity\transaction.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\entity\user.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\info\info.component.ts +FN:24,(anonymous_0) +FN:26,(anonymous_1) +FN:30,(anonymous_2) +FN:31,(anonymous_3) +FN:33,(anonymous_4) +FN:42,(anonymous_5) +FN:52,(anonymous_6) +FNF:7 +FNH:7 +FNDA:2,(anonymous_0) +FNDA:2,(anonymous_1) +FNDA:2,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:3,(anonymous_4) +FNDA:2,(anonymous_5) +FNDA:1,(anonymous_6) +DA:14,1 +DA:15,2 +DA:16,2 +DA:21,1 +DA:23,1 +DA:24,2 +DA:27,2 +DA:31,2 +DA:34,3 +DA:35,3 +DA:36,3 +DA:38,3 +DA:39,3 +DA:43,2 +DA:45,2 +DA:48,0 +DA:50,2 +DA:53,1 +DA:54,1 +DA:55,1 +DA:56,1 +LF:21 +LH:20 +BRDA:35,0,0,3 +BRDA:35,0,1,0 +BRDA:38,1,0,3 +BRDA:38,1,1,0 +BRDA:43,2,0,2 +BRDA:43,2,1,0 +BRDA:53,3,0,1 +BRDA:53,3,1,0 +BRDA:55,4,0,1 +BRDA:55,4,1,0 +BRF:10 +BRH:5 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\info\infocom.service.ts +FN:10,(anonymous_0) +FN:11,(anonymous_1) +FN:14,(anonymous_2) +FN:17,(anonymous_3) +FN:22,(anonymous_4) +FNF:5 +FNH:5 +FNDA:5,(anonymous_0) +FNDA:4,(anonymous_1) +FNDA:6,(anonymous_2) +FNDA:3,(anonymous_3) +FNDA:12,(anonymous_4) +DA:5,1 +DA:12,4 +DA:15,6 +DA:18,3 +DA:19,3 +DA:20,3 +DA:23,12 +LF:7 +LH:7 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\info-statistic\info-statistic.component.ts +FN:14,fdgFormatter +FN:36,(anonymous_1) +FN:37,(anonymous_2) +FN:48,(anonymous_3) +FN:52,(anonymous_4) +FN:58,(anonymous_5) +FN:62,(anonymous_6) +FN:64,(anonymous_7) +FN:66,(anonymous_8) +FN:68,(anonymous_9) +FN:73,(anonymous_10) +FN:140,(anonymous_11) +FN:160,(anonymous_12) +FN:183,(anonymous_13) +FN:197,(anonymous_14) +FN:208,(anonymous_15) +FN:210,(anonymous_16) +FN:274,(anonymous_17) +FN:283,(anonymous_18) +FN:295,(anonymous_19) +FN:299,(anonymous_20) +FN:399,(anonymous_21) +FN:402,(anonymous_22) +FN:406,(anonymous_23) +FN:408,(anonymous_24) +FN:417,(anonymous_25) +FN:482,(anonymous_26) +FN:489,(anonymous_27) +FNF:28 +FNH:18 +FNDA:2,fdgFormatter +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:1,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:1,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:1,(anonymous_12) +FNDA:27,(anonymous_13) +FNDA:27,(anonymous_14) +FNDA:2,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:0,(anonymous_18) +FNDA:3,(anonymous_19) +FNDA:9,(anonymous_20) +FNDA:1,(anonymous_21) +FNDA:1,(anonymous_22) +FNDA:2,(anonymous_23) +FNDA:0,(anonymous_24) +FNDA:0,(anonymous_25) +FNDA:1,(anonymous_26) +FNDA:1,(anonymous_27) +DA:11,1 +DA:16,2 +DA:17,1 +DA:18,1 +DA:19,1 +DA:26,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:35,1 +DA:36,1 +DA:38,1 +DA:39,1 +DA:40,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:44,1 +DA:45,1 +DA:49,1 +DA:53,1 +DA:54,1 +DA:55,1 +DA:56,1 +DA:58,1 +DA:59,0 +DA:63,1 +DA:64,1 +DA:65,1 +DA:66,1 +DA:67,1 +DA:68,1 +DA:69,0 +DA:74,1 +DA:81,1 +DA:141,0 +DA:161,1 +DA:185,27 +DA:197,27 +DA:209,2 +DA:210,2 +DA:211,0 +DA:212,0 +DA:213,0 +DA:214,0 +DA:216,0 +DA:218,2 +DA:219,2 +DA:220,0 +DA:222,2 +DA:275,0 +DA:284,0 +DA:296,3 +DA:297,3 +DA:298,3 +DA:299,3 +DA:300,9 +DA:301,9 +DA:302,3 +DA:303,3 +DA:304,2 +DA:305,1 +DA:306,1 +DA:308,1 +DA:309,1 +DA:312,6 +DA:313,5 +DA:314,5 +DA:315,3 +DA:316,2 +DA:317,1 +DA:319,2 +DA:320,2 +DA:324,3 +DA:325,3 +DA:326,3 +DA:327,3 +DA:328,3 +DA:329,3 +DA:330,5 +DA:335,5 +DA:336,5 +DA:337,2 +DA:339,3 +DA:341,3 +DA:342,1 +DA:344,2 +DA:346,3 +DA:347,5 +DA:350,3 +DA:400,1 +DA:403,1 +DA:404,1 +DA:407,2 +DA:408,2 +DA:409,0 +DA:410,0 +DA:411,0 +DA:412,0 +DA:414,0 +DA:416,2 +DA:417,2 +DA:418,0 +DA:419,0 +DA:420,0 +DA:421,0 +DA:423,0 +DA:425,2 +DA:426,2 +DA:427,0 +DA:430,2 +DA:431,2 +DA:432,0 +DA:434,2 +DA:482,1 +DA:489,1 +LF:116 +LH:93 +BRDA:16,0,0,1 +BRDA:16,0,1,1 +BRDA:18,1,0,1 +BRDA:18,1,1,0 +BRDA:54,2,0,1 +BRDA:54,2,1,0 +BRDA:67,3,0,1 +BRDA:67,3,1,0 +BRDA:211,4,0,0 +BRDA:211,4,1,0 +BRDA:213,5,0,0 +BRDA:213,5,1,0 +BRDA:300,6,0,0 +BRDA:300,6,1,9 +BRDA:301,7,0,3 +BRDA:301,7,1,6 +BRDA:301,8,0,9 +BRDA:301,8,1,9 +BRDA:303,9,0,2 +BRDA:303,9,1,1 +BRDA:304,10,0,1 +BRDA:304,10,1,1 +BRDA:312,11,0,5 +BRDA:312,11,1,1 +BRDA:312,12,0,6 +BRDA:312,12,1,6 +BRDA:314,13,0,3 +BRDA:314,13,1,2 +BRDA:315,14,0,2 +BRDA:315,14,1,1 +BRDA:336,15,0,2 +BRDA:336,15,1,3 +BRDA:341,16,0,1 +BRDA:341,16,1,2 +BRDA:403,17,0,1 +BRDA:403,17,1,0 +BRDA:409,18,0,0 +BRDA:409,18,1,0 +BRDA:409,19,0,0 +BRDA:409,19,1,0 +BRDA:411,20,0,0 +BRDA:411,20,1,0 +BRDA:418,21,0,0 +BRDA:418,21,1,0 +BRDA:418,22,0,0 +BRDA:418,22,1,0 +BRDA:420,23,0,0 +BRDA:420,23,1,0 +BRF:48 +BRH:27 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\info\buy-info\buy-info.component.ts +FN:24,(anonymous_0) +FN:26,(anonymous_1) +FN:31,(anonymous_2) +FN:46,(anonymous_3) +FN:51,(anonymous_4) +FN:58,(anonymous_5) +FN:64,(anonymous_6) +FNF:7 +FNH:7 +FNDA:4,(anonymous_0) +FNDA:3,(anonymous_1) +FNDA:5,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:2,(anonymous_4) +FNDA:6,(anonymous_5) +FNDA:6,(anonymous_6) +DA:13,1 +DA:14,4 +DA:16,4 +DA:17,4 +DA:18,4 +DA:20,4 +DA:24,4 +DA:27,3 +DA:28,3 +DA:32,5 +DA:34,1 +DA:36,1 +DA:38,1 +DA:40,1 +DA:42,1 +DA:47,1 +DA:48,1 +DA:52,2 +DA:53,1 +DA:55,1 +DA:59,6 +DA:60,6 +DA:61,6 +DA:62,6 +DA:63,6 +DA:65,6 +DA:66,0 +DA:67,0 +LF:28 +LH:26 +BRDA:33,0,0,1 +BRDA:33,0,1,1 +BRDA:33,0,2,1 +BRDA:33,0,3,1 +BRDA:33,0,4,1 +BRDA:52,1,0,1 +BRDA:52,1,1,1 +BRDA:52,2,0,2 +BRDA:52,2,1,1 +BRDA:65,3,0,6 +BRDA:65,3,1,0 +BRF:11 +BRH:10 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\info\sell-info\sell-info.component.ts +FN:25,(anonymous_0) +FN:27,(anonymous_1) +FN:32,(anonymous_2) +FN:46,(anonymous_3) +FN:52,(anonymous_4) +FN:59,(anonymous_5) +FN:64,(anonymous_6) +FNF:7 +FNH:7 +FNDA:4,(anonymous_0) +FNDA:3,(anonymous_1) +FNDA:5,(anonymous_2) +FNDA:6,(anonymous_3) +FNDA:6,(anonymous_4) +FNDA:1,(anonymous_5) +FNDA:2,(anonymous_6) +DA:14,1 +DA:15,4 +DA:18,4 +DA:19,4 +DA:21,4 +DA:25,4 +DA:28,3 +DA:29,3 +DA:33,5 +DA:35,1 +DA:37,1 +DA:39,1 +DA:41,1 +DA:43,1 +DA:47,6 +DA:48,6 +DA:49,6 +DA:50,6 +DA:51,6 +DA:53,6 +DA:54,0 +DA:55,0 +DA:60,1 +DA:61,1 +DA:65,2 +DA:66,1 +DA:68,1 +LF:27 +LH:25 +BRDA:34,0,0,1 +BRDA:34,0,1,1 +BRDA:34,0,2,1 +BRDA:34,0,3,1 +BRDA:34,0,4,1 +BRDA:53,1,0,6 +BRDA:53,1,1,0 +BRDA:65,2,0,1 +BRDA:65,2,1,1 +BRDA:65,3,0,2 +BRDA:65,3,1,1 +BRF:11 +BRH:10 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\infodetail\infodetail.component.ts +FN:28,(anonymous_0) +FN:34,(anonymous_1) +FN:39,(anonymous_2) +FN:44,(anonymous_3) +FN:46,(anonymous_4) +FN:52,(anonymous_5) +FN:55,(anonymous_6) +FN:59,(anonymous_7) +FN:67,(anonymous_8) +FN:75,(anonymous_9) +FN:80,(anonymous_10) +FN:83,(anonymous_11) +FN:86,(anonymous_12) +FNF:13 +FNH:13 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:3,(anonymous_5) +FNDA:3,(anonymous_6) +FNDA:1,(anonymous_7) +FNDA:1,(anonymous_8) +FNDA:2,(anonymous_9) +FNDA:1,(anonymous_10) +FNDA:1,(anonymous_11) +FNDA:1,(anonymous_12) +DA:15,1 +DA:17,1 +DA:20,1 +DA:22,1 +DA:23,1 +DA:26,1 +DA:27,1 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,1 +DA:35,1 +DA:36,1 +DA:40,1 +DA:41,1 +DA:42,1 +DA:45,1 +DA:47,1 +DA:48,0 +DA:53,3 +DA:56,3 +DA:57,3 +DA:58,1 +DA:60,1 +DA:61,0 +DA:62,0 +DA:63,0 +DA:65,2 +DA:66,1 +DA:68,1 +DA:69,0 +DA:70,0 +DA:71,0 +DA:76,2 +DA:77,2 +DA:78,2 +DA:79,1 +DA:80,1 +DA:81,1 +DA:82,1 +DA:83,1 +DA:87,1 +LF:42 +LH:35 +BRDA:47,0,0,0 +BRDA:47,0,1,1 +BRDA:57,1,0,1 +BRDA:57,1,1,2 +BRDA:60,2,0,1 +BRDA:60,2,1,0 +BRDA:65,3,0,1 +BRDA:65,3,1,1 +BRDA:68,4,0,1 +BRDA:68,4,1,0 +BRDA:76,5,0,0 +BRDA:76,5,1,2 +BRDA:78,6,0,1 +BRDA:78,6,1,1 +BRDA:81,7,0,1 +BRDA:81,7,1,0 +BRF:16 +BRH:11 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\login\login.component.ts +FN:17,(anonymous_0) +FN:21,(anonymous_1) +FN:25,(anonymous_2) +FN:26,(anonymous_3) +FN:31,(anonymous_4) +FNF:5 +FNH:4 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:1,(anonymous_4) +DA:14,1 +DA:17,1 +DA:18,1 +DA:26,1 +DA:32,1 +DA:33,1 +LF:6 +LH:6 +BRF:0 +BRH:0 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\user\user.component.ts +FN:19,(anonymous_0) +FN:21,(anonymous_1) +FN:25,(anonymous_2) +FN:32,(anonymous_3) +FN:39,(anonymous_4) +FN:45,(anonymous_5) +FN:47,(anonymous_6) +FN:54,(anonymous_7) +FNF:8 +FNH:8 +FNDA:3,(anonymous_0) +FNDA:2,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:3,(anonymous_5) +FNDA:2,(anonymous_6) +FNDA:1,(anonymous_7) +DA:12,1 +DA:15,3 +DA:17,3 +DA:19,3 +DA:22,2 +DA:26,3 +DA:27,1 +DA:29,1 +DA:31,2 +DA:33,2 +DA:34,0 +DA:35,0 +DA:40,1 +DA:41,0 +DA:43,1 +DA:46,3 +DA:48,2 +DA:49,0 +DA:50,0 +DA:55,1 +LF:20 +LH:15 +BRDA:26,0,0,1 +BRDA:26,0,1,2 +BRDA:26,1,0,3 +BRDA:26,1,1,2 +BRDA:33,2,0,2 +BRDA:33,2,1,0 +BRDA:40,3,0,0 +BRDA:40,3,1,1 +BRDA:40,4,0,1 +BRDA:40,4,1,1 +BRDA:48,5,0,2 +BRDA:48,5,1,0 +BRF:12 +BRH:9 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\userdetail\userdetail.component.ts +FN:11,fFormatter +FN:25,(anonymous_1) +FN:31,(anonymous_2) +FN:36,(anonymous_3) +FN:39,(anonymous_4) +FN:45,(anonymous_5) +FN:48,(anonymous_6) +FN:51,(anonymous_7) +FN:54,(anonymous_8) +FN:59,(anonymous_9) +FN:62,(anonymous_10) +FN:73,(anonymous_11) +FN:77,(anonymous_12) +FN:80,(anonymous_13) +FN:99,(anonymous_14) +FN:103,(anonymous_15) +FNF:16 +FNH:12 +FNDA:1,fFormatter +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:2,(anonymous_4) +FNDA:3,(anonymous_5) +FNDA:1,(anonymous_6) +FNDA:1,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:2,(anonymous_11) +FNDA:2,(anonymous_12) +FNDA:5,(anonymous_13) +FNDA:1,(anonymous_14) +FNDA:0,(anonymous_15) +DA:10,1 +DA:12,1 +DA:19,1 +DA:21,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:32,1 +DA:33,1 +DA:37,1 +DA:40,2 +DA:41,1 +DA:42,1 +DA:43,1 +DA:46,3 +DA:49,1 +DA:50,1 +DA:51,1 +DA:52,1 +DA:53,0 +DA:54,0 +DA:55,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:64,0 +DA:74,2 +DA:75,2 +DA:76,2 +DA:77,2 +DA:81,5 +DA:83,1 +DA:85,1 +DA:87,1 +DA:89,1 +DA:91,1 +DA:101,1 +DA:102,1 +DA:103,1 +DA:104,0 +DA:105,0 +DA:107,0 +DA:108,0 +DA:110,0 +DA:112,1 +LF:48 +LH:34 +BRDA:40,0,0,1 +BRDA:40,0,1,1 +BRDA:42,1,0,1 +BRDA:42,1,1,0 +BRDA:55,2,0,0 +BRDA:55,2,1,0 +BRDA:60,3,0,0 +BRDA:60,3,1,0 +BRDA:74,4,0,0 +BRDA:74,4,1,2 +BRDA:75,5,0,1 +BRDA:75,5,1,1 +BRDA:82,6,0,1 +BRDA:82,6,1,1 +BRDA:82,6,2,1 +BRDA:82,6,3,1 +BRDA:82,6,4,1 +BRDA:107,7,0,0 +BRDA:107,7,1,0 +BRF:19 +BRH:11 +end_of_record +TN: +SF:D:\SJTU-jiaojiao\admin-frontend\src\app\website\website.component.ts +FN:39,(anonymous_0) +FN:21,(anonymous_1) +FN:29,(anonymous_2) +FN:30,(anonymous_3) +FN:44,(anonymous_4) +FNF:5 +FNH:5 +FNDA:1,(anonymous_0) +FNDA:1,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:1,(anonymous_4) +DA:18,1 +DA:22,1 +DA:24,3 +DA:25,3 +DA:30,1 +DA:31,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:35,1 +DA:40,1 +DA:41,1 +DA:45,1 +LF:13 +LH:13 +BRDA:32,0,0,0 +BRDA:32,0,1,1 +BRDA:33,1,0,0 +BRDA:33,1,1,1 +BRDA:34,2,0,0 +BRDA:34,2,1,1 +BRF:6 +BRH:3 +end_of_record diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/prettify.css" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/prettify.css" new file mode 100644 index 0000000..b317a7c --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/prettify.css" @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/prettify.js" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/prettify.js" new file mode 100644 index 0000000..b322523 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/prettify.js" @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/sort-arrow-sprite.png" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/sort-arrow-sprite.png" new file mode 100644 index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jii$m5978H@?Fn+^JD|Y9yzj{W`447Gxa{7*dM7nnnD-Lb z6^}Hx2)'; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/Formatter/format.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/Formatter/format.ts.html" new file mode 100644 index 0000000..c94819c --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/Formatter/format.ts.html" @@ -0,0 +1,114 @@ + + + + Code coverage report for src/app/Formatter/format.ts + + + + + + + +
+
+

+ All files / src/app/Formatter format.ts +

+
+
+ 100% + Statements + 7/7 +
+
+ 66.67% + Branches + 4/6 +
+
+ 100% + Functions + 1/1 +
+
+ 100% + Lines + 5/5 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16  +  +4x +  +  +  +  +  +  +  +  +4x +4x +28x +4x + 
 
+export function Format (date, fmt) { //author: meizz 
+    var o = {
+        "M+": date.getMonth() + 1, //月份 
+        "d+": date.getDate(), //日 
+        "H+": date.getHours(), //小时 
+        "m+": date.getMinutes(), //分 
+        "s+": date.getSeconds(), //秒 
+        "q+": Math.floor((date.getMonth() + 3) / 3), //季度 
+        "S": date.getMilliseconds() //毫秒 
+    };
+    Eif (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+    for (var k in o)
+    if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
+    return fmt;
+  }
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/Formatter/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/Formatter/index.html" new file mode 100644 index 0000000..fe48638 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/Formatter/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/Formatter + + + + + + + +
+
+

+ All files src/app/Formatter +

+
+
+ 100% + Statements + 7/7 +
+
+ 66.67% + Branches + 4/6 +
+
+ 100% + Functions + 1/1 +
+
+ 100% + Lines + 5/5 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
format.ts
100%7/766.67%4/6100%1/1100%5/5
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activity/activity.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activity/activity.component.ts.html" new file mode 100644 index 0000000..93db8d2 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activity/activity.component.ts.html" @@ -0,0 +1,126 @@ + + + + Code coverage report for src/app/activity/activity.component.ts + + + + + + + +
+
+

+ All files / src/app/activity activity.component.ts +

+
+
+ 100% + Statements + 3/3 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 2/2 +
+
+ 100% + Lines + 2/2 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20  +  +  +  +  +  +  +1x +  +  +  +  +1x +  +  +  +  +  +  + 
import { Component, OnInit } from '@angular/core';
+ 
+@Component({
+  selector: 'app-activity',
+  templateUrl: './activity.component.html',
+  styleUrls: ['./activity.component.css']
+})
+export class ActivityComponent implements OnInit {
+  activitys: any;
+  constructor() { }
+ 
+  ngOnInit() {
+    this.activitys = [ {id: 4396, intro: '高星信用尊享图标', state: '正在进行'},
+    {id: 396, intro: '毕业季', state: '正在进行'},
+    {id: 96, intro: '垃圾分类新时尚', state: '已结束'},
+    {id: 6, intro: '我们需要你输入的tag!',  state: '未开始'}];
+  }
+ 
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activity/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activity/index.html" new file mode 100644 index 0000000..5d659a6 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activity/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/activity + + + + + + + +
+
+

+ All files src/app/activity +

+
+
+ 100% + Statements + 3/3 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 2/2 +
+
+ 100% + Lines + 2/2 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
activity.component.ts
100%3/3100%0/0100%2/2100%2/2
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activitydetail/activitydetail.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activitydetail/activitydetail.component.ts.html" new file mode 100644 index 0000000..9543d94 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activitydetail/activitydetail.component.ts.html" @@ -0,0 +1,324 @@ + + + + Code coverage report for src/app/activitydetail/activitydetail.component.ts + + + + + + + +
+
+

+ All files / src/app/activitydetail activitydetail.component.ts +

+
+
+ 100% + Statements + 4/4 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 3/3 +
+
+ 100% + Lines + 3/3 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +17x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Component, OnInit } from '@angular/core';
+ 
+@Component({
+  selector: 'app-activitydetail',
+  templateUrl: './activitydetail.component.html',
+  styleUrls: ['./activitydetail.component.css']
+})
+export class ActivitydetailComponent implements OnInit {
+  tsoption = {
+    backgroundColor: '#01193d',
+    title: {
+        text: 'Transaction Calendar'
+    },
+    tooltip : {
+        trigger: 'item'
+    },
+    grid: {
+      containLabel: true,
+    },
+    calendar: [{
+        left: 80,
+        range: ['2019'],
+        splitLine: {
+            show: true,
+            lineStyle: {
+                color: '#000',
+                width: 2,
+                type: 'solid'
+            }
+        },
+        width: '80%',
+        height: '80%',
+        dayLabel: {
+          textStyle: {
+              color: '#fff'
+          }
+        },
+        monthLabel: {
+          textStyle: {
+              color: '#fff'
+          }
+        },
+        yearLabel: {
+            formatter: '{start}',
+            textStyle: {
+                color: '#fff'
+            }
+        },
+        itemStyle: {
+            normal: {
+                color: '#323c48',
+                borderWidth: 1,
+                borderColor: '#111'
+            }
+        }
+    }],
+        series: [{
+          type: 'effectScatter',
+          coordinateSystem: 'calendar',
+          symbolSize: (val) => {
+              return val[1] / 40;
+          },
+          showEffectOn: 'render',
+          rippleEffect: {
+              brushType: 'stroke'
+          },
+          hoverAnimation: true,
+          itemStyle: {
+                  color: '#f4e925',
+                  shadowBlur: 10,
+                  shadowColor: '#333'
+          },
+            data: [['2019-01-02', 900], ['2019-01-03', 877], ['2019-01-04', 699], ['2019-01-07', 200], ['2019-01-10', 100],
+            ['2019-01-10', 430], ['2019-02-01', 250], ['2019-02-10', 430],
+            ['2019-03-10', 430], ['2019-04-01', 250], ['2019-05-10', 430],
+            ['2019-08-11', 430], ['2019-07-04', 250], ['2019-03-11', 430],
+            ['2019-09-23', 430], ['2019-06-01', 250], ['2019-12-12', 430]]
+        }]
+      };
+  constructor() { }
+ 
+  ngOnInit() {
+  }
+ 
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activitydetail/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activitydetail/index.html" new file mode 100644 index 0000000..3eeabf4 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/activitydetail/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/activitydetail + + + + + + + +
+
+

+ All files src/app/activitydetail +

+
+
+ 100% + Statements + 4/4 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 3/3 +
+
+ 100% + Lines + 3/3 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
activitydetail.component.ts
100%4/4100%0/0100%3/3100%3/3
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/app-routing.module.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/app-routing.module.ts.html" new file mode 100644 index 0000000..0af03d1 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/app-routing.module.ts.html" @@ -0,0 +1,174 @@ + + + + Code coverage report for src/app/app-routing.module.ts + + + + + + + +
+
+

+ All files / src/app app-routing.module.ts +

+
+
+ 100% + Statements + 3/3 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 0/0 +
+
+ 100% + Lines + 2/2 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x + 
import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { DashboardComponent } from './dashboard/dashboard.component';
+import { UserDetailComponent } from './userdetail/userdetail.component';
+import { UserComponent } from './user/user.component';
+import { LoginComponent } from './login/login.component';
+import { InfoComponent } from './info/info.component';
+import { InfoDetailComponent } from './infodetail/infodetail.component';
+import { WebsiteComponent } from './website/website.component';
+import { ActivityComponent } from './activity/activity.component';
+import { InfoStatisticComponent } from './info-statistic/info-statistic.component';
+import { ActivitydetailComponent } from './activitydetail/activitydetail.component';
+import { CallbackComponent } from './callback/callback.component';
+import { JWTGuard } from '@delon/auth';
+ 
+const routes: Routes = [
+  { path: 'dashboard', component: DashboardComponent,canActivate: [JWTGuard] },
+  { path: '', redirectTo: '/dashboard', pathMatch: 'full',canActivate: [JWTGuard] },
+  { path: 'user/:id', component: UserDetailComponent ,canActivate: [JWTGuard]},
+  { path: 'user', component: UserComponent,canActivate: [JWTGuard]},
+  { path: 'login', component: LoginComponent},
+  { path: 'info', component:  InfoComponent,canActivate: [JWTGuard]},
+  { path: 'info/:type/:id', component:  InfoDetailComponent,canActivate: [JWTGuard]},
+  { path: 'activity/:id', component:  ActivitydetailComponent,canActivate: [JWTGuard]},
+  { path: 'statistic', component:  InfoStatisticComponent,canActivate: [JWTGuard]},
+  { path: 'website', component:  WebsiteComponent,canActivate: [JWTGuard]},
+  { path: 'activity', component:  ActivityComponent,canActivate: [JWTGuard]},
+  { path: 'callback/:token',component:  CallbackComponent }
+];
+ 
+@NgModule({
+  imports: [RouterModule.forRoot(routes)],
+  exports: [RouterModule]
+})
+export class AppRoutingModule { }
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/app.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/app.component.ts.html" new file mode 100644 index 0000000..39ef5e3 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/app.component.ts.html" @@ -0,0 +1,132 @@ + + + + Code coverage report for src/app/app.component.ts + + + + + + + +
+
+

+ All files / src/app app.component.ts +

+
+
+ 100% + Statements + 10/10 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 2/2 +
+
+ 100% + Lines + 7/7 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +1x +1x +  +1x +  +  + 
import { Component } from '@angular/core';
+import { AuthService } from './auth.service';
+import { NzNotificationService } from 'ng-zorro-antd';
+import { Router } from '@angular/router';
+ 
+@Component({
+  selector: 'app-root',
+  templateUrl: './app.component.html',
+  styleUrls: ['./app.component.css'],
+})
+export class AppComponent {
+  title = 'JOJO-Admin';
+  isCollapsed = false;
+  constructor( private router: Router, public authService: AuthService, private notification: NzNotificationService){}
+  logout(): void{
+    this.authService.logout();
+    this.notification.create('success', '注销成功', '退出登录');
+    // Redirect the user
+    this.router.navigateByUrl('/login');
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/auth.service.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/auth.service.ts.html" new file mode 100644 index 0000000..39becb1 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/auth.service.ts.html" @@ -0,0 +1,159 @@ + + + + Code coverage report for src/app/auth.service.ts + + + + + + + +
+
+

+ All files / src/app auth.service.ts +

+
+
+ 100% + Statements + 10/10 +
+
+ 50% + Branches + 1/2 +
+
+ 100% + Functions + 3/3 +
+
+ 100% + Lines + 8/8 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31  +  +  +  +  +  +  +  +  +  +  +  +1x +13x +  +  +  +  +11x +11x +11x +11x +11x +  +  +  +  +13x +  +  + 
import { Injectable, Inject } from '@angular/core';
+ 
+import { Observable, of } from 'rxjs';
+import { tap, delay } from 'rxjs/operators';
+import { DA_SERVICE_TOKEN, ITokenService, JWTTokenModel, ITokenModel } from '@delon/auth';
+import { HttpClient } from '@angular/common/http';
+ 
+ 
+@Injectable({
+  providedIn: 'root',
+})
+ 
+export class AuthService {
+  constructor(private http: HttpClient, @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) {
+  }
+ 
+  login(res): void {
+    //JWTTokenModely
+    this.tokenService.set(res);
+    const jwt :JWTTokenModel =  this.tokenService.get<JWTTokenModel>(JWTTokenModel);
+    Eif(jwt.payload.role !== 10) {
+      this.logout();
+    console.log('error! not admin');
+  }
+  }
+ 
+  logout(): void {
+    this.tokenService.clear();
+  }
+ 
+}
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/callback/callback.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/callback/callback.component.ts.html" new file mode 100644 index 0000000..bfa4c45 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/callback/callback.component.ts.html" @@ -0,0 +1,150 @@ + + + + Code coverage report for src/app/callback/callback.component.ts + + + + + + + +
+
+

+ All files / src/app/callback callback.component.ts +

+
+
+ 100% + Statements + 9/9 +
+
+ 100% + Branches + 2/2 +
+
+ 100% + Functions + 3/3 +
+
+ 100% + Lines + 8/8 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28  +  +  +  +  +  +  +  +  +1x +  +1x +1x +  +  +  +1x +1x +  +  +  +2x +  +  +2x +1x +  + 
import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { SocialService, JWTTokenModel } from '@delon/auth';
+@Component({
+  selector: 'app-callback',
+  template: ``,
+  providers: [SocialService],
+})
+ 
+export class CallbackComponent implements OnInit {
+  constructor(
+    private socialService: SocialService,
+    private route: ActivatedRoute,
+  ) {}
+ 
+  ngOnInit(): void {
+    const token = this.route.snapshot.paramMap.get('token');
+    this.mockModel(token);
+  }
+ 
+  mockModel(token) {
+    const info: any = {
+      token: token
+    };
+    if(typeof(token)==='string')
+    this.socialService.callback(info);
+  }
+}
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/callback/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/callback/index.html" new file mode 100644 index 0000000..7c7da5f --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/callback/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/callback + + + + + + + +
+
+

+ All files src/app/callback +

+
+
+ 100% + Statements + 9/9 +
+
+ 100% + Branches + 2/2 +
+
+ 100% + Functions + 3/3 +
+
+ 100% + Lines + 8/8 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
callback.component.ts
100%9/9100%2/2100%3/3100%8/8
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/dashboard/dashboard.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/dashboard/dashboard.component.ts.html" new file mode 100644 index 0000000..0d63ec9 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/dashboard/dashboard.component.ts.html" @@ -0,0 +1,300 @@ + + + + Code coverage report for src/app/dashboard/dashboard.component.ts + + + + + + + +
+
+

+ All files / src/app/dashboard dashboard.component.ts +

+
+
+ 90.24% + Statements + 37/41 +
+
+ 100% + Branches + 5/5 +
+
+ 94.12% + Functions + 16/17 +
+
+ 87.88% + Lines + 29/33 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +1x +1x +1x +1x +  +  +1x +  +  +  +  +  +  +  +15x +  +  +1x +1x +1x +1x +2x +1x +1x +  +  +3x +  +1x +  +1x +  +1x +  +  +  +1x +2x +1x +1x +  +1x +1x +  +  +  +  + 
import { Component, OnInit } from '@angular/core';
+import { WebsiteService } from './../website.service';
+import { UserService } from './../user.service';
+import { InfoService } from '../info.service';
+import { sellInfo } from './../entity/info';
+import { getCurrencySymbol } from '@angular/common';
+import { trigger, transition, style, state, animate } from '@angular/animations';
+import { Route } from '@angular/compiler/src/core';
+ 
+@Component({
+  selector: 'app-dashboard',
+  templateUrl: './dashboard.component.html',
+  styleUrls: ['./dashboard.component.css']
+})
+export class DashboardComponent implements OnInit {
+  constructor( 
+    private ifService: InfoService, private wbService: WebsiteService,private usService: UserService) { }
+ 
+  site : any;
+  hst: any[];
+  
+  rsInfoNum: number;
+  infoNum: number;
+  acInfoNum: number;
+  
+  ngOnInit() {
+    this.getHistory();
+    this.wbService.getSite().subscribe(s => this.site= s);
+    this.ifService.getAllBuyInfo();
+    this.ifService.getAllSellInfo();
+    this.infoNum = this.ifService.getInfoNum()
+    this.acInfoNum = this.ifService.getAcInfo();
+    this.rsInfoNum = this.ifService.getReserveInfoNum();
+    this.getInfo();
+  }
+  getInfo(){
+    setTimeout(() => {
+      this.infoNum = this.ifService.getInfoNum()
+      this.acInfoNum = this.ifService.getAcInfo();
+      this.rsInfoNum = this.ifService.getReserveInfoNum();
+      this.getInfo();
+    },10000);
+  }
+  getHistory(){
+    this.wbService.getSiteHistory().subscribe( s =>this.hst =s.sort((a,b)=> a.time-b.time));
+  }
+  add() {
+    const newitem = {id: '',time:'2019-01-01',description:'init' };
+    const tmp = this.hst;
+    newitem.id = tmp.sort((a,b)=> b.id-a.id)[0].id +1;
+    this.hst.push(newitem);
+    this.hst =this.hst.sort((a,b)=> a.time-b.time)
+    this.wbService.addSiteHistory(newitem).subscribe(
+      _ => this.getHistory());
+  }          
+  getColor(item) {
+    switch(item.type){
+      case 1: 
+      return 'green';
+      case -1:
+        return 'red';
+      default:
+          return 'blue';
+    }
+  }
+  save() {
+    this.hst.forEach( e => {
+      if(e.description.trim())
+        this.wbService.updateSiteHistory(e).subscribe(
+          _ => this.getHistory());
+      else 
+        this.wbService.deleteSiteHistory(e).subscribe(
+          _ => this.getHistory()
+        );
+    });
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/dashboard/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/dashboard/index.html" new file mode 100644 index 0000000..8742c2b --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/dashboard/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/dashboard + + + + + + + +
+
+

+ All files src/app/dashboard +

+
+
+ 90.24% + Statements + 37/41 +
+
+ 100% + Branches + 5/5 +
+
+ 94.12% + Functions + 16/17 +
+
+ 87.88% + Lines + 29/33 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
dashboard.component.ts
90.24%37/41100%5/594.12%16/1787.88%29/33
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/index.html" new file mode 100644 index 0000000..5748ee7 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/index.html" @@ -0,0 +1,123 @@ + + + + Code coverage report for src/app/entity + + + + + + + +
+
+

+ All files src/app/entity +

+
+
+ 0% + Statements + 0/0 +
+
+ 0% + Branches + 0/0 +
+
+ 0% + Functions + 0/0 +
+
+ 0% + Lines + 0/0 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
info.ts
0%0/00%0/00%0/00%0/0
transaction.ts
0%0/00%0/00%0/00%0/0
user.ts
0%0/00%0/00%0/00%0/0
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/info.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/info.ts.html" new file mode 100644 index 0000000..abd3299 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/info.ts.html" @@ -0,0 +1,156 @@ + + + + Code coverage report for src/app/entity/info.ts + + + + + + + +
+
+

+ All files / src/app/entity info.ts +

+
+
+ 0% + Statements + 0/0 +
+
+ 0% + Branches + 0/0 +
+
+ 0% + Functions + 0/0 +
+
+ 0% + Lines + 0/0 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
export class sellInfo{
+    public sellInfoID : number;
+    public status : number;
+    public releaseTime: number;
+    public validTime: number;
+    public goodName: string;
+    public price: number;
+    public description: string;
+    public contentID: string;
+    public userID: number;
+    public tag: string [];
+}
+ 
+export class buyInfo{
+    public buyInfoID : number;
+    public status : number;
+    public releaseTime: number;
+    public validTime: number;
+    public goodName: string;
+    public price: number;
+    public description: string;
+    public contentID: string;
+    public userID: number;
+    public tag: string [];
+}
+ 
+export class InfoResponse{
+    public sellInfo: sellInfo[];
+    public buyInfo: buyInfo[];
+}
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/transaction.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/transaction.ts.html" new file mode 100644 index 0000000..90a15e4 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/transaction.ts.html" @@ -0,0 +1,93 @@ + + + + Code coverage report for src/app/entity/transaction.ts + + + + + + + +
+
+

+ All files / src/app/entity transaction.ts +

+
+
+ 0% + Statements + 0/0 +
+
+ 0% + Branches + 0/0 +
+
+ 0% + Functions + 0/0 +
+
+ 0% + Lines + 0/0 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9  +  +  +  +  +  +  +  + 
export class Transaction{
+    public transactionID:number;
+    public infoID: number;
+    public category:number;
+    public fromUserID: number;
+    public toUserID: number;
+    public createTime: number;  
+    public status: number;	
+}
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/user.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/user.ts.html" new file mode 100644 index 0000000..266316d --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/entity/user.ts.html" @@ -0,0 +1,114 @@ + + + + Code coverage report for src/app/entity/user.ts + + + + + + + +
+
+

+ All files / src/app/entity user.ts +

+
+
+ 0% + Statements + 0/0 +
+
+ 0% + Branches + 0/0 +
+
+ 0% + Functions + 0/0 +
+
+ 0% + Lines + 0/0 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
export class User
+{
+   userID: number;
+   userName: string;
+   avatarID: string;
+   telephone: string;
+   studentID: string;
+   studentName: string;
+   status: number;
+   role: number;
+}
+ 
+export class UserResponse
+{
+   user: User[];
+}
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/file.service.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/file.service.ts.html" new file mode 100644 index 0000000..447a8c9 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/file.service.ts.html" @@ -0,0 +1,189 @@ + + + + Code coverage report for src/app/file.service.ts + + + + + + + +
+
+

+ All files / src/app file.service.ts +

+
+
+ 100% + Statements + 10/10 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 4/4 +
+
+ 100% + Lines + 9/9 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +2x +2x +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +1x +  +  +  + 
import { Injectable } from '@angular/core';
+import { HttpHeaders, HttpClient } from '@angular/common/http';
+import { ContentResponse } from './entity/content';
+import { Observable, of } from 'rxjs';
+import { catchError } from 'rxjs/operators';
+ 
+const httpOptions = {
+  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
+};
+@Injectable({
+  providedIn: 'root'
+})
+ 
+export class FileService {
+ 
+  private contentUrl = 'api/content';  // URL to web api
+  constructor(private http: HttpClient) { }
+  /** GET info by id. Will 404 if id not found */
+  getContent(id: string): Observable<ContentResponse> {
+    const url = `${this.contentUrl}/${id}`;
+    return this.http.get<ContentResponse>(url).pipe(
+      catchError(this.handleError<ContentResponse>(`getContent id=${id}`))
+    );
+  }
+  
+  /**
+   * Handle Http operation that failed.
+   * Let the app continue.
+   * @param operation - name of the operation that failed
+   * @param result - optional value to return as the observable result
+   */
+  private handleError<T>(operation, result?: T) {
+    return (error: any): Observable<T> => {
+      // TODO: send the error to remote logging infrastructure
+      console.error(error); // log to console instead
+      // Let the app keep running by returning an empty result.
+      return of(result as T);
+    };
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/index.html" new file mode 100644 index 0000000..d4b90dd --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/index.html" @@ -0,0 +1,201 @@ + + + + Code coverage report for src/app + + + + + + + +
+
+

+ All files src/app +

+
+
+ 72.36% + Statements + 144/199 +
+
+ 41.12% + Branches + 44/107 +
+
+ 73.85% + Functions + 48/65 +
+
+ 75.3% + Lines + 125/166 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
app-routing.module.ts
100%3/3100%0/0100%0/0100%2/2
app.component.ts
100%10/10100%0/0100%2/2100%7/7
auth.service.ts
100%10/1050%1/2100%3/3100%8/8
file.service.ts
100%10/10100%0/0100%4/4100%9/9
info.service.ts
56.1%46/8245.71%32/7057.14%16/2861.19%41/67
inmemory-data.service.ts
100%5/5100%0/0100%1/1100%4/4
transaction.service.ts
58.54%24/4131.43%11/3560%6/1060.61%20/33
user.service.ts
88.24%15/17100%0/087.5%7/887.5%14/16
website.service.ts
100%21/21100%0/0100%9/9100%20/20
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info-statistic/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info-statistic/index.html" new file mode 100644 index 0000000..d2e4b80 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info-statistic/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/info-statistic + + + + + + + +
+
+

+ All files src/app/info-statistic +

+
+
+ 76.98% + Statements + 97/126 +
+
+ 56.25% + Branches + 27/48 +
+
+ 64.29% + Functions + 18/28 +
+
+ 80.17% + Lines + 93/116 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
info-statistic.component.ts
76.98%97/12656.25%27/4864.29%18/2880.17%93/116
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info-statistic/info-statistic.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info-statistic/info-statistic.component.ts.html" new file mode 100644 index 0000000..8056752 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info-statistic/info-statistic.component.ts.html" @@ -0,0 +1,1716 @@ + + + + Code coverage report for src/app/info-statistic/info-statistic.component.ts + + + + + + + +
+
+

+ All files / src/app/info-statistic info-statistic.component.ts +

+
+
+ 76.98% + Statements + 97/126 +
+
+ 56.25% + Branches + 27/48 +
+
+ 64.29% + Functions + 18/28 +
+
+ 80.17% + Lines + 93/116 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +2x +1x +1x +1x +  +  +  +  +  +  +1x +  +  +  +  +  +1x +1x +1x +1x +1x +  +1x +1x +1x +1x +1x +1x +1x +1x +  +  +  +1x +  +  +  +1x +1x +1x +1x +  +1x +  +  +  +  +1x +1x +1x +1x +1x +1x +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +27x +  +  +  +  +  +  +  +  +  +  +  +27x +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +2x +2x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +3x +9x +9x +3x +3x +2x +1x +1x +  +1x +1x +  +  +6x +5x +5x +3x +2x +1x +  +2x +2x +  +  +  +3x +3x +3x +3x +3x +3x +5x +  +  +  +  +5x +5x +2x +  +3x +  +3x +1x +  +2x +  +3x +5x +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +1x +1x +  +  +2x +2x +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +2x +2x +  +  +  +2x +2x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Component, OnInit } from '@angular/core';
+import { EChartOption} from 'echarts';
+import * as echarts from 'echarts/lib/echarts';
+import { InfoService } from '../info.service';
+import { buyInfo, sellInfo } from 'src/app/entity/info';
+import {prepareBoxplotData} from 'echarts/extension/dataTool';
+import { Transaction } from '../entity/transaction';
+import { TransactionService } from '../transaction.service';
+import { Format } from '../Formatter/format';
+import { Router } from '@angular/router';
+const name = ['LJH', 'WXZ', 'ZWJ', 'KHQ', 'MZD', 'ZEL', 'JZM', 'HJT', 'TRUMP',
+'LJH2', 'WXZ2', 'ZWJ2', 'KHQ2', 'MZD2', 'ZEL2', 'JZM2', 'HJT2', 'TRUMP2',
+'LJH3', 'WXZ3', 'ZWJ3', 'KHQ3', 'MZD3', 'ZEL3', 'JZM3', 'HJT3', 'TRUMP3'];
+export function fdgFormatter 
+    (p) {
+        if(p.dataType=='node')
+        return p.data.name + ' has completed '+ p.data.value + ' transaction';
+        Eif(p.dataType=='edge')
+        return p.data.source + ' has selled '+ p.data.value + ' goods to '+ p.data.target;
+    }
+@Component({
+  selector: 'app-info-statistic',
+  templateUrl: './info-statistic.component.html',
+  styleUrls: ['./info-statistic.component.css']
+})
+export class InfoStatisticComponent implements OnInit {
+  fdgoption: EChartOption;
+  cldoption: any;
+  tsoption: any;
+  lqoption: any;
+  goodoption: any;
+  bi: buyInfo[]=[];
+  si: sellInfo[]=[];
+  tr: Transaction[]=[];
+  pl: boolean = false;
+  constructor(private router: Router, private trs: TransactionService, private is: InfoService) { }
+  ngOnInit() {
+    const now = new Date().getFullYear();
+    this.getAllInfo();
+    this.getAllTR(new Date(now,1,1).getTime()/1000, new Date(now+1,1,1).getTime()/1000);
+    this.cloudGrpah();
+    this.forceGraph();
+    this.calenderGraph();
+    this.lineGraph();
+    this.boxGraph();    
+                
+  }
+  pauseLine(){
+      this.pl=!this.pl;
+  }
+ 
+  getAllTR(beg, end){
+    this.tr = this.trs.getAllTR(6,beg,end);
+    Eif(!this.pl){
+        this.calenderGraph();
+       this.forceGraph();
+    }
+    setTimeout(() => {
+        this.getAllTR(beg,end);
+    }, 10000);
+  }
+  getAllInfo(){
+    this.bi = this.is.getAllBuyInfo();
+    this.bi = this.bi.sort( (a,b) => a.releaseTime - b.releaseTime);
+    this.si = this.is.getAllSellInfo();
+    this.si = this.si.sort( (a,b) => a.releaseTime - b.releaseTime);
+    Eif(!this.pl)this.lineGraph();
+      setTimeout(() => {
+          this.getAllInfo();
+      }, 10000);
+  }
+ 
+  boxGraph() {
+    var data = prepareBoxplotData([
+    [850, 740, 900, 1070, 930, 850, 950, 980, 980, 880, 1000, 980, 930, 650, 760, 810, 1000, 1000, 960, 960],
+    [960, 940, 960, 940, 880, 800, 850, 880, 900, 840, 830, 790, 810, 880, 880, 830, 800, 790, 760, 800],
+    [880, 880, 880, 860, 720, 720, 620, 860, 970, 950, 880, 910, 850, 870, 840, 840, 850, 840, 840, 840],
+    [890, 810, 810, 820, 800, 770, 760, 740, 750, 760, 910, 920, 890, 860, 880, 720, 840, 850, 850, 780],
+    [890, 840, 780, 810, 760, 810, 790, 810, 820, 850, 870, 870, 810, 740, 810, 940, 950, 800, 810, 870]
+]);
+this.goodoption = {
+    backgroundColor: '#01193d',
+    title: [
+        {
+            text: '交易价格分布',
+            left: 'center',
+        }
+    ],
+    tooltip: {
+        trigger: 'item',
+        axisPointer: {
+            type: 'shadow'
+        }
+    },
+    dataZoom: [
+        {
+            show: true,
+            realtime: true,
+            start: 0,
+            end: 40
+        },
+        {
+            type: 'inside',
+            realtime: true,
+            start: 0,
+            end: 40
+        }
+    ],
+    grid: {
+        left: '10%',
+        right: '10%',
+        bottom: '15%'
+    },
+    xAxis: {
+        type: 'category',
+        data: data.axisData,
+        boundaryGap: true,
+        nameGap: 30,
+        axisLine: {onZero: false},
+        splitArea: {
+            show: false
+        },
+        axisLabel: {
+            formatter: 'tag {value}'
+        },
+        splitLine: {
+            show: false
+        },
+    },
+    yAxis: {
+        type: 'value',
+        name: 'yuan'
+    },
+    series: [
+        {
+            name: 'boxplot',
+            type: 'boxplot',
+            data: data.boxData,
+            tooltip: {
+                formatter: function (param) {
+                    return [
+                        'tag ' + param.name + ': ',
+                        'upper: ' + param.data[5],
+                        'Q3: ' + param.data[4],
+                        'median: ' + param.data[3],
+                        'Q1: ' + param.data[2],
+                        'lower: ' + param.data[1]
+                    ].join('<br/>');
+                }
+            }
+        },
+        {
+            name: 'outlier',
+            type: 'scatter',
+            data: data.outliers
+        }
+    ]
+};
+  }
+  cloudGrpah() {
+    this.cldoption = {
+    backgroundColor: '#01193d',
+      title: {
+      text: '标签热度',
+      left: 'center',
+  },
+  tooltip: {},
+  series: [{
+      type: 'wordCloud',
+      shape: 'circle',
+ 
+      left: 'center',
+      top: 'center',
+      sizeRange: [12, 30],
+      rotationRange: [-90, 90],
+      rotationStep: 45,
+      gridSize: 8,
+      drawOutOfBound: false,
+      textStyle: {
+          normal: {
+              fontFamily: 'sans-serif',
+              fontWeight: 'bold',
+              color: () => {
+                  // Random color
+                  return 'rgb(' + [
+                      Math.round(Math.random() * 250),
+                      Math.round(Math.random() * 250),
+                      Math.round(Math.random() * 250)
+                  ].join(',') + ')';
+              }
+          },
+          emphasis: {
+              shadowBlur: 10,
+              shadowColor: '#333'
+          }
+      },
+      data: name.map( node => {return { name: node,
+      value: Math.round(Math.random() * 1000),
+      textStyle: {
+          normal: {},
+          emphasis: {}
+      }
+  }; }
+  )
+  }]
+};
+  }
+  calenderGraph() {
+    let td =new Map();
+    this.tr.forEach( e => {
+        if(!e)return;
+       const str = Format(new Date(e.createTime*1000),'yyyy-MM-dd');
+       if(str in td)
+        td[str]+=1;
+        else 
+        td[str]=1;
+    });
+    let tdata = [];
+    for(let i in td){
+        tdata.push([i,td[i]]);
+    }
+    this.tsoption = {
+      backgroundColor: '#01193d',
+      title: {
+          text: '活跃度日历',
+          left: 'center'
+      },
+      tooltip : {
+          trigger: 'item'
+      },
+      grid: {
+        containLabel: true,
+      },
+      calendar: [{
+          left: 80,
+          range: ['2019'],
+          splitLine: {
+              show: true,
+              lineStyle: {
+                  color: '#000',
+                  width: 2,
+                  type: 'solid'
+              }
+          },
+          width: '80%',
+          height: '80%',
+          dayLabel: {
+            textStyle: {
+                color: '#fff'
+            }
+          },
+          monthLabel: {
+            textStyle: {
+                color: '#fff'
+            }
+          },
+          yearLabel: {
+              formatter: '{start}',
+              textStyle: {
+                  color: '#fff'
+              }
+          },
+          itemStyle: {
+              normal: {
+                  color: '#323c48',
+                  borderWidth: 1,
+                  borderColor: '#111'
+              }
+          }
+      }],
+          series: [{
+            type: 'effectScatter',
+            coordinateSystem: 'calendar',
+            symbolSize: (val) => {
+                return val[1];
+            },
+            showEffectOn: 'render',
+            rippleEffect: {
+                brushType: 'stroke'
+            },
+            hoverAnimation: true,
+            tooltip: {
+                formatter:(param)=>
+                param.data[1] + ' completed transactions created in ' +param.data[0]
+            },
+            itemStyle: {
+                    color: '#f4e925',
+                    shadowBlur: 10,
+                    shadowColor: '#333'
+            },
+              data: tdata
+          }]
+        };
+  }
+  forceGraph() {
+    let td =new Map();
+    let join = [];
+    console.log(this.tr);
+    this.tr.forEach( e => {
+        Iif(!e)return;
+        if(e&&e.category==2){
+            const other = e.toUserID;
+            if(e.fromUserID in td)
+                if(other in td[e.fromUserID])
+                    td[e.fromUserID][other] +=1;
+                else td[e.fromUserID][other] =1;
+            else {
+                td[e.fromUserID] = new Map();
+                td[e.fromUserID][other] = 1;
+            }
+        }
+        else if(e&& e.category==1){
+        const other = e.toUserID;
+        if(other in td)
+            if(e.fromUserID in td[other])
+                td[other][e.fromUserID] +=1;
+            else td[other][e.fromUserID] =1;
+        else {
+            td[other] = new Map();
+            td[other][e.fromUserID] = 1;
+        }
+    }
+});
+const VMAP= {};
+const E = [];
+const V = [];
+for( let i in td){
+    let sum = 0;
+    for( let j in td[i]){
+        E.push( 
+            {source: i, target: j
+            , value: td[i][j], lineStyle: {
+              width: td[i][j]
+            }});
+        sum += td[i][j];
+        if(j in VMAP)
+        VMAP[j]+=td[i][j];
+        else 
+        VMAP[j]= td[i][j];
+    }
+    if(i in VMAP)
+    VMAP[i]+=sum;
+    else 
+    VMAP[i]=sum;
+}
+for( let i in VMAP){
+    V.push({name: i,  value : VMAP[i], symbolSize: VMAP[i]*5,
+  draggable: true})
+}
+this.fdgoption = {
+backgroundColor: '#01193d',
+  title: {
+      text: '交易网络',
+      left: 'center',
+  },
+  tooltip: {
+      formatter: fdgFormatter
+  },
+  visualMap: {
+      type: 'continuous',
+      min: 1,
+      max: 10,
+      text:['Active','Lazy'],
+      realtime: false,
+      calculable : true,
+      color: ['orangered','yellow','lightskyblue']
+  },
+  animationDurationUpdate: 1500,
+  animationEasingUpdate: 'quinticInOut',
+  series : [
+      {
+          type: 'graph',
+          layout: 'force',
+          data: V, edges: E,
+    label: {
+      emphasis: {
+          position: 'right',
+          show: true
+      }
+  },
+  force: {
+    repulsion : 100
+  },
+  roam: true,
+  focusNodeAdjacency: true,
+  lineStyle: {
+      normal: {
+          color :'source',
+          type : 'solid',
+          width: 0.5,
+          curveness: 0.2,
+          opacity: 0.7
+      }
+  }
+}
+      ]
+  };
+  }
+  fmt(t: Date) {
+    return [t.getFullYear(), t.getMonth() + 1, t.getDate()].join('/');
+  }
+  clickForce(param){
+      Eif(param.dataType=='node')
+      this.router.navigateByUrl('/user/'+param.data.name);
+  }
+  lineGraph() {
+    let bd =new Map();
+    this.bi.forEach( e => {
+        if(!e||e.releaseTime<0)return;
+       const str = this.fmt(new Date(e.releaseTime*1000));
+       if(str in bd)
+        bd[str]+=1;
+        else 
+        bd[str]=1;
+    });
+    let sd =new Map();
+    this.si.forEach( e => {
+        if(!e||e.releaseTime<0)return;
+       const str = this.fmt(new Date(e.releaseTime*1000));
+       if(str in sd)
+        sd[str]+=1;
+        else 
+        sd[str]=1;
+    });
+    let bdata = [];
+    for(let i in bd){
+        bdata.push([i,bd[i]]);
+    }
+ 
+    let sdata = [];
+    for(let i in sd){
+        sdata.push([i,sd[i]]);
+    }
+    this.lqoption = {
+    backgroundColor: '#01193d',
+    title : {
+        text: '新增交易趋势',
+        x: 'center',
+        align: 'right'
+    },
+    grid: {
+        bottom: 80
+    },
+    tooltip : {
+        trigger: 'axis',
+        axisPointer: {
+            type: 'cross',
+            animation: false,
+            label: {
+                backgroundColor: '#505765'
+            }
+        }
+    },
+    legend: {
+        data: ['购买', '出售'],
+        x: 'left'
+    },
+    dataZoom: [
+        {
+            show: true,
+            realtime: true,
+            start: 0,
+            end: 100
+        },
+        {
+            type: 'inside',
+            realtime: true,
+            start: 0,
+            end: 100
+        }
+    ],
+    xAxis : [
+        {
+            type : 'time',
+            boundaryGap : false,
+            axisLine: {onZero: false},
+        }],
+    yAxis: [
+        {
+            name: '新增购买信息',
+            type: 'value',
+            max: (value) => value.max*3/2
+        },
+        {
+            name: '新增出售信息',
+            nameLocation: 'start',
+            type: 'value',
+            inverse: true,
+            max: (value) => value.max*3/2
+        }
+    ],
+    series: [
+        {
+            name: '购买',
+            yAxisIndex: 0,
+            type:'line',
+            smooth:true,
+            symbol: 'circle',
+            symbolSize: 1,
+            sampling: 'average',
+            itemStyle: {
+                normal: {
+                    color: '#d68262'
+                }
+            },
+            areaStyle: {
+                normal: {
+                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                        offset: 0,
+                        color: '#d68262'
+                    }, {
+                        offset: 1,
+                        color: '#ffe'
+                    }])
+                }
+            },
+            data: bdata
+        },
+        {
+            name: '出售',
+            type: 'line',
+            yAxisIndex: 1,
+            symbolSize: 5,
+            smooth: true,
+            symbol: 'circle',
+            sampling: 'average',
+            itemStyle: {
+                normal: {
+                    color: '#8ec6ad'
+                }
+            },
+            areaStyle: {
+                normal: {
+                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                        offset: 0,
+                        color: '#8ec6ad'
+                    }, {
+                        offset: 1,
+                        color: '#ffe'
+                    }])
+                }
+            },
+            data: sdata
+        }
+    ]
+};
+ 
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info.service.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info.service.ts.html" new file mode 100644 index 0000000..ac08f17 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info.service.ts.html" @@ -0,0 +1,612 @@ + + + + Code coverage report for src/app/info.service.ts + + + + + + + +
+
+

+ All files / src/app info.service.ts +

+
+
+ 56.1% + Statements + 46/82 +
+
+ 45.71% + Branches + 32/70 +
+
+ 57.14% + Functions + 16/28 +
+
+ 61.19% + Lines + 41/67 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +9x +9x +9x +9x +9x +  +  +1x +  +  +1x +  +  +1x +  +  +2x +  +2x +  +2x +  +  +  +2x +  +  +  +2x +  +2x +  +2x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +8x +8x +  +8x +8x +8x +8x +  +8x +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +8x +8x +8x +8x +8x +8x +8x +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +20x +  +20x +  +20x +  +  +  +  + 
import { Injectable } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+ 
+import { Observable, of } from 'rxjs';
+import { catchError, map, tap } from 'rxjs/operators';
+import { sellInfo, buyInfo, InfoResponse } from './entity/info';
+import { query } from '\@angular/animations';
+ 
+const httpOptions = {
+  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
+};
+ 
+@Injectable({
+  providedIn: 'root'
+})
+export class InfoService {
+ 
+  private sellinfoUrl = 'api/sellInfo';  // URL to web api
+  private buyinfoUrl = 'api/buyInfo';
+  constructor(private http: HttpClient) { }
+  bi: buyInfo[] = [];
+  si: sellInfo[] = [];
+ 
+  getAcInfo(){
+    return this.bi.filter( a => a.status<3).length+ this.si.filter(a =>a.status<3).length;
+  }
+  getInfoNum(){
+    return this.bi.length + this.si.length;
+  }
+  getReserveInfoNum(){
+    return this.bi.filter( a=> a.status ==2).length+ this.si.filter(a=> a.status ==2).length;
+  }
+  getAllSellInfo(): sellInfo[]{
+    Eif(this.si.length==0)
+    {
+      this.getSellInfos().subscribe(e=>
+        {
+        this.si = e.sellInfo;
+        this.getMoreSell(100,false);
+        })
+    }
+    return this.si;
+  }
+  
+  getAllBuyInfo(): buyInfo[]{
+    Eif(this.bi.length==0)
+    {
+      this.getBuyInfos().subscribe(e=>
+        {
+        this.bi = e.buyInfo;
+      this.getMoreBuy(100,false);
+        })
+    }
+    return this.bi;
+  }
+  
+  getMoreBuy(offset, dynamic){
+    if(!(this.bi.length%100) && !dynamic)
+      this.getBuyInfos(null,null,null,null,offset).subscribe(
+          e => {
+              if(e&&Object.keys(e).length!=0){
+              this.bi=this.bi.concat(e.buyInfo);
+              if(e.buyInfo.length!=100)
+              dynamic =! dynamic;
+            }
+              this.getMoreBuy(offset+100, dynamic);
+            }
+      );
+      else{
+          setTimeout(() => {
+              this.getBuyInfos(null,null,null,null,offset).subscribe(
+                  e => {
+                      if(e&&Object.keys(e).length!=0)
+                      this.bi=this.bi.concat(e.buyInfo);
+                      this.getMoreBuy(this.bi.length-1, true);
+          }
+      );}, 5000 );
+      }
+}
+ 
+getMoreSell(offset, dynamic){
+    if(!(this.si.length%100) && !dynamic)
+      this.getSellInfos(null,null,null,null,offset).subscribe(
+          e => {
+              if(e&&Object.keys(e).length!=0){
+              this.si= this.si.concat(e.sellInfo);   
+              if(e.sellInfo.length!=100)
+                dynamic=!dynamic;
+              }
+              this.getMoreSell(offset+100,dynamic)
+            }
+      );
+  else{
+      setTimeout(() => {
+          this.getSellInfos(null,null,null,null,offset).subscribe(
+              e => {
+                  if(e&&Object.keys(e).length!=0)
+                  this.si=this.si.concat(e.sellInfo);
+                  this.getMoreSell(this.si.length-1,true);
+      }
+  );}, 5000 );
+  }
+}
+  /** GET info by id. Will 404 if id not found */
+  getSellInfo(id: number): Observable<sellInfo> {
+    const url = `${this.sellinfoUrl}/${id}`;
+    return this.http.get<sellInfo>(url).pipe(
+      catchError(this.handleError<sellInfo>(`getInfo id=${id}`))
+    );
+  }
+ 
+  /** GET infos from the server */
+  getSellInfos(userID: string = null, status: number = null, goodName: string = null,limit:number=null, offset: number=null): Observable<InfoResponse> {    
+    let url = `${this.sellinfoUrl}?`;
+    if(userID && userID.trim()) url += `userID=${userID}&`;
+ 
+    Iif(status) url+= `status=${status}&`;
+    Iif(goodName && goodName.trim()) url+=`goodName=${goodName}&`;
+    if(limit) url+= `limit=${limit}&`;
+    Iif(offset) url+=`offset=${offset}&`;
+ 
+    return this.http.get<InfoResponse>(url)
+      .pipe(
+        catchError(this.handleError<InfoResponse>('getSellInfos'))
+      );
+ 
+    }
+ 
+  /** PUT: update the info on the server */
+  updateSellInfo(info: any): Observable<any> {
+    return this.http.put(this.sellinfoUrl, info, httpOptions).pipe(
+      catchError(this.handleError<any>('updateSellInfo'))
+    );
+  }
+ 
+  /** GET infos from the server */
+  getBuyInfos(userID: string = null, status: number = null, goodName: string = null,limit:number=null, offset: number=null):
+   Observable<InfoResponse> {    
+    let url = `${this.buyinfoUrl}?`;
+    if(userID && userID.trim()) url += `userID=${userID}&`;
+    Iif(status) url+= `status=${status}&`;
+    Iif(goodName && goodName.trim()) url+=`goodName=${goodName}&`;
+    if(limit) url+= `limit=${limit}&`;
+    Iif(offset) url+=`offset=${offset}&`;
+    return this.http.get<InfoResponse>(url)
+      .pipe(
+        catchError(this.handleError<InfoResponse>('getBuyInfos'))
+      );
+  }
+ 
+  /** GET info by id. Will 404 if id not found */
+  getBuyInfo(id: number): Observable<buyInfo> {
+    const url = `${this.buyinfoUrl}/${id}`;
+    return this.http.get<buyInfo>(url).pipe(
+      catchError(this.handleError<buyInfo>(`getBuy id=${id}`))
+    );
+  }
+ 
+  /** PUT: update the info on the server */
+  updateBuyInfo(info: any): Observable<any> {
+    return this.http.put(this.buyinfoUrl, info, httpOptions).pipe(
+      catchError(this.handleError<any>('updateBuyInfo'))
+    );
+  }
+ 
+  /**
+   * Handle Http operation that failed.
+   * Let the app continue.
+   * @param operation - name of the operation that failed
+   * @param result - optional value to return as the observable result
+   */
+  private handleError<T>(operation, result?: T) {
+    return (error: any): Observable<T> => {
+      // TODO: send the error to remote logging infrastructure
+      console.error(error); // log to console instead
+      // Let the app keep running by returning an empty result.
+      return of(result as T);
+    };
+  }
+ 
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/buy-info/buy-info.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/buy-info/buy-info.component.ts.html" new file mode 100644 index 0000000..964452d --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/buy-info/buy-info.component.ts.html" @@ -0,0 +1,282 @@ + + + + Code coverage report for src/app/info/buy-info/buy-info.component.ts + + + + + + + +
+
+

+ All files / src/app/info/buy-info buy-info.component.ts +

+
+
+ 93.55% + Statements + 29/31 +
+
+ 90.91% + Branches + 10/11 +
+
+ 100% + Functions + 7/7 +
+
+ 92.86% + Lines + 26/28 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72  +  +  +  +  +  +  +  +  +  +  +  +1x +4x +  +4x +4x +4x +  +4x +  +  +  +4x +  +  +3x +3x +  +  +  +5x +  +1x +  +1x +  +1x +  +1x +  +1x +  +  +  +  +1x +1x +  +  +  +2x +1x +  +1x +  +  +  +6x +6x +6x +6x +6x +  +6x +  +  +  +  +  +  + 
 
+import { Component, OnInit, ɵConsole } from '@angular/core';
+import { buyInfo } from '../../entity/info';
+import { InfoService } from '../../info.service';
+import { filter } from 'rxjs/operators';
+import { Format } from 'src/app/Formatter/format';
+import { InfoComService } from '../infocom.service';
+@Component({
+  selector: 'app-buy-info',
+  templateUrl: './buy-info.component.html',
+  styleUrls: ['./buy-info.component.css']
+})
+export class BuyInfoComponent implements OnInit {
+  tags = ['测试','数据'];
+  buyinfos: buyInfo[];
+  current : number = 1;
+  gridspan: number =12;
+  size :number = 4;
+  count : number;
+  searchTag: string[]=[];
+  searchUserID: string;
+  searchStatus: number;
+  searchGoodName: string;
+  constructor(private gs: InfoComService, private infoService: InfoService) { }
+ 
+  ngOnInit() {
+    this.getinfos();
+    this.gridspan=this.gs.get();
+  }
+ 
+  getstate(statecode: number): string {
+      switch (statecode){	
+        case 1:
+          return '待预约';
+        case 2: 
+          return '预约';
+        case 3:
+          return '完成';
+        case 4: 
+          return '失效';
+        case 5:
+          return '关闭';
+      }
+  }
+ 
+  stringToDate(params) {
+      const date = new Date(params*1000);
+      return Format(date,'yyyy-MM-dd HH:mm:ss');
+      }
+ 
+  checkcount(){
+    if(this.buyinfos && this.buyinfos.length === this.size)
+    this.count = (this.current + 1) * this.size;
+    else 
+    this.count = this.current * this.size;
+  }
+ 
+  getinfos(): void {
+    const st = this.gs.unstorage();
+    this.searchUserID=st.u;
+    this.searchGoodName =st.g;
+    this.searchStatus =st.s;
+    this.infoService.getBuyInfos(this.searchUserID,this.searchStatus, this.searchGoodName, this.size, this.current*this.size-this.size)
+    .subscribe(infos => {
+      Eif(!infos) return;
+      this.buyinfos = infos.buyInfo;
+      this.checkcount();
+    });
+  }
+ 
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/buy-info/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/buy-info/index.html" new file mode 100644 index 0000000..c7efc08 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/buy-info/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/info/buy-info + + + + + + + +
+
+

+ All files src/app/info/buy-info +

+
+
+ 93.55% + Statements + 29/31 +
+
+ 90.91% + Branches + 10/11 +
+
+ 100% + Functions + 7/7 +
+
+ 92.86% + Lines + 26/28 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
buy-info.component.ts
93.55%29/3190.91%10/11100%7/792.86%26/28
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/index.html" new file mode 100644 index 0000000..485f538 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/index.html" @@ -0,0 +1,110 @@ + + + + Code coverage report for src/app/info + + + + + + + +
+
+

+ All files src/app/info +

+
+
+ 96.77% + Statements + 30/31 +
+
+ 50% + Branches + 5/10 +
+
+ 100% + Functions + 12/12 +
+
+ 96.43% + Lines + 27/28 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
info.component.ts
95.65%22/2350%5/10100%7/795.24%20/21
infocom.service.ts
100%8/8100%0/0100%5/5100%7/7
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/info.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/info.component.ts.html" new file mode 100644 index 0000000..031b21c --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/info.component.ts.html" @@ -0,0 +1,243 @@ + + + + Code coverage report for src/app/info/info.component.ts + + + + + + + +
+
+

+ All files / src/app/info info.component.ts +

+
+
+ 95.65% + Statements + 22/23 +
+
+ 50% + Branches + 5/10 +
+
+ 100% + Functions + 7/7 +
+
+ 95.24% + Lines + 20/21 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59  +  +  +  +  +  +  +  +  +  +  +  +  +1x +2x +2x +  +  +  +  +1x +  +1x +2x +  +  +2x +  +  +  +2x +  +  +3x +3x +3x +  +3x +3x +  +  +  +2x +  +2x +  +  +  +  +2x +  +  +1x +1x +1x +1x +  +  + 
import { Component, OnInit, ɵConsole, ViewChild, AfterViewInit } from '@angular/core';
+import { sellInfo,buyInfo } from '../entity/info';
+import { InfoService } from '../info.service';
+import { filter } from 'rxjs/operators';
+import { SellInfoComponent } from './sell-info/sell-info.component';
+import { BuyInfoComponent } from './buy-info/buy-info.component';
+import { InfoComService } from './infocom.service';
+ 
+@Component({
+  selector: 'app-info',
+  templateUrl: './info.component.html',
+  styleUrls: ['./info.component.css'],
+})
+export class InfoComponent implements OnInit, AfterViewInit {
+  searchTag: string[]=[];
+  searchType: number=-1;
+  searchUserID: string;
+  searchStatus: number;
+  searchGoodName: string;
+  @ViewChild(SellInfoComponent, {static: false})
+  schild: SellInfoComponent;
+  @ViewChild(BuyInfoComponent, {static: false})
+  bchild: BuyInfoComponent;
+  constructor(private gs: InfoComService) { }
+ 
+  ngOnInit() {      
+    this.gs.set(12);   
+  }
+ 
+  ngAfterViewInit() {
+    setTimeout(()=> this.selectType(-1), 0);
+  }
+  search(){
+    this.gs.storage(this.searchUserID,this.searchStatus,this.searchGoodName);
+    Eif(this.searchType!==0){
+    this.bchild.getinfos();
+    }
+    Eif(this.searchType!==1){
+    this.schild.getinfos(); 
+    }
+  }
+  selectType(type: number){
+    Eif(type===-1)
+    {
+      this.gs.set(12);   
+  }
+    else{
+      this.gs.set(6);
+    }
+    this.search();
+  }
+  selectTag(tag: string[]){
+    Eif(this.searchType!==0)
+    this.bchild.searchTag =tag;
+    Eif(this.searchType!==1)
+    this.schild.searchTag =tag;
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/infocom.service.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/infocom.service.ts.html" new file mode 100644 index 0000000..67068e7 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/infocom.service.ts.html" @@ -0,0 +1,156 @@ + + + + Code coverage report for src/app/info/infocom.service.ts + + + + + + + +
+
+

+ All files / src/app/info infocom.service.ts +

+
+
+ 100% + Statements + 8/8 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 5/5 +
+
+ 100% + Lines + 7/7 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30  +  +  +  +1x +  +  +  +  +  +  +4x +  +  +6x +  +  +3x +3x +3x +  +  +12x +  +  +  +  +  +  + 
import { Injectable } from '@angular/core';
+@Injectable({
+  providedIn: 'root'
+})
+export class InfoComService {
+  gridspan:number;
+  searchUserID: string;
+  searchStatus: number;
+  searchGoodName: string;
+  constructor() { }
+  set(gs){
+    this.gridspan = gs;
+  }
+  get(){{
+    return this.gridspan;
+  }}
+  storage(u,s,g){
+    this.searchUserID=u;
+    this.searchGoodName=g;
+    this.searchStatus=s;
+  }
+  unstorage(){
+    return{
+      u: this.searchUserID,
+      s: this.searchStatus,
+      g: this.searchGoodName
+    }
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/sell-info/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/sell-info/index.html" new file mode 100644 index 0000000..7640417 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/sell-info/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/info/sell-info + + + + + + + +
+
+

+ All files src/app/info/sell-info +

+
+
+ 93.33% + Statements + 28/30 +
+
+ 90.91% + Branches + 10/11 +
+
+ 100% + Functions + 7/7 +
+
+ 92.59% + Lines + 25/27 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
sell-info.component.ts
93.33%28/3090.91%10/11100%7/792.59%25/27
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/sell-info/sell-info.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/sell-info/sell-info.component.ts.html" new file mode 100644 index 0000000..70ad63b --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/info/sell-info/sell-info.component.ts.html" @@ -0,0 +1,279 @@ + + + + Code coverage report for src/app/info/sell-info/sell-info.component.ts + + + + + + + +
+
+

+ All files / src/app/info/sell-info sell-info.component.ts +

+
+
+ 93.33% + Statements + 28/30 +
+
+ 90.91% + Branches + 10/11 +
+
+ 100% + Functions + 7/7 +
+
+ 92.59% + Lines + 25/27 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71  +  +  +  +  +  +  +  +  +  +  +  +  +1x +4x +  +  +4x +4x +  +4x +  +  +  +4x +  +  +3x +3x +  +  +  +5x +  +1x +  +1x +  +1x +  +1x +  +1x +  +  +  +6x +6x +6x +6x +6x +  +6x +  +  +  +  +  +  +1x +1x +  +  +  +2x +1x +  +1x +  +  + 
 
+import { Component, OnInit, ɵConsole } from '@angular/core';
+import { sellInfo,buyInfo } from '../../entity/info';
+import { InfoService } from '../../info.service';
+import { filter } from 'rxjs/operators';
+import { Format } from 'src/app/Formatter/format';
+import { InfoComService } from '../infocom.service';
+ 
+@Component({
+  selector: 'app-sell-info',
+  templateUrl: './sell-info.component.html',
+  styleUrls: ['./sell-info.component.css']
+})
+export class SellInfoComponent implements OnInit {
+  tags = ['测试','数据'];
+  sellinfos: sellInfo[];
+  gridspan: number;
+  current : number = 1;
+  size : number = 4;
+  count : number;
+  searchTag: string[]=[];
+  searchUserID: string;
+  searchStatus: number;
+  searchGoodName: string;
+  constructor(private gs: InfoComService, private infoService: InfoService) { }
+ 
+  ngOnInit() {
+    this.getinfos();
+    this.gridspan = this.gs.get();
+  }
+ 
+  getstate(statecode: number): string {
+      switch (statecode){	
+        case 1:
+          return '待预约';
+        case 2: 
+          return '预约';
+        case 3:
+          return '完成';
+        case 4: 
+          return '失效';
+        case 5:
+          return '关闭';
+      }
+  }
+  getinfos(): void {    
+    const st = this.gs.unstorage();
+    this.searchUserID=st.u;
+    this.searchGoodName =st.g;
+    this.searchStatus =st.s;
+    this.infoService.getSellInfos(this.searchUserID,this.searchStatus, this.searchGoodName, this.size, this.current*this.size-this.size)
+    .subscribe(infos => {
+      Eif(!infos) return;
+      this.sellinfos = infos.sellInfo;
+      this.checkcount();
+    });
+  }
+ 
+  stringToDate(params) {
+      const date = new Date(params*1000);
+      return Format(date,'yyyy-MM-dd HH:mm:ss');
+  }
+ 
+  checkcount(){
+    if(this.sellinfos && this.sellinfos.length === this.size)
+    this.count = (this.current + 1) * this.size;
+    else 
+    this.count = this.current * this.size;
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/infodetail/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/infodetail/index.html" new file mode 100644 index 0000000..72befb3 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/infodetail/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/infodetail + + + + + + + +
+
+

+ All files src/app/infodetail +

+
+
+ 82.61% + Statements + 38/46 +
+
+ 68.75% + Branches + 11/16 +
+
+ 100% + Functions + 13/13 +
+
+ 83.33% + Lines + 35/42 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
infodetail.component.ts
82.61%38/4668.75%11/16100%13/1383.33%35/42
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/infodetail/infodetail.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/infodetail/infodetail.component.ts.html" new file mode 100644 index 0000000..cc6bfce --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/infodetail/infodetail.component.ts.html" @@ -0,0 +1,501 @@ + + + + Code coverage report for src/app/infodetail/infodetail.component.ts + + + + + + + +
+
+

+ All files / src/app/infodetail infodetail.component.ts +

+
+
+ 82.61% + Statements + 38/46 +
+
+ 68.75% + Branches + 11/16 +
+
+ 100% + Functions + 13/13 +
+
+ 83.33% + Lines + 35/42 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +1x +  +1x +1x +  +  +1x +1x +  +1x +1x +1x +1x +  +  +1x +1x +  +  +  +1x +1x +1x +  +  +1x +  +1x +  +  +  +  +  +3x +  +  +3x +3x +1x +  +1x +  +  +  +  +2x +1x +  +1x +  +  +  +  +  +  +  +2x +2x +2x +1x +1x +1x +1x +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Component, OnInit, Input } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { sellInfo } from '../entity/info';
+import { Location } from '@angular/common';
+import { InfoService } from '../info.service';
+import { Format } from '../Formatter/format';
+import { FileService } from './../file.service';
+import { Media } from '../entity/content';
+ 
+@Component({
+  selector: 'app-infodetail',
+  templateUrl: './infodetail.component.html',
+  styleUrls: ['./infodetail.component.css']
+})
+export class InfoDetailComponent implements OnInit {
+ 
+  d = [];
+  fnoption: any;
+  type :string;
+  state: number =0;
+  contents: Media[];
+  now = new Date(1997, 9, 3);
+  oneDay = 24 * 3600 * 1000;
+  option: any;
+  deadLine: Date;
+  value = Math.random() * 1000;
+  @Input() info: any ;
+  constructor(
+  private route: ActivatedRoute,
+  private infoService: InfoService,
+  private location: Location,
+  private fileService:FileService
+) {}
+stringToDate(params) {
+    const date = new Date(params*1000);
+    return Format(date,'yyyy-MM-dd HH:mm:ss');
+    }
+ 
+  ngOnInit() {
+      this.graph();
+      this.type = this.route.snapshot.paramMap.get('type');
+      this.getinfo();
+  }
+    getContent(): void {
+    this.fileService.getContent(this.info.contentID).subscribe(
+        e => {
+            Iif(e)
+            this.contents = e.files;
+        }
+    )
+    }
+    goBack(): void {
+    this.location.back();
+  }
+    getinfo(): void {
+    const id = parseInt(this.route.snapshot.paramMap.get('id'));
+    if(this.type === 'sellInfo')
+    this.infoService.getSellInfo(id)
+      .subscribe(info => {
+          Eif(!info)return;
+          this.info = info;
+          this.deadLine = new Date(this.info.validTime*1000);
+          this.getContent();
+      });
+    else if(this.type === 'buyInfo')
+    this.infoService.getBuyInfo(id)
+      .subscribe(info => {
+        Eif(!info)return;
+          this.info = info;
+          this.deadLine = new Date(this.info.validTime*1000);
+          this.getContent();
+      });
+  }
+ 
+    save(): void {
+    Iif(!this.info) return;
+    this.info.validTime = this.deadLine.getTime()/1000;
+    if(this.type==='sellInfo')
+    this.infoService.updateSellInfo(this.info)
+        .subscribe(() => this.goBack());
+    else Eif(this.type ==='buyInfo')
+    this.infoService.updateBuyInfo(this.info)
+        .subscribe(() => this.goBack());
+    }
+ 
+  graph() {
+    this.fnoption = {
+    title: {
+    },
+    tooltip: {
+        trigger: 'item',
+        formatter: '{a} <br/>{b} : {c}'
+    },
+    legend: {
+        data: ['展现', '点击' , '申请' , '预约' , '完成']
+    },
+    calculable: true,
+    series: [
+        {
+            name: '漏斗图',
+            type: 'funnel',
+            left: '10%',
+            top: 60,
+            bottom: 60,
+            width: '80%',
+            min: 0,
+            max: 100,
+            minSize: '0%',
+            maxSize: '100%',
+            sort: 'descending',
+            gap: 2,
+            label: {
+                show: true,
+                position: 'inside'
+            },
+            labelLine: {
+                length: 10,
+                lineStyle: {
+                    width: 1,
+                    type: 'solid'
+                }
+            },
+            itemStyle: {
+                borderColor: '#fff',
+                borderWidth: 1
+            },
+            emphasis: {
+                label: {
+                    fontSize: 20
+                }
+            },
+            data: [
+                {value: 1, name: '完成'},
+                {value: 2, name: '预约'},
+                {value: 10, name: '申请'},
+                {value: 100, name: '点击'},
+                {value: 1000, name: '展现'}
+            ]
+        }
+    ]
+};
+ 
+}
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/inmemory-data.service.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/inmemory-data.service.ts.html" new file mode 100644 index 0000000..f0fe955 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/inmemory-data.service.ts.html" @@ -0,0 +1,120 @@ + + + + Code coverage report for src/app/inmemory-data.service.ts + + + + + + + +
+
+

+ All files / src/app inmemory-data.service.ts +

+
+
+ 100% + Statements + 5/5 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 1/1 +
+
+ 100% + Lines + 4/4 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18  +  +  +  +  +  +  +1x +  +12x +12x +  +  +  +  +12x +  + 
import { InMemoryDbService } from 'angular-in-memory-web-api';
+import { Injectable } from '@angular/core';
+import { sellInfo } from 'src/app/entity/info';
+ 
+@Injectable({
+  providedIn: 'root',
+})
+export class InMemoryDataService implements InMemoryDbService {
+  createDb() {
+    const site = [{id: 0, name: 'jiaojiao', status: true, cp: '2019 jiaojiao'}];
+    const history = [ {id: 0, description: '项目启动', time: '2019-07-01', type: 0},
+    {id: 1, description: '第一次迭代', time: '2019-07-12', type: 1},
+    {id: 2, description: '第二次迭代', time: '2019-07-23', type: 1},
+    {id: 3, description: '紧急维护', time: '', type: -1}
+  ];
+    return { site , history};
+  }
+}
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/login/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/login/index.html" new file mode 100644 index 0000000..9a0f8a1 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/login/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/login + + + + + + + +
+
+

+ All files src/app/login +

+
+
+ 100% + Statements + 8/8 +
+
+ 100% + Branches + 0/0 +
+
+ 80% + Functions + 4/5 +
+
+ 100% + Lines + 6/6 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
login.component.ts
100%8/8100%0/080%4/5100%6/6
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/login/login.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/login/login.component.ts.html" new file mode 100644 index 0000000..dd6d4cd --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/login/login.component.ts.html" @@ -0,0 +1,174 @@ + + + + Code coverage report for src/app/login/login.component.ts + + + + + + + +
+
+

+ All files / src/app/login login.component.ts +

+
+
+ 100% + Statements + 8/8 +
+
+ 100% + Branches + 0/0 +
+
+ 80% + Functions + 4/5 +
+
+ 100% + Lines + 6/6 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +1x +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +1x +1x +  +  + 
import { Component, OnInit, Inject } from '@angular/core';
+import { SocialService, JWTGuard, JWTTokenModel } from '@delon/auth';
+import { AuthService } from '../auth.service';
+import { Router } from '@angular/router';
+import { NzNotificationService } from 'ng-zorro-antd';
+ 
+@Component({
+  selector: 'app-login',
+  templateUrl: './login.component.html',
+  styleUrls: ['./login.component.css'],
+  providers: [ SocialService ]
+ 
+})
+export class LoginComponent implements OnInit {
+ 
+  t: any;
+  constructor( private socialService: SocialService , private notification: NzNotificationService
+    ,private authService: AuthService) {
+  }
+ 
+  ngOnInit(): void {
+  }
+ 
+  
+ login() {
+    this.socialService.login('/api/auth','/callback',{type: 'window'} ).subscribe(res => {
+//      this.authService.login(res);
+    })
+  }
+ 
+  pretend() {
+    this.authService.login({token: this.t});
+    this.notification.create('success', '导入token成功', 'Token已更新');
+  }
+ 
+  }
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/transaction.service.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/transaction.service.ts.html" new file mode 100644 index 0000000..7c54d43 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/transaction.service.ts.html" @@ -0,0 +1,327 @@ + + + + Code coverage report for src/app/transaction.service.ts + + + + + + + +
+
+

+ All files / src/app transaction.service.ts +

+
+
+ 58.54% + Statements + 24/41 +
+
+ 31.43% + Branches + 11/35 +
+
+ 60% + Functions + 6/10 +
+
+ 60.61% + Lines + 20/33 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87  +  +  +  +  +  +  +  +  +1x +  +2x +2x +2x +  +  +1x +  +1x +  +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +1x +1x +1x +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +1x +  +  +  + 
import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Transaction } from './entity/transaction';
+import { Observable, of } from 'rxjs';
+import { catchError } from 'rxjs/operators';
+ 
+@Injectable({
+  providedIn: 'root'
+})
+export class TransactionService {
+ 
+  private trUrl = 'api/transaction';  // URL to web api
+  tr: Transaction[]=[];
+  constructor(private http: HttpClient) { }
+  
+  getAllTR(status,lowCreateTime,highCreateTime): Transaction[]{
+    Eif(this.tr.length==0)
+    {
+      this.getTransactions(null,status,null,lowCreateTime,highCreateTime).subscribe(e=>
+        {
+        this.tr = e.transactions;
+        this.getMoreTransaction(100,false,status,lowCreateTime,highCreateTime);
+        })
+    }
+    return this.tr;
+  }
+ 
+  getMoreTransaction(offset, dynamic,status,lowCreateTime,highCreateTime){
+    if(!(this.tr.length%100) && !dynamic)
+      this.getTransactions(null,null,null,lowCreateTime,highCreateTime, null,offset).subscribe(
+          e => {
+              if(e){
+              this.tr=this.tr.concat(e.transactions);
+              if(e.buyInfo.length!=100)
+              dynamic =! dynamic;
+            }
+              this.getMoreTransaction(offset+100, dynamic,status,lowCreateTime,highCreateTime);
+            }
+      );
+      else{
+          setTimeout(() => {
+              this.getTransactions(null,null,null,lowCreateTime,highCreateTime, null,offset).subscribe(
+                  e => {
+                      if(e)
+                      this.tr=this.tr.concat(e.buyInfo);
+                      this.getMoreTransaction(this.tr.length-1, true,status,lowCreateTime,highCreateTime);
+          }
+      );}, 5000 );
+      }
+}
+ 
+  /** GET infos from the server */
+  getTransactions(userID: string = null, status: number = null, infoID: number = null, 
+    lowCreateTime :number = null, highCreateTime: number =null, limit:number=null, offset: number=null): 
+    Observable<any> 
+    {    
+    let url = `${this.trUrl}?`;
+    Iif(userID && userID.trim()) url += `userID=${userID}&`;
+    Eif(status) url+= `status=${status}&`;
+    Iif(infoID) url+=`goodName=${infoID}&`;
+    Iif(limit) url+= `limit=${limit}&`;
+    Eif(lowCreateTime) url+=`lowCreateTime=${lowCreateTime}&`;
+    Eif(highCreateTime) url+=`highCreateTime=${highCreateTime}&`;
+    Iif(offset) url+=`offset=${offset}&`;
+    return this.http.get<any>(url).pipe(
+        catchError(this.handleError<any>('getTransactions'))
+      );
+  }
+ 
+  /**
+   * Handle Http operation that failed.
+   * Let the app continue.
+   * @param operation - name of the operation that failed
+   * @param result - optional value to return as the observable result
+   *
+   */
+  
+  private handleError<T>(operation, result?: T) {
+    return (error: any): Observable<T> => {
+      // TODO: send the error to remote logging infrastructure
+      console.error(error); // log to console instead
+      // Let the app keep running by returning an empty result.
+      return of(result as T);
+    };
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user.service.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user.service.ts.html" new file mode 100644 index 0000000..80dfb28 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user.service.ts.html" @@ -0,0 +1,288 @@ + + + + Code coverage report for src/app/user.service.ts + + + + + + + +
+
+

+ All files / src/app user.service.ts +

+
+
+ 88.24% + Statements + 15/17 +
+
+ 100% + Branches + 0/0 +
+
+ 87.5% + Functions + 7/8 +
+
+ 87.5% + Lines + 14/16 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74  +  +  +  +  +1x +  +  +  +  +1x +  +4x +  +4x +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +7x +  +  +7x +  +  +  + 
import { Injectable } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Observable, of } from 'rxjs';
+import { catchError, map, tap } from 'rxjs/operators';
+import { User, UserResponse } from './entity/user'
+const httpOptions = {
+  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
+};
+ 
+@Injectable({ providedIn: 'root' })
+export class UserService {
+ 
+  private usersUrl = 'api/user';  // URL to web api
+ 
+  constructor(private http: HttpClient) { }
+ 
+  /** GET users from the server */
+  getPageUsers(limit:number, offset: number): Observable<UserResponse> {
+    const url = `${this.usersUrl}?limit=${limit}&offset=${offset}`;
+    return this.http.get<UserResponse>(url,httpOptions)
+      .pipe(
+        catchError(this.handleError<UserResponse>('getUsers'))
+      );
+  }
+  /** GET users from the server */
+  getUsers(): Observable<UserResponse> {
+    const url = `${this.usersUrl}?limit=100000`;
+    return this.http.get<UserResponse>(url,httpOptions)
+      .pipe(
+        catchError(this.handleError<UserResponse>('getUsers'))
+      );
+  }
+  /** GET user by id. Will 404 if id not found */
+  getUser(id: string): Observable<User> {
+    const url = `${this.usersUrl}/${id}`;
+    return this.http.get<User>(url).pipe(
+      catchError(this.handleError<User>(`getUser id=${id}`))
+    );
+  }
+ 
+  /* GET users whose name contains search term */
+  searchUsers(term: string,limit:number, offset: number): Observable<UserResponse> {
+    const url =`${this.usersUrl}?userName=${term}&limit=${limit}&offset=${offset}`;
+    return this.http.get<UserResponse>(url).pipe(
+      catchError(this.handleError<UserResponse>('searchUsers'))
+    );
+  }
+ 
+ 
+  /** PUT: update the user on the server */
+  updateUser(user): Observable<any> {
+    return this.http.put(this.usersUrl, user, httpOptions).pipe(
+      catchError(this.handleError<any>('updateUser'))
+    );
+  }
+ 
+  /**
+   * Handle Http operation that failed.
+   * Let the app continue.
+   * @param operation - name of the operation that failed
+   * @param result - optional value to return as the observable result
+   */
+  private handleError<T>(operation, result?: T) {
+    return (error: any): Observable<T> => {
+ 
+      // TODO: send the error to remote logging infrastructure
+      console.error(error); // log to console instead
+ 
+      // Let the app keep running by returning an empty result.
+      return of(result as T);
+    };
+  }
+ 
+}
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user/index.html" new file mode 100644 index 0000000..46f7610 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/user + + + + + + + +
+
+

+ All files src/app/user +

+
+
+ 78.26% + Statements + 18/23 +
+
+ 75% + Branches + 9/12 +
+
+ 100% + Functions + 8/8 +
+
+ 75% + Lines + 15/20 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
user.component.ts
78.26%18/2375%9/12100%8/875%15/20
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user/user.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user/user.component.ts.html" new file mode 100644 index 0000000..fdadc40 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/user/user.component.ts.html" @@ -0,0 +1,261 @@ + + + + Code coverage report for src/app/user/user.component.ts + + + + + + + +
+
+

+ All files / src/app/user user.component.ts +

+
+
+ 78.26% + Statements + 18/23 +
+
+ 75% + Branches + 9/12 +
+
+ 100% + Functions + 8/8 +
+
+ 75% + Lines + 15/20 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65  +  +  +  +  +  +  +  +  +  +  +1x +  +  +3x +  +3x +  +3x +  +  +2x +  +  +  +3x +1x +  +1x +  +2x +  +2x +  +  +  +  +  +  +1x +  +  +1x +  +  +3x +  +2x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  + 
import { Component, OnInit } from '@angular/core';
+import { User } from '../entity/user';
+import { UserService } from '../user.service';
+import { HTTP_INTERCEPTORS } from '@angular/common/http';
+import { JWTInterceptor } from '@delon/auth';
+ 
+@Component({
+  selector: 'app-user',
+  templateUrl: './user.component.html',
+  styleUrls: ['./user.component.css']
+})
+export class UserComponent implements OnInit {
+  users: User[];
+  threshold: number;
+  current : number = 1;
+  count: number;
+  size: number = 4;
+  searchName: string;
+  constructor(private userService: UserService) { }
+ 
+  ngOnInit() {
+    this.getusers();
+  }
+ 
+  searchByName(): void {    
+    if (!this.searchName || !this.searchName.trim()) {
+    this.getusers();
+    // if not search term, return all user array.
+    return;
+  }
+    this.userService.searchUsers(this.searchName,this.size, this.current*this.size-this.size)
+    .subscribe(users => {
+      Eif(!users) return;
+      this.users = users.user;
+      this.checkcount();
+    });
+  }
+ 
+  checkcount(){
+    Iif(this.users && this.users.length === this.size)
+    this.count = (this.current + 1) * this.size;
+    else 
+    this.count = this.current * this.size;
+  }
+  getusers(): void {
+    this.userService.getPageUsers(this.size, this.current*this.size-this.size)
+    .subscribe(users => {
+      Eif(!users) return;
+      this.users = users.user;
+      this.checkcount();
+    });
+  }
+ 
+  onChange(){
+    this.searchByName();
+  }
+  /*forbid(): void {
+    this.users.filter(m => m.score < this.threshold).map( m => {m.forbid = true; return m;}).forEach(element => 
+      this.userService.updateUser(element).subscribe());
+    this.users.filter(m => m.score >= this.threshold).map( m => {m.forbid = false; return m;}).forEach(element => 
+        this.userService.updateUser(element).subscribe());
+  }*/
+ 
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/userdetail/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/userdetail/index.html" new file mode 100644 index 0000000..6defee4 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/userdetail/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/userdetail + + + + + + + +
+
+

+ All files src/app/userdetail +

+
+
+ 68.63% + Statements + 35/51 +
+
+ 57.89% + Branches + 11/19 +
+
+ 75% + Functions + 12/16 +
+
+ 70.83% + Lines + 34/48 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
userdetail.component.ts
68.63%35/5157.89%11/1975%12/1670.83%34/48
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/userdetail/userdetail.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/userdetail/userdetail.component.ts.html" new file mode 100644 index 0000000..9a35837 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/userdetail/userdetail.component.ts.html" @@ -0,0 +1,534 @@ + + + + Code coverage report for src/app/userdetail/userdetail.component.ts + + + + + + + +
+
+

+ All files / src/app/userdetail userdetail.component.ts +

+
+
+ 68.63% + Statements + 35/51 +
+
+ 57.89% + Branches + 11/19 +
+
+ 75% + Functions + 12/16 +
+
+ 70.83% + Lines + 34/48 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +1x +  +1x +  +  +  +  +1x +1x +1x +1x +  +  +1x +1x +  +  +  +1x +  +  +2x +1x +1x +1x +  +  +3x +  +  +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +2x +2x +  +  +  +5x +  +1x +  +1x +  +1x +  +1x +  +1x +  +  +  +  +  +  +  +  +  +1x +1x +1x +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { Component, OnInit, Input } from '@angular/core';
+import { UserService } from '../user.service';
+import { ActivatedRoute } from '@angular/router';
+import { User } from '../entity/user';
+import { Location } from '@angular/common';
+import { InfoService } from '../info.service';
+import { Format } from '../Formatter/format';
+import { SellInfoComponent } from '../info/sell-info/sell-info.component';
+import { sellInfo, buyInfo } from '../entity/info';
+const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+export function fFormatter(params) {
+     return params.value + ' activities in ' + params.name;
+}
+@Component({
+  selector: 'app-userdetail',
+  templateUrl: './userdetail.component.html',
+  styleUrls: ['./userdetail.component.css']
+})
+export class UserDetailComponent implements OnInit {
+  option: any;
+  @Input() user: User;
+  forbid : boolean;
+  userName : string;
+  infos : any[];
+  constructor(
+  private route: ActivatedRoute,
+  private userService: UserService,
+  private infoService: InfoService,
+  private location: Location
+) {}
+stringToDate(params) {
+    const date = new Date(parseInt(params+'000'));
+    return Format(date,'yyyy-MM-dd HH:mm:ss');
+    }
+ 
+  ngOnInit(): void {
+  this.getuser();
+}
+  typeof(obj): string {
+    if( obj['sellInfoID'])
+    return 'sellInfo';
+    Eif( obj['buyInfoID'])
+    return 'buyInfo';
+  }
+    goBack(): void {
+    this.location.back();
+  }
+    getuser(): void {
+    const id = this.route.snapshot.paramMap.get('id');
+    this.userService.getUser(id)
+      .subscribe(user => {this.user = user; 
+        this.forbid = this.user.status === 2;
+        this.userName = this.user.userName;
+        this.infoService.getSellInfos(id).subscribe(e => {
+          if(e.sellInfo)
+          {
+        this.infos = e.sellInfo;
+          }
+          this.infoService.getBuyInfos(id).subscribe(e => {
+            if(e.buyInfo)
+          this.infos = this.infos.concat(e.buyInfo);
+          this.infos= this.infos.sort((a,b )=>parseInt(a.releaseTime)-
+      parseInt(b.releaseTime));
+          this.graph();
+            }
+          );
+ 
+ 
+        });
+      });
+   
+  }
+    save(): void {
+    Iif(!this.user) return;
+    const status = this.forbid? 2: 1;
+    this.userService.updateUser({userID: this.user.userID, status: status, userName: this.userName, role: this.user.role})
+      .subscribe(() => this.goBack());
+  }
+ 
+  getstate(statecode: number): string {
+    switch (statecode){	
+      case 1:
+        return '待预约';
+      case 2: 
+        return '预约';
+      case 3:
+        return '完成';
+      case 4: 
+        return '失效';
+      case 5: 
+        return '关闭';
+    }
+}
+ 
+ 
+ 
+ 
+ 
+  graph() {
+ 
+const sellData = [ 0 , 0 , 0 , 0 , 0 ,0 ,0 , 0 ,0 , 0 ,0 ,0];
+const buyData = [ 0 , 0 , 0 , 0 , 0 ,0 ,0 , 0 ,0 , 0 ,0 ,0];
+this.infos.forEach(element => {
+  const y =new Date(element.releaseTime*1000).getFullYear(); 
+  const m =new Date(element.releaseTime*1000).getMonth() + 1;
+  //if((ynow == y + 1 && m > mnow) || (ynow == y && m <= mnow) )
+    if(this.typeof(element)=='sellInfo')
+      sellData[m-1] +=1;
+    else 
+      buyData[m-1] +=1;
+});
+    this.option = {
+title: {
+},
+legend: {
+    data: ['出售', '求购']
+},
+polar: {},
+tooltip: {
+  formatter: fFormatter
+},
+angleAxis: {
+    type: 'category',
+    data: months,
+    boundaryGap: false,
+    splitLine: {
+        show: true,
+        lineStyle: {
+            color: '#999',
+            type: 'dashed'
+        }
+    },
+    axisLine: {
+        show: false
+    }
+},
+radiusAxis: {
+    type: 'value',
+      minInterval: 1
+},
+series: [{
+  name: 'Sell Record',
+  type: 'bar',
+  data: sellData,
+  coordinateSystem: 'polar'
+},
+{
+  name: 'Buy Record',
+  type: 'bar',
+  data: buyData,
+  coordinateSystem: 'polar'
+}]
+};
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website.service.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website.service.ts.html" new file mode 100644 index 0000000..d700d35 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website.service.ts.html" @@ -0,0 +1,300 @@ + + + + Code coverage report for src/app/website.service.ts + + + + + + + +
+
+

+ All files / src/app website.service.ts +

+
+
+ 100% + Statements + 21/21 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 9/9 +
+
+ 100% + Lines + 20/20 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +3x +3x +3x +  +  +  +2x +2x +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +4x +4x +  +  +  +  +  +1x +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +10x +  +1x +  +1x +  +  +  + 
import { Injectable } from "@angular/core";
+import { HttpHeaders, HttpClient } from "@angular/common/http";
+import { Observable, of } from "rxjs";
+import { catchError, max } from "rxjs/operators";
+ 
+const httpOptions = {
+  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
+};
+ 
+@Injectable({
+  providedIn: 'root'
+})
+export class WebsiteService {
+ 
+  private siteUrl = 'api/site';  // URL to web api
+  private hstUrl = 'api/history';
+  constructor(private http: HttpClient) { }
+ 
+  /** GET info by id. Will 404 if id not found */
+  getSite(): Observable<any> {
+    const url = `${this.siteUrl}/0`;
+    return this.http.get<any>(url).pipe(
+      catchError(this.handleError<any>(`getWebsite`))
+    );
+  }
+ 
+  /** PUT: update the info on the server */
+  updateSite(site): Observable<any> {
+    const url = `${this.siteUrl}`;
+    return this.http.put(this.siteUrl, site, httpOptions).pipe(
+      catchError(this.handleError<any>('updateInfo'))
+    );
+  }
+ 
+  /** GET info by id. Will 404 if id not found */
+  getSiteHistory(): Observable<any[]> {
+    const url = `${this.hstUrl}`;
+    return this.http.get<any>(url).pipe(
+      catchError(this.handleError<any>(`getWebsiteHistory`))
+    );
+  }
+ 
+  deleteSiteHistory(item: any){
+    const url = `${this.hstUrl}/${item.id}`;
+    return this.http.delete<any>(url).pipe(
+      catchError(this.handleError<any>(`deleteWebsiteHistory`))
+    );
+  }
+ 
+  updateSiteHistory(item: any){
+  const url = `${this.hstUrl}`;
+  return this.http.put<any>(url,item,httpOptions).pipe(
+    catchError(this.handleError<any>(`updateWebsiteHistory`))
+  );
+  }
+ 
+  addSiteHistory(item: any){
+    const url = `${this.hstUrl}`;
+    return this.http.post<any>(url,item,httpOptions).pipe(
+      catchError(this.handleError<any>(`addWebsiteHistory`))
+    );
+  }
+  /**
+   * Handle Http operation that failed.
+   * Let the app continue.
+   * @param operation - name of the operation that failed
+   * @param result - optional value to return as the observable result
+   */
+  private handleError<T>(operation, result?: T) {
+    return (error: any): Observable<T> => {
+      // TODO: send the error to remote logging infrastructure
+      console.error(error); // log to console instead
+      // Let the app keep running by returning an empty result.
+      return of(result as T);
+    };
+  }
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website/index.html" new file mode 100644 index 0000000..84644e8 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website/index.html" @@ -0,0 +1,97 @@ + + + + Code coverage report for src/app/website + + + + + + + +
+
+

+ All files src/app/website +

+
+
+ 100% + Statements + 17/17 +
+
+ 50% + Branches + 3/6 +
+
+ 100% + Functions + 5/5 +
+
+ 100% + Lines + 13/13 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
website.component.ts
100%17/1750%3/6100%5/5100%13/13
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website/website.component.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website/website.component.ts.html" new file mode 100644 index 0000000..5965428 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/app/website/website.component.ts.html" @@ -0,0 +1,225 @@ + + + + Code coverage report for src/app/website/website.component.ts + + + + + + + +
+
+

+ All files / src/app/website website.component.ts +

+
+
+ 100% + Statements + 17/17 +
+
+ 50% + Branches + 3/6 +
+
+ 100% + Functions + 5/5 +
+
+ 100% + Lines + 13/13 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +1x +  +3x +3x +  +  +  +  +1x +1x +1x +1x +1x +1x +  +  +  +  +1x +1x +  +  +  +1x +  +  +  +  +  +  +  + 
import { Component, OnInit } from '@angular/core';
+import { Location } from '@angular/common';
+import {
+  FormBuilder,
+  FormGroup,
+  Validators
+} from '@angular/forms';
+ 
+import { NzNotificationService } from 'ng-zorro-antd';
+import { Router } from '@angular/router';
+import { WebsiteService } from './../website.service';
+ 
+@Component({
+  selector: 'app-website',
+  templateUrl: './website.component.html',
+  styleUrls: ['./website.component.css']
+})
+export class WebsiteComponent implements OnInit {
+  validateForm: FormGroup;
+  site: any;
+  submitForm(): void {
+    for (const i in this.validateForm.controls) {
+      //if (this.validateForm.controls.hasOwnProperty(i)) {
+        this.validateForm.controls[ i ].markAsDirty();
+        this.validateForm.controls[ i ].updateValueAndValidity();
+      //}
+    }
+  }
+  update(): void{
+    this.service.getSite().subscribe( e => {
+      this.site =e;
+      this.site.name = this.validateForm.controls.name.valid? this.validateForm.controls.name.value: this.site.name;
+      this.site.cp = this.validateForm.controls.copyright.valid? this.validateForm.controls.copyright.value: this.site.cp;
+      this.site.status = this.validateForm.controls.status.valid? this.validateForm.controls.status.value: this.site.status;
+      this.service.updateSite(this.site).subscribe();
+     } );
+  }
+ 
+  constructor(
+    private service: WebsiteService,
+    private location: Location, private router: Router, private fb: FormBuilder, private notification: NzNotificationService) {
+  }
+ 
+  ngOnInit(): void {
+    this.validateForm = this.fb.group({
+      name: [ null, [ Validators.required ] ],
+      copyright: [ null, [ Validators.required ] ],
+      status: [ null, [ Validators.required ] ]
+    });
+  }
+ 
+}
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/index.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/index.html" new file mode 100644 index 0000000..74cfb2b --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/index.html" @@ -0,0 +1,110 @@ + + + + Code coverage report for src + + + + + + + +
+
+

+ All files src +

+
+
+ 100% + Statements + 3/3 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 0/0 +
+
+ 100% + Lines + 3/3 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
polyfills.ts
0%0/00%0/00%0/00%0/0
test.ts
100%3/3100%0/0100%0/0100%3/3
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/polyfills.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/polyfills.ts.html" new file mode 100644 index 0000000..31093c5 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/polyfills.ts.html" @@ -0,0 +1,258 @@ + + + + Code coverage report for src/polyfills.ts + + + + + + + +
+
+

+ All files / src polyfills.ts +

+
+
+ 0% + Statements + 0/0 +
+
+ 0% + Branches + 0/0 +
+
+ 0% + Functions + 0/0 +
+
+ 0% + Lines + 0/0 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ *      file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/guide/browser-support
+ */
+ 
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+ 
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+// import 'classlist.js';  // Run `npm install --save classlist.js`.
+ 
+/**
+ * Web Animations `@angular/platform-browser/animations`
+ * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
+ * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
+ */
+// import 'web-animations-js';  // Run `npm install --save web-animations-js`.
+ 
+/**
+ * By default, zone.js will patch all possible macroTask and DomEvents
+ * user can disable parts of macroTask/DomEvents patch by setting following flags
+ * because those flags need to be set before `zone.js` being loaded, and webpack
+ * will put import in the top of bundle, so user need to create a separate file
+ * in this directory (for example: zone-flags.ts), and put the following flags
+ * into that file, and then add the following code before importing zone.js.
+ * import './zone-flags.ts';
+ *
+ * The flags allowed in zone-flags.ts are listed here.
+ *
+ * The following flags will work for all browsers.
+ *
+ * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+ *
+ *  in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
+ *  with the following flag, it will bypass `zone.js` patch for IE/Edge
+ *
+ *  (window as any).__Zone_enable_cross_context_check = true;
+ *
+ */
+ 
+/***************************************************************************************************
+ * Zone JS is required by default for Angular itself.
+ */
+import 'zone.js/dist/zone';  // Included with Angular CLI.
+ 
+ 
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/test.ts.html" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/test.ts.html" new file mode 100644 index 0000000..ec57fe7 --- /dev/null +++ "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web \345\211\215\347\253\257\346\265\213\350\257\225\346\212\245\345\221\212/coverage/jiaojiaoadmin/src/test.ts.html" @@ -0,0 +1,129 @@ + + + + Code coverage report for src/test.ts + + + + + + + +
+
+

+ All files / src test.ts +

+
+
+ 100% + Statements + 3/3 +
+
+ 100% + Branches + 0/0 +
+
+ 100% + Functions + 0/0 +
+
+ 100% + Lines + 3/3 +
+
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +1x +  +1x + 
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+ 
+import 'zone.js/dist/zone-testing';
+import { getTestBed } from '@angular/core/testing';
+import {
+  BrowserDynamicTestingModule,
+  platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+ 
+declare const require: any;
+ 
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+  BrowserDynamicTestingModule,
+  platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
+ 
+
+
+ + + + + + + + diff --git "a/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web\345\211\215\347\253\257\346\265\213\350\257\225\347\224\250\344\276\213.xls" "b/docs/3_\347\254\254\344\270\211\346\254\241\350\277\255\344\273\243\347\232\204\346\226\207\346\241\243\346\261\207\346\200\273/\346\265\213\350\257\225\346\212\245\345\221\212&\346\265\213\350\257\225\347\224\250\344\276\213/WebFrontend/Web\345\211\215\347\253\257\346\265\213\350\257\225\347\224\250\344\276\213.xls" new file mode 100644 index 0000000000000000000000000000000000000000..f3923eaccb779fe9e319371783ace7929cb56035 GIT binary patch literal 125440 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 literal 0 HcmV?d00001 From 205d3be082fd8ab9bcc8a1af9c4c4ca6f9a85366 Mon Sep 17 00:00:00 2001 From: MXWXZ Date: Fri, 2 Aug 2019 01:55:24 +0800 Subject: [PATCH 15/17] message srv --- backend/api/message/main.go | 58 +-- backend/api/message/main_test.go | 8 - backend/doc/api_data.js | 32 +- backend/doc/api_data.json | 32 +- backend/doc/api_project.js | 2 +- backend/doc/api_project.json | 2 +- backend/doc/css/style.css | 569 ++++++++++++++++++++++++ backend/srv/content/main.go | 2 +- backend/srv/message/main.go | 272 +++++------ backend/srv/message/main_test.go | 2 +- backend/srv/message/proto/message.pb.go | 224 ++++------ backend/srv/message/proto/message.proto | 46 +- 12 files changed, 859 insertions(+), 390 deletions(-) create mode 100644 backend/doc/css/style.css diff --git a/backend/api/message/main.go b/backend/api/message/main.go index 378bef1..f29f3d6 100644 --- a/backend/api/message/main.go +++ b/backend/api/message/main.go @@ -27,30 +27,29 @@ func setupRouter() *gin.Engine { * @api {post} /message AddMessage * @apiVersion 1.0.0 * @apiGroup Message - * @apiPermission self/admin + * @apiPermission self * @apiName AddMessage * @apiDescription Add chat message * - * @apiParam {--} Param see [Message Service](#api-Service-Message_Create) + * @apiParam {--} Param see [Message Service](#api-Service-Message_Create)
Self userID should in fromUser * @apiSuccess (Success 200) {Response} response see [Message Service](#api-Service-Message_Create) * @apiUse InvalidParam * @apiUse MessageServiceDown */ func addMessage(c *gin.Context) { type param struct { - FromUser int32 `form:"fromUser" binding:"required"` - ToUser int32 `form:"toUser" binding:"required"` - Type message.MessageCreateRequest_Type `form:"type" binding:"required"` - Text string `form:"text"` + FromUser int32 `form:"fromUser" binding:"required"` + ToUser int32 `form:"toUser" binding:"required"` + Type int32 `form:"type" binding:"required"` } var p param - var data []byte + var msg []byte if !utils.LogContinue(c.ShouldBind(&p), utils.Warning) { - if p.Type == message.MessageCreateRequest_PICTURE || p.Type == message.MessageCreateRequest_VIDEO { + if p.Type == int32(message.Type_PICTURE) || p.Type == int32(message.Type_VIDEO) { var code int var err error - data, code, err = utils.GetQueryFile(c, "file", 1024*1024*50) // 50M + msg, code, err = utils.GetQueryFile(c, "msg", int64(utils.If(p.Type == int32(message.Type_PICTURE), 1024*1024*5, 1024*1024*50).(int))) if err != nil { c.AbortWithStatus(400) return @@ -59,10 +58,16 @@ func addMessage(c *gin.Context) { c.AbortWithStatus(code) return } + } else { + s := c.PostForm("msg") + if s != "" { + msg = []byte(s) + } else { + msg = []byte{0} + } } - role1 := utils.GetRoleID(c, int32(p.FromUser)) - role2 := utils.GetRoleID(c, int32(p.FromUser)) - if !(role1.Self || role1.Admin || role2.Self || role2.Admin) { + role := utils.GetRoleID(c, int32(p.FromUser)) + if !role.Self { c.Status(403) return } @@ -72,11 +77,10 @@ func addMessage(c *gin.Context) { rsp, err := srv.Create(context.TODO(), &message.MessageCreateRequest{ FromUser: p.FromUser, ToUser: p.ToUser, - Type: p.Type, - Text: p.Text, - File: data, + Type: message.Type(utils.EnumConvert(p.Type, message.Type_name)), + Msg: msg, }) - if utils.LogContinue(err, utils.Warning, "Message service error: %v", err) { + if utils.LogContinue(err, utils.Error) { c.JSON(500, err) return } @@ -101,17 +105,17 @@ func addMessage(c *gin.Context) { */ func findMessage(c *gin.Context) { type param struct { - FromUser int32 `form:"fromUser" binding:"required"` - ToUser int32 `form:"toUser" binding:"required"` - Way message.MessageFindRequest_Way `form:"way" binding:"required"` - Limit int32 `form:"limit"` - Offset int32 `form:"offset"` + FromUser int32 `form:"fromUser" binding:"required"` + ToUser int32 `form:"toUser" binding:"required"` + Way int32 `form:"way" binding:"required"` + Limit int32 `form:"limit"` + Offset int32 `form:"offset"` } var p param - if !utils.LogContinue(c.ShouldBind(&p), utils.Warning) { + if !utils.LogContinue(c.ShouldBindQuery(&p), utils.Warning) { role1 := utils.GetRoleID(c, int32(p.FromUser)) - role2 := utils.GetRoleID(c, int32(p.FromUser)) + role2 := utils.GetRoleID(c, int32(p.ToUser)) if !(role1.Self || role1.Admin || role2.Self || role2.Admin) { c.Status(403) return @@ -122,9 +126,9 @@ func findMessage(c *gin.Context) { rsp, err := srv.Find(context.TODO(), &message.MessageFindRequest{ FromUser: p.FromUser, ToUser: p.ToUser, - Way: p.Way, + Way: message.MessageFindRequest_Way(utils.EnumConvert(p.Way, message.MessageFindRequest_Way_name)), }) - if utils.LogContinue(err, utils.Warning, "Message service error: %v", err) { + if utils.LogContinue(err, utils.Error) { c.JSON(500, err) return } @@ -155,7 +159,7 @@ func getMessage(c *gin.Context) { if !utils.LogContinue(c.ShouldBindUri(&p), utils.Warning) { role := utils.GetRoleID(c, int32(p.UserID)) - if !(role.Self || role.Admin) { + if !role.Self && !role.Admin { c.Status(403) return } @@ -165,7 +169,7 @@ func getMessage(c *gin.Context) { rsp, err := srv.Query(context.TODO(), &message.MessageQueryRequest{ UserID: p.UserID, }) - if utils.LogContinue(err, utils.Warning, "Message service error: %v", err) { + if utils.LogContinue(err, utils.Error) { c.JSON(500, err) return } diff --git a/backend/api/message/main_test.go b/backend/api/message/main_test.go index 044ddc1..ac506b0 100644 --- a/backend/api/message/main_test.go +++ b/backend/api/message/main_test.go @@ -2,16 +2,8 @@ package main import ( "testing" - - . "github.com/smartystreets/goconvey/convey" ) -func Test_(t *testing.T) { - Convey("test", t, func() { - - }) -} - func TestMain(m *testing.M) { main() m.Run() diff --git a/backend/doc/api_data.js b/backend/doc/api_data.js index 8dc6614..c77d808 100644 --- a/backend/doc/api_data.js +++ b/backend/doc/api_data.js @@ -660,7 +660,7 @@ define({ "api": [ "group": "Message", "permission": [ { - "name": "self/admin" + "name": "self" } ], "name": "AddMessage", @@ -673,7 +673,7 @@ define({ "api": [ "type": "--", "optional": false, "field": "Param", - "description": "

see Message Service

" + "description": "

see Message Service
Self userID should in fromUser

" } ] } @@ -2090,19 +2090,12 @@ define({ "api": [ "field": "type", "description": "

1 for text
2 for picture
3 for video

" }, - { - "group": "Parameter", - "type": "string", - "optional": true, - "field": "text", - "description": "

plain message text if type is text

" - }, { "group": "Parameter", "type": "bytes", - "optional": true, - "field": "file", - "description": "

file stream bytes, valid only if type is picture or video

" + "optional": false, + "field": "msg", + "description": "

file stream bytes if type is picture or video, plain text if type is text

" } ] } @@ -2165,11 +2158,12 @@ define({ "api": [ "type": "int32", "optional": false, "field": "way", - "description": "

1 for only pull message
2 for read message
3 for query history message

" + "description": "

1 for read message
2 for query history message
Note: only 1 will set unread to false

" }, { "group": "Parameter", - "type": "int32", + "type": "uint32", + "size": "0-20", "optional": false, "field": "limit", "defaultValue": "20", @@ -2177,7 +2171,7 @@ define({ "api": [ }, { "group": "Parameter", - "type": "int32", + "type": "uint32", "optional": false, "field": "offset", "defaultValue": "0", @@ -2249,7 +2243,7 @@ define({ "api": [ }, { "group": "MessageInfo", - "type": "string", + "type": "bytes", "optional": false, "field": "text", "description": "

plain message text if type is text
fileID if type is picture or video

" @@ -2286,7 +2280,7 @@ define({ "api": [ "version": "1.0.0", "group": "Service", "name": "Message_Query", - "description": "

Query New Message

", + "description": "

Query New Message, do NOT set read

", "parameter": { "fields": { "Parameter": [ @@ -2345,7 +2339,7 @@ define({ "api": [ "type": "MessageInfo", "optional": false, "field": "info", - "description": "

see below MessageInfo

" + "description": "

newest one msg for each dialog, see below MessageInfo

" } ], "MessageInfo": [ @@ -2382,7 +2376,7 @@ define({ "api": [ "type": "bool", "optional": false, "field": "unread", - "description": "

false for having read
true for not having read

" + "description": "

always true

" } ] } diff --git a/backend/doc/api_data.json b/backend/doc/api_data.json index 4f9ede4..5730235 100644 --- a/backend/doc/api_data.json +++ b/backend/doc/api_data.json @@ -660,7 +660,7 @@ "group": "Message", "permission": [ { - "name": "self/admin" + "name": "self" } ], "name": "AddMessage", @@ -673,7 +673,7 @@ "type": "--", "optional": false, "field": "Param", - "description": "

see Message Service

" + "description": "

see Message Service
Self userID should in fromUser

" } ] } @@ -2090,19 +2090,12 @@ "field": "type", "description": "

1 for text
2 for picture
3 for video

" }, - { - "group": "Parameter", - "type": "string", - "optional": true, - "field": "text", - "description": "

plain message text if type is text

" - }, { "group": "Parameter", "type": "bytes", - "optional": true, - "field": "file", - "description": "

file stream bytes, valid only if type is picture or video

" + "optional": false, + "field": "msg", + "description": "

file stream bytes if type is picture or video, plain text if type is text

" } ] } @@ -2165,11 +2158,12 @@ "type": "int32", "optional": false, "field": "way", - "description": "

1 for only pull message
2 for read message
3 for query history message

" + "description": "

1 for read message
2 for query history message
Note: only 1 will set unread to false

" }, { "group": "Parameter", - "type": "int32", + "type": "uint32", + "size": "0-20", "optional": false, "field": "limit", "defaultValue": "20", @@ -2177,7 +2171,7 @@ }, { "group": "Parameter", - "type": "int32", + "type": "uint32", "optional": false, "field": "offset", "defaultValue": "0", @@ -2249,7 +2243,7 @@ }, { "group": "MessageInfo", - "type": "string", + "type": "bytes", "optional": false, "field": "text", "description": "

plain message text if type is text
fileID if type is picture or video

" @@ -2286,7 +2280,7 @@ "version": "1.0.0", "group": "Service", "name": "Message_Query", - "description": "

Query New Message

", + "description": "

Query New Message, do NOT set read

", "parameter": { "fields": { "Parameter": [ @@ -2345,7 +2339,7 @@ "type": "MessageInfo", "optional": false, "field": "info", - "description": "

see below MessageInfo

" + "description": "

newest one msg for each dialog, see below MessageInfo

" } ], "MessageInfo": [ @@ -2382,7 +2376,7 @@ "type": "bool", "optional": false, "field": "unread", - "description": "

false for having read
true for not having read

" + "description": "

always true

" } ] } diff --git a/backend/doc/api_project.js b/backend/doc/api_project.js index d7f1c53..3e50ee3 100644 --- a/backend/doc/api_project.js +++ b/backend/doc/api_project.js @@ -21,7 +21,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T08:56:23.414Z", + "time": "2019-08-01T17:54:38.573Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/api_project.json b/backend/doc/api_project.json index fe37563..bb5f1ae 100644 --- a/backend/doc/api_project.json +++ b/backend/doc/api_project.json @@ -21,7 +21,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T08:56:23.414Z", + "time": "2019-08-01T17:54:38.573Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/css/style.css b/backend/doc/css/style.css new file mode 100644 index 0000000..6468b2b --- /dev/null +++ b/backend/doc/css/style.css @@ -0,0 +1,569 @@ +/* ------------------------------------------------------------------------------------------ + * Content + * ------------------------------------------------------------------------------------------ */ +body { + min-width: 980px; + max-width: 1280px; +} + +body, p, a, div, th, td { + font-family: "Source Sans Pro", sans-serif; + font-weight: 400; + font-size: 16px; +} + +td.code { + font-size: 14px; + font-family: "Source Code Pro", monospace; + font-style: normal; + font-weight: 400; +} + +#content { + padding-top: 16px; + z-Index: -1; + margin-left: 270px; +} + +p { + color: #808080; +} + +h1 { + font-family: "Source Sans Pro Semibold", sans-serif; + font-weight: normal; + font-size: 44px; + line-height: 50px; + margin: 0 0 10px 0; + padding: 0; +} + +h2 { + font-family: "Source Sans Pro", sans-serif; + font-weight: normal; + font-size: 24px; + line-height: 40px; + margin: 0 0 20px 0; + padding: 0; +} + +section { + border-top: 1px solid #ebebeb; + padding: 30px 0; +} + +section h1 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 700; + font-size: 32px; + line-height: 40px; + padding-bottom: 14px; + margin: 0 0 20px 0; + padding: 0; +} + +article { + padding: 14px 0 30px 0; +} + +article h1 { + font-family: "Source Sans Pro Bold", sans-serif; + font-weight: 600; + font-size: 24px; + line-height: 26px; +} + +article h2 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; + font-size: 18px; + line-height: 24px; + margin: 0 0 10px 0; +} + +article h3 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; + font-size: 16px; + line-height: 18px; + margin: 0 0 10px 0; +} + +article h4 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; + font-size: 14px; + line-height: 16px; + margin: 0 0 8px 0; +} + +table { + border-collapse: collapse; + width: 100%; + margin: 0 0 20px 0; +} + +th { + background-color: #f5f5f5; + text-align: left; + font-family: "Source Sans Pro", sans-serif; + font-weight: 700; + padding: 4px 8px; + border: #e0e0e0 1px solid; +} + +td { + vertical-align: top; + padding: 10px 8px 0 8px; + border: #e0e0e0 1px solid; +} + +#generator .content { + color: #b0b0b0; + border-top: 1px solid #ebebeb; + padding: 10px 0; +} + +.label-optional { + float: right; + background-color: grey; + margin-top: 4px; +} + +.open-left { + right: 0; + left: auto; +} + +/* ------------------------------------------------------------------------------------------ + * apidoc - intro + * ------------------------------------------------------------------------------------------ */ + +#apidoc .apidoc { + border-top: 1px solid #ebebeb; + padding: 30px 0; +} + +#apidoc h1 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 700; + font-size: 32px; + line-height: 40px; + padding-bottom: 14px; + margin: 0 0 20px 0; + padding: 0; +} + +#apidoc h2 { + font-family: "Source Sans Pro Bold", sans-serif; + font-weight: 600; + font-size: 22px; + line-height: 26px; + padding-top: 14px; +} + +/* ------------------------------------------------------------------------------------------ + * pre / code + * ------------------------------------------------------------------------------------------ */ +pre { + background-color: #292b36; + color: #ffffff; + padding: 10px; + border-radius: 6px; + position: relative; + margin: 10px 0 20px 0; + overflow-x: auto; +} + +pre.prettyprint { + width: 100%; +} + +code.language-text { + word-wrap: break-word; +} + +pre.language-json { + overflow: auto; +} + +pre.language-html { + margin: 0 0 20px 0; +} + +.type { + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; + font-size: 15px; + display: inline-block; + margin: 0 0 5px 0; + padding: 4px 5px; + border-radius: 6px; + text-transform: uppercase; + background-color: #3387CC; + color: #ffffff; +} + +.type__get { + background-color: green; +} + +.type__put { + background-color: #e5c500; +} + +.type__post { + background-color: #4070ec; +} + +.type__delete { + background-color: #ed0039; +} + +pre.language-api .str { + color: #ffffff; +} + +pre.language-api .pln, +pre.language-api .pun { + color: #65B042; +} + +pre code { + display: block; + font-size: 14px; + font-family: "Source Code Pro", monospace; + font-style: normal; + font-weight: 400; + word-wrap: normal; + white-space: pre; +} + +pre code.sample-request-response-json { + white-space: pre-wrap; + max-height: 500px; + overflow: auto; +} + +/* ------------------------------------------------------------------------------------------ + * Sidenav + * ------------------------------------------------------------------------------------------ */ +.sidenav { + width: 228px; + margin: 0; + padding: 0 20px 20px 20px; + position: fixed; + top: 50px; + left: 0; + bottom: 0; + overflow-x: hidden; + overflow-y: auto; + background-color: #f5f5f5; + z-index: 10; +} + +.sidenav > li > a { + display: block; + width: 192px; + margin: 0; + padding: 2px 11px; + border: 0; + border-left: transparent 4px solid; + border-right: transparent 4px solid; + font-family: "Source Sans Pro", sans-serif; + font-weight: 400; + font-size: 14px; +} + +.sidenav > li.nav-header { + margin-top: 8px; + margin-bottom: 8px; +} + +.sidenav > li.nav-header > a { + padding: 5px 15px; + border: 1px solid #e5e5e5; + width: 190px; + font-family: "Source Sans Pro", sans-serif; + font-weight: 700; + font-size: 16px; + background-color: #ffffff; +} + +.sidenav > li.active > a { + position: relative; + z-index: 2; + background-color: #0088cc; + color: #ffffff; +} + +.sidenav > li.has-modifications a { + border-right: #60d060 4px solid; +} + +.sidenav > li.is-new a { + border-left: #e5e5e5 4px solid; +} + +/* ------------------------------------------------------------------------------------------ + * Side nav search + * ------------------------------------------------------------------------------------------ */ +.sidenav-search { + width: 228px; + left: 0px; + position: fixed; + padding: 16px 20px 10px 20px; + background-color: #F5F5F5; + z-index: 11; +} + +.sidenav-search .search { + height: 26px; +} + +.search-reset { + position: absolute; + display: block; + cursor: pointer; + width: 20px; + height: 20px; + text-align: center; + right: 28px; + top: 17px; + background-color: #fff; +} + +/* ------------------------------------------------------------------------------------------ + * Compare + * ------------------------------------------------------------------------------------------ */ + +ins { + background: #60d060; + text-decoration: none; + color: #000000; +} + +del { + background: #f05050; + color: #000000; +} + +.label-ins { + background-color: #60d060; +} + +.label-del { + background-color: #f05050; + text-decoration: line-through; +} + +pre.ins { + background-color: #60d060; +} + +pre.del { + background-color: #f05050; + text-decoration: line-through; +} + +table.ins th, +table.ins td { + background-color: #60d060; +} + +table.del th, +table.del td { + background-color: #f05050; + text-decoration: line-through; +} + +tr.ins td { + background-color: #60d060; +} + +tr.del td { + background-color: #f05050; + text-decoration: line-through; +} + +/* ------------------------------------------------------------------------------------------ + * Spinner + * ------------------------------------------------------------------------------------------ */ + +#loader { + position: absolute; + width: 100%; +} + +#loader p { + padding-top: 80px; + margin-left: -4px; +} + +.spinner { + margin: 200px auto; + width: 60px; + height: 60px; + position: relative; +} + +.container1 > div, .container2 > div, .container3 > div { + width: 14px; + height: 14px; + background-color: #0088cc; + + border-radius: 100%; + position: absolute; + -webkit-animation: bouncedelay 1.2s infinite ease-in-out; + animation: bouncedelay 1.2s infinite ease-in-out; + /* Prevent first frame from flickering when animation starts */ + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +.spinner .spinner-container { + position: absolute; + width: 100%; + height: 100%; +} + +.container2 { + -webkit-transform: rotateZ(45deg); + transform: rotateZ(45deg); +} + +.container3 { + -webkit-transform: rotateZ(90deg); + transform: rotateZ(90deg); +} + +.circle1 { top: 0; left: 0; } +.circle2 { top: 0; right: 0; } +.circle3 { right: 0; bottom: 0; } +.circle4 { left: 0; bottom: 0; } + +.container2 .circle1 { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; +} + +.container3 .circle1 { + -webkit-animation-delay: -1.0s; + animation-delay: -1.0s; +} + +.container1 .circle2 { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; +} + +.container2 .circle2 { + -webkit-animation-delay: -0.8s; + animation-delay: -0.8s; +} + +.container3 .circle2 { + -webkit-animation-delay: -0.7s; + animation-delay: -0.7s; +} + +.container1 .circle3 { + -webkit-animation-delay: -0.6s; + animation-delay: -0.6s; +} + +.container2 .circle3 { + -webkit-animation-delay: -0.5s; + animation-delay: -0.5s; +} + +.container3 .circle3 { + -webkit-animation-delay: -0.4s; + animation-delay: -0.4s; +} + +.container1 .circle4 { + -webkit-animation-delay: -0.3s; + animation-delay: -0.3s; +} + +.container2 .circle4 { + -webkit-animation-delay: -0.2s; + animation-delay: -0.2s; +} + +.container3 .circle4 { + -webkit-animation-delay: -0.1s; + animation-delay: -0.1s; +} + +@-webkit-keyframes bouncedelay { + 0%, 80%, 100% { -webkit-transform: scale(0.0) } + 40% { -webkit-transform: scale(1.0) } +} + +@keyframes bouncedelay { + 0%, 80%, 100% { + transform: scale(0.0); + -webkit-transform: scale(0.0); + } 40% { + transform: scale(1.0); + -webkit-transform: scale(1.0); + } +} + +/* ------------------------------------------------------------------------------------------ + * Tabs + * ------------------------------------------------------------------------------------------ */ +ul.nav-tabs { + margin: 0; +} + +p.deprecated span{ + color: #ff0000; + font-weight: bold; + text-decoration: underline; +} + +/* ------------------------------------------------------------------------------------------ + * Print + * ------------------------------------------------------------------------------------------ */ + +@media print { + + #sidenav, + #version, + #versions, + section .version, + section .versions { + display: none; + } + + #content { + margin-left: 0; + } + + a { + text-decoration: none; + color: inherit; + } + + a:after { + content: " [" attr(href) "] "; + } + + p { + color: #000000 + } + + pre { + background-color: #ffffff; + color: #000000; + padding: 10px; + border: #808080 1px solid; + border-radius: 6px; + position: relative; + margin: 10px 0 20px 0; + } + +} /* /@media print */ diff --git a/backend/srv/content/main.go b/backend/srv/content/main.go index 08b6520..4caa822 100644 --- a/backend/srv/content/main.go +++ b/backend/srv/content/main.go @@ -67,7 +67,7 @@ func (a *srv) Create(ctx context.Context, req *content.ContentCreateRequest, rsp return nil } - if !utils.CheckInTest() && !filetype.IsImage(req.Content) && !filetype.IsVideo(req.Content) { + if !utils.CheckFile(req.Content, filetype.IsImage, filetype.IsVideo) { rsp.Status = content.ContentCreateResponse_INVALID_TYPE return nil } diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index f0855c2..7b4002e 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "errors" db "jiaojiao/database" "jiaojiao/srv/file/mock" file "jiaojiao/srv/file/proto" @@ -9,6 +10,7 @@ import ( "jiaojiao/utils" "time" + "github.com/h2non/filetype" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/bson/primitive" @@ -21,11 +23,11 @@ import ( type srv struct{} type MsgInfo struct { - Time time.Time `bson:"time"` - Forward bool `bson:"forward"` - Type message.MessageInfo_Type `bson:"type"` - Text string `bson:"text"` - Unread bool `bson:"unread"` + Time time.Time `bson:"time"` + Forward bool `bson:"forward"` + Type message.Type `bson:"type"` + Msg string `bson:"msg"` + Unread bool `bson:"unread"` } type ChatLog struct { @@ -46,35 +48,42 @@ type ChatLog struct { * @apiParam {int32} fromUser user who launch the chat at first time * @apiParam {int32} toUser user who accept the chat at first time * @apiParam {int32} type 1 for text
2 for picture
3 for video - * @apiParam {string} [text] plain message text if type is text - * @apiParam {bytes} [file] file stream bytes, valid only if type is picture or video + * @apiParam {bytes} msg file stream bytes if type is picture or video, plain text if type is text * @apiSuccess {int32} status -1 for invalid param
1 for success * @apiUse DBServerDown */ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp *message.MessageCreateResponse) error { - if !utils.RequireParam(req.FromUser, req.ToUser, req.Type) { + if !utils.RequireParam(req.FromUser, req.ToUser, req.Type, req.Msg) || req.FromUser == req.ToUser { rsp.Status = message.MessageCreateResponse_INVALID_PARAM return nil } - if req.Type == message.MessageCreateRequest_TEXT && !utils.RequireParam(req.Text) { - rsp.Status = message.MessageCreateResponse_INVALID_PARAM + if (req.Type == message.Type_PICTURE && !utils.CheckFile(req.Msg, filetype.IsImage)) || + (req.Type == message.Type_VIDEO && !utils.CheckFile(req.Msg, filetype.IsVideo)) { + rsp.Status = message.MessageCreateResponse_INVALID_TYPE return nil } - if req.Type == message.MessageCreateRequest_PICTURE || req.Type == message.MessageCreateRequest_VIDEO { + + // upload file + if req.Type == message.Type_PICTURE || req.Type == message.Type_VIDEO { srv := utils.CallMicroService("file", func(name string, c client.Client) interface{} { return file.NewFileService(name, c) }, func() interface{} { return mock.NewFileService() }).(file.FileService) microRsp, err := srv.Create(context.TODO(), &file.FileCreateRequest{ - File: req.File, + File: req.Msg, }) - if err != nil || microRsp.Status != file.FileCreateResponse_SUCCESS { - rsp.Status = message.MessageCreateResponse_INVALID_PARAM - return nil + if utils.LogContinue(err, utils.Error) { + return err } - req.Text = microRsp.FileID + if microRsp.Status != file.FileCreateResponse_SUCCESS { + _, s := utils.LogContinueS("File create return "+microRsp.Status.String(), utils.Error) + return errors.New(s) + } + + req.Msg = []byte(microRsp.FileID) } + // find existence ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() collection := db.MongoDatabase.Collection("message") @@ -88,77 +97,13 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp "toUser": req.FromUser, }).Decode(&res2) - if err1 == nil && err2 != nil { //fromUser to toUser - _, err := collection.UpdateOne(ctx, bson.M{ - "fromUser": req.FromUser, - "toUser": req.ToUser, - }, bson.M{"$push": bson.M{ - "infos": bson.M{ - "$each": bson.A{ - bson.M{ - "time": time.Now(), - "forward": true, - "type": req.Type, - "text": req.Text, - "unread": true, - }, - }, - "$position": 0, - }, - }}) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageCreateResponse_UNKNOWN - return nil - } - - _, err = collection.UpdateOne(ctx, bson.M{ - "fromUser": req.FromUser, - "toUser": req.ToUser, - }, bson.M{"$set": bson.M{ - "badge": res1.Badge + 1, - }}) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageCreateResponse_UNKNOWN - return nil - } - rsp.Status = message.MessageCreateResponse_SUCCESS - return nil - } else if err1 != nil && err2 == nil { //toUser to fromUser - _, err := collection.UpdateOne(ctx, bson.M{ - "fromUser": req.ToUser, - "toUser": req.FromUser, - }, bson.M{"$push": bson.M{ - "infos": bson.M{ - "$each": bson.A{ - bson.M{ - "time": time.Now(), - "forward": false, - "type": req.Type, - "text": req.Text, - "unread": true, - }, - }, - "$position": 0, - }, - }}) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageCreateResponse_UNKNOWN - return nil - } + if err1 == nil && err2 == nil { + utils.Error("chat structure violated") + return errors.New("chat structure violated") + } - _, err = collection.UpdateOne(ctx, bson.M{ - "fromUser": req.ToUser, - "toUser": req.FromUser, - }, bson.M{"$set": bson.M{ - "badge": res2.Badge + 1, - }}) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageCreateResponse_UNKNOWN - return nil - } - rsp.Status = message.MessageCreateResponse_SUCCESS - return nil - } else if err1 != nil && err2 != nil { //new chat + // new chat + if err1 != nil && err2 != nil { _, err := collection.InsertOne(ctx, bson.M{ "fromUser": req.FromUser, "toUser": req.ToUser, @@ -167,19 +112,58 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp "time": time.Now(), "forward": true, "type": req.Type, - "text": req.Text, + "msg": string(req.Msg), "unread": true, }}, }) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageCreateResponse_UNKNOWN - return nil + if utils.LogContinue(err, utils.Error) { + return err } rsp.Status = message.MessageCreateResponse_SUCCESS return nil - } else { - rsp.Status = message.MessageCreateResponse_INVALID_PARAM } + + // exist + from := req.FromUser + to := req.ToUser + forward := true + if err1 != nil && err2 == nil { + from = req.ToUser + to = req.FromUser + forward = false + } + + _, err := collection.UpdateOne(ctx, bson.M{ + "fromUser": from, + "toUser": to, + }, bson.M{"$push": bson.M{ + "infos": bson.M{ + "$each": bson.A{ + bson.M{ + "time": time.Now(), + "forward": forward, + "type": req.Type, + "msg": string(req.Msg), + "unread": true, + }, + }, + "$position": 0, + }, + }}) + if utils.LogContinue(err, utils.Error) { + return err + } + + _, err = collection.UpdateOne(ctx, bson.M{ + "fromUser": from, + "toUser": to, + }, bson.M{"$set": bson.M{ + "badge": res1.Badge + 1, + }}) + if utils.LogContinue(err, utils.Error) { + return err + } + rsp.Status = message.MessageCreateResponse_SUCCESS return nil } @@ -192,9 +176,9 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp * * @apiParam {int32} fromUser user who launch the chat at first time * @apiParam {int32} toUser user who accept the chat at first time - * @apiParam {int32} way 1 for only pull message
2 for read message
3 for query history message - * @apiParam {int32} limit=20 limit of return message infos, only for history query - * @apiParam {int32} offset=0 offset from the latest message info, only for history query + * @apiParam {int32} way 1 for read message
2 for query history message
Note: only 1 will set unread to false + * @apiParam {uint32{0-20}} limit=20 limit of return message infos, only for history query + * @apiParam {uint32} offset=0 offset from the latest message info, only for history query * @apiSuccess {int32} fromUser user who launch the chat at first time * @apiSuccess {int32} toUser user who accept the chat at first time * @apiSuccess {int32} badge count of message still unread @@ -203,7 +187,7 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp * @apiSuccess (MessageInfo) {int64} time message create time * @apiSuccess (MessageInfo) {bool} forward false for chat from toUser to fromUser
true for chat from fromUser to toUser * @apiSuccess (MessageInfo) {int32} type 1 for text
2 for picture
3 for video - * @apiSuccess (MessageInfo) {string} text plain message text if type is text
fileID if type is picture or video + * @apiSuccess (MessageInfo) {bytes} text plain message text if type is text
fileID if type is picture or video * @apiSuccess (MessageInfo) {bool} unread false for having read
true for not having read * @apiUse DBServerDown */ @@ -215,6 +199,9 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me if req.Limit == 0 { req.Limit = 20 } + if req.Limit > 20 { + req.Limit = 20 + } decodeRes := func(src *ChatLog, dest *message.MessageFindResponse) { dest.FromUser = src.FromUser @@ -225,7 +212,7 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me Time: v.Time.Unix(), Forward: v.Forward, Type: v.Type, - Text: v.Text, + Msg: v.Msg, Unread: v.Unread, }) } @@ -251,14 +238,14 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me rsp.FromUser = req.ToUser rsp.ToUser = req.FromUser } else if err1 != nil && err2 != nil { - rsp.Status = message.MessageFindResponse_NOT_FOUND + rsp.Status = message.MessageFindResponse_SUCCESS return nil } else { rsp.Status = message.MessageFindResponse_INVALID_PARAM return nil } - if req.Way == message.MessageFindRequest_ONLY_PULL || req.Way == message.MessageFindRequest_READ_MESSAGE { + if req.Way == message.MessageFindRequest_READ_MESSAGE { var res ChatLog cur, err := collection.Aggregate(ctx, bson.A{ bson.M{ @@ -287,46 +274,39 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me }, }, }) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageFindResponse_UNKNOWN - return nil + if utils.LogContinue(err, utils.Error) { + return err } cur.Next(ctx) err = cur.Decode(&res) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageFindResponse_UNKNOWN - return nil + if utils.LogContinue(err, utils.Error) { + return err } decodeRes(&res, rsp) - if req.Way == message.MessageFindRequest_READ_MESSAGE { - _, err := collection.UpdateMany(ctx, bson.M{ - "fromUser": rsp.FromUser, - "toUser": rsp.ToUser, - "infos.forward": req.FromUser == rsp.FromUser, - "infos.unread": true, - }, bson.M{ - "$set": bson.M{ - "badge": 0, - "infos.$[elem].unread": false, - }, - }, &options.UpdateOptions{ - ArrayFilters: &options.ArrayFilters{ - Filters: bson.A{bson.M{ - "elem.forward": req.FromUser == rsp.FromUser, - "elem.unread": true, - }}, - }, - }) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageFindResponse_UNKNOWN - return nil - } + _, err = collection.UpdateMany(ctx, bson.M{ + "fromUser": rsp.FromUser, + "toUser": rsp.ToUser, + "infos.forward": req.FromUser == rsp.FromUser, + "infos.unread": true, + }, bson.M{ + "$set": bson.M{ + "badge": 0, + "infos.$[elem].unread": false, + }, + }, &options.UpdateOptions{ + ArrayFilters: &options.ArrayFilters{ + Filters: bson.A{bson.M{ + "elem.forward": req.FromUser == rsp.FromUser, + "elem.unread": true, + }}, + }, + }) + if utils.LogContinue(err, utils.Error) { + return err } - rsp.Status = message.MessageFindResponse_SUCCESS - return nil - } else if req.Way == message.MessageFindRequest_HISTORY { + } else { var res ChatLog err := collection.FindOne(ctx, bson.M{ "fromUser": rsp.FromUser, @@ -338,15 +318,13 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me }, }, }).Decode(&res) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageFindResponse_UNKNOWN - return nil + if utils.LogContinue(err, utils.Error) { + return err } decodeRes(&res, rsp) - rsp.Status = message.MessageFindResponse_SUCCESS - return nil } + rsp.Status = message.MessageFindResponse_SUCCESS return nil } @@ -355,7 +333,7 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me * @apiVersion 1.0.0 * @apiGroup Service * @apiName Message.Query - * @apiDescription Query New Message + * @apiDescription Query New Message, do NOT set read * * @apiParam {int32} userID user who wants to pull new message * @apiSuccess {int32} status -1 for invalid param
1 for success
2 for not found @@ -363,12 +341,12 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me * @apiSuccess (NewMessage) {int32} fromUser user who launch the chat at first time * @apiSuccess (NewMessage) {int32} toUser user who accept the chat at first time * @apiSuccess (NewMessage) {int32} badge count of message still unread - * @apiSuccess (NewMessage) {MessageInfo} info see below MessageInfo + * @apiSuccess (NewMessage) {MessageInfo} info newest one msg for each dialog, see below MessageInfo * @apiSuccess (MessageInfo) {int64} time message create time * @apiSuccess (MessageInfo) {bool} forward false for chat from toUser to fromUser
true for chat from fromUser to toUser * @apiSuccess (MessageInfo) {int32} type 1 for text
2 for picture
3 for video * @apiSuccess (MessageInfo) {string} text plain message text if type is text
fileID if type is picture or video - * @apiSuccess (MessageInfo) {bool} unread false for having read
true for not having read + * @apiSuccess (MessageInfo) {bool} unread always true * @apiUse DBServerDown */ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp *message.MessageQueryResponse) error { @@ -385,7 +363,7 @@ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp * Time: src.Infos[0].Time.Unix(), Forward: src.Infos[0].Forward, Type: src.Infos[0].Type, - Text: src.Infos[0].Text, + Msg: src.Infos[0].Msg, Unread: src.Infos[0].Unread, } } @@ -422,28 +400,22 @@ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp * "$slice": 1, }, }}) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageQueryResponse_NOT_FOUND - return nil + if utils.LogContinue(err, utils.Error) { + return err } for cur.Next(ctx) { var res ChatLog var newMessage message.NewMessage err = cur.Decode(&res) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = message.MessageQueryResponse_UNKNOWN - return nil + if utils.LogContinue(err, utils.Error) { + return err } decodeRes(&res, &newMessage) rsp.News = append(rsp.News, &newMessage) } - if rsp.News == nil || len(rsp.News) == 0 { - rsp.Status = message.MessageQueryResponse_NOT_FOUND - return nil - } rsp.Status = message.MessageQueryResponse_SUCCESS return nil } diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index d1f6cc5..940cc3f 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -36,7 +36,7 @@ func TestCreate(t *testing.T) { So(chat.Badge, ShouldEqual, 3) So(len(chat.Infos), ShouldEqual, 3) So(chat.Infos[0].Forward, ShouldEqual, false) - So(chat.Infos[1].Text, ShouldEqual, "1234567890abcdef12345678") + So(chat.Infos[1].Msg, ShouldEqual, "1234567890abcdef12345678") } Convey("Test Create Message", t, func() { diff --git a/backend/srv/message/proto/message.pb.go b/backend/srv/message/proto/message.pb.go index cf30b37..4c39b35 100644 --- a/backend/srv/message/proto/message.pb.go +++ b/backend/srv/message/proto/message.pb.go @@ -20,66 +20,35 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package -type MessageInfo_Type int32 +type Type int32 const ( - MessageInfo_UNKNOWN MessageInfo_Type = 0 - MessageInfo_TEXT MessageInfo_Type = 1 - MessageInfo_PICTURE MessageInfo_Type = 2 - MessageInfo_VIDEO MessageInfo_Type = 3 + Type_UNKNOWN Type = 0 + Type_TEXT Type = 1 + Type_PICTURE Type = 2 + Type_VIDEO Type = 3 ) -var MessageInfo_Type_name = map[int32]string{ +var Type_name = map[int32]string{ 0: "UNKNOWN", 1: "TEXT", 2: "PICTURE", 3: "VIDEO", } -var MessageInfo_Type_value = map[string]int32{ +var Type_value = map[string]int32{ "UNKNOWN": 0, "TEXT": 1, "PICTURE": 2, "VIDEO": 3, } -func (x MessageInfo_Type) String() string { - return proto.EnumName(MessageInfo_Type_name, int32(x)) +func (x Type) String() string { + return proto.EnumName(Type_name, int32(x)) } -func (MessageInfo_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_33c57e4bae7b9afd, []int{0, 0} -} - -type MessageCreateRequest_Type int32 - -const ( - MessageCreateRequest_UNKNOWN MessageCreateRequest_Type = 0 - MessageCreateRequest_TEXT MessageCreateRequest_Type = 1 - MessageCreateRequest_PICTURE MessageCreateRequest_Type = 2 - MessageCreateRequest_VIDEO MessageCreateRequest_Type = 3 -) - -var MessageCreateRequest_Type_name = map[int32]string{ - 0: "UNKNOWN", - 1: "TEXT", - 2: "PICTURE", - 3: "VIDEO", -} - -var MessageCreateRequest_Type_value = map[string]int32{ - "UNKNOWN": 0, - "TEXT": 1, - "PICTURE": 2, - "VIDEO": 3, -} - -func (x MessageCreateRequest_Type) String() string { - return proto.EnumName(MessageCreateRequest_Type_name, int32(x)) -} - -func (MessageCreateRequest_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_33c57e4bae7b9afd, []int{1, 0} +func (Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_33c57e4bae7b9afd, []int{0} } type MessageCreateResponse_Status int32 @@ -88,18 +57,21 @@ const ( MessageCreateResponse_UNKNOWN MessageCreateResponse_Status = 0 MessageCreateResponse_INVALID_PARAM MessageCreateResponse_Status = -1 MessageCreateResponse_SUCCESS MessageCreateResponse_Status = 1 + MessageCreateResponse_INVALID_TYPE MessageCreateResponse_Status = 2 ) var MessageCreateResponse_Status_name = map[int32]string{ 0: "UNKNOWN", -1: "INVALID_PARAM", 1: "SUCCESS", + 2: "INVALID_TYPE", } var MessageCreateResponse_Status_value = map[string]int32{ "UNKNOWN": 0, "INVALID_PARAM": -1, "SUCCESS": 1, + "INVALID_TYPE": 2, } func (x MessageCreateResponse_Status) String() string { @@ -114,23 +86,20 @@ type MessageFindRequest_Way int32 const ( MessageFindRequest_UNKNOWN MessageFindRequest_Way = 0 - MessageFindRequest_ONLY_PULL MessageFindRequest_Way = 1 - MessageFindRequest_READ_MESSAGE MessageFindRequest_Way = 2 - MessageFindRequest_HISTORY MessageFindRequest_Way = 3 + MessageFindRequest_READ_MESSAGE MessageFindRequest_Way = 1 + MessageFindRequest_HISTORY MessageFindRequest_Way = 2 ) var MessageFindRequest_Way_name = map[int32]string{ 0: "UNKNOWN", - 1: "ONLY_PULL", - 2: "READ_MESSAGE", - 3: "HISTORY", + 1: "READ_MESSAGE", + 2: "HISTORY", } var MessageFindRequest_Way_value = map[string]int32{ "UNKNOWN": 0, - "ONLY_PULL": 1, - "READ_MESSAGE": 2, - "HISTORY": 3, + "READ_MESSAGE": 1, + "HISTORY": 2, } func (x MessageFindRequest_Way) String() string { @@ -147,21 +116,18 @@ const ( MessageFindResponse_UNKNOWN MessageFindResponse_Status = 0 MessageFindResponse_INVALID_PARAM MessageFindResponse_Status = -1 MessageFindResponse_SUCCESS MessageFindResponse_Status = 1 - MessageFindResponse_NOT_FOUND MessageFindResponse_Status = 2 ) var MessageFindResponse_Status_name = map[int32]string{ 0: "UNKNOWN", -1: "INVALID_PARAM", 1: "SUCCESS", - 2: "NOT_FOUND", } var MessageFindResponse_Status_value = map[string]int32{ "UNKNOWN": 0, "INVALID_PARAM": -1, "SUCCESS": 1, - "NOT_FOUND": 2, } func (x MessageFindResponse_Status) String() string { @@ -178,21 +144,18 @@ const ( MessageQueryResponse_UNKNOWN MessageQueryResponse_Status = 0 MessageQueryResponse_INVALID_PARAM MessageQueryResponse_Status = -1 MessageQueryResponse_SUCCESS MessageQueryResponse_Status = 1 - MessageQueryResponse_NOT_FOUND MessageQueryResponse_Status = 2 ) var MessageQueryResponse_Status_name = map[int32]string{ 0: "UNKNOWN", -1: "INVALID_PARAM", 1: "SUCCESS", - 2: "NOT_FOUND", } var MessageQueryResponse_Status_value = map[string]int32{ "UNKNOWN": 0, "INVALID_PARAM": -1, "SUCCESS": 1, - "NOT_FOUND": 2, } func (x MessageQueryResponse_Status) String() string { @@ -204,14 +167,14 @@ func (MessageQueryResponse_Status) EnumDescriptor() ([]byte, []int) { } type MessageInfo struct { - Time int64 `protobuf:"varint,1,opt,name=time,proto3" json:"time,omitempty"` - Forward bool `protobuf:"varint,2,opt,name=forward,proto3" json:"forward,omitempty"` - Type MessageInfo_Type `protobuf:"varint,3,opt,name=type,proto3,enum=MessageInfo_Type" json:"type,omitempty"` - Text string `protobuf:"bytes,4,opt,name=text,proto3" json:"text,omitempty"` - Unread bool `protobuf:"varint,5,opt,name=unread,proto3" json:"unread,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Time int64 `protobuf:"varint,1,opt,name=time,proto3" json:"time,omitempty"` + Forward bool `protobuf:"varint,2,opt,name=forward,proto3" json:"forward,omitempty"` + Type Type `protobuf:"varint,3,opt,name=type,proto3,enum=Type" json:"type,omitempty"` + Msg string `protobuf:"bytes,4,opt,name=msg,proto3" json:"msg,omitempty"` + Unread bool `protobuf:"varint,5,opt,name=unread,proto3" json:"unread,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *MessageInfo) Reset() { *m = MessageInfo{} } @@ -253,16 +216,16 @@ func (m *MessageInfo) GetForward() bool { return false } -func (m *MessageInfo) GetType() MessageInfo_Type { +func (m *MessageInfo) GetType() Type { if m != nil { return m.Type } - return MessageInfo_UNKNOWN + return Type_UNKNOWN } -func (m *MessageInfo) GetText() string { +func (m *MessageInfo) GetMsg() string { if m != nil { - return m.Text + return m.Msg } return "" } @@ -275,14 +238,13 @@ func (m *MessageInfo) GetUnread() bool { } type MessageCreateRequest struct { - FromUser int32 `protobuf:"varint,1,opt,name=fromUser,proto3" json:"fromUser,omitempty"` - ToUser int32 `protobuf:"varint,2,opt,name=toUser,proto3" json:"toUser,omitempty"` - Type MessageCreateRequest_Type `protobuf:"varint,3,opt,name=type,proto3,enum=MessageCreateRequest_Type" json:"type,omitempty"` - Text string `protobuf:"bytes,4,opt,name=text,proto3" json:"text,omitempty"` - File []byte `protobuf:"bytes,5,opt,name=file,proto3" json:"file,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + FromUser int32 `protobuf:"varint,1,opt,name=fromUser,proto3" json:"fromUser,omitempty"` + ToUser int32 `protobuf:"varint,2,opt,name=toUser,proto3" json:"toUser,omitempty"` + Type Type `protobuf:"varint,3,opt,name=type,proto3,enum=Type" json:"type,omitempty"` + Msg []byte `protobuf:"bytes,4,opt,name=msg,proto3" json:"msg,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *MessageCreateRequest) Reset() { *m = MessageCreateRequest{} } @@ -324,23 +286,16 @@ func (m *MessageCreateRequest) GetToUser() int32 { return 0 } -func (m *MessageCreateRequest) GetType() MessageCreateRequest_Type { +func (m *MessageCreateRequest) GetType() Type { if m != nil { return m.Type } - return MessageCreateRequest_UNKNOWN -} - -func (m *MessageCreateRequest) GetText() string { - if m != nil { - return m.Text - } - return "" + return Type_UNKNOWN } -func (m *MessageCreateRequest) GetFile() []byte { +func (m *MessageCreateRequest) GetMsg() []byte { if m != nil { - return m.File + return m.Msg } return nil } @@ -388,8 +343,8 @@ type MessageFindRequest struct { FromUser int32 `protobuf:"varint,1,opt,name=fromUser,proto3" json:"fromUser,omitempty"` ToUser int32 `protobuf:"varint,2,opt,name=toUser,proto3" json:"toUser,omitempty"` Way MessageFindRequest_Way `protobuf:"varint,3,opt,name=way,proto3,enum=MessageFindRequest_Way" json:"way,omitempty"` - Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` - Offset int32 `protobuf:"varint,5,opt,name=offset,proto3" json:"offset,omitempty"` + Limit uint32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` + Offset uint32 `protobuf:"varint,5,opt,name=offset,proto3" json:"offset,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -441,14 +396,14 @@ func (m *MessageFindRequest) GetWay() MessageFindRequest_Way { return MessageFindRequest_UNKNOWN } -func (m *MessageFindRequest) GetLimit() int32 { +func (m *MessageFindRequest) GetLimit() uint32 { if m != nil { return m.Limit } return 0 } -func (m *MessageFindRequest) GetOffset() int32 { +func (m *MessageFindRequest) GetOffset() uint32 { if m != nil { return m.Offset } @@ -676,8 +631,7 @@ func (m *MessageQueryResponse) GetNews() []*NewMessage { } func init() { - proto.RegisterEnum("MessageInfo_Type", MessageInfo_Type_name, MessageInfo_Type_value) - proto.RegisterEnum("MessageCreateRequest_Type", MessageCreateRequest_Type_name, MessageCreateRequest_Type_value) + proto.RegisterEnum("Type", Type_name, Type_value) proto.RegisterEnum("MessageCreateResponse_Status", MessageCreateResponse_Status_name, MessageCreateResponse_Status_value) proto.RegisterEnum("MessageFindRequest_Way", MessageFindRequest_Way_name, MessageFindRequest_Way_value) proto.RegisterEnum("MessageFindResponse_Status", MessageFindResponse_Status_name, MessageFindResponse_Status_value) @@ -695,46 +649,44 @@ func init() { func init() { proto.RegisterFile("message.proto", fileDescriptor_33c57e4bae7b9afd) } var fileDescriptor_33c57e4bae7b9afd = []byte{ - // 655 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xdf, 0x6e, 0x12, 0x4f, - 0x14, 0xc7, 0x7f, 0xb3, 0x7f, 0xa0, 0x3d, 0xb4, 0xcd, 0xfe, 0xa6, 0xb4, 0x6e, 0x50, 0x23, 0x99, - 0xc4, 0x04, 0x2f, 0x9c, 0x44, 0xda, 0xc6, 0x3b, 0x23, 0x01, 0xaa, 0x1b, 0x61, 0xa9, 0xb3, 0xd0, - 0xda, 0x2b, 0xb2, 0x0d, 0xb3, 0x0d, 0x49, 0x61, 0x71, 0x67, 0x09, 0xe5, 0x09, 0xbc, 0xf3, 0x45, - 0x7c, 0x05, 0x6f, 0x7d, 0x08, 0xaf, 0x7d, 0x10, 0xcd, 0x0e, 0x43, 0x0b, 0xeb, 0x1a, 0x93, 0x56, - 0xae, 0xe6, 0xcc, 0x39, 0x9c, 0x39, 0xdf, 0xcf, 0x99, 0x33, 0x0b, 0xdb, 0x23, 0x2e, 0x84, 0x7f, - 0xc9, 0xe9, 0x24, 0x0a, 0xe3, 0x90, 0x7c, 0x43, 0x50, 0x68, 0x2f, 0x76, 0x9c, 0x71, 0x10, 0x62, - 0x0c, 0x46, 0x3c, 0x1c, 0x71, 0x1b, 0x95, 0x51, 0x45, 0x67, 0x72, 0x8d, 0x6d, 0xc8, 0x07, 0x61, - 0x34, 0xf3, 0xa3, 0x81, 0xad, 0x95, 0x51, 0x65, 0x83, 0x2d, 0x4d, 0xfc, 0x14, 0x8c, 0x78, 0x3e, - 0xe1, 0xb6, 0x5e, 0x46, 0x95, 0x9d, 0xea, 0xff, 0x74, 0x25, 0x13, 0xed, 0xce, 0x27, 0x9c, 0x49, - 0xb7, 0x4c, 0xca, 0xaf, 0x63, 0xdb, 0x28, 0xa3, 0xca, 0x26, 0x93, 0x6b, 0xbc, 0x0f, 0xb9, 0xe9, - 0x38, 0xe2, 0xfe, 0xc0, 0x36, 0x65, 0x4e, 0x65, 0x91, 0x23, 0x30, 0x92, 0x7f, 0xe2, 0x02, 0xe4, - 0x7b, 0xee, 0x3b, 0xb7, 0x73, 0xe6, 0x5a, 0xff, 0xe1, 0x0d, 0x30, 0xba, 0xcd, 0x0f, 0x5d, 0x0b, - 0x25, 0xdb, 0x27, 0x4e, 0xbd, 0xdb, 0x63, 0x4d, 0x4b, 0xc3, 0x9b, 0x60, 0x9e, 0x3a, 0x8d, 0x66, - 0xc7, 0xd2, 0xc9, 0x77, 0x04, 0x45, 0x75, 0x7a, 0x3d, 0xe2, 0x7e, 0xcc, 0x19, 0xff, 0x38, 0xe5, - 0x22, 0xc6, 0x25, 0xd8, 0x08, 0xa2, 0x70, 0xd4, 0x13, 0x3c, 0x92, 0xa2, 0x4c, 0x76, 0x63, 0x27, - 0x35, 0xc4, 0xa1, 0xf4, 0x68, 0xd2, 0xa3, 0x2c, 0x4c, 0xd7, 0x64, 0x95, 0x68, 0x56, 0xe2, 0xbf, - 0xe9, 0xc3, 0x60, 0x04, 0xc3, 0x2b, 0x2e, 0xd5, 0x6d, 0x31, 0xb9, 0xbe, 0xab, 0xb6, 0xcf, 0x08, - 0xf6, 0x52, 0x25, 0x88, 0x49, 0x38, 0x16, 0x1c, 0x1f, 0x41, 0x4e, 0xc4, 0x7e, 0x3c, 0x15, 0x52, - 0xda, 0x4e, 0xf5, 0x31, 0xcd, 0x8c, 0xa3, 0x9e, 0x0c, 0x62, 0x2a, 0x98, 0xbc, 0x82, 0xdc, 0x62, - 0x67, 0xbd, 0x92, 0x12, 0x6c, 0x3b, 0xee, 0x69, 0xad, 0xe5, 0x34, 0xfa, 0x27, 0x35, 0x56, 0x6b, - 0x5b, 0x3f, 0x97, 0x3f, 0x59, 0x9b, 0xd7, 0xab, 0xd7, 0x9b, 0x9e, 0x67, 0x21, 0xf2, 0x03, 0x01, - 0x56, 0x07, 0x1d, 0x0f, 0xc7, 0x83, 0xfb, 0xa0, 0x7e, 0x06, 0xfa, 0xcc, 0x9f, 0x2b, 0xd2, 0x0f, - 0xe8, 0xef, 0x59, 0xe9, 0x99, 0x3f, 0x67, 0x49, 0x0c, 0x2e, 0x82, 0x79, 0x35, 0x1c, 0x0d, 0x17, - 0x98, 0x4d, 0xb6, 0x30, 0x92, 0xc4, 0x61, 0x10, 0x08, 0x1e, 0x4b, 0xd2, 0x26, 0x53, 0x16, 0x79, - 0x0d, 0xfa, 0x99, 0x3f, 0x5f, 0x17, 0xb8, 0x0d, 0x9b, 0x1d, 0xb7, 0x75, 0xde, 0x3f, 0xe9, 0xb5, - 0x5a, 0x16, 0xc2, 0x16, 0x6c, 0xb1, 0x66, 0xad, 0xd1, 0x6f, 0x37, 0x3d, 0xaf, 0xf6, 0x26, 0x81, - 0x5e, 0x80, 0xfc, 0x5b, 0xc7, 0xeb, 0x76, 0xd8, 0xb9, 0xa5, 0x93, 0x4f, 0x1a, 0xec, 0xae, 0xd5, - 0xa3, 0xa0, 0x1f, 0xa4, 0xa0, 0x3f, 0xa4, 0x19, 0x51, 0x29, 0xe4, 0x6b, 0x6c, 0xb4, 0x3f, 0xb2, - 0xd1, 0xd7, 0xd8, 0x14, 0xc1, 0xbc, 0xf0, 0x07, 0x97, 0x7c, 0x29, 0x58, 0x1a, 0x98, 0x80, 0x39, - 0x1c, 0x07, 0xa1, 0xb0, 0xcd, 0xb2, 0x5e, 0x29, 0x54, 0xb7, 0x56, 0x87, 0x8e, 0x2d, 0x5c, 0xa4, - 0x7d, 0xbf, 0x06, 0x27, 0xa0, 0xdc, 0x4e, 0xb7, 0x7f, 0xdc, 0xe9, 0xb9, 0x0d, 0x4b, 0x23, 0xd7, - 0x00, 0x2e, 0x9f, 0xa9, 0x73, 0xee, 0xd4, 0xe6, 0x1b, 0x29, 0xfa, 0xaa, 0x94, 0x32, 0x18, 0x49, - 0xbd, 0x52, 0x5f, 0x5a, 0x89, 0xf4, 0x90, 0xe7, 0x37, 0x2d, 0x78, 0x3f, 0xe5, 0xd1, 0x7c, 0x79, - 0xd3, 0x92, 0xc7, 0x43, 0xf0, 0xc8, 0x69, 0xa8, 0x02, 0x94, 0x45, 0xbe, 0xde, 0xbe, 0x02, 0x2a, - 0x5e, 0xf5, 0xec, 0x30, 0xd5, 0xb3, 0x47, 0x34, 0x2b, 0x2c, 0xdd, 0xb4, 0x27, 0x60, 0x8c, 0xf9, - 0x4c, 0xd8, 0x9a, 0x24, 0x5d, 0xa0, 0xb7, 0x10, 0x98, 0x74, 0xfc, 0x63, 0xce, 0xd5, 0x2f, 0x08, - 0xf2, 0x4b, 0xca, 0x2f, 0x21, 0xb7, 0x18, 0x62, 0xbc, 0x97, 0xf9, 0xfe, 0x94, 0xf6, 0xb3, 0x67, - 0x1d, 0xbf, 0x00, 0x23, 0xb9, 0x88, 0x78, 0x37, 0x63, 0x98, 0x4a, 0xc5, 0xac, 0xbb, 0x8a, 0x0f, - 0xc1, 0x94, 0x1c, 0x70, 0x91, 0x66, 0xd0, 0x2e, 0xed, 0x65, 0xc2, 0xba, 0xc8, 0xc9, 0x2f, 0xc8, - 0xc1, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x2d, 0xd2, 0xc0, 0x52, 0x06, 0x00, 0x00, + // 618 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x5f, 0x6f, 0xd3, 0x3e, + 0x14, 0xfd, 0x39, 0x7f, 0xba, 0xed, 0xb6, 0x9d, 0x22, 0xaf, 0xdb, 0x2f, 0x14, 0x10, 0x95, 0x9f, + 0x0a, 0x12, 0x96, 0xd6, 0x6d, 0xe2, 0x0d, 0xa9, 0x6a, 0x03, 0x44, 0xb0, 0xae, 0x38, 0xed, 0xc6, + 0x9e, 0xa6, 0x4c, 0x75, 0xa6, 0x4a, 0x34, 0x29, 0x71, 0xaa, 0x92, 0x37, 0x3e, 0x0a, 0xef, 0x88, + 0x6f, 0xc3, 0x87, 0xe1, 0x0d, 0x14, 0xc7, 0x2d, 0x6b, 0x08, 0x12, 0x62, 0x7d, 0xca, 0xf1, 0x3d, + 0xbd, 0x3e, 0x3e, 0xc7, 0xd7, 0x50, 0x9f, 0x71, 0x21, 0xfc, 0x1b, 0x4e, 0xe7, 0x71, 0x94, 0x44, + 0xe4, 0x13, 0x82, 0xea, 0x69, 0xbe, 0xe2, 0x86, 0x41, 0x84, 0x31, 0x18, 0xc9, 0x74, 0xc6, 0x6d, + 0xd4, 0x42, 0x6d, 0x9d, 0xc9, 0x6f, 0x6c, 0xc3, 0x56, 0x10, 0xc5, 0x4b, 0x3f, 0x9e, 0xd8, 0x5a, + 0x0b, 0xb5, 0xb7, 0xd9, 0x0a, 0xe2, 0x7b, 0x60, 0x24, 0xe9, 0x9c, 0xdb, 0x7a, 0x0b, 0xb5, 0x77, + 0x3b, 0x26, 0x1d, 0xa5, 0x73, 0xce, 0xe4, 0x12, 0xb6, 0x40, 0x9f, 0x89, 0x1b, 0xdb, 0x68, 0xa1, + 0xf6, 0x0e, 0xcb, 0x3e, 0xf1, 0x01, 0x54, 0x16, 0x61, 0xcc, 0xfd, 0x89, 0x6d, 0xca, 0x2e, 0x0a, + 0x91, 0x25, 0x34, 0x94, 0x82, 0x5e, 0xcc, 0xfd, 0x84, 0x33, 0xfe, 0x61, 0xc1, 0x45, 0x82, 0x9b, + 0xb0, 0x1d, 0xc4, 0xd1, 0x6c, 0x2c, 0x78, 0x2c, 0xe5, 0x98, 0x6c, 0x8d, 0xb3, 0x5e, 0x49, 0x24, + 0x2b, 0x9a, 0xac, 0x28, 0xf4, 0x97, 0x82, 0x6a, 0x52, 0x10, 0xf9, 0x8c, 0x60, 0xbf, 0xb0, 0xb3, + 0x98, 0x47, 0xa1, 0xe0, 0xf8, 0x04, 0x2a, 0x22, 0xf1, 0x93, 0x85, 0x90, 0x1b, 0xef, 0x76, 0x1e, + 0xd2, 0x52, 0x1e, 0xf5, 0x24, 0x89, 0x29, 0x32, 0x19, 0x42, 0x25, 0x5f, 0xc1, 0x55, 0xd8, 0x1a, + 0x0f, 0x5e, 0x0f, 0xce, 0x2e, 0x06, 0xd6, 0x7f, 0xb8, 0x09, 0x75, 0x77, 0x70, 0xde, 0x7d, 0xe3, + 0xf6, 0xaf, 0x86, 0x5d, 0xd6, 0x3d, 0xb5, 0x7e, 0xac, 0x7e, 0x28, 0x23, 0x7a, 0xe3, 0x5e, 0xcf, + 0xf1, 0x3c, 0x0b, 0x61, 0x0b, 0x6a, 0x2b, 0xe2, 0xe8, 0x72, 0xe8, 0x58, 0x1a, 0xf9, 0x86, 0x00, + 0xab, 0xad, 0x5f, 0x4c, 0xc3, 0xc9, 0x5d, 0xac, 0x79, 0x0c, 0xfa, 0xd2, 0x4f, 0x95, 0x33, 0xff, + 0xd3, 0xdf, 0xbb, 0xd2, 0x0b, 0x3f, 0x65, 0x19, 0x07, 0x37, 0xc0, 0x7c, 0x3f, 0x9d, 0x4d, 0x13, + 0x69, 0x56, 0x9d, 0xe5, 0x20, 0x6b, 0x1c, 0x05, 0x81, 0xe0, 0x89, 0xcc, 0xaf, 0xce, 0x14, 0x22, + 0x87, 0xa0, 0x5f, 0xf8, 0xe9, 0xe6, 0x91, 0x2d, 0xa8, 0x31, 0xa7, 0xdb, 0xbf, 0x3a, 0x75, 0x3c, + 0xaf, 0xfb, 0xd2, 0xb1, 0xe4, 0x41, 0x5f, 0xb9, 0xde, 0xe8, 0x8c, 0x5d, 0x5a, 0x1a, 0xf9, 0x8e, + 0x60, 0x6f, 0x43, 0x80, 0xf2, 0xfd, 0xa8, 0xe0, 0xfb, 0x7d, 0x5a, 0xc2, 0x2a, 0xb8, 0xbe, 0x61, + 0x86, 0xf6, 0x47, 0x33, 0xf4, 0x0d, 0x33, 0x1a, 0x60, 0x5e, 0xfb, 0x93, 0x1b, 0x2e, 0x4f, 0x68, + 0xb2, 0x1c, 0x60, 0x02, 0xe6, 0x34, 0x0c, 0x22, 0x61, 0x9b, 0x2d, 0xbd, 0x5d, 0xed, 0xd4, 0xe8, + 0xad, 0xc9, 0x60, 0x79, 0x89, 0x3c, 0xbf, 0x5b, 0xc6, 0xe4, 0x23, 0xc0, 0x80, 0x2f, 0x55, 0xe3, + 0x7f, 0x0a, 0x72, 0xad, 0x5d, 0xbf, 0xad, 0xbd, 0x05, 0x46, 0x26, 0x50, 0x1e, 0xa8, 0x28, 0x5d, + 0x56, 0xc8, 0xd3, 0xb5, 0xe7, 0x6f, 0x17, 0x3c, 0x4e, 0x57, 0x77, 0x29, 0x1b, 0x4b, 0xc1, 0x63, + 0xb7, 0xaf, 0x04, 0x28, 0x44, 0xbe, 0xa2, 0xf5, 0x5c, 0x2a, 0xbe, 0x0a, 0xe9, 0xb8, 0x10, 0xd2, + 0x03, 0x5a, 0x46, 0x2b, 0xa6, 0xf4, 0x08, 0x8c, 0x90, 0x2f, 0x85, 0xad, 0x49, 0x6b, 0xab, 0xf4, + 0x97, 0x09, 0x4c, 0x16, 0xee, 0x6a, 0xec, 0x93, 0x13, 0x30, 0xb2, 0x69, 0xdf, 0xfc, 0xf7, 0x36, + 0x18, 0x23, 0xe7, 0xdd, 0x28, 0xbf, 0x7f, 0x43, 0xb7, 0x37, 0x1a, 0x33, 0xc7, 0xd2, 0xf0, 0x0e, + 0x98, 0xe7, 0x6e, 0xdf, 0x39, 0xb3, 0xf4, 0xce, 0x17, 0x04, 0x5b, 0xab, 0x34, 0x9e, 0x41, 0x25, + 0x1f, 0x70, 0xbc, 0x4f, 0xcb, 0x9e, 0xa4, 0xe6, 0x41, 0xf9, 0x3b, 0x80, 0x0f, 0xc1, 0xc8, 0x6e, + 0x28, 0xde, 0x2b, 0x19, 0xab, 0x66, 0xa3, 0xec, 0x12, 0xe3, 0x63, 0x30, 0xa5, 0x5f, 0xb8, 0x41, + 0x4b, 0x52, 0x69, 0xee, 0x97, 0x9a, 0x7a, 0x5d, 0x91, 0xaf, 0xf6, 0xd1, 0xcf, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x68, 0xa0, 0x17, 0x29, 0xc6, 0x05, 0x00, 0x00, } diff --git a/backend/srv/message/proto/message.proto b/backend/srv/message/proto/message.proto index a6f9434..21bc0a3 100644 --- a/backend/srv/message/proto/message.proto +++ b/backend/srv/message/proto/message.proto @@ -6,32 +6,26 @@ service Message { rpc Query (MessageQueryRequest) returns (MessageQueryResponse); } -message MessageInfo{ - enum Type { - UNKNOWN = 0; - TEXT = 1; - PICTURE = 2; - VIDEO = 3; - } +enum Type { + UNKNOWN = 0; + TEXT = 1; + PICTURE = 2; + VIDEO = 3; +} + +message MessageInfo { int64 time = 1; bool forward = 2; Type type = 3; - string text = 4; + string msg = 4; bool unread = 5; } -message MessageCreateRequest{ - enum Type { - UNKNOWN = 0; - TEXT = 1; - PICTURE = 2; - VIDEO = 3; - } +message MessageCreateRequest { int32 fromUser = 1; int32 toUser = 2; Type type = 3; - string text = 4; - bytes file = 5; + bytes msg = 4; } message MessageCreateResponse { @@ -39,6 +33,7 @@ message MessageCreateResponse { UNKNOWN = 0; INVALID_PARAM = -1; SUCCESS = 1; + INVALID_TYPE = 2; } Status status = 1; } @@ -46,15 +41,14 @@ message MessageCreateResponse { message MessageFindRequest { enum Way { UNKNOWN = 0; - ONLY_PULL = 1; - READ_MESSAGE = 2; - HISTORY = 3; + READ_MESSAGE = 1; + HISTORY = 2; } int32 fromUser = 1; int32 toUser = 2; Way way = 3; - int32 limit = 4; - int32 offset = 5; + uint32 limit = 4; + uint32 offset = 5; } message MessageFindResponse { @@ -62,7 +56,6 @@ message MessageFindResponse { UNKNOWN = 0; INVALID_PARAM = -1; SUCCESS = 1; - NOT_FOUND = 2; } Status status = 1; int32 fromUser = 2; @@ -71,23 +64,22 @@ message MessageFindResponse { repeated MessageInfo infos = 5; } -message NewMessage{ +message NewMessage { int32 fromUser = 1; int32 toUser = 2; int32 badge = 3; MessageInfo info = 4; } -message MessageQueryRequest{ +message MessageQueryRequest { int32 userID = 1; } -message MessageQueryResponse{ +message MessageQueryResponse { enum Status { UNKNOWN = 0; INVALID_PARAM = -1; SUCCESS = 1; - NOT_FOUND = 2; } Status status = 1; repeated NewMessage news = 2; From 2d18c52e5dabb4a64645874a0d320437851f00ab Mon Sep 17 00:00:00 2001 From: MXWXZ Date: Fri, 2 Aug 2019 02:01:38 +0800 Subject: [PATCH 16/17] style fix --- backend/srv/message/main.go | 22 +++++++++++----------- backend/srv/message/main_test.go | 2 +- backend/srv/message/mock/mock.go | 5 ++++- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/backend/srv/message/main.go b/backend/srv/message/main.go index 7b4002e..b06e6ed 100644 --- a/backend/srv/message/main.go +++ b/backend/srv/message/main.go @@ -22,7 +22,7 @@ import ( type srv struct{} -type MsgInfo struct { +type msgInfo struct { Time time.Time `bson:"time"` Forward bool `bson:"forward"` Type message.Type `bson:"type"` @@ -30,12 +30,12 @@ type MsgInfo struct { Unread bool `bson:"unread"` } -type ChatLog struct { +type chatLog struct { ID primitive.ObjectID `bson:"_id"` FromUser int32 `bson:"fromUser"` ToUser int32 `bson:"toUser"` Badge int32 `bson:"badge"` - Infos []MsgInfo `bson:"infos"` + Infos []msgInfo `bson:"infos"` } /** @@ -87,7 +87,7 @@ func (a *srv) Create(ctx context.Context, req *message.MessageCreateRequest, rsp ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() collection := db.MongoDatabase.Collection("message") - var res1, res2 ChatLog + var res1, res2 chatLog err1 := collection.FindOne(ctx, bson.M{ "fromUser": req.FromUser, "toUser": req.ToUser, @@ -203,7 +203,7 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me req.Limit = 20 } - decodeRes := func(src *ChatLog, dest *message.MessageFindResponse) { + decodeRes := func(src *chatLog, dest *message.MessageFindResponse) { dest.FromUser = src.FromUser dest.ToUser = src.ToUser dest.Badge = src.Badge @@ -221,7 +221,7 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() collection := db.MongoDatabase.Collection("message") - var res1, res2 ChatLog + var res1, res2 chatLog err1 := collection.FindOne(ctx, bson.M{ "fromUser": req.FromUser, "toUser": req.ToUser, @@ -240,13 +240,13 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me } else if err1 != nil && err2 != nil { rsp.Status = message.MessageFindResponse_SUCCESS return nil - } else { + } else if err1 == nil && err2 == nil { rsp.Status = message.MessageFindResponse_INVALID_PARAM return nil } if req.Way == message.MessageFindRequest_READ_MESSAGE { - var res ChatLog + var res chatLog cur, err := collection.Aggregate(ctx, bson.A{ bson.M{ "$match": bson.M{ @@ -307,7 +307,7 @@ func (a *srv) Find(ctx context.Context, req *message.MessageFindRequest, rsp *me return err } } else { - var res ChatLog + var res chatLog err := collection.FindOne(ctx, bson.M{ "fromUser": rsp.FromUser, "toUser": rsp.ToUser, @@ -355,7 +355,7 @@ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp * return nil } - decodeRes := func(src *ChatLog, dest *message.NewMessage) { + decodeRes := func(src *chatLog, dest *message.NewMessage) { dest.FromUser = src.FromUser dest.ToUser = src.ToUser dest.Badge = src.Badge @@ -405,7 +405,7 @@ func (a *srv) Query(ctx context.Context, req *message.MessageQueryRequest, rsp * } for cur.Next(ctx) { - var res ChatLog + var res chatLog var newMessage message.NewMessage err = cur.Decode(&res) if utils.LogContinue(err, utils.Error) { diff --git a/backend/srv/message/main_test.go b/backend/srv/message/main_test.go index 940cc3f..b7429dd 100644 --- a/backend/srv/message/main_test.go +++ b/backend/srv/message/main_test.go @@ -31,7 +31,7 @@ func TestCreate(t *testing.T) { So(count, ShouldEqual, 1) So(err, ShouldBeNil) - var chat ChatLog + var chat chatLog So(collection.FindOne(ctx, filter).Decode(&chat), ShouldBeNil) So(chat.Badge, ShouldEqual, 3) So(len(chat.Infos), ShouldEqual, 3) diff --git a/backend/srv/message/mock/mock.go b/backend/srv/message/mock/mock.go index f0c6295..ea9f8af 100644 --- a/backend/srv/message/mock/mock.go +++ b/backend/srv/message/mock/mock.go @@ -9,25 +9,28 @@ import ( type mockMessageSrv struct{} +// Find is message find mock func (a *mockMessageSrv) Find(ctx context.Context, in *message.MessageFindRequest, opts ...client.CallOption) (*message.MessageFindResponse, error) { var rsp message.MessageFindResponse // TODO return &rsp, nil } +// Query is message query mock func (a *mockMessageSrv) Query(ctx context.Context, in *message.MessageQueryRequest, opts ...client.CallOption) (*message.MessageQueryResponse, error) { var rsp message.MessageQueryResponse // TODO return &rsp, nil } +// Create is message create mock func (a *mockMessageSrv) Create(ctx context.Context, in *message.MessageCreateRequest, opts ...client.CallOption) (*message.MessageCreateResponse, error) { var rsp message.MessageCreateResponse // TODO return &rsp, nil } -// is service mock +// NewMessageService is service mock func NewMessageService() message.MessageService { return new(mockMessageSrv) } From 9d582b6247e2f85108ca6d29a1b5b8a9347bb4da Mon Sep 17 00:00:00 2001 From: MXWXZ Date: Fri, 2 Aug 2019 02:38:37 +0800 Subject: [PATCH 17/17] v0.3.0 --- backend/CHANGELOG.md | 7 ++ backend/api/auth/main.go | 1 - backend/api/content/main.go | 2 + backend/doc/api_data.js | 4 +- backend/doc/api_data.json | 4 +- backend/doc/api_project.js | 2 +- backend/doc/api_project.json | 2 +- backend/srv/content/main.go | 82 +++++++++++++++------ backend/srv/content/proto/content.pb.go | 94 ++++++++++++++----------- backend/srv/content/proto/content.proto | 7 +- backend/utils/function.go | 6 +- 11 files changed, 134 insertions(+), 77 deletions(-) diff --git a/backend/CHANGELOG.md b/backend/CHANGELOG.md index 187825f..48c6aed 100644 --- a/backend/CHANGELOG.md +++ b/backend/CHANGELOG.md @@ -1,4 +1,11 @@ # 后端API更新日志 +## v0.3.0 2019-08-02 +### 修复 +1. `DELETE /content` 删除单独content file已可使用 + +### 新增 +1. message相关功能已可以使用 + ## v0.2.2 2019-08-01 ### 禁用 1. `DELETE /content` 删除单独content file暂不可用 diff --git a/backend/api/auth/main.go b/backend/api/auth/main.go index ab0bcd7..0ba3c6d 100644 --- a/backend/api/auth/main.go +++ b/backend/api/auth/main.go @@ -86,7 +86,6 @@ func getAuth(c *gin.Context) { return } - utils.Error(rsp2.User.Status) // sign token if rsp2.User.Status == user.UserInfo_NORMAL { if rsp2.User.Role == user.UserInfo_USER { diff --git a/backend/api/content/main.go b/backend/api/content/main.go index cd65aec..69f3af7 100644 --- a/backend/api/content/main.go +++ b/backend/api/content/main.go @@ -101,6 +101,7 @@ func deleteContent(c *gin.Context) { type param struct { ContentID string `form:"contentID" binding:"required"` ContentToken string `form:"contentToken" binding:"required"` + FileID string `form:"fileID"` } var p param role := utils.GetRole(c) @@ -115,6 +116,7 @@ func deleteContent(c *gin.Context) { rsp, err := srv.Delete(context.TODO(), &content.ContentDeleteRequest{ ContentID: p.ContentID, ContentToken: p.ContentToken, + FileID: p.FileID, }) if utils.LogContinue(err, utils.Error) { c.JSON(500, err) diff --git a/backend/doc/api_data.js b/backend/doc/api_data.js index c77d808..aef07d5 100644 --- a/backend/doc/api_data.js +++ b/backend/doc/api_data.js @@ -1555,7 +1555,7 @@ define({ "api": [ "type": "int32", "optional": false, "field": "status", - "description": "

-1 for invalid param
1 for success
2 for invalid token
2 for invalid type

" + "description": "

-1 for invalid param
1 for success
2 for invalid token
3 for invalid type

" }, { "group": "Success 200", @@ -1639,7 +1639,7 @@ define({ "api": [ "type": "int32", "optional": false, "field": "status", - "description": "

-1 for invalid param
1 for success
2 for invalid token
2 for invalid type

" + "description": "

-1 for invalid param
1 for success
2 for invalid token
3 for invalid type

" }, { "group": "Success 200", diff --git a/backend/doc/api_data.json b/backend/doc/api_data.json index 5730235..46eda4a 100644 --- a/backend/doc/api_data.json +++ b/backend/doc/api_data.json @@ -1555,7 +1555,7 @@ "type": "int32", "optional": false, "field": "status", - "description": "

-1 for invalid param
1 for success
2 for invalid token
2 for invalid type

" + "description": "

-1 for invalid param
1 for success
2 for invalid token
3 for invalid type

" }, { "group": "Success 200", @@ -1639,7 +1639,7 @@ "type": "int32", "optional": false, "field": "status", - "description": "

-1 for invalid param
1 for success
2 for invalid token
2 for invalid type

" + "description": "

-1 for invalid param
1 for success
2 for invalid token
3 for invalid type

" }, { "group": "Success 200", diff --git a/backend/doc/api_project.js b/backend/doc/api_project.js index 3e50ee3..8b58381 100644 --- a/backend/doc/api_project.js +++ b/backend/doc/api_project.js @@ -21,7 +21,7 @@ define({ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T17:54:38.573Z", + "time": "2019-08-01T18:33:38.978Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/doc/api_project.json b/backend/doc/api_project.json index bb5f1ae..b42be10 100644 --- a/backend/doc/api_project.json +++ b/backend/doc/api_project.json @@ -21,7 +21,7 @@ "apidoc": "0.3.0", "generator": { "name": "apidoc", - "time": "2019-08-01T17:54:38.573Z", + "time": "2019-08-01T18:33:38.978Z", "url": "http://apidocjs.com", "version": "0.17.7" } diff --git a/backend/srv/content/main.go b/backend/srv/content/main.go index 4caa822..4ff469b 100644 --- a/backend/srv/content/main.go +++ b/backend/srv/content/main.go @@ -31,7 +31,7 @@ type srv struct{} * @apiParam {string} [contentToken] content token, left empty for first upload * @apiParam {bytes} content binary bytes, file accept [image](https://github.com/h2non/filetype#image) and [video](https://github.com/h2non/filetype#video) * @apiParam {int32} type 1 for picture
2 for video - * @apiSuccess {int32} status -1 for invalid param
1 for success
2 for invalid token
2 for invalid type + * @apiSuccess {int32} status -1 for invalid param
1 for success
2 for invalid token
3 for invalid type * @apiSuccess {string} contentID 24 bytes contentID * @apiSuccess {string} contentToken random uuid content token * @apiSuccess {string} fileID 24 bytes fileID @@ -81,7 +81,7 @@ func (a *srv) Create(ctx context.Context, req *content.ContentCreateRequest, rsp token := uuid.NewV4().String() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") + collection := db.MongoDatabase.Collection("content") res, err := collection.InsertOne(ctx, bson.M{ "token": token, "files": bson.A{ @@ -111,7 +111,7 @@ func (a *srv) Create(ctx context.Context, req *content.ContentCreateRequest, rsp ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") + collection := db.MongoDatabase.Collection("content") rid, _ := primitive.ObjectIDFromHex(req.ContentID) _, err = collection.UpdateOne(ctx, bson.D{ {"_id", rid}, @@ -147,7 +147,7 @@ func (a *srv) Create(ctx context.Context, req *content.ContentCreateRequest, rsp * @apiParam {string} [contentID] 24 bytes content id, left empty for first upload * @apiParam {string} [contentToken] content token, left empty for first upload * @apiParam {list} tags {string} tag - * @apiSuccess {int32} status -1 for invalid param
1 for success
2 for invalid token
2 for invalid type + * @apiSuccess {int32} status -1 for invalid param
1 for success
2 for invalid token
3 for invalid type * @apiSuccess {string} contentID 24 bytes contentID * @apiSuccess {string} contentToken random uuid content token * @apiUse DBServerDown @@ -163,7 +163,7 @@ func (a *srv) CreateTag(ctx context.Context, req *content.ContentCreateTagReques token := uuid.NewV4().String() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") + collection := db.MongoDatabase.Collection("content") res, err := collection.InsertOne(ctx, bson.M{ "token": token, "tags": req.Tags, @@ -183,7 +183,7 @@ func (a *srv) CreateTag(ctx context.Context, req *content.ContentCreateTagReques ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") + collection := db.MongoDatabase.Collection("content") rid, err := primitive.ObjectIDFromHex(req.ContentID) if utils.LogContinue(err, utils.Warning) { rsp.Status = content.ContentCreateTagResponse_INVALID_TOKEN @@ -242,7 +242,7 @@ func (a *srv) Update(ctx context.Context, req *content.ContentUpdateRequest, rsp // check id ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") + collection := db.MongoDatabase.Collection("content") rid, _ := primitive.ObjectIDFromHex(req.ContentID) oldFid, err := primitive.ObjectIDFromHex(req.FileID) if utils.LogContinue(err, utils.Warning) { @@ -328,27 +328,42 @@ func (a *srv) Delete(ctx context.Context, req *content.ContentDeleteRequest, rsp ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") + collection := db.MongoDatabase.Collection("content") rid, err := primitive.ObjectIDFromHex(req.ContentID) if utils.LogContinue(err, utils.Warning) { rsp.Status = content.ContentDeleteResponse_INVALID_TOKEN return nil } - var res result - err = collection.FindOneAndDelete(ctx, bson.D{ - {"_id", rid}, - {"token", req.ContentToken}, - }).Decode(&res) - if utils.LogContinue(err, utils.Warning) { - rsp.Status = content.ContentDeleteResponse_INVALID_TOKEN - return nil - } srv := utils.CallMicroService("file", func(name string, c client.Client) interface{} { return file.NewFileService(name, c) }, func() interface{} { return mock.NewFileService() }).(file.FileService) - for _, v := range res.Files { + if utils.RequireParam(req.FileID) { // delete single file + fid, err := primitive.ObjectIDFromHex(req.FileID) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = content.ContentDeleteResponse_NOT_FOUND + return nil + } + + res, err := collection.UpdateOne(ctx, bson.D{ + {"_id", rid}, + {"token", req.ContentToken}, + }, bson.D{ + {"$pull", bson.D{ + {"files", bson.D{ + {"fileID", fid}, + }}, + }}, + }) + if utils.LogContinue(err, utils.Error) { + return err + } + if res.ModifiedCount == 0 { + rsp.Status = content.ContentDeleteResponse_NOT_FOUND + return nil + } + microRsp, err := srv.Delete(context.TODO(), &file.FileRequest{ - FileID: v.FileID.Hex(), + FileID: req.FileID, }) if utils.LogContinue(err, utils.Error) { return err @@ -357,6 +372,31 @@ func (a *srv) Delete(ctx context.Context, req *content.ContentDeleteRequest, rsp _, s := utils.LogContinueS("File delete return "+microRsp.Status.String(), utils.Error) return errors.New(s) } + } else { + var res result + err = collection.FindOneAndDelete(ctx, bson.D{ + {"_id", rid}, + {"token", req.ContentToken}, + }).Decode(&res) + if utils.LogContinue(err, utils.Warning) { + rsp.Status = content.ContentDeleteResponse_INVALID_TOKEN + return nil + } + + srv := utils.CallMicroService("file", func(name string, c client.Client) interface{} { return file.NewFileService(name, c) }, + func() interface{} { return mock.NewFileService() }).(file.FileService) + for _, v := range res.Files { + microRsp, err := srv.Delete(context.TODO(), &file.FileRequest{ + FileID: v.FileID.Hex(), + }) + if utils.LogContinue(err, utils.Error) { + return err + } + if microRsp.Status != file.FileDeleteResponse_SUCCESS { + _, s := utils.LogContinueS("File delete return "+microRsp.Status.String(), utils.Error) + return errors.New(s) + } + } } rsp.Status = content.ContentDeleteResponse_SUCCESS return nil @@ -394,7 +434,7 @@ func (a *srv) Query(ctx context.Context, req *content.ContentQueryRequest, rsp * ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") + collection := db.MongoDatabase.Collection("content") rid, err := primitive.ObjectIDFromHex(req.ContentID) if utils.LogContinue(err, utils.Warning) { rsp.Status = content.ContentQueryResponse_INVALID_PARAM @@ -454,7 +494,7 @@ func validCheck(contentID string, contentToken string) bool { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - collection := db.MongoDatabase.Collection("sellinfo") + collection := db.MongoDatabase.Collection("content") rid, err := primitive.ObjectIDFromHex(contentID) if utils.LogContinue(err, utils.Warning) { return false diff --git a/backend/srv/content/proto/content.pb.go b/backend/srv/content/proto/content.pb.go index b6fea8e..e4c67dd 100644 --- a/backend/srv/content/proto/content.pb.go +++ b/backend/srv/content/proto/content.pb.go @@ -614,6 +614,7 @@ func (m *ContentUpdateResponse) GetFileID() string { type ContentDeleteRequest struct { ContentID string `protobuf:"bytes,1,opt,name=contentID,proto3" json:"contentID,omitempty"` ContentToken string `protobuf:"bytes,2,opt,name=contentToken,proto3" json:"contentToken,omitempty"` + FileID string `protobuf:"bytes,3,opt,name=fileID,proto3" json:"fileID,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -658,6 +659,13 @@ func (m *ContentDeleteRequest) GetContentToken() string { return "" } +func (m *ContentDeleteRequest) GetFileID() string { + if m != nil { + return m.FileID + } + return "" +} + type ContentDeleteResponse struct { Status ContentDeleteResponse_Status `protobuf:"varint,1,opt,name=status,proto3,enum=ContentDeleteResponse_Status" json:"status,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -958,47 +966,47 @@ func init() { func init() { proto.RegisterFile("content.proto", fileDescriptor_61cc9617ce0cf609) } var fileDescriptor_61cc9617ce0cf609 = []byte{ - // 663 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcd, 0x6e, 0xd3, 0x4c, - 0x14, 0xfd, 0xfc, 0x9b, 0xcf, 0xb7, 0x3f, 0x32, 0x43, 0x5b, 0xdc, 0xa8, 0x20, 0x6b, 0x56, 0x11, - 0x48, 0x5e, 0xa4, 0x45, 0x65, 0xc1, 0x82, 0xca, 0x4e, 0x25, 0xab, 0xd4, 0x29, 0x8e, 0x43, 0x61, - 0x55, 0x42, 0x19, 0x42, 0xd5, 0x28, 0x0e, 0xb1, 0xb3, 0xc8, 0x43, 0x74, 0xcd, 0x6b, 0xb0, 0xe5, - 0x55, 0x58, 0xf2, 0x0a, 0x2c, 0x59, 0x80, 0x62, 0x4f, 0x3c, 0x1e, 0xc7, 0x51, 0x8a, 0x30, 0x74, - 0xd5, 0x99, 0x9c, 0x99, 0xb9, 0xf7, 0x9c, 0x7b, 0xee, 0x35, 0x6c, 0x5c, 0x86, 0xc3, 0x98, 0x0c, - 0x63, 0x6b, 0x34, 0x0e, 0xe3, 0x10, 0xdf, 0x08, 0xb0, 0x65, 0xa7, 0x3b, 0xf6, 0x98, 0xf4, 0x62, - 0xe2, 0x93, 0x8f, 0x13, 0x12, 0xc5, 0x68, 0x0f, 0x34, 0x8a, 0x74, 0x1d, 0x43, 0x30, 0x85, 0x86, - 0xe6, 0xb3, 0x0d, 0x84, 0x61, 0x9d, 0x2e, 0x82, 0xf0, 0x9a, 0x0c, 0x0d, 0x31, 0x01, 0x70, 0x7b, - 0xc8, 0x80, 0x1a, 0x5d, 0x1b, 0x92, 0x29, 0x34, 0xd6, 0xfd, 0xf9, 0x12, 0xed, 0x82, 0x1c, 0x4f, - 0x47, 0xc4, 0x90, 0x4d, 0xa1, 0xb1, 0xd9, 0x54, 0xac, 0x60, 0x3a, 0x22, 0x7e, 0xb2, 0x85, 0x6f, - 0x44, 0xd8, 0x2e, 0xc4, 0x13, 0x8d, 0xc2, 0x61, 0x44, 0xd0, 0x63, 0x50, 0xa3, 0xb8, 0x17, 0x4f, - 0xa2, 0x24, 0x9a, 0xcd, 0xe6, 0x7d, 0xab, 0x14, 0x67, 0x75, 0x12, 0x90, 0x4f, 0xc1, 0x7c, 0x1e, - 0xe2, 0xaa, 0x3c, 0xa4, 0x92, 0x3c, 0x76, 0x40, 0x7d, 0x7f, 0x35, 0x20, 0xae, 0x93, 0xc4, 0xab, - 0xf9, 0x74, 0x85, 0x2f, 0x41, 0x4d, 0xdf, 0x42, 0x6b, 0x50, 0xeb, 0x7a, 0x27, 0x5e, 0xfb, 0xdc, - 0xd3, 0xff, 0x43, 0x75, 0xd8, 0x70, 0xbd, 0x97, 0x47, 0xcf, 0x5d, 0xe7, 0xe2, 0xec, 0xc8, 0x3f, - 0x3a, 0xd5, 0x7f, 0xce, 0xff, 0x84, 0x19, 0xb0, 0xd3, 0xb5, 0xed, 0x56, 0xa7, 0xa3, 0x0b, 0xe8, - 0x0e, 0x03, 0x06, 0xed, 0x93, 0x96, 0xa7, 0x8b, 0x48, 0x87, 0xf5, 0x6c, 0xeb, 0xf5, 0x59, 0x4b, - 0x97, 0x70, 0x08, 0xf7, 0xb8, 0x34, 0x83, 0x5e, 0xbf, 0x3a, 0x85, 0x10, 0xc8, 0x71, 0xaf, 0x1f, - 0x19, 0xb2, 0x29, 0x35, 0x34, 0x3f, 0xf9, 0x1f, 0xff, 0x10, 0xc0, 0x58, 0x7c, 0x91, 0x6a, 0xf0, - 0xa4, 0xa0, 0x81, 0x69, 0x2d, 0x83, 0x56, 0x2e, 0xc3, 0xbf, 0xa1, 0xfb, 0x0b, 0xb3, 0x43, 0x77, - 0xf4, 0xae, 0x52, 0x3b, 0xb0, 0x32, 0x92, 0xf2, 0x65, 0x94, 0xb7, 0x89, 0x5c, 0x6e, 0x13, 0x65, - 0xc1, 0x26, 0x99, 0x72, 0x6a, 0x4e, 0xb9, 0xaf, 0x42, 0x66, 0x9d, 0x79, 0xec, 0xab, 0xac, 0xc3, - 0xe3, 0x8a, 0x9a, 0xb1, 0x88, 0x45, 0xae, 0xf0, 0xc7, 0xd5, 0x2b, 0xb1, 0x01, 0x9a, 0xd7, 0x0e, - 0x2e, 0x8e, 0xdb, 0x5d, 0xcf, 0xd1, 0xa5, 0x05, 0x61, 0x64, 0xfc, 0x2a, 0xd3, 0xc5, 0x21, 0x03, - 0x52, 0xa1, 0x2e, 0xf8, 0x33, 0xa3, 0x6d, 0x7e, 0xf5, 0x2a, 0xda, 0x78, 0x5c, 0x81, 0x36, 0xfc, - 0xe6, 0x6f, 0xd3, 0x83, 0x9f, 0x42, 0xed, 0xf8, 0x6a, 0x40, 0x4e, 0xa3, 0x7e, 0x4e, 0x23, 0x81, - 0xab, 0xaa, 0x79, 0xed, 0x88, 0x8b, 0x2d, 0x76, 0x1f, 0xee, 0xd2, 0x3c, 0x5e, 0x4c, 0xc8, 0x78, - 0x7a, 0x2b, 0x26, 0xf1, 0x77, 0x66, 0x0c, 0x7a, 0x8a, 0x92, 0x74, 0x50, 0x20, 0x69, 0xcf, 0x2a, - 0x83, 0x15, 0x4b, 0xeb, 0x36, 0x86, 0x79, 0x00, 0xca, 0x2c, 0x99, 0xc8, 0x90, 0x4c, 0xa9, 0xb1, - 0xd6, 0xfc, 0xdf, 0xa2, 0x39, 0xfb, 0xe9, 0x76, 0x69, 0xf7, 0x3a, 0xfd, 0x43, 0xee, 0x39, 0xa2, - 0x45, 0x7c, 0x9e, 0x51, 0x65, 0x7f, 0x20, 0x97, 0xd7, 0xd5, 0x15, 0xdd, 0xa7, 0xdc, 0xd8, 0x4d, - 0x6f, 0x5e, 0x45, 0x27, 0x07, 0x2b, 0x96, 0x9c, 0xfb, 0xfb, 0x69, 0x6b, 0xa0, 0x24, 0xbf, 0xe8, - 0x09, 0x03, 0x14, 0xa6, 0x8b, 0x0f, 0x1f, 0x81, 0x3c, 0xab, 0x15, 0xfe, 0xa2, 0x35, 0xa8, 0x9d, - 0xb9, 0x76, 0xd0, 0xf5, 0x5b, 0x7a, 0x7a, 0xd2, 0x75, 0x5a, 0x6d, 0x5d, 0x6c, 0x7e, 0x13, 0xa1, - 0x46, 0xe3, 0x43, 0x87, 0xa0, 0xa6, 0x53, 0x00, 0x6d, 0x5b, 0x65, 0x5f, 0x14, 0xf5, 0x9d, 0xf2, - 0x81, 0x8d, 0x9e, 0x81, 0x96, 0x8d, 0x0f, 0x64, 0x58, 0x4b, 0xc6, 0x5d, 0x7d, 0x77, 0xe9, 0xac, - 0x99, 0x3d, 0x9d, 0x76, 0x32, 0xf6, 0x34, 0xd7, 0xbd, 0xd9, 0xd3, 0x85, 0xc6, 0x78, 0x08, 0x6a, - 0xea, 0x65, 0x76, 0x90, 0x6b, 0x2f, 0xec, 0x60, 0xa1, 0x35, 0x1c, 0x80, 0x92, 0xd4, 0x37, 0xda, - 0xb2, 0x4a, 0xbc, 0x54, 0xdf, 0xb6, 0x96, 0x78, 0x45, 0x49, 0x64, 0x64, 0xa7, 0xf2, 0x65, 0xc5, - 0x4e, 0x71, 0x5a, 0xbf, 0x55, 0x93, 0x2f, 0xb5, 0xfd, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc1, - 0x77, 0x71, 0xc0, 0xba, 0x09, 0x00, 0x00, + // 662 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcb, 0x6e, 0xd3, 0x4c, + 0x14, 0xfe, 0x7d, 0xcd, 0xef, 0xd3, 0x8b, 0xcc, 0xd0, 0x16, 0x37, 0x2a, 0xc8, 0x9a, 0x55, 0x04, + 0x92, 0x17, 0x69, 0x51, 0x59, 0xb0, 0xa0, 0xb2, 0x53, 0xc9, 0x2a, 0x75, 0x8a, 0xe3, 0x50, 0xb1, + 0x2a, 0xa1, 0x0c, 0xa1, 0x6a, 0x14, 0x9b, 0xd8, 0x59, 0xe4, 0x21, 0xba, 0xe6, 0x35, 0xd8, 0xf2, + 0x2a, 0x2c, 0x79, 0x05, 0x96, 0x2c, 0x40, 0xb1, 0x27, 0x1e, 0x8f, 0xe3, 0x28, 0x45, 0x84, 0x66, + 0x95, 0x19, 0x7f, 0xc7, 0xe7, 0x9c, 0xef, 0x3b, 0x17, 0xc3, 0xc6, 0x65, 0x38, 0x4c, 0xc8, 0x30, + 0xb1, 0xa2, 0x51, 0x98, 0x84, 0xf8, 0x46, 0x80, 0x2d, 0x3b, 0xbb, 0xb1, 0x47, 0xa4, 0x97, 0x10, + 0x9f, 0x7c, 0x1a, 0x93, 0x38, 0x41, 0x7b, 0xa0, 0x51, 0xa4, 0xeb, 0x18, 0x82, 0x29, 0x34, 0x34, + 0x9f, 0x5d, 0x20, 0x0c, 0xeb, 0xf4, 0x10, 0x84, 0xd7, 0x64, 0x68, 0x88, 0x29, 0x80, 0xbb, 0x43, + 0x06, 0xd4, 0xe8, 0xd9, 0x90, 0x4c, 0xa1, 0xb1, 0xee, 0xcf, 0x8e, 0x68, 0x17, 0xe4, 0x64, 0x12, + 0x11, 0x43, 0x36, 0x85, 0xc6, 0x66, 0x53, 0xb1, 0x82, 0x49, 0x44, 0xfc, 0xf4, 0x0a, 0xdf, 0x88, + 0xb0, 0x5d, 0x8a, 0x27, 0x8e, 0xc2, 0x61, 0x4c, 0xd0, 0x53, 0x50, 0xe3, 0xa4, 0x97, 0x8c, 0xe3, + 0x34, 0x9a, 0xcd, 0xe6, 0x43, 0xab, 0x12, 0x67, 0x75, 0x52, 0x90, 0x4f, 0xc1, 0x7c, 0x1e, 0xe2, + 0xb2, 0x3c, 0xa4, 0x8a, 0x3c, 0x76, 0x40, 0xfd, 0x70, 0x35, 0x20, 0xae, 0x93, 0xc6, 0xab, 0xf9, + 0xf4, 0x84, 0x2f, 0x41, 0xcd, 0x7c, 0xa1, 0x35, 0xa8, 0x75, 0xbd, 0x13, 0xaf, 0x7d, 0xee, 0xe9, + 0xff, 0xa1, 0x3a, 0x6c, 0xb8, 0xde, 0xeb, 0xa3, 0x97, 0xae, 0x73, 0x71, 0x76, 0xe4, 0x1f, 0x9d, + 0xea, 0xbf, 0x66, 0x3f, 0x61, 0x0a, 0xec, 0x74, 0x6d, 0xbb, 0xd5, 0xe9, 0xe8, 0x02, 0xba, 0xc7, + 0x80, 0x41, 0xfb, 0xa4, 0xe5, 0xe9, 0x22, 0xd2, 0x61, 0x3d, 0xbf, 0x7a, 0x73, 0xd6, 0xd2, 0x25, + 0x1c, 0xc2, 0x03, 0x2e, 0xcd, 0xa0, 0xd7, 0x5f, 0x9d, 0x42, 0x08, 0xe4, 0xa4, 0xd7, 0x8f, 0x0d, + 0xd9, 0x94, 0x1a, 0x9a, 0x9f, 0xfe, 0xc7, 0x3f, 0x05, 0x30, 0xe6, 0x3d, 0x52, 0x0d, 0x9e, 0x95, + 0x34, 0x30, 0xad, 0x45, 0xd0, 0x95, 0xcb, 0x70, 0x37, 0x74, 0x7f, 0x65, 0xed, 0xd0, 0x8d, 0xde, + 0xaf, 0xb4, 0x1d, 0x58, 0x19, 0x49, 0xc5, 0x32, 0x2a, 0xb6, 0x89, 0x5c, 0xdd, 0x26, 0xca, 0x5c, + 0x9b, 0xe4, 0xca, 0xa9, 0x05, 0xe5, 0xbe, 0x09, 0x79, 0xeb, 0xcc, 0x62, 0x5f, 0xd6, 0x3a, 0x3c, + 0xae, 0xac, 0x19, 0x8b, 0x58, 0xe4, 0x0a, 0x7f, 0xb4, 0x7a, 0x25, 0x36, 0x40, 0xf3, 0xda, 0xc1, + 0xc5, 0x71, 0xbb, 0xeb, 0x39, 0xba, 0x34, 0x27, 0x8c, 0x8c, 0xa3, 0x5c, 0x17, 0x87, 0x0c, 0xc8, + 0x1d, 0xe8, 0x82, 0xbf, 0x30, 0x3a, 0x67, 0x2e, 0x97, 0xd1, 0xc9, 0xe3, 0x4a, 0x74, 0xe2, 0xb7, + 0xff, 0x9a, 0x36, 0xfc, 0x1c, 0x6a, 0xc7, 0x57, 0x03, 0x72, 0x1a, 0xf7, 0x0b, 0x59, 0x09, 0x5c, + 0xb5, 0xcd, 0x6a, 0x4a, 0x9c, 0x1f, 0xbd, 0xfb, 0x70, 0x9f, 0xe6, 0xf1, 0x6a, 0x4c, 0x46, 0x93, + 0x5b, 0x31, 0x8c, 0x7f, 0xb0, 0x86, 0xa1, 0x56, 0x94, 0xa4, 0x83, 0x12, 0x49, 0x7b, 0x56, 0x15, + 0xac, 0x5c, 0x72, 0xb7, 0x11, 0xec, 0x11, 0x28, 0xd3, 0x64, 0x62, 0x43, 0x32, 0xa5, 0xc6, 0x5a, + 0xf3, 0x7f, 0x8b, 0xe6, 0xec, 0x67, 0xd7, 0x95, 0x53, 0xed, 0xf4, 0x2f, 0xb9, 0xe7, 0x88, 0x16, + 0xf1, 0x79, 0x4e, 0x95, 0xfd, 0x91, 0x5c, 0x5e, 0xaf, 0xac, 0x18, 0xf1, 0xe7, 0xc2, 0x3a, 0xce, + 0xde, 0xbc, 0x8c, 0x4e, 0x0e, 0x56, 0x2e, 0x39, 0xf7, 0xcf, 0xd3, 0xd6, 0x40, 0x49, 0x9f, 0xe8, + 0x29, 0x03, 0x14, 0xa6, 0x8b, 0x8f, 0x9f, 0x80, 0x3c, 0xad, 0x15, 0xfe, 0x45, 0x6b, 0x50, 0x3b, + 0x73, 0xed, 0xa0, 0xeb, 0xb7, 0xf4, 0xcc, 0xd2, 0x75, 0x5a, 0x6d, 0x5d, 0x6c, 0x7e, 0x17, 0xa1, + 0x46, 0xe3, 0x43, 0x87, 0xa0, 0x66, 0xdb, 0x01, 0x6d, 0x5b, 0x55, 0x5f, 0x1a, 0xf5, 0x9d, 0xea, + 0x45, 0x8e, 0x5e, 0x80, 0x96, 0xaf, 0x15, 0x64, 0x58, 0x0b, 0xd6, 0x60, 0x7d, 0x77, 0xe1, 0x0e, + 0x9a, 0xba, 0xce, 0x26, 0x1c, 0x73, 0xcd, 0x4d, 0x75, 0xe6, 0xba, 0x34, 0x30, 0x0f, 0x41, 0xcd, + 0x7a, 0x99, 0x19, 0x72, 0x63, 0x87, 0x19, 0x96, 0x46, 0xc3, 0x01, 0x28, 0x69, 0x7d, 0xa3, 0x2d, + 0xab, 0xa2, 0x97, 0xea, 0xdb, 0xd6, 0x82, 0x5e, 0x51, 0x52, 0x19, 0x99, 0x55, 0xb1, 0xac, 0x98, + 0x15, 0xa7, 0xf5, 0x3b, 0x35, 0xfd, 0x82, 0xdb, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x25, 0x7c, + 0x91, 0x13, 0xd2, 0x09, 0x00, 0x00, } diff --git a/backend/srv/content/proto/content.proto b/backend/srv/content/proto/content.proto index 7a4bae4..79086b6 100644 --- a/backend/srv/content/proto/content.proto +++ b/backend/srv/content/proto/content.proto @@ -2,7 +2,7 @@ syntax = "proto3"; service Content { rpc Create (ContentCreateRequest) returns (ContentCreateResponse); - rpc CreateTag(ContentCreateTagRequest)returns (ContentCreateTagResponse); + rpc CreateTag (ContentCreateTagRequest) returns (ContentCreateTagResponse); rpc Update (ContentUpdateRequest) returns (ContentUpdateResponse); rpc Delete (ContentDeleteRequest) returns (ContentDeleteResponse); rpc Query (ContentQueryRequest) returns (ContentQueryResponse); @@ -36,13 +36,13 @@ message ContentCreateResponse { string fileID = 4; } -message ContentCreateTagRequest{ +message ContentCreateTagRequest { string contentID = 1; string contentToken = 2; repeated string tags = 4; } -message ContentCreateTagResponse{ +message ContentCreateTagResponse { enum Status { UNKNOWN = 0; INVALID_PARAM = -1; @@ -80,6 +80,7 @@ message ContentUpdateResponse { message ContentDeleteRequest { string contentID = 1; string contentToken = 2; + string fileID = 3; } message ContentDeleteResponse { diff --git a/backend/utils/function.go b/backend/utils/function.go index 73305ec..f86abc9 100644 --- a/backend/utils/function.go +++ b/backend/utils/function.go @@ -116,9 +116,9 @@ func CheckFile(file []byte, f ...func(buf []byte) bool) bool { return string(file) == "valid_file" } for _, v := range f { - if !v(file) { - return false + if v(file) { + return true } } - return true + return false }