Ver código fonte

Merge branch 'dev' of http://gogs.hnwmzp.cn/chengwenliang/nshop into dev

chengwl 1 dia atrás
pai
commit
d678024e86

+ 17 - 0
bootstrap/cache/packages.php

@@ -6,6 +6,16 @@
       0 => 'Astrotomic\\Translatable\\TranslatableServiceProvider',
     ),
   ),
+  'bagisto/bagisto-package-generator' => 
+  array (
+    'aliases' => 
+    array (
+    ),
+    'providers' => 
+    array (
+      0 => 'Webkul\\PackageGenerator\\Providers\\PackageGeneratorServiceProvider',
+    ),
+  ),
   'bagisto/laravel-datafaker' => 
   array (
     'aliases' => 
@@ -161,6 +171,13 @@
       0 => 'Prettus\\Repository\\Providers\\RepositoryServiceProvider',
     ),
   ),
+  'spatie/laravel-medialibrary' => 
+  array (
+    'providers' => 
+    array (
+      0 => 'Spatie\\MediaLibrary\\MediaLibraryServiceProvider',
+    ),
+  ),
   'spatie/laravel-responsecache' => 
   array (
     'aliases' => 

+ 134 - 126
bootstrap/cache/services.php

@@ -25,71 +25,75 @@
     21 => 'Illuminate\\Validation\\ValidationServiceProvider',
     22 => 'Illuminate\\View\\ViewServiceProvider',
     23 => 'Astrotomic\\Translatable\\TranslatableServiceProvider',
-    24 => 'Webkul\\Faker\\Providers\\FakerServiceProvider',
-    25 => 'Barryvdh\\Debugbar\\ServiceProvider',
-    26 => 'Barryvdh\\DomPDF\\ServiceProvider',
-    27 => 'Diglactic\\Breadcrumbs\\ServiceProvider',
-    28 => 'Kalnoy\\Nestedset\\NestedSetServiceProvider',
-    29 => 'Konekt\\Concord\\ConcordServiceProvider',
-    30 => 'Konekt\\Enum\\Eloquent\\EnumServiceProvider',
-    31 => 'Laravel\\Octane\\OctaneServiceProvider',
-    32 => 'Laravel\\Sanctum\\SanctumServiceProvider',
-    33 => 'Laravel\\Tinker\\TinkerServiceProvider',
-    34 => 'Laravel\\Ui\\UiServiceProvider',
-    35 => 'Maatwebsite\\Excel\\ExcelServiceProvider',
-    36 => 'Carbon\\Laravel\\ServiceProvider',
-    37 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
-    38 => 'Termwind\\Laravel\\TermwindServiceProvider',
-    39 => 'OpenAI\\Laravel\\ServiceProvider',
-    40 => 'Pest\\Laravel\\PestServiceProvider',
-    41 => 'Prettus\\Repository\\Providers\\RepositoryServiceProvider',
-    42 => 'Spatie\\ResponseCache\\ResponseCacheServiceProvider',
-    43 => 'Spatie\\Sitemap\\SitemapServiceProvider',
-    44 => 'Stevebauman\\Purify\\PurifyServiceProvider',
-    45 => 'ApiPlatform\\Laravel\\ApiPlatformProvider',
-    46 => 'ApiPlatform\\Laravel\\ApiPlatformDeferredProvider',
-    47 => 'ApiPlatform\\Laravel\\Eloquent\\ApiPlatformEventProvider',
-    48 => 'App\\Providers\\AppServiceProvider',
-    49 => 'Webkul\\Admin\\Providers\\AdminServiceProvider',
-    50 => 'Longyi\\Core\\Providers\\LongyiCoreServiceProvider',
-    51 => 'Longyi\\DynamicMenu\\Providers\\DynamicMenuServiceProvider',
-    52 => 'Longyi\\Email\\Providers\\EmailServiceProvider',
-    53 => 'Longyi\\RewardPoints\\Providers\\RewardPointsServiceProvider',
-    54 => 'Longyi\\ImageUpload\\Providers\\ImageUploadServiceProvider',
-    55 => 'Webkul\\Attribute\\Providers\\AttributeServiceProvider',
-    56 => 'Webkul\\BookingProduct\\Providers\\BookingProductServiceProvider',
-    57 => 'Webkul\\CMS\\Providers\\CMSServiceProvider',
-    58 => 'Webkul\\CartRule\\Providers\\CartRuleServiceProvider',
-    59 => 'Webkul\\CatalogRule\\Providers\\CatalogRuleServiceProvider',
-    60 => 'Webkul\\Category\\Providers\\CategoryServiceProvider',
-    61 => 'Webkul\\Checkout\\Providers\\CheckoutServiceProvider',
-    62 => 'Webkul\\Core\\Providers\\CoreServiceProvider',
-    63 => 'Webkul\\Core\\Providers\\EnvValidatorServiceProvider',
-    64 => 'Webkul\\Customer\\Providers\\CustomerServiceProvider',
-    65 => 'Webkul\\DataGrid\\Providers\\DataGridServiceProvider',
-    66 => 'Webkul\\DataTransfer\\Providers\\DataTransferServiceProvider',
-    67 => 'Webkul\\DebugBar\\Providers\\DebugBarServiceProvider',
-    68 => 'Webkul\\FPC\\Providers\\FPCServiceProvider',
-    69 => 'Webkul\\GDPR\\Providers\\GDPRServiceProvider',
-    70 => 'Webkul\\Installer\\Providers\\InstallerServiceProvider',
-    71 => 'Webkul\\Inventory\\Providers\\InventoryServiceProvider',
-    72 => 'Webkul\\MagicAI\\Providers\\MagicAIServiceProvider',
-    73 => 'Webkul\\Marketing\\Providers\\MarketingServiceProvider',
-    74 => 'Webkul\\Notification\\Providers\\NotificationServiceProvider',
-    75 => 'Webkul\\Payment\\Providers\\PaymentServiceProvider',
-    76 => 'Webkul\\Paypal\\Providers\\PaypalServiceProvider',
-    77 => 'Webkul\\Product\\Providers\\ProductServiceProvider',
-    78 => 'Webkul\\Rule\\Providers\\RuleServiceProvider',
-    79 => 'Webkul\\Sales\\Providers\\SalesServiceProvider',
-    80 => 'Webkul\\Shipping\\Providers\\ShippingServiceProvider',
-    81 => 'Webkul\\Shop\\Providers\\ShopServiceProvider',
-    82 => 'Webkul\\Sitemap\\Providers\\SitemapServiceProvider',
-    83 => 'Webkul\\SocialLogin\\Providers\\SocialLoginServiceProvider',
-    84 => 'Webkul\\SocialShare\\Providers\\SocialShareServiceProvider',
-    85 => 'Webkul\\Tax\\Providers\\TaxServiceProvider',
-    86 => 'Webkul\\Theme\\Providers\\ThemeServiceProvider',
-    87 => 'Webkul\\User\\Providers\\UserServiceProvider',
-    88 => 'Webkul\\BagistoApi\\Providers\\BagistoApiServiceProvider',
+    24 => 'Webkul\\PackageGenerator\\Providers\\PackageGeneratorServiceProvider',
+    25 => 'Webkul\\Faker\\Providers\\FakerServiceProvider',
+    26 => 'Barryvdh\\Debugbar\\ServiceProvider',
+    27 => 'Barryvdh\\DomPDF\\ServiceProvider',
+    28 => 'Diglactic\\Breadcrumbs\\ServiceProvider',
+    29 => 'Kalnoy\\Nestedset\\NestedSetServiceProvider',
+    30 => 'Konekt\\Concord\\ConcordServiceProvider',
+    31 => 'Konekt\\Enum\\Eloquent\\EnumServiceProvider',
+    32 => 'Laravel\\Octane\\OctaneServiceProvider',
+    33 => 'Laravel\\Sanctum\\SanctumServiceProvider',
+    34 => 'Laravel\\Tinker\\TinkerServiceProvider',
+    35 => 'Laravel\\Ui\\UiServiceProvider',
+    36 => 'Maatwebsite\\Excel\\ExcelServiceProvider',
+    37 => 'Carbon\\Laravel\\ServiceProvider',
+    38 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
+    39 => 'Termwind\\Laravel\\TermwindServiceProvider',
+    40 => 'OpenAI\\Laravel\\ServiceProvider',
+    41 => 'Pest\\Laravel\\PestServiceProvider',
+    42 => 'Prettus\\Repository\\Providers\\RepositoryServiceProvider',
+    43 => 'Spatie\\MediaLibrary\\MediaLibraryServiceProvider',
+    44 => 'Spatie\\ResponseCache\\ResponseCacheServiceProvider',
+    45 => 'Spatie\\Sitemap\\SitemapServiceProvider',
+    46 => 'Stevebauman\\Purify\\PurifyServiceProvider',
+    47 => 'ApiPlatform\\Laravel\\ApiPlatformProvider',
+    48 => 'ApiPlatform\\Laravel\\ApiPlatformDeferredProvider',
+    49 => 'ApiPlatform\\Laravel\\Eloquent\\ApiPlatformEventProvider',
+    50 => 'App\\Providers\\AppServiceProvider',
+    51 => 'Webkul\\Admin\\Providers\\AdminServiceProvider',
+    52 => 'Longyi\\Core\\Providers\\LongyiCoreServiceProvider',
+    53 => 'Longyi\\DynamicMenu\\Providers\\DynamicMenuServiceProvider',
+    54 => 'Longyi\\Email\\Providers\\EmailServiceProvider',
+    55 => 'Longyi\\ImageUpload\\Providers\\ImageUploadServiceProvider',
+    56 => 'Longyi\\RewardPoints\\Providers\\RewardPointsServiceProvider',
+    57 => 'Longyi\\Member\\Providers\\MemberServiceProvider',
+    58 => 'Longyi\\Gift\\Providers\\GiftServiceProvider',
+    59 => 'Webkul\\Attribute\\Providers\\AttributeServiceProvider',
+    60 => 'Webkul\\BookingProduct\\Providers\\BookingProductServiceProvider',
+    61 => 'Webkul\\CMS\\Providers\\CMSServiceProvider',
+    62 => 'Webkul\\CartRule\\Providers\\CartRuleServiceProvider',
+    63 => 'Webkul\\CatalogRule\\Providers\\CatalogRuleServiceProvider',
+    64 => 'Webkul\\Category\\Providers\\CategoryServiceProvider',
+    65 => 'Webkul\\Checkout\\Providers\\CheckoutServiceProvider',
+    66 => 'Webkul\\Core\\Providers\\CoreServiceProvider',
+    67 => 'Webkul\\Core\\Providers\\EnvValidatorServiceProvider',
+    68 => 'Webkul\\Customer\\Providers\\CustomerServiceProvider',
+    69 => 'Webkul\\DataGrid\\Providers\\DataGridServiceProvider',
+    70 => 'Webkul\\DataTransfer\\Providers\\DataTransferServiceProvider',
+    71 => 'Webkul\\DebugBar\\Providers\\DebugBarServiceProvider',
+    72 => 'Webkul\\FPC\\Providers\\FPCServiceProvider',
+    73 => 'Webkul\\GDPR\\Providers\\GDPRServiceProvider',
+    74 => 'Webkul\\Installer\\Providers\\InstallerServiceProvider',
+    75 => 'Webkul\\Inventory\\Providers\\InventoryServiceProvider',
+    76 => 'Webkul\\MagicAI\\Providers\\MagicAIServiceProvider',
+    77 => 'Webkul\\Marketing\\Providers\\MarketingServiceProvider',
+    78 => 'Webkul\\Notification\\Providers\\NotificationServiceProvider',
+    79 => 'Webkul\\Payment\\Providers\\PaymentServiceProvider',
+    80 => 'Webkul\\Paypal\\Providers\\PaypalServiceProvider',
+    81 => 'Webkul\\Product\\Providers\\ProductServiceProvider',
+    82 => 'Webkul\\Rule\\Providers\\RuleServiceProvider',
+    83 => 'Webkul\\Sales\\Providers\\SalesServiceProvider',
+    84 => 'Webkul\\Shipping\\Providers\\ShippingServiceProvider',
+    85 => 'Webkul\\Shop\\Providers\\ShopServiceProvider',
+    86 => 'Webkul\\Sitemap\\Providers\\SitemapServiceProvider',
+    87 => 'Webkul\\SocialLogin\\Providers\\SocialLoginServiceProvider',
+    88 => 'Webkul\\SocialShare\\Providers\\SocialShareServiceProvider',
+    89 => 'Webkul\\Tax\\Providers\\TaxServiceProvider',
+    90 => 'Webkul\\Theme\\Providers\\ThemeServiceProvider',
+    91 => 'Webkul\\User\\Providers\\UserServiceProvider',
+    92 => 'Webkul\\BagistoApi\\Providers\\BagistoApiServiceProvider',
   ),
   'eager' => 
   array (
@@ -104,67 +108,71 @@
     8 => 'Illuminate\\Session\\SessionServiceProvider',
     9 => 'Illuminate\\View\\ViewServiceProvider',
     10 => 'Astrotomic\\Translatable\\TranslatableServiceProvider',
-    11 => 'Webkul\\Faker\\Providers\\FakerServiceProvider',
-    12 => 'Barryvdh\\Debugbar\\ServiceProvider',
-    13 => 'Barryvdh\\DomPDF\\ServiceProvider',
-    14 => 'Kalnoy\\Nestedset\\NestedSetServiceProvider',
-    15 => 'Konekt\\Concord\\ConcordServiceProvider',
-    16 => 'Konekt\\Enum\\Eloquent\\EnumServiceProvider',
-    17 => 'Laravel\\Octane\\OctaneServiceProvider',
-    18 => 'Laravel\\Sanctum\\SanctumServiceProvider',
-    19 => 'Laravel\\Ui\\UiServiceProvider',
-    20 => 'Maatwebsite\\Excel\\ExcelServiceProvider',
-    21 => 'Carbon\\Laravel\\ServiceProvider',
-    22 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
-    23 => 'Termwind\\Laravel\\TermwindServiceProvider',
-    24 => 'Pest\\Laravel\\PestServiceProvider',
-    25 => 'Prettus\\Repository\\Providers\\RepositoryServiceProvider',
-    26 => 'Spatie\\ResponseCache\\ResponseCacheServiceProvider',
-    27 => 'Spatie\\Sitemap\\SitemapServiceProvider',
-    28 => 'Stevebauman\\Purify\\PurifyServiceProvider',
-    29 => 'ApiPlatform\\Laravel\\ApiPlatformProvider',
-    30 => 'ApiPlatform\\Laravel\\Eloquent\\ApiPlatformEventProvider',
-    31 => 'App\\Providers\\AppServiceProvider',
-    32 => 'Webkul\\Admin\\Providers\\AdminServiceProvider',
-    33 => 'Longyi\\Core\\Providers\\LongyiCoreServiceProvider',
-    34 => 'Longyi\\DynamicMenu\\Providers\\DynamicMenuServiceProvider',
-    35 => 'Longyi\\Email\\Providers\\EmailServiceProvider',
-    36 => 'Longyi\\RewardPoints\\Providers\\RewardPointsServiceProvider',
-    37 => 'Longyi\\ImageUpload\\Providers\\ImageUploadServiceProvider',
-    38 => 'Webkul\\Attribute\\Providers\\AttributeServiceProvider',
-    39 => 'Webkul\\BookingProduct\\Providers\\BookingProductServiceProvider',
-    40 => 'Webkul\\CMS\\Providers\\CMSServiceProvider',
-    41 => 'Webkul\\CartRule\\Providers\\CartRuleServiceProvider',
-    42 => 'Webkul\\CatalogRule\\Providers\\CatalogRuleServiceProvider',
-    43 => 'Webkul\\Category\\Providers\\CategoryServiceProvider',
-    44 => 'Webkul\\Checkout\\Providers\\CheckoutServiceProvider',
-    45 => 'Webkul\\Core\\Providers\\CoreServiceProvider',
-    46 => 'Webkul\\Core\\Providers\\EnvValidatorServiceProvider',
-    47 => 'Webkul\\Customer\\Providers\\CustomerServiceProvider',
-    48 => 'Webkul\\DataGrid\\Providers\\DataGridServiceProvider',
-    49 => 'Webkul\\DataTransfer\\Providers\\DataTransferServiceProvider',
-    50 => 'Webkul\\DebugBar\\Providers\\DebugBarServiceProvider',
-    51 => 'Webkul\\FPC\\Providers\\FPCServiceProvider',
-    52 => 'Webkul\\GDPR\\Providers\\GDPRServiceProvider',
-    53 => 'Webkul\\Installer\\Providers\\InstallerServiceProvider',
-    54 => 'Webkul\\Inventory\\Providers\\InventoryServiceProvider',
-    55 => 'Webkul\\MagicAI\\Providers\\MagicAIServiceProvider',
-    56 => 'Webkul\\Marketing\\Providers\\MarketingServiceProvider',
-    57 => 'Webkul\\Notification\\Providers\\NotificationServiceProvider',
-    58 => 'Webkul\\Payment\\Providers\\PaymentServiceProvider',
-    59 => 'Webkul\\Paypal\\Providers\\PaypalServiceProvider',
-    60 => 'Webkul\\Product\\Providers\\ProductServiceProvider',
-    61 => 'Webkul\\Rule\\Providers\\RuleServiceProvider',
-    62 => 'Webkul\\Sales\\Providers\\SalesServiceProvider',
-    63 => 'Webkul\\Shipping\\Providers\\ShippingServiceProvider',
-    64 => 'Webkul\\Shop\\Providers\\ShopServiceProvider',
-    65 => 'Webkul\\Sitemap\\Providers\\SitemapServiceProvider',
-    66 => 'Webkul\\SocialLogin\\Providers\\SocialLoginServiceProvider',
-    67 => 'Webkul\\SocialShare\\Providers\\SocialShareServiceProvider',
-    68 => 'Webkul\\Tax\\Providers\\TaxServiceProvider',
-    69 => 'Webkul\\Theme\\Providers\\ThemeServiceProvider',
-    70 => 'Webkul\\User\\Providers\\UserServiceProvider',
-    71 => 'Webkul\\BagistoApi\\Providers\\BagistoApiServiceProvider',
+    11 => 'Webkul\\PackageGenerator\\Providers\\PackageGeneratorServiceProvider',
+    12 => 'Webkul\\Faker\\Providers\\FakerServiceProvider',
+    13 => 'Barryvdh\\Debugbar\\ServiceProvider',
+    14 => 'Barryvdh\\DomPDF\\ServiceProvider',
+    15 => 'Kalnoy\\Nestedset\\NestedSetServiceProvider',
+    16 => 'Konekt\\Concord\\ConcordServiceProvider',
+    17 => 'Konekt\\Enum\\Eloquent\\EnumServiceProvider',
+    18 => 'Laravel\\Octane\\OctaneServiceProvider',
+    19 => 'Laravel\\Sanctum\\SanctumServiceProvider',
+    20 => 'Laravel\\Ui\\UiServiceProvider',
+    21 => 'Maatwebsite\\Excel\\ExcelServiceProvider',
+    22 => 'Carbon\\Laravel\\ServiceProvider',
+    23 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
+    24 => 'Termwind\\Laravel\\TermwindServiceProvider',
+    25 => 'Pest\\Laravel\\PestServiceProvider',
+    26 => 'Prettus\\Repository\\Providers\\RepositoryServiceProvider',
+    27 => 'Spatie\\MediaLibrary\\MediaLibraryServiceProvider',
+    28 => 'Spatie\\ResponseCache\\ResponseCacheServiceProvider',
+    29 => 'Spatie\\Sitemap\\SitemapServiceProvider',
+    30 => 'Stevebauman\\Purify\\PurifyServiceProvider',
+    31 => 'ApiPlatform\\Laravel\\ApiPlatformProvider',
+    32 => 'ApiPlatform\\Laravel\\Eloquent\\ApiPlatformEventProvider',
+    33 => 'App\\Providers\\AppServiceProvider',
+    34 => 'Webkul\\Admin\\Providers\\AdminServiceProvider',
+    35 => 'Longyi\\Core\\Providers\\LongyiCoreServiceProvider',
+    36 => 'Longyi\\DynamicMenu\\Providers\\DynamicMenuServiceProvider',
+    37 => 'Longyi\\Email\\Providers\\EmailServiceProvider',
+    38 => 'Longyi\\ImageUpload\\Providers\\ImageUploadServiceProvider',
+    39 => 'Longyi\\RewardPoints\\Providers\\RewardPointsServiceProvider',
+    40 => 'Longyi\\Member\\Providers\\MemberServiceProvider',
+    41 => 'Longyi\\Gift\\Providers\\GiftServiceProvider',
+    42 => 'Webkul\\Attribute\\Providers\\AttributeServiceProvider',
+    43 => 'Webkul\\BookingProduct\\Providers\\BookingProductServiceProvider',
+    44 => 'Webkul\\CMS\\Providers\\CMSServiceProvider',
+    45 => 'Webkul\\CartRule\\Providers\\CartRuleServiceProvider',
+    46 => 'Webkul\\CatalogRule\\Providers\\CatalogRuleServiceProvider',
+    47 => 'Webkul\\Category\\Providers\\CategoryServiceProvider',
+    48 => 'Webkul\\Checkout\\Providers\\CheckoutServiceProvider',
+    49 => 'Webkul\\Core\\Providers\\CoreServiceProvider',
+    50 => 'Webkul\\Core\\Providers\\EnvValidatorServiceProvider',
+    51 => 'Webkul\\Customer\\Providers\\CustomerServiceProvider',
+    52 => 'Webkul\\DataGrid\\Providers\\DataGridServiceProvider',
+    53 => 'Webkul\\DataTransfer\\Providers\\DataTransferServiceProvider',
+    54 => 'Webkul\\DebugBar\\Providers\\DebugBarServiceProvider',
+    55 => 'Webkul\\FPC\\Providers\\FPCServiceProvider',
+    56 => 'Webkul\\GDPR\\Providers\\GDPRServiceProvider',
+    57 => 'Webkul\\Installer\\Providers\\InstallerServiceProvider',
+    58 => 'Webkul\\Inventory\\Providers\\InventoryServiceProvider',
+    59 => 'Webkul\\MagicAI\\Providers\\MagicAIServiceProvider',
+    60 => 'Webkul\\Marketing\\Providers\\MarketingServiceProvider',
+    61 => 'Webkul\\Notification\\Providers\\NotificationServiceProvider',
+    62 => 'Webkul\\Payment\\Providers\\PaymentServiceProvider',
+    63 => 'Webkul\\Paypal\\Providers\\PaypalServiceProvider',
+    64 => 'Webkul\\Product\\Providers\\ProductServiceProvider',
+    65 => 'Webkul\\Rule\\Providers\\RuleServiceProvider',
+    66 => 'Webkul\\Sales\\Providers\\SalesServiceProvider',
+    67 => 'Webkul\\Shipping\\Providers\\ShippingServiceProvider',
+    68 => 'Webkul\\Shop\\Providers\\ShopServiceProvider',
+    69 => 'Webkul\\Sitemap\\Providers\\SitemapServiceProvider',
+    70 => 'Webkul\\SocialLogin\\Providers\\SocialLoginServiceProvider',
+    71 => 'Webkul\\SocialShare\\Providers\\SocialShareServiceProvider',
+    72 => 'Webkul\\Tax\\Providers\\TaxServiceProvider',
+    73 => 'Webkul\\Theme\\Providers\\ThemeServiceProvider',
+    74 => 'Webkul\\User\\Providers\\UserServiceProvider',
+    75 => 'Webkul\\BagistoApi\\Providers\\BagistoApiServiceProvider',
   ),
   'deferred' => 
   array (

+ 1 - 1
composer.json

@@ -37,7 +37,7 @@
         "laravel/socialite": "^5.0",
         "laravel/tinker": "^2.0",
         "laravel/ui": "^4.0",
-        "league/flysystem-aws-s3-v3": "^3.25",
+        "league/flysystem-aws-s3-v3": "^3.0",
         "maatwebsite/excel": "^3.1.46",
         "mpdf/mpdf": "^8.2",
         "nesbot/carbon": "^2.72.2",

+ 162 - 7
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "d8c84f1ab224d9264bc558050dc253b8",
+    "content-hash": "c378778fb9d9f7b784858297dea09780",
     "packages": [
         {
             "name": "api-platform/documentation",
@@ -1160,6 +1160,157 @@
             ],
             "time": "2024-08-28T09:20:26+00:00"
         },
+        {
+            "name": "aws/aws-crt-php",
+            "version": "v1.2.7",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/awslabs/aws-crt-php.git",
+                "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e",
+                "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5",
+                "yoast/phpunit-polyfills": "^1.0"
+            },
+            "suggest": {
+                "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality."
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "AWS SDK Common Runtime Team",
+                    "email": "aws-sdk-common-runtime@amazon.com"
+                }
+            ],
+            "description": "AWS Common Runtime for PHP",
+            "homepage": "https://github.com/awslabs/aws-crt-php",
+            "keywords": [
+                "amazon",
+                "aws",
+                "crt",
+                "sdk"
+            ],
+            "support": {
+                "issues": "https://github.com/awslabs/aws-crt-php/issues",
+                "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7"
+            },
+            "time": "2024-10-18T22:15:13+00:00"
+        },
+        {
+            "name": "aws/aws-sdk-php",
+            "version": "3.384.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/aws/aws-sdk-php.git",
+                "reference": "a6c85b3a1f5f8327076291040329214b3a2caf2b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a6c85b3a1f5f8327076291040329214b3a2caf2b",
+                "reference": "a6c85b3a1f5f8327076291040329214b3a2caf2b",
+                "shasum": ""
+            },
+            "require": {
+                "aws/aws-crt-php": "^1.2.3",
+                "ext-json": "*",
+                "ext-pcre": "*",
+                "ext-simplexml": "*",
+                "guzzlehttp/guzzle": "^7.4.5",
+                "guzzlehttp/promises": "^2.0",
+                "guzzlehttp/psr7": "^2.4.5",
+                "mtdowling/jmespath.php": "^2.8.0",
+                "php": ">=8.1",
+                "psr/http-message": "^1.0 || ^2.0",
+                "symfony/filesystem": "^v5.4.45 || ^v6.4.3 || ^v7.1.0 || ^v8.0.0"
+            },
+            "require-dev": {
+                "andrewsville/php-token-reflection": "^1.4",
+                "aws/aws-php-sns-message-validator": "~1.0",
+                "behat/behat": "~3.0",
+                "composer/composer": "^2.7.8",
+                "dms/phpunit-arraysubset-asserts": "^v0.5.0",
+                "doctrine/cache": "~1.4",
+                "ext-dom": "*",
+                "ext-openssl": "*",
+                "ext-sockets": "*",
+                "phpunit/phpunit": "^10.0",
+                "psr/cache": "^2.0 || ^3.0",
+                "psr/simple-cache": "^2.0 || ^3.0",
+                "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0",
+                "yoast/phpunit-polyfills": "^2.0"
+            },
+            "suggest": {
+                "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications",
+                "doctrine/cache": "To use the DoctrineCacheAdapter",
+                "ext-curl": "To send requests using cURL",
+                "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages",
+                "ext-pcntl": "To use client-side monitoring",
+                "ext-sockets": "To use client-side monitoring"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "src/functions.php"
+                ],
+                "psr-4": {
+                    "Aws\\": "src/"
+                },
+                "exclude-from-classmap": [
+                    "src/data/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Amazon Web Services",
+                    "homepage": "https://aws.amazon.com"
+                }
+            ],
+            "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project",
+            "homepage": "https://aws.amazon.com/sdk-for-php",
+            "keywords": [
+                "amazon",
+                "aws",
+                "cloud",
+                "dynamodb",
+                "ec2",
+                "glacier",
+                "s3",
+                "sdk"
+            ],
+            "support": {
+                "forum": "https://github.com/aws/aws-sdk-php/discussions",
+                "issues": "https://github.com/aws/aws-sdk-php/issues",
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.384.2"
+            },
+            "time": "2026-06-03T18:07:33+00:00"
+        },
         {
             "name": "bagisto/bagisto-package-generator",
             "version": "v2.1.2",
@@ -4593,20 +4744,20 @@
         },
         {
             "name": "league/flysystem-aws-s3-v3",
-            "version": "3.29.0",
+            "version": "3.34.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git",
-                "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9"
+                "reference": "0c62fdac907791d8649ad3c61cb7a77628344fb8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://repo.huaweicloud.com/repository/php/league/flysystem-aws-s3-v3/3.29.0/league-flysystem-aws-s3-v3-3.29.0.zip",
-                "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9",
+                "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/0c62fdac907791d8649ad3c61cb7a77628344fb8",
+                "reference": "0c62fdac907791d8649ad3c61cb7a77628344fb8",
                 "shasum": ""
             },
             "require": {
-                "aws/aws-sdk-php": "^3.295.10",
+                "aws/aws-sdk-php": "^3.371.5",
                 "league/flysystem": "^3.10.0",
                 "league/mime-type-detection": "^1.0.0",
                 "php": "^8.0.2"
@@ -4621,6 +4772,7 @@
                     "League\\Flysystem\\AwsS3V3\\": ""
                 }
             },
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -4640,7 +4792,10 @@
                 "s3",
                 "storage"
             ],
