diff --git a/backend/app/http/admin/medias.go b/backend/app/http/admin/medias.go index 28ad3b8..03b499e 100644 --- a/backend/app/http/admin/medias.go +++ b/backend/app/http/admin/medias.go @@ -3,12 +3,15 @@ package admin import ( "quyun/app/models" "quyun/app/requests" + "quyun/providers/ali" "github.com/gofiber/fiber/v3" ) // @provider -type medias struct{} +type medias struct { + oss *ali.OSSClient +} // List medias // @Router /v1/admin/medias [get] @@ -18,3 +21,20 @@ func (ctl *medias) List(ctx fiber.Ctx, pagination *requests.Pagination, query *L cond := models.Medias.BuildConditionWithKey(query.Keyword) return models.Medias.List(ctx.Context(), pagination, cond) } + +// Show media +// @Router /v1/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 { + return ctx.SendString("Media not found") + } + + url, err := ctl.oss.GetSignedUrl(ctx.Context(), media.Path) + if err != nil { + return err + } + + return ctx.Redirect().To(url) +} diff --git a/backend/app/http/admin/posts.go b/backend/app/http/admin/posts.go index 841e9c7..7f59ca9 100644 --- a/backend/app/http/admin/posts.go +++ b/backend/app/http/admin/posts.go @@ -28,6 +28,7 @@ func (ctl *posts) List(ctx fiber.Ctx, pagination *requests.Pagination, query *Li type PostForm struct { Title string `json:"title"` + HeadImage int64 `json:"head_image"` Price int64 `json:"price"` Discount int16 `json:"discount"` Introduction string `json:"introduction"` diff --git a/backend/app/http/admin/provider.gen.go b/backend/app/http/admin/provider.gen.go index 61e8afd..938ed8e 100755 --- a/backend/app/http/admin/provider.gen.go +++ b/backend/app/http/admin/provider.gen.go @@ -23,8 +23,12 @@ func Provide(opts ...opt.Option) error { }); err != nil { return err } - if err := container.Container.Provide(func() (*medias, error) { - obj := &medias{} + if err := container.Container.Provide(func( + oss *ali.OSSClient, + ) (*medias, error) { + obj := &medias{ + oss: oss, + } return obj, nil }); err != nil { diff --git a/backend/app/http/admin/routes.gen.go b/backend/app/http/admin/routes.gen.go index cae2dc4..cdc5b81 100644 --- a/backend/app/http/admin/routes.gen.go +++ b/backend/app/http/admin/routes.gen.go @@ -45,6 +45,11 @@ func (r *Routes) Register(router fiber.Router) { Query[ListQuery]("query"), )) + router.Get("/v1/admin/medias/:id", Func1( + r.medias.Show, + PathParam[int64]("id"), + )) + // 注册路由组: orders router.Get("/v1/admin/orders", DataFunc2( r.orders.List, @@ -81,10 +86,11 @@ func (r *Routes) Register(router fiber.Router) { )) // 注册路由组: uploads - router.Get("/v1/admin/uploads/pre-uploaded-check/:md5.:ext", DataFunc2( + router.Get("/v1/admin/uploads/pre-uploaded-check/:md5.:ext", DataFunc3( r.uploads.PreUploadCheck, PathParam[string]("md5"), PathParam[string]("ext"), + QueryParam[string]("mime"), )) router.Post("/v1/admin/uploads/post-uploaded-action", Func1( diff --git a/backend/app/http/admin/uploads.go b/backend/app/http/admin/uploads.go index 6e65cee..abfd882 100644 --- a/backend/app/http/admin/uploads.go +++ b/backend/app/http/admin/uploads.go @@ -32,10 +32,11 @@ type PreCheckResp struct { // @Router /v1/admin/uploads/pre-uploaded-check/:md5.:ext [get] // @Bind md5 path // @Bind ext path -func (up *uploads) PreUploadCheck(ctx fiber.Ctx, md5, ext string) (*PreCheckResp, error) { +// @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) { - preSign, err := up.oss.PreSignUpload(ctx.Context(), fmt.Sprintf("%s.%s", md5, ext)) + preSign, err := up.oss.PreSignUpload(ctx.Context(), fmt.Sprintf("%s.%s", md5, ext), mime) if err != nil { return nil, err } diff --git a/backend/app/http/routes.gen.go b/backend/app/http/routes.gen.go index dbb0dd8..8cb323b 100644 --- a/backend/app/http/routes.gen.go +++ b/backend/app/http/routes.gen.go @@ -68,9 +68,10 @@ func (r *Routes) Register(router fiber.Router) { Query[ListQuery]("query"), )) - router.Get("/api/posts/buy/:id", Func1( + router.Get("/api/posts/buy/:id", DataFunc2( r.posts.Buy, PathParam[int64]("id"), + Local[*model.Users]("user"), )) } diff --git a/backend/app/jobs/provider.gen.go b/backend/app/jobs/provider.gen.go index 4982468..ce2eb79 100755 --- a/backend/app/jobs/provider.gen.go +++ b/backend/app/jobs/provider.gen.go @@ -2,6 +2,7 @@ package jobs import ( "quyun/providers/ali" + "quyun/providers/app" "quyun/providers/job" "github.com/riverqueue/river" @@ -40,9 +41,49 @@ func Provide(opts ...opt.Option) error { } if err := container.Container.Provide(func( __job *job.Job, + app *app.Config, + job *job.Job, oss *ali.OSSClient, ) (contracts.Initial, error) { obj := &DownloadFromAliOSSWorker{ + app: app, + job: job, + oss: oss, + } + if err := river.AddWorkerSafely(__job.Workers, obj); err != nil { + return nil, err + } + + return obj, nil + }, atom.GroupInitial); err != nil { + return err + } + if err := container.Container.Provide(func( + __job *job.Job, + job *job.Job, + oss *ali.OSSClient, + ) (contracts.Initial, error) { + obj := &ExtractAudioFromVideoWorker{ + job: job, + oss: oss, + } + if err := river.AddWorkerSafely(__job.Workers, obj); err != nil { + return nil, err + } + + return obj, nil + }, atom.GroupInitial); err != nil { + return err + } + if err := container.Container.Provide(func( + __job *job.Job, + app *app.Config, + job *job.Job, + oss *ali.OSSClient, + ) (contracts.Initial, error) { + obj := &ExtractHeadImageFromVideoWorker{ + app: app, + job: job, oss: oss, } if err := river.AddWorkerSafely(__job.Workers, obj); err != nil { diff --git a/backend/app/models/medias.go b/backend/app/models/medias.go index 2e4215a..3189c7b 100644 --- a/backend/app/models/medias.go +++ b/backend/app/models/medias.go @@ -241,8 +241,8 @@ func (m *mediasModel) GetByID(ctx context.Context, id int64) (*model.Medias, err m.log.Infof("sql: %s", stmt.DebugSql()) var media model.Medias - err := stmt.QueryContext(ctx, db, &media) - if err != nil { + + if err := stmt.QueryContext(ctx, db, &media); err != nil { m.log.Errorf("error querying media item by ID: %v", err) return nil, err } diff --git a/backend/config.toml b/backend/config.toml index 8312165..c2b6e6c 100644 --- a/backend/config.toml +++ b/backend/config.toml @@ -28,7 +28,7 @@ DB = 0 AccessKeyId = "LTAI5t86SjiP9zRd3q2w7jQN" AccessKeySecret = "hV7spvJuWh8w0EEIXj8NFi2uBlF4aS" Bucket ="rogee-test" -#Host ="abc" +Host ="https://assets.jdwan.com" Region ="cn-beijing" CallbackURL = "https://www.baidu.com" diff --git a/backend/database/migrations/20250322100215_create_posts.sql b/backend/database/migrations/20250322100215_create_posts.sql index 2b28a7f..4bd6b0f 100644 --- a/backend/database/migrations/20250322100215_create_posts.sql +++ b/backend/database/migrations/20250322100215_create_posts.sql @@ -7,6 +7,7 @@ CREATE TABLE posts( deleted_at timestamp, status int2 NOT NULL DEFAULT 0, title varchar(128) NOT NULL, + head_image int8 NOT NULL DEFAULT 0, description varchar(256) NOT NULL, content text NOT NULL, price int8 NOT NULL DEFAULT 0, diff --git a/backend/providers/ali/config.go b/backend/providers/ali/config.go index 5f19875..35de32a 100644 --- a/backend/providers/ali/config.go +++ b/backend/providers/ali/config.go @@ -41,7 +41,7 @@ func Provide(opts ...opt.Option) error { WithRegion(config.Region) return &OSSClient{ - client: oss.NewClient(cfg), + client: oss.NewClient(cfg.WithUseCName(true).WithEndpoint(*config.Host)), internalClient: oss.NewClient(cfg.WithUseInternalEndpoint(true)), config: &config, }, nil diff --git a/backend/providers/ali/oss_client.go b/backend/providers/ali/oss_client.go index c98e942..47f1116 100644 --- a/backend/providers/ali/oss_client.go +++ b/backend/providers/ali/oss_client.go @@ -3,6 +3,7 @@ package ali import ( "context" "strings" + "time" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss" ) @@ -17,11 +18,11 @@ func (c *OSSClient) GetClient() *oss.Client { return c.client } -func (c *OSSClient) PreSignUpload(ctx context.Context, path string) (*oss.PresignResult, error) { +func (c *OSSClient) PreSignUpload(ctx context.Context, path, mimeType string) (*oss.PresignResult, error) { request := &oss.PutObjectRequest{ Bucket: oss.Ptr(c.config.Bucket), Key: oss.Ptr("quyun/" + strings.Trim(path, "/")), - ContentType: oss.Ptr("multipart/form-data"), + ContentType: oss.Ptr(mimeType), } return c.client.Presign(ctx, request) } @@ -38,3 +39,17 @@ func (c *OSSClient) Download(ctx context.Context, path, dest string) error { } return nil } + +// GetSignedUrl +func (c *OSSClient) GetSignedUrl(ctx context.Context, path string) (string, error) { + request := &oss.GetObjectRequest{ + Bucket: oss.Ptr(c.config.Bucket), + Key: oss.Ptr(path), + } + + preSign, err := c.client.Presign(ctx, request, oss.PresignExpires(time.Minute*5)) + if err != nil { + return "", err + } + return preSign.URL, nil +} diff --git a/backend/test.http b/backend/test.http index be8b5bc..11aa9d9 100644 --- a/backend/test.http +++ b/backend/test.http @@ -65,4 +65,9 @@ Content-Type: application/json ### precheck GET {{host}}/v1/admin/uploads/pre-uploaded-check/abc.mp4 HTTP/1.1 Content-Type: application/json -authorization: {{token}} \ No newline at end of file +authorization: {{token}} + + +### get media url +GET {{host}}/v1/admin/medias/6 HTTP/1.1 +Authorization: {{token}} \ No newline at end of file diff --git a/frontend/admin/src/api/mediaService.js b/frontend/admin/src/api/mediaService.js index 0625f38..1c311cb 100644 --- a/frontend/admin/src/api/mediaService.js +++ b/frontend/admin/src/api/mediaService.js @@ -11,8 +11,10 @@ export const mediaService = { return httpClient.post('/admin/medias', mediaInfo); }, - preUploadedCheck(md5, ext) { - return httpClient.get(`/admin/uploads/pre-uploaded-check/${md5}.${ext}`); + preUploadedCheck(md5, ext, mime) { + return httpClient.get(`/admin/uploads/pre-uploaded-check/${md5}.${ext}`, { + params: { mime } + }); }, uploadedSuccess(data) { diff --git a/frontend/admin/src/pages/MediaUploadPage.vue b/frontend/admin/src/pages/MediaUploadPage.vue index 79ef0ea..f2b63a9 100644 --- a/frontend/admin/src/pages/MediaUploadPage.vue +++ b/frontend/admin/src/pages/MediaUploadPage.vue @@ -99,8 +99,10 @@ const processNextUpload = async () => { const md5Hash = await calculateMD5(nextFile.file); // get file ext const fileExt = nextFile.file.name.split('.').pop(); + + console.log(nextFile.file) // Check if file exists before upload - const checkResult = await mediaService.preUploadedCheck(md5Hash, fileExt); + const checkResult = await mediaService.preUploadedCheck(md5Hash, fileExt, nextFile.file.type); if (checkResult.data.exists) { // Skip upload and mark as completed diff --git a/frontend/admin/src/pages/PostCreatePage.vue b/frontend/admin/src/pages/PostCreatePage.vue index b419c0c..dc5ed63 100644 --- a/frontend/admin/src/pages/PostCreatePage.vue +++ b/frontend/admin/src/pages/PostCreatePage.vue @@ -30,6 +30,7 @@ const post = reactive({ selectedMedia: [], medias: [], status: 0, + head_image: null, // Add head image field }); // Validation state @@ -37,7 +38,8 @@ const errors = reactive({ title: '', introduction: '', selectedMedia: '', - discount: '' + discount: '', + head_image: '', // Add head image error field }); // Media selection dialog state @@ -46,6 +48,7 @@ const selectedMediaItems = ref([]); const mediaLoading = ref(false); const mediaGlobalFilter = ref(''); const mediaItems = ref([]); +const isHeadImageSelection = ref(false); // Track if we're selecting head image // Add pagination state for media dialog const mediaFirst = ref(0); @@ -63,8 +66,18 @@ const statusOptions = [ { label: '草稿', value: 0 } ]; +// Open media selection dialog for head image +const openHeadImageDialog = () => { + isHeadImageSelection.value = true; + mediaDialogVisible.value = true; + mediaCurrentPage.value = 1; + mediaFirst.value = 0; + loadMediaItems(); +}; + // Open media selection dialog const openMediaDialog = () => { + isHeadImageSelection.value = false; mediaDialogVisible.value = true; mediaCurrentPage.value = 1; mediaFirst.value = 0; @@ -99,10 +112,16 @@ const onMediaPage = (event) => { // Confirm media selection const confirmMediaSelection = () => { - if (selectedMediaItems.value.length) { + if (isHeadImageSelection.value) { + if (selectedMediaItems.value.length) { + post.head_image = selectedMediaItems.value[0]; + errors.head_image = ''; + } + } else if (selectedMediaItems.value.length) { post.selectedMedia = [...selectedMediaItems.value]; errors.selectedMedia = ''; } + selectedMediaItems.value = []; mediaDialogVisible.value = false; }; @@ -119,6 +138,11 @@ const removeMedia = (media) => { } }; +// Remove head image +const removeHeadImage = () => { + post.head_image = null; +}; + // Save the post const savePost = async () => { // Reset errors @@ -149,13 +173,19 @@ const savePost = async () => { valid = false; } + if (!post.head_image) { + errors.head_image = '请选择封面图片'; + valid = false; + } + if (!valid) { toast.add({ severity: 'error', summary: '表单错误', detail: '请检查表单中的错误并修正', life: 3000 }); return; } try { - post.medias = post.selectedMedia.map(media => media.id) + post.medias = post.selectedMedia.map(media => media.id); + post.head_image_id = post.head_image.id; // Add head image ID to submission const resp = await postService.createPost(post); console.log(resp) @@ -229,6 +259,34 @@ const formatFileSize = (bytes) => {
+ +
+ +
+
+ +

