From 42c1c17c0a20eae961bae88c4c2d5b6276ae7be8 Mon Sep 17 00:00:00 2001 From: Rogee Date: Wed, 30 Apr 2025 17:06:10 +0800 Subject: [PATCH] feat: add wxshare --- backend/app/http/admin/auth.go | 5 +- backend/app/http/admin/medias.go | 17 +++-- backend/app/http/admin/orders.go | 7 +- backend/app/http/admin/posts.go | 36 +++++---- backend/app/http/admin/statistics.go | 3 +- backend/app/http/admin/uploads.go | 14 ++-- backend/app/http/admin/users.go | 19 +++-- backend/app/http/auth.go | 10 +-- backend/app/http/pays.go | 5 +- backend/app/http/posts.go | 39 +++++----- backend/app/http/provider.gen.go | 10 ++- backend/app/http/routes.gen.go | 18 +++-- backend/app/http/users.go | 11 +-- backend/app/http/wechat.go | 19 ----- backend/app/http/wechats.go | 21 +++++ backend/main.go | 28 +++---- backend/providers/wechat/funcs.go | 16 +++- backend/providers/wechat/wechat.go | 30 ++++++++ frontend/wechat/bun.lockb | Bin 70237 -> 71979 bytes frontend/wechat/package.json | 5 +- frontend/wechat/src/api/wechatApi.js | 11 +++ frontend/wechat/src/hooks/useRandom.js | 14 ++++ frontend/wechat/src/hooks/useWxSDK.js | 80 ++++++++++++++++++++ frontend/wechat/src/views/ArticleDetail.vue | 42 +++------- 24 files changed, 313 insertions(+), 147 deletions(-) delete mode 100644 backend/app/http/wechat.go create mode 100644 backend/app/http/wechats.go create mode 100644 frontend/wechat/src/api/wechatApi.js create mode 100644 frontend/wechat/src/hooks/useRandom.js create mode 100644 frontend/wechat/src/hooks/useWxSDK.js diff --git a/backend/app/http/admin/auth.go b/backend/app/http/admin/auth.go index 0b77bad..cf39079 100644 --- a/backend/app/http/admin/auth.go +++ b/backend/app/http/admin/auth.go @@ -21,8 +21,9 @@ type TokenResponse struct { } // Login -// @Router /admin/auth [post] -// @Bind body body +// +// @Router /admin/auth [post] +// @Bind body body func (ctl *auth) Login(ctx fiber.Ctx, body *AuthBody) (*TokenResponse, error) { if body.Username == "pl.yang" && body.Password == "Xixi@0202" { claim := ctl.jwt.CreateClaims(jwt.BaseClaims{ diff --git a/backend/app/http/admin/medias.go b/backend/app/http/admin/medias.go index a72b12b..568666a 100644 --- a/backend/app/http/admin/medias.go +++ b/backend/app/http/admin/medias.go @@ -14,17 +14,19 @@ type medias struct { } // List medias -// @Router /admin/medias [get] -// @Bind pagination query -// @Bind query query +// +// @Router /admin/medias [get] +// @Bind pagination query +// @Bind query query func (ctl *medias) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery) (*requests.Pager, error) { cond := models.Medias.BuildConditionWithKey(query.Keyword) return models.Medias.List(ctx.Context(), pagination, cond) } // Show media -// @Router /admin/medias/:id [get] -// @Bind id path +// +// @Router /admin/medias/:id [get] +// @Bind id path func (ctl *medias) Show(ctx fiber.Ctx, id int64) error { media, err := models.Medias.GetByID(ctx.Context(), id) if err != nil { @@ -40,8 +42,9 @@ func (ctl *medias) Show(ctx fiber.Ctx, id int64) error { } // Delete -// @Router /admin/medias/:id [delete] -// @Bind id path +// +// @Router /admin/medias/:id [delete] +// @Bind id path func (ctl *medias) Delete(ctx fiber.Ctx, id int64) error { media, err := models.Medias.GetByID(ctx.Context(), id) if err != nil { diff --git a/backend/app/http/admin/orders.go b/backend/app/http/admin/orders.go index c3aca74..ae2552f 100644 --- a/backend/app/http/admin/orders.go +++ b/backend/app/http/admin/orders.go @@ -16,9 +16,10 @@ type OrderListQuery struct { type orders struct{} // List users -// @Router /admin/orders [get] -// @Bind pagination query -// @Bind query query +// +// @Router /admin/orders [get] +// @Bind pagination query +// @Bind query query func (ctl *orders) List(ctx fiber.Ctx, pagination *requests.Pagination, query *OrderListQuery) (*requests.Pager, error) { cond := models.Orders.BuildConditionWithKey(query.OrderNumber, query.UserID) return models.Orders.List(ctx.Context(), pagination, cond) diff --git a/backend/app/http/admin/posts.go b/backend/app/http/admin/posts.go index d1c389f..7d57108 100644 --- a/backend/app/http/admin/posts.go +++ b/backend/app/http/admin/posts.go @@ -18,9 +18,10 @@ type ListQuery struct { type posts struct{} // List posts -// @Router /admin/posts [get] -// @Bind pagination query -// @Bind query query +// +// @Router /admin/posts [get] +// @Bind pagination query +// @Bind query query func (ctl *posts) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery) (*requests.Pager, error) { cond := models.Posts.BuildConditionWithKey(query.Keyword) pager, err := models.Posts.List(ctx.Context(), pagination, cond) @@ -63,8 +64,9 @@ type PostForm struct { } // Create -// @Router /admin/posts [post] -// @Bind form body +// +// @Router /admin/posts [post] +// @Bind form body func (ctl *posts) Create(ctx fiber.Ctx, form *PostForm) error { post := model.Posts{ Title: form.Title, @@ -100,9 +102,10 @@ func (ctl *posts) Create(ctx fiber.Ctx, form *PostForm) error { } // Update posts -// @Router /admin/posts/:id [put] -// @Bind id path -// @Bind form body +// +// @Router /admin/posts/:id [put] +// @Bind id path +// @Bind form body func (ctl *posts) Update(ctx fiber.Ctx, id int64, form *PostForm) error { oldPost, err := models.Posts.GetByID(ctx.Context(), id) if err != nil { @@ -148,8 +151,9 @@ func (ctl *posts) Update(ctx fiber.Ctx, id int64, form *PostForm) error { } // Delete posts -// @Router /admin/posts/:id [delete] -// @Bind id path +// +// @Router /admin/posts/:id [delete] +// @Bind id path func (ctl *posts) Delete(ctx fiber.Ctx, id int64) error { post, err := models.Posts.GetByID(ctx.Context(), id) if err != nil { @@ -172,8 +176,9 @@ type PostItem struct { } // Show posts by id -// @Router /admin/posts/:id [get] -// @Bind id path +// +// @Router /admin/posts/:id [get] +// @Bind id path func (ctl *posts) Show(ctx fiber.Ctx, id int64) (*PostItem, error) { post, err := models.Posts.GetByID(ctx.Context(), id) if err != nil { @@ -193,9 +198,10 @@ func (ctl *posts) Show(ctx fiber.Ctx, id int64) (*PostItem, error) { } // SendTo -// @Router /admin/posts/:id/send-to/:userId [post] -// @Bind id path -// @Bind userId path +// +// @Router /admin/posts/:id/send-to/:userId [post] +// @Bind id path +// @Bind userId path func (ctl *posts) SendTo(ctx fiber.Ctx, id, userId int64) error { if _, err := models.Posts.GetByID(ctx.Context(), id); err != nil { return err diff --git a/backend/app/http/admin/statistics.go b/backend/app/http/admin/statistics.go index 08ef45d..45f5062 100644 --- a/backend/app/http/admin/statistics.go +++ b/backend/app/http/admin/statistics.go @@ -22,7 +22,8 @@ type StatisticsResponse struct { } // dashboard statistics -// @Router /admin/statistics [get] +// +// @Router /admin/statistics [get] func (s *statistics) statistics(ctx fiber.Ctx) (*StatisticsResponse, error) { statistics := &StatisticsResponse{} diff --git a/backend/app/http/admin/uploads.go b/backend/app/http/admin/uploads.go index ab9aa39..5d91720 100644 --- a/backend/app/http/admin/uploads.go +++ b/backend/app/http/admin/uploads.go @@ -33,10 +33,11 @@ type PreCheckResp struct { } // PreUploadCheck -// @Router /admin/uploads/pre-uploaded-check/:md5.:ext [get] -// @Bind md5 path -// @Bind ext path -// @Bind mime query +// +// @Router /admin/uploads/pre-uploaded-check/:md5.:ext [get] +// @Bind md5 path +// @Bind ext path +// @Bind mime query func (up *uploads) PreUploadCheck(ctx fiber.Ctx, md5, ext, mime string) (*PreCheckResp, error) { _, err := models.Medias.GetByHash(ctx.Context(), md5) if err != nil && errors.Is(err, qrm.ErrNoRows) { @@ -59,8 +60,9 @@ type PostUploadedForm struct { } // PostUploadedAction -// @Router /admin/uploads/post-uploaded-action [post] -// @Bind body body +// +// @Router /admin/uploads/post-uploaded-action [post] +// @Bind body body func (up *uploads) PostUploadedAction(ctx fiber.Ctx, body *PostUploadedForm) error { m, err := models.Medias.GetByHash(ctx.Context(), body.Md5) if err != nil && !errors.Is(err, qrm.ErrNoRows) { diff --git a/backend/app/http/admin/users.go b/backend/app/http/admin/users.go index f4c7e93..669dba7 100644 --- a/backend/app/http/admin/users.go +++ b/backend/app/http/admin/users.go @@ -16,25 +16,28 @@ type UserListQuery struct { type users struct{} // List users -// @Router /admin/users [get] -// @Bind pagination query -// @Bind query query +// +// @Router /admin/users [get] +// @Bind pagination query +// @Bind query query func (ctl *users) List(ctx fiber.Ctx, pagination *requests.Pagination, query *UserListQuery) (*requests.Pager, error) { cond := models.Users.BuildConditionWithKey(query.Keyword) return models.Users.List(ctx.Context(), pagination, cond) } // Show user -// @Router /admin/users/:id [get] -// @Bind id path +// +// @Router /admin/users/:id [get] +// @Bind id path func (ctl *users) Show(ctx fiber.Ctx, id int64) (*model.Users, error) { return models.Users.GetByID(ctx.Context(), id) } // Articles show user bought articles -// @Router /admin/users/:id/articles [get] -// @Bind id path -// @Bind pagination query +// +// @Router /admin/users/:id/articles [get] +// @Bind id path +// @Bind pagination query func (ctl *users) Articles(ctx fiber.Ctx, id int64, pagination *requests.Pagination) (*requests.Pager, error) { return models.Posts.Bought(ctx.Context(), id, pagination) } diff --git a/backend/app/http/auth.go b/backend/app/http/auth.go index c645b81..e60b3af 100644 --- a/backend/app/http/auth.go +++ b/backend/app/http/auth.go @@ -27,10 +27,10 @@ type auth struct { jwt *jwt.JWT } -// @Router /auth/login [get] -// @Bind code query -// @Bind state query -// @Bind redirect query +// @Router /auth/login [get] +// @Bind code query +// @Bind state query +// @Bind redirect query func (ctl *auth) Login(ctx fiber.Ctx, code, state, redirect string) error { log.Debugf("code: %s, state: %s", code, state) @@ -100,7 +100,7 @@ func (ctl *auth) Login(ctx fiber.Ctx, code, state, redirect string) error { } // @Router /auth/wechat [get] -// @Bind redirect query +// @Bind redirect query func (ctl *auth) Wechat(ctx fiber.Ctx, redirect string) error { log.Debugf("%s, query: %v", ctx.OriginalURL(), ctx.Queries()) diff --git a/backend/app/http/pays.go b/backend/app/http/pays.go index f853797..d4279aa 100644 --- a/backend/app/http/pays.go +++ b/backend/app/http/pays.go @@ -22,8 +22,9 @@ type pays struct { } // Callback -// @Router /pay/callback/:channel [get] -// @Bind channel path +// +// @Router /pay/callback/:channel [get] +// @Bind channel path func (ctl *pays) Callback(ctx fiber.Ctx, channel string) error { log := log.WithField("method", "pays.Callback") diff --git a/backend/app/http/posts.go b/backend/app/http/posts.go index 4d9d5e4..9ccb2b5 100644 --- a/backend/app/http/posts.go +++ b/backend/app/http/posts.go @@ -29,10 +29,11 @@ type posts struct { } // List posts -// @Router /posts [get] -// @Bind pagination query -// @Bind query query -// @Bind user local +// +// @Router /posts [get] +// @Bind pagination query +// @Bind query query +// @Bind user local func (ctl *posts) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery, user *model.Users) (*requests.Pager, error) { log.Infof("ok", pagination, query.Keyword, user.ID) @@ -99,9 +100,10 @@ type PostItem struct { } // Show -// @Router /posts/:id/show [get] -// @Bind id path -// @Bind user local +// +// @Router /posts/:id/show [get] +// @Bind id path +// @Bind user local func (ctl *posts) Show(ctx fiber.Ctx, id int64, user *model.Users) (*PostItem, error) { log.Infof("Fetching post with ID: %d", id) post, err := models.Posts.GetByID(ctx.Context(), id) @@ -148,9 +150,10 @@ type PlayUrl struct { } // Play -// @Router /posts/:id/play [get] -// @Bind id path -// @Bind user local +// +// @Router /posts/:id/play [get] +// @Bind id path +// @Bind user local func (ctl *posts) Play(ctx fiber.Ctx, id int64, user *model.Users) (*PlayUrl, error) { log.Infof("Fetching play URL for post ID: %d", id) post, err := models.Posts.GetByID(ctx.Context(), id) @@ -181,10 +184,11 @@ func (ctl *posts) Play(ctx fiber.Ctx, id int64, user *model.Users) (*PlayUrl, er } // Mine posts -// @Router /posts/mine [get] -// @Bind pagination query -// @Bind query query -// @Bind user local +// +// @Router /posts/mine [get] +// @Bind pagination query +// @Bind query query +// @Bind user local func (ctl *posts) Mine(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery, user *model.Users) (*requests.Pager, error) { log.Infof("Fetching posts for user with pagination: %+v and keyword: %v", pagination, query.Keyword) @@ -236,9 +240,10 @@ func (ctl *posts) Mine(ctx fiber.Ctx, pagination *requests.Pagination, query *Li } // Buy -// @Router /posts/:id/buy [get] -// @Bind id path -// @Bind user local +// +// @Router /posts/:id/buy [get] +// @Bind id path +// @Bind user local func (ctl *posts) Buy(ctx fiber.Ctx, id int64, user *model.Users) (*wechat.JSAPIPayParams, error) { post, err := models.Posts.GetByID(ctx.Context(), id) if err != nil { diff --git a/backend/app/http/provider.gen.go b/backend/app/http/provider.gen.go index 843f797..6d3b0bb 100755 --- a/backend/app/http/provider.gen.go +++ b/backend/app/http/provider.gen.go @@ -58,12 +58,14 @@ func Provide(opts ...opt.Option) error { pays *pays, posts *posts, users *users, + wechats *wechats, ) (contracts.HttpRoute, error) { obj := &Routes{ - auth: auth, - pays: pays, - posts: posts, - users: users, + auth: auth, + pays: pays, + posts: posts, + users: users, + wechats: wechats, } if err := obj.Prepare(); err != nil { return nil, err diff --git a/backend/app/http/routes.gen.go b/backend/app/http/routes.gen.go index 3168d6d..303650b 100644 --- a/backend/app/http/routes.gen.go +++ b/backend/app/http/routes.gen.go @@ -14,11 +14,12 @@ import ( // @provider contracts.HttpRoute atom.GroupRoutes type Routes struct { - log *log.Entry `inject:"false"` - auth *auth - pays *pays - posts *posts - users *users + log *log.Entry `inject:"false"` + auth *auth + pays *pays + posts *posts + users *users + wechats *wechats } func (r *Routes) Prepare() error { @@ -95,4 +96,11 @@ func (r *Routes) Register(router fiber.Router) { Body[ProfileForm]("form"), )) + // 注册路由组: wechats + router.Get("/wechats/js-sdk", DataFunc2( + r.wechats.GetJsSDK, + QueryParam[string]("url"), + Local[*model.Users]("user"), + )) + } diff --git a/backend/app/http/users.go b/backend/app/http/users.go index 17624a2..b801e0a 100644 --- a/backend/app/http/users.go +++ b/backend/app/http/users.go @@ -19,8 +19,8 @@ type UserInfo struct { Username string `json:"username,omitempty"` } -// @Router /users/profile [get] -// @Bind user local +// @Router /users/profile [get] +// @Bind user local func (ctl *users) Profile(ctx fiber.Ctx, user *model.Users) (*UserInfo, error) { return &UserInfo{ ID: user.ID, @@ -34,9 +34,10 @@ type ProfileForm struct { } // Update -// @Router /users/username [put] -// @Bind user local -// @Bind form body +// +// @Router /users/username [put] +// @Bind user local +// @Bind form body func (ctl *users) Update(ctx fiber.Ctx, user *model.Users, form *ProfileForm) error { username := strings.TrimSpace(form.Username) if len([]rune(username)) > 12 { diff --git a/backend/app/http/wechat.go b/backend/app/http/wechat.go deleted file mode 100644 index 4ae8264..0000000 --- a/backend/app/http/wechat.go +++ /dev/null @@ -1,19 +0,0 @@ -package http - -import ( - "quyun/database/schemas/public/model" - "quyun/providers/wechat" - - "github.com/gofiber/fiber/v3" -) - -// @provider -type wechats struct { - wechat *wechat.Client -} - -// @Router /wechat/js-ticket [get] -// @Bind user local -func (ctl *wechats) GetTicket(ctx fiber.Ctx, user *model.Users) (string, error) { - return ctl.wechat.GetJSTicket(user.AuthToken.Data.AccessToken) -} diff --git a/backend/app/http/wechats.go b/backend/app/http/wechats.go new file mode 100644 index 0000000..6a5f3ab --- /dev/null +++ b/backend/app/http/wechats.go @@ -0,0 +1,21 @@ +package http + +import ( + "quyun/database/schemas/public/model" + "quyun/providers/wechat" + + "github.com/gofiber/fiber/v3" +) + +// @provider +type wechats struct { + wechat *wechat.Client +} + +// GetJsSDK +// @Router /wechats/js-sdk [get] +// @Bind url query +// @Bind user local +func (ctl *wechats) GetJsSDK(ctx fiber.Ctx, url string, user *model.Users) (*wechat.JsSDK, error) { + return ctl.wechat.GetJsSDK(user.AuthToken.Data.StableAccessToken, url) +} diff --git a/backend/main.go b/backend/main.go index e1b908c..c0a8513 100644 --- a/backend/main.go +++ b/backend/main.go @@ -9,20 +9,20 @@ import ( "go.ipao.vip/atom" ) -// @title ApiDoc -// @version 1.0 -// @description This is a sample server celler server. -// @termsOfService http://swagger.io/terms/ -// @contact.name UserName -// @contact.url http://www.swagger.io/support -// @contact.email support@swagger.io -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html -// @host localhost:8080 -// @BasePath /api/v1 -// @securityDefinitions.basic BasicAuth -// @externalDocs.description OpenAPI -// @externalDocs.url https://swagger.io/resources/open-api/ +// @title ApiDoc +// @version 1.0 +// @description This is a sample server celler server. +// @termsOfService http://swagger.io/terms/ +// @contact.name UserName +// @contact.url http://www.swagger.io/support +// @contact.email support@swagger.io +// @license.name Apache 2.0 +// @license.url http://www.apache.org/licenses/LICENSE-2.0.html +// @host localhost:8080 +// @BasePath /api/v1 +// @securityDefinitions.basic BasicAuth +// @externalDocs.description OpenAPI +// @externalDocs.url https://swagger.io/resources/open-api/ func main() { opts := []atom.Option{ atom.Name("quyun"), diff --git a/backend/providers/wechat/funcs.go b/backend/providers/wechat/funcs.go index 89a9699..c5c3de2 100644 --- a/backend/providers/wechat/funcs.go +++ b/backend/providers/wechat/funcs.go @@ -1,14 +1,24 @@ package wechat -import "math/rand" +import ( + "crypto/sha1" + "encoding/hex" + "math/rand" +) // RandomString generate random size string -func randomString(size int) (string, error) { +func randomString(size int) string { // generate size string [0-9a-zA-Z] const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" b := make([]byte, size) for i := range b { b[i] = chars[rand.Intn(len(chars))] } - return string(b), nil + return string(b) +} + +func hashSha1(input string) string { + h := sha1.New() + h.Write([]byte(input)) + return hex.EncodeToString(h.Sum(nil)) } diff --git a/backend/providers/wechat/wechat.go b/backend/providers/wechat/wechat.go index 3cd8165..95c4d07 100644 --- a/backend/providers/wechat/wechat.go +++ b/backend/providers/wechat/wechat.go @@ -3,6 +3,7 @@ package wechat import ( "crypto/sha1" "encoding/hex" + "fmt" "net/url" "sort" "strings" @@ -287,3 +288,32 @@ func (we *Client) GetJSTicket(token string) (string, error) { return data.Ticket, nil } + +type JsSDK struct { + Debug bool `json:"debug"` + AppID string `json:"appId"` + Timestamp int64 `json:"timestamp"` + NonceStr string `json:"nonceStr"` + Signature string `json:"signature"` +} + +// GetJSTicket +func (we *Client) GetJsSDK(token, url string) (*JsSDK, error) { + sdk := &JsSDK{ + Debug: false, + AppID: we.appID, + Timestamp: time.Now().Unix(), + NonceStr: randomString(16), + Signature: "", + } + // get ticket + ticket, err := we.GetJSTicket(token) + if err != nil { + return nil, errors.Wrap(err, "get wechat ticket failed") + } + + input := fmt.Sprintf("jsapi_ticket=%s&noncestr=%s×tamp=%d&url=%s", ticket, sdk.NonceStr, sdk.Timestamp, url) + sdk.Signature = hashSha1(input) + + return sdk, nil +} diff --git a/frontend/wechat/bun.lockb b/frontend/wechat/bun.lockb index 9fad4b6030b7f5c827d7e5361de74451e90879cf..b4ae202a4f0110a7c3c0910112324ab06aef86f3 100755 GIT binary patch delta 12646 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 V#?$(b0N7yp+55~?6L?jp|8Moeq7?uD delta 11656 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 diff --git a/frontend/wechat/package.json b/frontend/wechat/package.json index 21a3197..c544a0c 100644 --- a/frontend/wechat/package.json +++ b/frontend/wechat/package.json @@ -15,10 +15,13 @@ "dplayer": "^1.27.1", "pinia": "^3.0.2", "plyr": "^3.7.8", + "sha1": "^1.1.1", "tailwindcss": "^4.1.4", "vue": "^3.5.13", "vue-icons-plus": "^0.1.8", - "vue-router": "^4.5.0" + "vue-router": "^4.5.0", + "wechat-js-sdk": "^1.3.3", + "weixin-js-sdk": "^1.6.5" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.2", diff --git a/frontend/wechat/src/api/wechatApi.js b/frontend/wechat/src/api/wechatApi.js new file mode 100644 index 0000000..bfc9a84 --- /dev/null +++ b/frontend/wechat/src/api/wechatApi.js @@ -0,0 +1,11 @@ +import client from './client'; + +export const wechatApi = { + jsSdk() { + return client.get('/wechats/js-sdk', { + params: { + url: window.location.href.split('#')[0], + }, + }); + }, +} \ No newline at end of file diff --git a/frontend/wechat/src/hooks/useRandom.js b/frontend/wechat/src/hooks/useRandom.js new file mode 100644 index 0000000..a3f04b1 --- /dev/null +++ b/frontend/wechat/src/hooks/useRandom.js @@ -0,0 +1,14 @@ +export function useRandom() { + function string(size) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const charactersLength = characters.length; + for (let i = 0; i < size; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; + } + return { + string, + }; +} \ No newline at end of file diff --git a/frontend/wechat/src/hooks/useWxSDK.js b/frontend/wechat/src/hooks/useWxSDK.js new file mode 100644 index 0000000..48551ea --- /dev/null +++ b/frontend/wechat/src/hooks/useWxSDK.js @@ -0,0 +1,80 @@ +import wx from "weixin-js-sdk"; + +export function useWxSDK() { + /** + * 初始化设置 + */ + function initConfig(config) { + return new Promise((resolve) => { + wx.config({ + debug: config.debug, + appId: config.appId, + timestamp: config.timestamp, + nonceStr: config.nonceStr, + signature: config.signature, + jsApiList: [ + "chooseImage", + "uploadImage", + "previewImage", + "onMenuShareTimeline", + "onMenuShareAppMessage", + "chooseWXPay", + ], + openTagList: [], + }); + wx.ready(() => { + console.log("wx.ready called"); + resolve(true); + }); + }); + } + + /** 设置微信分享 */ + function setShareInfo( + shareInfo, + onSuccess = () => { }, + onCancel = () => { } + ) { + wx.onMenuShareTimeline({ + title: shareInfo.title, // 分享标题 + link: shareInfo.link, // 分享链接,可以不是当前页面,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 + imgUrl: shareInfo.imgUrl, + success: function () { + // 用户确认分享后执行的回调函数 + onSuccess(); + }, + cancel: function () { + onCancel(); + // 用户取消分享后执行的回调函数 + }, + }); + wx.onMenuShareAppMessage({ + title: shareInfo.title, // 分享标题 + desc: shareInfo.desc, + link: shareInfo.link, // 分享链接,可以不是当前页面,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 + imgUrl: shareInfo.imgUrl, + type: "link", // 分享类型,music、video或link,不填默认为link + success: function (e) { + // 用户确认分享后执行的回调函数 + onSuccess(); + console.log("分享成功", e); + }, + cancel: function (e) { + // 用户取消分享后执行的回调函数 + onCancel(); + console.log("分享取消", e); + }, + }); + } + + /** 是否是ios微信 */ + function isiOSWechat() { + return window.__wxjs_is_wkwebview; + } + + return { + initConfig, + setShareInfo, + isiOSWechat, + }; +} \ No newline at end of file diff --git a/frontend/wechat/src/views/ArticleDetail.vue b/frontend/wechat/src/views/ArticleDetail.vue index 23e9b4e..f1085e6 100644 --- a/frontend/wechat/src/views/ArticleDetail.vue +++ b/frontend/wechat/src/views/ArticleDetail.vue @@ -5,7 +5,10 @@ import { onMounted, onUnmounted, ref } from 'vue' import { BsChevronLeft } from 'vue-icons-plus/bs' import { useRoute, useRouter } from 'vue-router' import { postApi } from '../api/postApi' +import { wechatApi } from '../api/wechatApi' +import { useWxSDK } from '../hooks/useWxSDK' +const wx = useWxSDK() const route = useRoute() const router = useRouter() const article = ref(null) @@ -90,40 +93,13 @@ const fetchArticle = async () => { article.value = data document.title = article.value.title - // 定义“分享给朋友”及“分享到QQ”按钮的分享内容 - const shareContent = { + // 调用微信 JS SDK 分享接口 + wx.setShareInfo({ title: data.title, desc: data.content, link: window.location.href, imgUrl: data.head_images[0] - } - // 调用微信 JS SDK 分享接口 - if (window.wx) { - wx.updateTimelineShareData({ - title: shareContent.title, - link: shareContent.link, - imgUrl: shareContent.imgUrl, - success: function () { - console.log('分享成功') - }, - cancel: function () { - console.log('分享取消') - } - }) - - wx.updateAppMessageShareData({ - title: shareContent.title, - desc: shareContent.desc, - link: shareContent.link, - imgUrl: shareContent.imgUrl, - success: function () { - console.log('分享成功') - }, - cancel: function () { - console.log('分享取消') - } - }) - } + }) } catch (error) { console.error('Failed to fetch article:', error) alert("加载失败!") @@ -137,6 +113,12 @@ const handleBack = () => { onMounted(async () => { await fetchArticle() initializePlayer() + + wechatApi.jsSdk().then(resp => { + wx.initConfig(resp.data) + }).catch(error => { + console.error('Failed to initialize WeChat SDK:', error) + }) }) onUnmounted(() => {