-            "time": "2024-08-17T13:10:48+00:00"
+            "support": {
+                "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.34.0"
+            },
+            "time": "2026-05-04T08:24:00+00:00"
         },
         {
             "name": "league/flysystem-local",

+ 239 - 0
config/media-library.php

@@ -0,0 +1,239 @@
+<?php
+
+use Spatie\MediaLibrary\Conversions\ImageGenerators\Image;
+use Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf;
+use Spatie\MediaLibrary\Conversions\ImageGenerators\Svg;
+use Spatie\MediaLibrary\Conversions\ImageGenerators\Video;
+use Spatie\MediaLibrary\Conversions\ImageGenerators\Webp;
+use Spatie\MediaLibrary\Conversions\ImageGenerators\Avif;
+use Spatie\MediaLibrary\Conversions\Jobs\PerformConversionsJob;
+use Spatie\MediaLibrary\Downloaders\DefaultDownloader;
+use Spatie\MediaLibrary\MediaCollections\Models\Media;
+use Spatie\MediaLibrary\MediaCollections\Models\Observers\MediaObserver;
+use Spatie\MediaLibrary\ResponsiveImages\Jobs\GenerateResponsiveImagesJob;
+use Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\Blurred;
+use Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\FileSizeOptimizedWidthCalculator;
+use Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer;
+use Spatie\MediaLibrary\Support\FileRemover\DefaultFileRemover;
+use Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator;
+use Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator;
+use Spatie\MediaLibraryPro\Models\TemporaryUpload;
+
+return [
+
+    /*
+     * The disk on which to store added files and derived images by default.
+     */
+    'disk_name' => env('MEDIA_DISK', 's3'),
+
+    /*
+     * The disk for conversions when not explicitly specified.
+     */
+    'conversions_disk_name' => env('MEDIA_CONVERSIONS_DISK', null),
+
+    /*
+     * The maximum file size of an item in bytes.
+     */
+    'max_file_size' => 1024 * 1024 * 10,
+
+    /*
+     * Disallowed file extensions.
+     */
+    'disallowed_extensions' => [
+        'php', 'php3', 'php4', 'php5', 'php6', 'php7', 'php8',
+        'phtml', 'phtm', 'pht', 'phps', 'phar',
+        'shtml', 'shtm', 'stm',
+        'htaccess', 'htpasswd',
+        'cgi', 'pl', 'asp', 'aspx', 'jsp', 'jspx',
+    ],
+
+    /*
+     * Allowed file extensions filter.
+     */
+    'allowed_extensions' => null,
+
+    /*
+     * Queue connection for generating derived images.
+     */
+    'queue_connection_name' => env('QUEUE_CONNECTION', 'sync'),
+
+    /*
+     * Queue name for generating derived images.
+     */
+    'queue_name' => env('MEDIA_QUEUE', ''),
+
+    /*
+     * Queue conversions by default.
+     */
+    'queue_conversions_by_default' => env('QUEUE_CONVERSIONS_BY_DEFAULT', true),
+
+    /*
+     * Should DB transactions be run after DB commits.
+     */
+    'queue_conversions_after_database_commit' => env('QUEUE_CONVERSIONS_AFTER_DB_COMMIT', true),
+
+    /*
+     * The fully qualified class name of the media model.
+     */
+    'media_model' => Media::class,
+
+    /*
+     * The fully qualified class name of the media observer.
+     */
+    'media_observer' => MediaObserver::class,
+
+    /*
+     * Media collection serialization.
+     */
+    'use_default_collection_serialization' => false,
+
+    /*
+     * Temporary upload model (Media Library Pro).
+     */
+    'temporary_upload_model' => TemporaryUpload::class,
+
+    /*
+     * Enable temporary uploads session affinity.
+     */
+    'enable_temporary_uploads_session_affinity' => true,
+
+    /*
+     * Generate thumbnails for temporary uploads.
+     */
+    'generate_thumbnails_for_temporary_uploads' => true,
+
+    /*
+     * File namer class.
+     */
+    'file_namer' => DefaultFileNamer::class,
+
+    /*
+     * Path generator class.
+     */
+    'path_generator' => DefaultPathGenerator::class,
+
+    /*
+     * File remover class.
+     */
+    'file_remover_class' => DefaultFileRemover::class,
+
+    /*
+     * Custom path generators per model.
+     */
+    'custom_path_generators' => [],
+
+    /*
+     * URL generator class.
+     */
+    'url_generator' => DefaultUrlGenerator::class,
+
+    /*
+     * Moves media on update to keep path consistent.
+     */
+    'moves_media_on_update' => false,
+
+    /*
+     * Version urls with ?v=xx query string.
+     */
+    'version_urls' => false,
+
+    /*
+     * Image optimizers.
+     */
+    'image_optimizers' => [
+        // Left empty - optimization handled by project's ImageUpload service
+    ],
+
+    /*
+     * Image generators.
+     */
+    'image_generators' => [
+        Image::class,
+        Webp::class,
+        Avif::class,
+        Pdf::class,
+        Svg::class,
+        Video::class,
+    ],
+
+    /*
+     * Temporary directory path for image conversions.
+     */
+    'temporary_directory_path' => null,
+
+    /*
+     * Image driver: gd, imagick or vips.
+     */
+    'image_driver' => env('IMAGE_DRIVER', 'gd'),
+
+    /*
+     * FFMPEG paths.
+     */
+    'ffmpeg_path' => env('FFMPEG_PATH', '/usr/bin/ffmpeg'),
+    'ffprobe_path' => env('FFPROBE_PATH', '/usr/bin/ffprobe'),
+
+    /*
+     * FFMPEG timeout in seconds.
+     */
+    'ffmpeg_timeout' => env('FFMPEG_TIMEOUT', 900),
+
+    /*
+     * FFMPEG threads.
+     */
+    'ffmpeg_threads' => env('FFMPEG_THREADS', 0),
+
+    /*
+     * Jobs used by the package.
+     */
+    'jobs' => [
+        'perform_conversions' => PerformConversionsJob::class,
+        'generate_responsive_images' => GenerateResponsiveImagesJob::class,
+    ],
+
+    /*
+     * Media downloader used by addMediaFromUrl.
+     */
+    'media_downloader' => DefaultDownloader::class,
+
+    /*
+     * SSL verification for remote media downloads.
+     */
+    'media_downloader_ssl' => env('MEDIA_DOWNLOADER_SSL', true),
+
+    /*
+     * Default lifetime in minutes for temporary URLs.
+     */
+    'temporary_url_default_lifetime' => env('MEDIA_TEMPORARY_URL_DEFAULT_LIFETIME', 5),
+
+    'remote' => [
+        'extra_headers' => [
+            'CacheControl' => 'max-age=604800',
+        ],
+    ],
+
+    'responsive_images' => [
+        'width_calculator' => FileSizeOptimizedWidthCalculator::class,
+        'use_tiny_placeholders' => true,
+        'tiny_placeholder_generator' => Blurred::class,
+    ],
+
+    /*
+     * Enable Vapor uploads for Media Library Pro.
+     */
+    'enable_vapor_uploads' => env('ENABLE_MEDIA_LIBRARY_VAPOR_UPLOADS', false),
+
+    /*
+     * Default loading attribute for img tags.
+     */
+    'default_loading_attribute_value' => null,
+
+    /*
+     * Storage prefix for media.
+     */
+    'prefix' => env('MEDIA_PREFIX', ''),
+
+    /*
+     * Force lazy loading.
+     */
+    'force_lazy_loading' => env('FORCE_MEDIA_LIBRARY_LAZY_LOADING', true),
+];

+ 19 - 0
config/visitor.php

@@ -34,4 +34,23 @@ return [
         'jenssegers' => \Shetabit\Visitor\Drivers\JenssegersAgent::class,
         'UAParser'   => \Shetabit\Visitor\Drivers\UAParser::class,
     ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | GeoIP Enrichment
+    |--------------------------------------------------------------------------
+    |
+    | When enabled, visits can be enriched with geolocation data stored
+    | in the "geo_raw" JSON column. This package ships with a default
+    | resolver (stevebauman/location). You may implement your own by
+    | adding it to the drivers array below. Each driver must implement
+    | Shetabit\Visitor\Contracts\GeoIpResolver.
+    |
+    */
+    'geoip'    => false,            // disable enrichment by default
+    'resolver' => 'stevebauman',    // default resolver
+    'resolvers' => [
+        'stevebauman' => \Shetabit\Visitor\Resolvers\GeoIp\SteveBaumanResolver::class,
+        'null'        => \Shetabit\Visitor\Resolvers\GeoIp\NullResolver::class,
+    ],
 ];

+ 20 - 3
packages/Longyi/Core/src/Repositories/ProductImageRepository.php

@@ -2,6 +2,7 @@
 
 namespace Longyi\Core\Repositories;
 
+use Aws\S3\S3Client;
 use Illuminate\Http\UploadedFile;
 use Illuminate\Support\Facades\Storage;
 use Illuminate\Support\Str;
@@ -99,14 +100,30 @@ class ProductImageRepository extends BaseProductImageRepository
      */
     protected function storeFile(UploadedFile $file, $product): string
     {
-        $directory = 'product/' . $product->id;
+        $directory = 'uploads/product/' . $product->id;
 
         if (Str::contains($file->getMimeType(), 'image')) {
             $manager = new ImageManager;
             $image   = $manager->make($file)->encode('webp');
             $path    = $directory . '/' . Str::random(40) . '.webp';
-            Storage::put($path, $image);
-
+            //Storage::put($path, $image);
+            $s3Client = new S3Client([
+                'version' => 'latest',
+                'region'  => env('AWS_DEFAULT_REGION'),
+                'credentials' => [
+                    'key'    => env('AWS_ACCESS_KEY_ID'),
+                    'secret' => env('AWS_SECRET_ACCESS_KEY'),
+                ],
+                'http'    => [
+                    'verify' => false,  // 临时禁用 SSL 验证用于测试
+                ],
+            ]);
+             $s3Client->putObject([
+                'Bucket'      => env('AWS_BUCKET'),
+                'Key'         => $path,
+                'Body'        => (string) $image,
+                'ContentType' => 'image/webp',
+            ]);
             return $path;
         }
 

+ 111 - 0
packages/Longyi/Gift/src/Console/Commands/ImportGiftCards.php

@@ -0,0 +1,111 @@
+<?php
+
+namespace Longyi\Gift\Console\Commands;
+
+use Illuminate\Console\Command;
+use Longyi\Gift\Models\GiftCards;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
+use Monolog\Logger;
+use Monolog\Handler\StreamHandler;
+
+class ImportGiftCards extends Command
+{
+    protected $signature = 'gift-cards:import {--force}';
+    protected $customLogger = null;
+    protected $logFile = 'gift_import.log';
+
+    public function handle()
+    {
+        set_time_limit(0);
+        $limit = 500;
+        $offset = 0;
+        // 初始化自定义日志
+        $this->initCustomLogger($this->logFile);
+        //用户等级
+        $data = [];
+        do {
+            try {
+                $data = $this->fetchData($offset, $limit);
+                $this->saveDatas($data);
+                $offset = $offset + $limit;
+            } catch (\Exception $e) {
+                $this->logError(sprintf('[GiftCard Import] Error at offset %d: %s', $offset, $e->getMessage()));
+                exit(1);
+            }
+            echo $offset;
+            echo PHP_EOL;
+
+        } while (is_array($data) && !empty($data));
+
+        echo 'gift card import over~~';
+        echo PHP_EOL;
+    }
+
+    protected function fetchData($offset, $limit)
+    {
+        $sql = "select * from giftcard_customer where status=1 and endtime > '" . date('Y-m-d H:i:s') . "' order by gitfcard_id ASC limit {$offset}, {$limit}";
+        return DB::select($sql);
+    }
+    protected function saveDatas($data)
+    {
+        if (!$data) {
+            return false;
+        }
+        foreach ($data as $item) {
+            $this->saveGiftCard($item);
+        }
+    }
+
+    protected function saveGiftCard($item)
+    {
+        GiftCards::addGiftCard(
+            $item->customer_id,
+            $item->giftcard_amount,
+            0,
+            $item->endtime,
+            'activity_26_06_03',
+            '手动迁移'
+        );
+    }
+
+
+    /**
+     * Initialize custom logger with specified file
+     *
+     * @param string $logFile
+     */
+    protected function initCustomLogger(string $logFile)
+    {
+        $this->customLogger = new Logger('gift-card-import');
+        $this->customLogger->pushHandler(new StreamHandler($logFile, Logger::INFO));
+    }
+
+    /**
+     * Log info message
+     *
+     * @param string $message
+     */
+    protected function logInfo(string $message)
+    {
+        if ($this->customLogger) {
+            $this->customLogger->info($message);
+        } else {
+            Log::info($message);
+        }
+    }
+
+    /**
+     * Log error message
+     *
+     * @param string $message
+     */
+    protected function logError(string $message)
+    {
+        if ($this->customLogger) {
+            $this->customLogger->error($message);
+        } else {
+            Log::error($message);
+        }
+    }
+}

+ 49 - 13
packages/Longyi/Gift/src/Http/Controllers/Shop/GiftController.php

@@ -6,16 +6,20 @@ use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Illuminate\Http\Resources\Json\JsonResource;
 use Illuminate\Http\Response;
+use Longyi\RewardPoints\Repositories\RewardPointRepository;
 use Webkul\Checkout\Facades\Cart;
 use Webkul\Shop\Http\Controllers\Controller;
 use Longyi\Gift\Repositories\GiftCardsRepository;
 use Longyi\Gift\Models\GiftCards;
 use Longyi\Gift\Http\Resources\CustomCartResource;
+use Longyi\RewardPoints\Helpers\ApiResponse;
 
 class GiftController extends Controller
 {
     public function __construct(
-        protected GiftCardsRepository $giftCardRepository
+        protected GiftCardsRepository $giftCardRepository,
+        protected GiftCards $giftCardsModel,
+        protected RewardPointRepository $rewardPointRepository
     ) {
     }
 
@@ -24,6 +28,44 @@ class GiftController extends Controller
         echo 111;exit;
         return view('giftcard::shop.index');
     }
+
+    public function lists(): JsonResponse
+    {
+        $customerId = auth()->user()->id;
+        // 获取用户拥有的所有礼品卡
+        $userGiftCards = GiftCards::where('customer_id', $customerId)
+            ->where('giftcard_status', 1)
+            ->get()
+            ->keyBy('channel');
+        $gifts = $this->giftCardsModel->giftcards();
+        foreach ($gifts as &$gift) {
+            $channel = $gift['channel'];
+            if (isset($userGiftCards[$channel])) {
+                $gift['status'] = true;
+            } else {
+                $gift['status'] = false;
+            }
+        }
+        return ApiResponse::success([
+            'lists' => $gifts,
+            'myPoints' => $this->rewardPointRepository->getCustomerPoints($customerId)
+        ]);
+    }
+
+    public function add(Request $request): JsonResponse
+    {
+        $id = $request->input('id');
+        if (!$id) {
+            return ApiResponse::error('Gift card not found');
+        }
+        $customerId = auth()->user()->id;
+        try {
+            $this->giftCardsModel->add($id, $customerId);
+        } catch (\Exception $e) {
+            return ApiResponse::error($e->getMessage());
+        }
+        return ApiResponse::success('Gift card added successfully');
+    }
     /**
      * Get customer's gift cards list
      */
@@ -37,10 +79,8 @@ class GiftController extends Controller
                 ->where('expirationdate', '>=', now())
                 ->orderBy('created_at', 'desc')
                 ->get();
-
-            return response()->json([
-                'success' => true,
-                'data' => $giftCards->map(function ($giftCard) {
+            return ApiResponse::success(
+                $giftCards->map(function ($giftCard) {
                     return [
                         'id' => $giftCard->id,
                         'giftcard_number' => $giftCard->giftcard_number,
@@ -49,16 +89,12 @@ class GiftController extends Controller
                         'formatted_remaining_giftcard_amount' => core()->formatPrice(core()->convertPrice($giftCard->remaining_giftcard_amount)),
                         'used_giftcard_amount' => $giftCard->used_giftcard_amount,
                         'expirationdate' => $giftCard->expirationdate->format('Y-m-d'),
-                        'giftcard_status' => $giftCard->giftcard_status,
+                        'giftcard_status' => $giftCard->giftcard_status
                     ];
-                }),
-            ]);
+                })
+            );
         } catch (\Exception $e) {
-            return response()->json([
-                'success' => false,
-                'message' => 'Failed to fetch gift cards',
-                'error' => $e->getMessage(),
-            ], Response::HTTP_INTERNAL_SERVER_ERROR);
+            return ApiResponse::error($e->getMessage());
         }
     }
     /**

+ 132 - 1
packages/Longyi/Gift/src/Models/GiftCards.php

@@ -7,6 +7,11 @@ use Longyi\Gift\Models\GiftCardUsageLog;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Longyi\Gift\Contracts\GiftCards as GiftCardsContract;
+use Longyi\RewardPoints\Config\TransactionType;
+use Longyi\RewardPoints\Repositories\RewardPointRepository;
+use function Symfony\Component\Translation\t;
+use Illuminate\Support\Facades\DB;
+use Carbon\Carbon;
 
 class GiftCards extends Model implements GiftCardsContract
 {
@@ -105,18 +110,49 @@ class GiftCards extends Model implements GiftCardsContract
                 throw new \Exception('gift num is not enough');
             }
         }
+        $expirationDate = self::calculateExpirationDate($expirationdate);
         static::create([
             'giftcard_number' => self::generateGiftCardNumber(),
             'giftcard_amount' => $giftcardAmount,
             'used_giftcard_amount' => 0,
             'remaining_giftcard_amount' => $giftcardAmount,
             'customer_id' => $customerId,
-            'expirationdate' => now()->addDays($expirationdate),
+            'expirationdate' => $expirationDate,
             'giftcard_status' => 1,
             'channel' => $channel,
             'notes' => $notes
         ]);
     }
+    /**
+     * Calculate expiration date from various input types.
+     *
+     * @param  mixed  $expirationdate  Days (int), date string, or Carbon instance
+     * @return \Carbon\Carbon  Calculated expiration date
+     * @throws \Exception If the input type is invalid
+     */
+    protected static function calculateExpirationDate($expirationdate): Carbon
+    {
+        if ($expirationdate instanceof Carbon) {
+            return $expirationdate;
+        }
+
+        if (is_string($expirationdate)) {
+            try {
+                return Carbon::parse($expirationdate);
+            } catch (\Exception $e) {
+                throw new \Exception("Invalid date format: {$expirationdate}. Use Y-m-d format.");
+            }
+        }
+
+        if (is_int($expirationdate) || is_float($expirationdate)) {
+            if ($expirationdate <= 0) {
+                throw new \Exception('Expiration days must be greater than 0');
+            }
+            return now()->addDays((int) $expirationdate);
+        }
+
+        throw new \Exception('Invalid expiration date type. Must be integer (days), string (Y-m-d), or Carbon instance.');
+    }
     public static function generateGiftCardNumber()
     {
         do {
@@ -132,4 +168,99 @@ class GiftCards extends Model implements GiftCardsContract
 
         return $code;
     }
+
+    public function giftcards()
+    {
+        return [
+            1 => [
+                'id' => 1,
+                'name' => 'Gift Card 1',
+                'amount' => 20.00,
+                'points' => 20,
+                'num' => 0,
+                'expirationdate' => 30,
+                'channel' => 'activity_26_04_21',
+                'notes' => ''
+            ],
+            2 => [
+                'id' => 2,
+                'name' => 'Gift Card 2',
+                'amount' => 30.00,
+                'points' => 30,
+                'num' => 0,
+                'expirationdate' => 30,
+                'channel' => 'activity_26_04_21',
+                'notes' => ''
+            ],
+            3 => [
+                'id' => 3,
+                'name' => 'Gift Card 3',
+                'amount' => 40.00,
+                'points' => 40,
+                'num' => 0,
+                'expirationdate' => 30,
+                'channel' => 'activity_26_04_21',
+                'notes' => ''
+            ],
+            4 => [
+                'id' => 4,
+                'name' => 'Gift Card 4',
+                'amount' => 50.00,
+                'points' => 50,
+                'num' => 0,
+                'expirationdate' => 30,
+                'channel' => 'activity_26_04_21',
+                'notes' => ''
+            ],
+        ];
+    }
+
+    /**
+     * Add a gift card for a customer using points
+     *
+     * @param int $id Gift card ID from giftcards() array
+     * @param int $customerId Customer ID
+     * @return array|true
+     */
+    public function add($id, $customerId)
+    {
+        if (empty($customerId)) {
+            throw new \Exception('customer id is empty');
+        }
+        if (empty($id)) {
+            throw new \Exception('gift card id is empty');
+        }
+        $gifts = $this->giftcards();
+        $giftInfo = $gifts[$id] ?? null;
+        if (!$giftInfo) {
+            throw new \Exception("gift card not found (ID: {$id})");
+        }
+        $points = $giftInfo['points'] ?? 0;
+        if ($points <= 0) {
+            throw new \Exception("gift card points configuration error (points: {$points})");
+        }
+        try {
+            DB::beginTransaction();
+            self::addGiftCard(
+                $customerId,
+                $giftInfo['amount'],
+                $giftInfo['num'],
+                $giftInfo['expirationdate'],
+                $giftInfo['channel'],
+                $giftInfo['notes']
+            );
+            $rewardPointRepository = app(RewardPointRepository::class);
+            $rewardPointRepository->deductPoints(
+                $customerId,
+                $points,
+                TransactionType::GIFT_CARD_REDEEM,
+                'Gift Card Redeem'
+            );
+            DB::commit();
+            return true;
+        } catch (\Exception $e) {
+            DB::rollBack();
+            throw $e;
+        }
+    }
 }