请选择封面图片

+
+
+
+ +
+ {{ post.head_image.name }} +
+
+
+
+
+
+
+
@@ -316,15 +374,15 @@ const formatFileSize = (bytes) => {
- +
diff --git a/frontend/wechat/bun.lock b/frontend/wechat/bun.lock index 4116340..736f680 100644 --- a/frontend/wechat/bun.lock +++ b/frontend/wechat/bun.lock @@ -6,6 +6,7 @@ "dependencies": { "@tailwindcss/vite": "^4.1.4", "@vueuse/core": "^13.1.0", + "axios": "^1.8.4", "pinia": "^3.0.2", "tailwindcss": "^4.1.4", "vue": "^3.5.13", @@ -187,26 +188,46 @@ "@vueuse/shared": ["@vueuse/shared@13.1.0", "https://registry.npmmirror.com/@vueuse/shared/-/shared-13.1.0.tgz", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-IVS/qRRjhPTZ6C2/AM3jieqXACGwFZwWTdw5sNTSKk2m/ZpkuuN+ri+WCVUP8TqaKwJYt/KuMwmXspMAw8E6ew=="], + "asynckit": ["asynckit@0.4.0", "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + "autoprefixer": ["autoprefixer@10.4.21", "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.21.tgz", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="], + "axios": ["axios@1.8.4", "https://registry.npmmirror.com/axios/-/axios-1.8.4.tgz", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw=="], + "birpc": ["birpc@0.2.19", "https://registry.npmmirror.com/birpc/-/birpc-0.2.19.tgz", {}, "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ=="], "browserslist": ["browserslist@4.24.4", "https://registry.npmmirror.com/browserslist/-/browserslist-4.24.4.tgz", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="], + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001714", "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001714.tgz", {}, "sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg=="], + "combined-stream": ["combined-stream@1.0.8", "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + "copy-anything": ["copy-anything@3.0.5", "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w=="], "csstype": ["csstype@3.1.3", "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "delayed-stream": ["delayed-stream@1.0.0", "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + "detect-libc": ["detect-libc@2.0.3", "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.3.tgz", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], + "dunder-proto": ["dunder-proto@1.0.1", "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + "electron-to-chromium": ["electron-to-chromium@1.5.137", "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.137.tgz", {}, "sha512-/QSJaU2JyIuTbbABAo/crOs+SuAZLS+fVVS10PVrIT9hrRkmZl8Hb0xPSkKRUUWHQtYzXHpQUW3Dy5hwMzGZkA=="], "enhanced-resolve": ["enhanced-resolve@5.18.1", "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg=="], "entities": ["entities@4.5.0", "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "es-define-property": ["es-define-property@1.0.1", "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + "esbuild": ["esbuild@0.25.2", "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.2.tgz", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.2", "@esbuild/android-arm": "0.25.2", "@esbuild/android-arm64": "0.25.2", "@esbuild/android-x64": "0.25.2", "@esbuild/darwin-arm64": "0.25.2", "@esbuild/darwin-x64": "0.25.2", "@esbuild/freebsd-arm64": "0.25.2", "@esbuild/freebsd-x64": "0.25.2", "@esbuild/linux-arm": "0.25.2", "@esbuild/linux-arm64": "0.25.2", "@esbuild/linux-ia32": "0.25.2", "@esbuild/linux-loong64": "0.25.2", "@esbuild/linux-mips64el": "0.25.2", "@esbuild/linux-ppc64": "0.25.2", "@esbuild/linux-riscv64": "0.25.2", "@esbuild/linux-s390x": "0.25.2", "@esbuild/linux-x64": "0.25.2", "@esbuild/netbsd-arm64": "0.25.2", "@esbuild/netbsd-x64": "0.25.2", "@esbuild/openbsd-arm64": "0.25.2", "@esbuild/openbsd-x64": "0.25.2", "@esbuild/sunos-x64": "0.25.2", "@esbuild/win32-arm64": "0.25.2", "@esbuild/win32-ia32": "0.25.2", "@esbuild/win32-x64": "0.25.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ=="], "escalade": ["escalade@3.2.0", "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -215,12 +236,30 @@ "fdir": ["fdir@6.4.3", "https://registry.npmmirror.com/fdir/-/fdir-6.4.3.tgz", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="], + "follow-redirects": ["follow-redirects@1.15.9", "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="], + + "form-data": ["form-data@4.0.2", "https://registry.npmmirror.com/form-data/-/form-data-4.0.2.tgz", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" } }, "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w=="], + "fraction.js": ["fraction.js@4.3.7", "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="], "fsevents": ["fsevents@2.3.3", "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "function-bind": ["function-bind@1.1.2", "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-proto": ["get-proto@1.0.1", "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "gopd": ["gopd@1.2.0", "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + "graceful-fs": ["graceful-fs@4.2.11", "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "has-symbols": ["has-symbols@1.1.0", "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.2", "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + "hookable": ["hookable@5.5.3", "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], "is-what": ["is-what@4.1.16", "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz", {}, "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="], @@ -251,6 +290,12 @@ "magic-string": ["magic-string@0.30.17", "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], + "math-intrinsics": ["math-intrinsics@1.1.0", "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mime-db": ["mime-db@1.52.0", "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "mitt": ["mitt@3.0.1", "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="], "nanoid": ["nanoid@3.3.11", "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], @@ -271,6 +316,8 @@ "postcss-value-parser": ["postcss-value-parser@4.2.0", "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + "proxy-from-env": ["proxy-from-env@1.1.0", "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + "rfdc": ["rfdc@1.4.1", "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], "rollup": ["rollup@4.40.0", "https://registry.npmmirror.com/rollup/-/rollup-4.40.0.tgz", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.40.0", "@rollup/rollup-android-arm64": "4.40.0", "@rollup/rollup-darwin-arm64": "4.40.0", "@rollup/rollup-darwin-x64": "4.40.0", "@rollup/rollup-freebsd-arm64": "4.40.0", "@rollup/rollup-freebsd-x64": "4.40.0", "@rollup/rollup-linux-arm-gnueabihf": "4.40.0", "@rollup/rollup-linux-arm-musleabihf": "4.40.0", "@rollup/rollup-linux-arm64-gnu": "4.40.0", "@rollup/rollup-linux-arm64-musl": "4.40.0", "@rollup/rollup-linux-loongarch64-gnu": "4.40.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0", "@rollup/rollup-linux-riscv64-gnu": "4.40.0", "@rollup/rollup-linux-riscv64-musl": "4.40.0", "@rollup/rollup-linux-s390x-gnu": "4.40.0", "@rollup/rollup-linux-x64-gnu": "4.40.0", "@rollup/rollup-linux-x64-musl": "4.40.0", "@rollup/rollup-win32-arm64-msvc": "4.40.0", "@rollup/rollup-win32-ia32-msvc": "4.40.0", "@rollup/rollup-win32-x64-msvc": "4.40.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w=="], diff --git a/frontend/wechat/package.json b/frontend/wechat/package.json index d639ef7..1e02a4b 100644 --- a/frontend/wechat/package.json +++ b/frontend/wechat/package.json @@ -11,6 +11,7 @@ "dependencies": { "@tailwindcss/vite": "^4.1.4", "@vueuse/core": "^13.1.0", + "axios": "^1.8.4", "pinia": "^3.0.2", "tailwindcss": "^4.1.4", "vue": "^3.5.13",