feat: 完善移动端会员业务流程

This commit is contained in:
richjohnrambo
2026-10-13 14:19:55 +08:00
parent 32c6238751
commit b2ebea4c80
59 changed files with 1516 additions and 470 deletions
+3 -3
View File
@@ -5,9 +5,9 @@ import (
"net/http"
"strings"
accountsvc "git.118im.com/im_team/im_workbench/internal/accounts"
"git.118im.com/im_team/im_workbench/internal/auth"
"git.118im.com/im_team/im_workbench/internal/store"
accountsvc "git.118im.com/im_team/olons_server/internal/accounts"
"git.118im.com/im_team/olons_server/internal/auth"
"git.118im.com/im_team/olons_server/internal/store"
)
type accountRegisterRequest struct {
+20 -15
View File
@@ -3,25 +3,27 @@ package httpapi
import (
"net/http"
"git.118im.com/im_team/im_workbench/internal/accounts"
"git.118im.com/im_team/im_workbench/internal/auth"
"git.118im.com/im_team/im_workbench/internal/finance"
"git.118im.com/im_team/im_workbench/internal/mall"
"git.118im.com/im_team/im_workbench/internal/portal"
"git.118im.com/im_team/im_workbench/internal/tasks"
"git.118im.com/im_team/olons_server/internal/accounts"
"git.118im.com/im_team/olons_server/internal/attachments"
"git.118im.com/im_team/olons_server/internal/auth"
"git.118im.com/im_team/olons_server/internal/finance"
"git.118im.com/im_team/olons_server/internal/mall"
"git.118im.com/im_team/olons_server/internal/portal"
"git.118im.com/im_team/olons_server/internal/tasks"
)
type API struct {
auth *auth.Authenticator
accounts *accounts.Service
portal *portal.Service
tasks *tasks.Service
mall *mall.Service
finance *finance.Service
auth *auth.Authenticator
accounts *accounts.Service
portal *portal.Service
tasks *tasks.Service
mall *mall.Service
finance *finance.Service
attachments *attachments.Service
}
func New(authenticator *auth.Authenticator, accountService *accounts.Service, portalService *portal.Service, taskService *tasks.Service, mallService *mall.Service, financeService *finance.Service) *API {
return &API{auth: authenticator, accounts: accountService, portal: portalService, tasks: taskService, mall: mallService, finance: financeService}
func New(authenticator *auth.Authenticator, accountService *accounts.Service, portalService *portal.Service, taskService *tasks.Service, mallService *mall.Service, financeService *finance.Service, attachmentService *attachments.Service) *API {
return &API{auth: authenticator, accounts: accountService, portal: portalService, tasks: taskService, mall: mallService, finance: financeService, attachments: attachmentService}
}
func (a *API) Register(mux *http.ServeMux) {
@@ -39,6 +41,8 @@ func (a *API) Register(mux *http.ServeMux) {
mux.HandleFunc("/v1/leaderboard", a.leaderboard)
mux.HandleFunc("/v1/customer-services", a.customerServices)
mux.HandleFunc("/v1/notices", a.notices)
mux.HandleFunc("/v1/notices/popup", a.popupNotice)
mux.HandleFunc("/v1/notices/", a.noticeResource)
mux.HandleFunc("/v1/task-halls", a.taskHalls)
mux.HandleFunc("/v1/tasks/eligibility", a.taskEligibility)
mux.HandleFunc("/v1/tasks/stats", a.taskStats)
@@ -48,6 +52,7 @@ func (a *API) Register(mux *http.ServeMux) {
mux.HandleFunc("/v1/manual-products", a.manualProducts)
mux.HandleFunc("/v1/manual-products/", a.manualProduct)
mux.HandleFunc("/v1/payment-accounts", a.paymentAccounts)
mux.HandleFunc("/v1/attachments/images", a.uploadImage)
mux.HandleFunc("/v1/wallet/ledgers", a.walletLedgers)
mux.HandleFunc("/v1/recharge/channels", a.rechargeChannels)
mux.HandleFunc("/v1/recharge-orders", a.rechargeOrders)
@@ -58,5 +63,5 @@ func (a *API) Register(mux *http.ServeMux) {
}
func (a *API) Healthz(w http.ResponseWriter, r *http.Request) {
writeSuccess(w, r, map[string]any{"status": "ok", "service": "workbench"})
writeSuccess(w, r, map[string]any{"status": "ok", "service": "olons_server"})
}
+36
View File
@@ -0,0 +1,36 @@
package httpapi
import (
"errors"
"net/http"
"git.118im.com/im_team/olons_server/internal/attachments"
)
func (a *API) uploadImage(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
methodNotAllowed(w, r, http.MethodPost)
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
r.Body = http.MaxBytesReader(w, r.Body, 6<<20)
file, header, err := r.FormFile("file")
if err != nil {
writeError(w, r, http.StatusBadRequest, 30000, "IMAGE_INVALID", "validation failed", map[string]any{"field": "file"})
return
}
defer file.Close()
result, err := a.attachments.UploadImage(r.Context(), principal.MemberID, header.Filename, file)
if err != nil {
if errors.Is(err, attachments.ErrImageInvalid) {
writeError(w, r, http.StatusBadRequest, 30000, "IMAGE_INVALID", "validation failed", map[string]any{"field": "file"})
} else {
writeError(w, r, http.StatusInternalServerError, 90000, reasonInternal, "internal error", nil)
}
return
}
writeSuccess(w, r, result)
}
+3 -3
View File
@@ -6,9 +6,9 @@ import (
"strconv"
"strings"
"git.118im.com/im_team/im_workbench/internal/auth"
"git.118im.com/im_team/im_workbench/internal/finance"
"git.118im.com/im_team/im_workbench/internal/store"
"git.118im.com/im_team/olons_server/internal/auth"
"git.118im.com/im_team/olons_server/internal/finance"
"git.118im.com/im_team/olons_server/internal/store"
)
func (a *API) paymentAccounts(w http.ResponseWriter, r *http.Request) {
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"strconv"
"strings"
"git.118im.com/im_team/im_workbench/internal/mall"
"git.118im.com/im_team/im_workbench/internal/store"
"git.118im.com/im_team/olons_server/internal/mall"
"git.118im.com/im_team/olons_server/internal/store"
)
func (a *API) manualProducts(w http.ResponseWriter, r *http.Request) {
+53 -2
View File
@@ -3,10 +3,11 @@ package httpapi
import (
"errors"
"net/http"
"strconv"
"strings"
"git.118im.com/im_team/im_workbench/internal/portal"
"git.118im.com/im_team/im_workbench/internal/store"
"git.118im.com/im_team/olons_server/internal/portal"
"git.118im.com/im_team/olons_server/internal/store"
)
var publicContentKeys = map[string]struct{}{
@@ -187,6 +188,56 @@ func (a *API) notices(w http.ResponseWriter, r *http.Request) {
writeSuccess(w, r, result)
}
func (a *API) popupNotice(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
methodNotAllowed(w, r, http.MethodGet)
return
}
if !a.ensurePortal(w, r) {
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
result, err := a.portal.PopupNotice(r.Context(), principal.TenantID, principal.MemberID)
if err != nil {
writePortalError(w, r, err)
return
}
writeSuccess(w, r, result)
}
func (a *API) noticeResource(w http.ResponseWriter, r *http.Request) {
path := strings.Trim(strings.TrimPrefix(r.URL.Path, "/v1/notices/"), "/")
parts := strings.Split(path, "/")
if len(parts) != 2 || parts[1] != "read" {
writePortalError(w, r, store.ErrResourceNotFound)
return
}
noticeID, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil || noticeID <= 0 {
writePortalError(w, r, store.ErrResourceNotFound)
return
}
if r.Method != http.MethodPost {
methodNotAllowed(w, r, http.MethodPost)
return
}
if !a.ensurePortal(w, r) {
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
if err := a.portal.MarkNoticeRead(r.Context(), principal.TenantID, principal.MemberID, noticeID); err != nil {
writePortalError(w, r, err)
return
}
writeSuccess(w, r, struct{}{})
}
func (a *API) ensurePortal(w http.ResponseWriter, r *http.Request) bool {
if a.portal != nil {
return true
+3 -3
View File
@@ -4,9 +4,9 @@ import (
"errors"
"net/http"
accountsvc "git.118im.com/im_team/im_workbench/internal/accounts"
"git.118im.com/im_team/im_workbench/internal/auth"
"git.118im.com/im_team/im_workbench/internal/store"
accountsvc "git.118im.com/im_team/olons_server/internal/accounts"
"git.118im.com/im_team/olons_server/internal/auth"
"git.118im.com/im_team/olons_server/internal/store"
)
type avatarRequest struct {
+3 -3
View File
@@ -6,9 +6,9 @@ import (
"strconv"
"strings"
"git.118im.com/im_team/im_workbench/internal/auth"
"git.118im.com/im_team/im_workbench/internal/store"
"git.118im.com/im_team/im_workbench/internal/tasks"
"git.118im.com/im_team/olons_server/internal/auth"
"git.118im.com/im_team/olons_server/internal/store"
"git.118im.com/im_team/olons_server/internal/tasks"
)
type taskClaimRequest struct {