+ 11 - 8
packages/Longyi/Gift/src/Routes/shop-routes.php

@@ -2,13 +2,16 @@
 
 use Illuminate\Support\Facades\Route;
 use Longyi\Gift\Http\Controllers\Shop\GiftController;
+use Longyi\RewardPoints\Http\Middleware\ApiCustomerAuthenticate;
 
-Route::group(['middleware' => ['web', 'theme', 'locale', 'currency'], 'prefix' => 'gift'], function () {
-    Route::get('', [GiftController::class, 'index'])->name('shop.gift.index');
-});
-Route::group(['middleware' => ['web', 'theme', 'locale', 'currency', 'customer'], 'prefix' => 'gift'], function () {
-    Route::get('/my-gift-cards', [GiftController::class, 'getCustomerGiftCards'])->name('shop.api.checkout.cart.giftcard.list');
-    Route::post('/activate', [GiftController::class, 'activateGiftCard'])->name('shop.api.checkout.cart.giftcard.activate');
-    Route::delete('/remove', [GiftController::class, 'destroyGiftCard'])->name('shop.api.checkout.cart.giftcard.remove');
-    Route::post('/auto-apply-expiring', [GiftController::class, 'autoApplyExpiringGiftCard'])->name('shop.api.checkout.cart.giftcard.auto-apply');
+Route::group(['prefix' => 'api'], function () {
+    Route::group(['middleware' => ['api', ApiCustomerAuthenticate::class], 'prefix' => 'gift'], function () {
+        Route::get('/lists', [GiftController::class, 'lists'])->name('shop.gift.lists');
+        Route::post('/add', [GiftController::class, 'add'])->name('shop.gift.add');
+        Route::get('/my-gift-cards', [GiftController::class, 'getCustomerGiftCards'])->name('shop.api.checkout.cart.giftcard.list');
+        Route::post('/activate', [GiftController::class, 'activateGiftCard'])->name('shop.api.checkout.cart.giftcard.activate');
+        Route::delete('/remove', [GiftController::class, 'destroyGiftCard'])->name('shop.api.checkout.cart.giftcard.remove');
+        Route::post('/auto-apply-expiring', [GiftController::class, 'autoApplyExpiringGiftCard'])->name('shop.api.checkout.cart.giftcard.auto-apply');
+    });
 });
+

+ 47 - 1
packages/Longyi/RewardPoints/src/Http/Middleware/ApiCustomerAuthenticate.php

@@ -6,21 +6,59 @@ use Closure;
 use Illuminate\Http\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Laravel\Sanctum\PersonalAccessToken;
+use Webkul\BagistoApi\Services\ApiKeyService;
 
 class ApiCustomerAuthenticate
 {
+    protected ?ApiKeyService $apiKeyService = null;
+
     /**
      * Handle an incoming request.
      *
      * 支持三种认证方式:
      * 1. Session Cookie(传统 Web 登录)
      * 2. Sanctum Bearer Token(BagistoApi 登录)
-     * 3. Storefront Key + Customer Session
+     * 3. Storefront Key(X-STOREFRONT-KEY 请求头)→ 由 BagistoApi 的 ApiKeyService 统一验证
      *
      * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
      */
     public function handle(Request $request, Closure $next): Response
     {
+        // 方式 3: Storefront Key 认证(X-STOREFRONT-KEY 请求头)
+        $storefrontKey = $request->header('X-STOREFRONT-KEY');
+        if ($storefrontKey) {
+            $apiKeyService = $this->getApiKeyService();
+
+            // 验证 key 有效性
+            $validation = $apiKeyService->validate(
+                $storefrontKey,
+                ApiKeyService::KEY_TYPE_SHOP,
+                $request->ip()
+            );
+
+            if (! ($validation['valid'] ?? false)) {
+                return response()->json([
+                    'error'   => 'invalid_storefront_key',
+                    'message' => $validation['message'] ?? 'The provided storefront key is invalid or inactive.',
+                ], 403);
+            }
+
+            // 频率限制检查
+            $rateLimit = $apiKeyService->checkRateLimit($validation['client']);
+            if (! ($rateLimit['allowed'] ?? false)) {
+                return response()->json([
+                    'error'       => 'rate_limit_exceeded',
+                    'message'     => 'Rate limit exceeded. Please retry later.',
+                    'retry_after' => $rateLimit['reset_at'] ?? 60,
+                ], 429);
+            }
+        } else {
+            return response()->json([
+                'error'   => 'invalid_storefront_key',
+                'message' => 'X-STOREFRONT-KEY header is required',
+            ], 403);
+        }
+
         // 方式 1: Session Cookie 认证(传统 Web 登录)
         if (auth()->guard('customer')->check()) {
             return $next($request);
@@ -44,6 +82,14 @@ class ApiCustomerAuthenticate
         ], 401);
     }
 
+    /**
+     * 懒加载 ApiKeyService 实例
+     */
+    protected function getApiKeyService(): ApiKeyService
+    {
+        return $this->apiKeyService ??= app(ApiKeyService::class);
+    }
+
     /**
      * 通过 Sanctum Token 验证客户
      *

+ 3 - 3
packages/Longyi/RewardPoints/src/Repositories/RewardPointRepository.php

@@ -214,7 +214,7 @@ class RewardPointRepository extends Repository
 
                 if (!$customerPoints) {
                     Log::warning('Customer points record not found', ['customer_id' => $customerId]);
-                    return false;
+                    throw new \Exception('Customer points record not found');
                 }
 
                 if ($customerPoints->mw_reward_point < $amount) {
@@ -223,7 +223,7 @@ class RewardPointRepository extends Repository
                         'current' => $customerPoints->mw_reward_point,
                         'required' => $amount
                     ]);
-                    return false;
+                    throw new \Exception('Insufficient points');
                 }
 
                 $currentBalance = (int) $customerPoints->mw_reward_point;
@@ -264,7 +264,7 @@ class RewardPointRepository extends Repository
                 'amount' => $amount,
                 'error' => $e->getMessage()
             ]);
-            return false;
+            throw $e;
         }
     }
     public function getHistory($customerId, $limit = 20, $page = null)

+ 1 - 1
packages/Webkul/Product/src/Repositories/ProductAttributeValueRepository.php

@@ -56,7 +56,7 @@ class ProductAttributeValueRepository extends Repository
 
             if (in_array($attribute->type, ['image', 'file'])) {
                 $data[$attribute->code] = gettype($data[$attribute->code]) === 'object'
-                    ? request()->file($attribute->code)->store('product/'.$product->id)
+                    ? request()->file($attribute->code)->store('uploads/product/'.$product->id)
                     : $data[$attribute->code];
             }
 

+ 1 - 1
packages/Webkul/Product/src/Repositories/ProductMediaRepository.php

@@ -34,7 +34,7 @@ class ProductMediaRepository extends Repository
      */
     public function getProductDirectory($product): string
     {
-        return 'uploads/'.date('Ym/d');
+        return 'uploads/product/' . $product->id;
     }
 
     /**