From 5e552c572ef4aec884842d8e636572fcc765e150 Mon Sep 17 00:00:00 2001
From: liqianjin <949671634@qq.com>
Date: Sat, 27 May 2023 11:47:26 +0800
Subject: [PATCH] init
---
.editorconfig | 21 +
.env | 28 +
.htaccess | 21 +
.styleci.yml | 14 +
404.html | 7 +
LICENSE | 172 +
README.md | 110 +
app/Console/Kernel.php | 32 +
app/Exceptions/Handler.php | 75 +
.../RegisterAdminErrorViewPaths.php | 23 +
app/Http/Controllers/Controller.php | 13 +
app/Http/Kernel.php | 94 +
app/Http/Middleware/Authenticate.php | 22 +
app/Http/Middleware/CheckoutAuthenticate.php | 72 +
app/Http/Middleware/EncryptCookies.php | 17 +
.../PreventRequestsDuringMaintenance.php | 17 +
.../Middleware/RedirectIfAuthenticated.php | 32 +
app/Http/Middleware/SetLocaleAdmin.php | 29 +
app/Http/Middleware/SetLocaleFromSession.php | 31 +
app/Http/Middleware/SetLocaleInstaller.php | 35 +
app/Http/Middleware/ShareViewData.php | 75 +
app/Http/Middleware/ShopAuthenticate.php | 64 +
app/Http/Middleware/TrimStrings.php | 19 +
app/Http/Middleware/TrustHosts.php | 20 +
app/Http/Middleware/TrustProxies.php | 28 +
app/Http/Middleware/VerifyCsrfToken.php | 17 +
app/Http/Requests/ContactRequest.php | 30 +
app/Providers/AppServiceProvider.php | 31 +
app/Providers/AuthServiceProvider.php | 32 +
app/Providers/BroadcastServiceProvider.php | 21 +
app/Providers/EventServiceProvider.php | 32 +
app/Providers/HorizonServiceProvider.php | 42 +
app/Providers/RouteServiceProvider.php | 63 +
artisan | 53 +
.../Admin/Database/Seeders/ProductSeeder.php | 62 +
.../Http/Controllers/AddressController.php | 68 +
.../Http/Controllers/AdminRoleController.php | 88 +
.../Http/Controllers/AdminUserController.php | 70 +
.../Http/Controllers/AttributeController.php | 151 +
.../Controllers/AttributeGroupController.php | 68 +
.../Http/Controllers/BrandController.php | 129 +
.../Http/Controllers/CategoryController.php | 108 +
beike/Admin/Http/Controllers/Controller.php | 89 +
.../Http/Controllers/CountryController.php | 60 +
.../Http/Controllers/CurrencyController.php | 74 +
.../Http/Controllers/CustomerController.php | 141 +
.../Controllers/CustomerGroupController.php | 65 +
.../Http/Controllers/DesignController.php | 82 +
.../Controllers/DesignFooterController.php | 65 +
.../Http/Controllers/DesignMenuController.php | 42 +
.../Admin/Http/Controllers/EditController.php | 25 +
.../Controllers/FileManagerController.php | 134 +
.../Http/Controllers/ForgottenController.php | 53 +
.../Admin/Http/Controllers/HomeController.php | 27 +
.../Http/Controllers/LanguageController.php | 74 +
.../Http/Controllers/LoginController.php | 37 +
.../Http/Controllers/LogoutController.php | 18 +
.../Http/Controllers/MarketingController.php | 100 +
.../Http/Controllers/OrderController.php | 123 +
.../Controllers/PageCategoryController.php | 153 +
.../Http/Controllers/PagesController.php | 145 +
.../Http/Controllers/PluginController.php | 137 +
.../Http/Controllers/ProductController.php | 215 +
.../Http/Controllers/RegionController.php | 55 +
.../Admin/Http/Controllers/RmaController.php | 74 +
.../Http/Controllers/RmaReasonController.php | 63 +
.../Http/Controllers/SettingController.php | 76 +
.../Http/Controllers/TaxClassController.php | 56 +
.../Http/Controllers/TaxRateController.php | 58 +
.../Http/Controllers/ThemeController.php | 83 +
.../Admin/Http/Controllers/ZoneController.php | 69 +
.../Admin/Http/Requests/AdminRoleRequest.php | 46 +
.../Admin/Http/Requests/AdminUserRequest.php | 50 +
beike/Admin/Http/Requests/CategoryRequest.php | 37 +
beike/Admin/Http/Requests/CurrencyRequest.php | 47 +
.../Http/Requests/CustomerGroupRequest.php | 48 +
beike/Admin/Http/Requests/CustomerRequest.php | 58 +
.../Admin/Http/Requests/ForgottenRequest.php | 37 +
beike/Admin/Http/Requests/LoginRequest.php | 31 +
.../Http/Requests/PageCategoryRequest.php | 49 +
beike/Admin/Http/Requests/PageRequest.php | 51 +
beike/Admin/Http/Requests/ProductRequest.php | 56 +
beike/Admin/Http/Requests/RmaRequest.php | 60 +
beike/Admin/Http/Requests/TaxRateRequest.php | 57 +
beike/Admin/Http/Requests/UploadRequest.php | 39 +
.../Admin/Http/Requests/VerifyCodeRequest.php | 37 +
.../Admin/Http/Resources/AddressResource.php | 32 +
.../Admin/Http/Resources/AdminUserDetail.php | 31 +
.../Resources/AttributeDetailResource.php | 30 +
.../Http/Resources/AttributeResource.php | 27 +
.../Http/Resources/AttributeValueResource.php | 28 +
.../Http/Resources/AutocompleteResource.php | 24 +
.../Admin/Http/Resources/CategoryResource.php | 29 +
.../Http/Resources/CustomerGroupDetail.php | 31 +
.../Admin/Http/Resources/CustomerResource.php | 39 +
beike/Admin/Http/Resources/OrderSimple.php | 33 +
.../Http/Resources/PageCategoryResource.php | 36 +
beike/Admin/Http/Resources/PluginResource.php | 35 +
.../Resources/ProductAttributeResource.php | 33 +
.../Admin/Http/Resources/ProductResource.php | 38 +
beike/Admin/Http/Resources/RmaDetail.php | 42 +
.../Admin/Http/Resources/RmaHistoryDetail.php | 32 +
.../Admin/Http/Resources/RmaReasonDetail.php | 26 +
beike/Admin/Http/Resources/TaxClassDetail.php | 30 +
.../Admin/Providers/AdminServiceProvider.php | 197 +
beike/Admin/Repositories/AdminRoleRepo.php | 91 +
beike/Admin/Repositories/AdminUserRepo.php | 95 +
.../Admin/Repositories/AttributeGroupRepo.php | 78 +
beike/Admin/Repositories/AttributeRepo.php | 141 +
beike/Admin/Repositories/DashboardRepo.php | 120 +
beike/Admin/Repositories/PageRepo.php | 132 +
beike/Admin/Repositories/PermissionRepo.php | 485 +
beike/Admin/Repositories/RegionRepo.php | 77 +
.../Repositories/Report/OrderReportRepo.php | 143 +
beike/Admin/Repositories/TaxClassRepo.php | 66 +
beike/Admin/Repositories/TaxRateRepo.php | 56 +
beike/Admin/Routes/admin.php | 246 +
beike/Admin/Services/AddressService.php | 57 +
beike/Admin/Services/CategoryService.php | 182 +
beike/Admin/Services/CustomerGroupService.php | 76 +
beike/Admin/Services/CustomerService.php | 26 +
beike/Admin/Services/FileManagerService.php | 222 +
beike/Admin/Services/LanguageService.php | 86 +
beike/Admin/Services/MarketingService.php | 112 +
beike/Admin/Services/ProductService.php | 73 +
beike/Admin/Services/UserService.php | 69 +
beike/Admin/View/Components/Alert.php | 23 +
beike/Admin/View/Components/Filter.php | 33 +
beike/Admin/View/Components/Form/Image.php | 26 +
beike/Admin/View/Components/Form/Input.php | 47 +
.../View/Components/Form/InputLocale.php | 87 +
beike/Admin/View/Components/Form/RichText.php | 38 +
beike/Admin/View/Components/Form/Select.php | 35 +
.../View/Components/Form/SwitchRadio.php | 26 +
beike/Admin/View/Components/Form/Textarea.php | 29 +
beike/Admin/View/Components/Header.php | 108 +
beike/Admin/View/Components/NoData.php | 20 +
beike/Admin/View/Components/Sidebar.php | 285 +
beike/Admin/View/DesignBuilders/Brand.php | 44 +
beike/Admin/View/DesignBuilders/Icons.php | 44 +
beike/Admin/View/DesignBuilders/Image100.php | 44 +
beike/Admin/View/DesignBuilders/Image200.php | 44 +
beike/Admin/View/DesignBuilders/Image300.php | 44 +
beike/Admin/View/DesignBuilders/Image401.php | 44 +
beike/Admin/View/DesignBuilders/Product.php | 44 +
beike/Admin/View/DesignBuilders/RichText.php | 44 +
beike/Admin/View/DesignBuilders/SlideShow.php | 45 +
.../Admin/View/DesignBuilders/TabProduct.php | 44 +
beike/Config/beike.php | 19 +
beike/Console/Commands/ChangeRootPassword.php | 41 +
beike/Console/Commands/FetchCurrencyRate.php | 35 +
.../Console/Commands/GenerateDatabaseDict.php | 51 +
beike/Console/Commands/GenerateSitemap.php | 32 +
beike/Console/Commands/MakeRootAdminUser.php | 34 +
.../Console/Commands/MigrateFromOpenCart.php | 460 +
beike/Helpers.php | 720 +
beike/Hook/Callback.php | 37 +
beike/Hook/Console/HookListeners.php | 48 +
beike/Hook/Facades/Hook.php | 13 +
beike/Hook/Hook.php | 246 +
beike/Hook/HookServiceProvider.php | 89 +
.../Controllers/DatabaseController.php | 68 +
.../Controllers/EnvironmentController.php | 175 +
.../Installer/Controllers/FinalController.php | 34 +
.../Controllers/PermissionsController.php | 38 +
.../Controllers/RequirementsController.php | 41 +
.../Controllers/WelcomeController.php | 43 +
beike/Installer/Helpers/DatabaseManager.php | 95 +
.../Installer/Helpers/EnvironmentManager.php | 133 +
.../Installer/Helpers/FinalInstallManager.php | 79 +
.../Helpers/InstalledFileManager.php | 40 +
beike/Installer/Helpers/MigrationsHelper.php | 31 +
.../Installer/Helpers/PermissionsChecker.php | 83 +
.../Installer/Helpers/RequirementsChecker.php | 116 +
beike/Installer/Helpers/functions.php | 28 +
.../Installer/Lang/en/installer_messages.php | 187 +
.../Lang/zh_cn/installer_messages.php | 109 +
.../Providers/InstallerServiceProvider.php | 30 +
beike/Installer/Routes/installer.php | 28 +
.../Views/environment-wizard.blade.php | 260 +
beike/Installer/Views/finished.blade.php | 33 +
.../Installer/Views/layouts/master.blade.php | 93 +
beike/Installer/Views/permissions.blade.php | 46 +
beike/Installer/Views/requirements.blade.php | 55 +
beike/Installer/Views/welcome.blade.php | 267 +
beike/Installer/assets/scss/_install-1.scss | 20 +
beike/Installer/assets/scss/_steps.scss | 88 +
beike/Installer/assets/scss/app.scss | 52 +
beike/Installer/config.php | 131 +
beike/Libraries/Breadcrumb.php | 69 +
beike/Libraries/Notification.php | 27 +
beike/Libraries/Tax.php | 212 +
beike/Libraries/Url.php | 134 +
beike/Mail/CustomerForgotten.php | 47 +
beike/Mail/CustomerNewOrder.php | 49 +
beike/Mail/CustomerRegistration.php | 45 +
beike/Mail/CustomerUpdateOrder.php | 52 +
beike/Mail/UserForgotten.php | 47 +
beike/Models/Address.php | 32 +
beike/Models/AdminUser.php | 29 +
beike/Models/Attribute.php | 43 +
beike/Models/AttributeDescription.php | 21 +
beike/Models/AttributeGroup.php | 37 +
beike/Models/AttributeGroupDescription.php | 21 +
beike/Models/AttributeValue.php | 38 +
beike/Models/AttributeValueDescription.php | 21 +
beike/Models/Base.php | 23 +
beike/Models/Brand.php | 35 +
beike/Models/Cart.php | 30 +
beike/Models/CartProduct.php | 32 +
beike/Models/Category.php | 66 +
beike/Models/CategoryDescription.php | 20 +
beike/Models/CategoryPath.php | 27 +
beike/Models/Country.php | 27 +
beike/Models/Currency.php | 36 +
beike/Models/Customer.php | 69 +
beike/Models/CustomerGroup.php | 22 +
beike/Models/CustomerGroupDescription.php | 12 +
beike/Models/CustomerWishlist.php | 18 +
beike/Models/Language.php | 21 +
beike/Models/Order.php | 115 +
beike/Models/OrderHistory.php | 26 +
beike/Models/OrderProduct.php | 38 +
beike/Models/OrderShipment.php | 21 +
beike/Models/OrderTotal.php | 26 +
beike/Models/Page.php | 57 +
beike/Models/PageCategory.php | 59 +
beike/Models/PageCategoryDescription.php | 23 +
beike/Models/PageDescription.php | 19 +
beike/Models/PageProduct.php | 27 +
beike/Models/Plugin.php | 17 +
beike/Models/Product.php | 91 +
beike/Models/ProductAttribute.php | 32 +
beike/Models/ProductCategory.php | 24 +
beike/Models/ProductDescription.php | 12 +
beike/Models/ProductRelation.php | 24 +
beike/Models/ProductSku.php | 48 +
beike/Models/Region.php | 30 +
beike/Models/RegionZone.php | 27 +
beike/Models/Rma.php | 48 +
beike/Models/RmaHistory.php | 21 +
beike/Models/RmaReason.php | 21 +
beike/Models/Setting.php | 16 +
beike/Models/TaxClass.php | 27 +
beike/Models/TaxRate.php | 24 +
beike/Models/TaxRule.php | 29 +
beike/Models/VerifyCode.php | 23 +
beike/Models/Zone.php | 21 +
.../AdminForgottenNotification.php | 91 +
beike/Notifications/ForgottenNotification.php | 91 +
beike/Notifications/NewOrderNotification.php | 88 +
.../RegistrationNotification.php | 88 +
.../Notifications/UpdateOrderNotification.php | 91 +
beike/Plugin/Asset.php | 70 +
beike/Plugin/Manager.php | 208 +
beike/Plugin/Plugin.php | 354 +
beike/Repositories/AddressRepo.php | 85 +
beike/Repositories/BrandRepo.php | 218 +
beike/Repositories/CartRepo.php | 155 +
beike/Repositories/CategoryRepo.php | 228 +
beike/Repositories/CountryRepo.php | 124 +
beike/Repositories/CurrencyRepo.php | 102 +
beike/Repositories/CustomerGroupRepo.php | 85 +
beike/Repositories/CustomerRepo.php | 212 +
beike/Repositories/FooterRepo.php | 39 +
beike/Repositories/LanguageRepo.php | 103 +
beike/Repositories/MenuRepo.php | 73 +
beike/Repositories/OrderHistoryRepo.php | 16 +
beike/Repositories/OrderProductRepo.php | 60 +
beike/Repositories/OrderRepo.php | 288 +
beike/Repositories/OrderTotalRepo.php | 31 +
beike/Repositories/PageCategoryRepo.php | 160 +
beike/Repositories/PageRepo.php | 97 +
beike/Repositories/PluginRepo.php | 334 +
beike/Repositories/ProductRepo.php | 399 +
beike/Repositories/RmaReasonRepo.php | 91 +
beike/Repositories/RmaRepo.php | 170 +
beike/Repositories/SettingRepo.php | 158 +
beike/Repositories/SystemSettingRepo.php | 16 +
beike/Repositories/ThemeRepo.php | 33 +
beike/Repositories/UserRepo.php | 95 +
beike/Repositories/VerifyCodeRepo.php | 60 +
beike/Repositories/ZoneRepo.php | 139 +
beike/Services/CurrencyService.php | 117 +
beike/Services/DesignService.php | 250 +
beike/Services/ImageService.php | 106 +
beike/Services/ShipmentService.php | 72 +
beike/Services/ShippingMethodService.php | 55 +
beike/Services/SitemapService.php | 54 +
beike/Services/StateMachineService.php | 372 +
.../Controllers/Account/AccountController.php | 55 +
.../Controllers/Account/AddressController.php | 64 +
.../Controllers/Account/EditController.php | 40 +
.../Account/ForgottenController.php | 53 +
.../Controllers/Account/LoginController.php | 54 +
.../Controllers/Account/LogoutController.php | 31 +
.../Controllers/Account/OrderController.php | 137 +
.../Account/RegisterController.php | 36 +
.../Controllers/Account/RmaController.php | 76 +
.../Account/WishlistController.php | 46 +
.../Shop/Http/Controllers/BrandController.php | 55 +
.../Shop/Http/Controllers/CartController.php | 134 +
.../Http/Controllers/CategoryController.php | 46 +
.../Http/Controllers/CheckoutController.php | 62 +
beike/Shop/Http/Controllers/Controller.php | 12 +
.../Http/Controllers/CurrencyController.php | 29 +
.../Shop/Http/Controllers/FileController.php | 25 +
.../Shop/Http/Controllers/HomeController.php | 57 +
.../Http/Controllers/LanguageController.php | 29 +
.../Controllers/PageCategoryController.php | 51 +
.../Shop/Http/Controllers/PageController.php | 41 +
.../Http/Controllers/PluginController.php | 35 +
.../Http/Controllers/ProductController.php | 59 +
.../Shop/Http/Controllers/ZoneController.php | 31 +
beike/Shop/Http/Requests/AddressRequest.php | 45 +
beike/Shop/Http/Requests/CartRequest.php | 57 +
beike/Shop/Http/Requests/EditRequest.php | 39 +
beike/Shop/Http/Requests/ForgottenRequest.php | 37 +
beike/Shop/Http/Requests/LoginRequest.php | 39 +
beike/Shop/Http/Requests/RegisterRequest.php | 39 +
beike/Shop/Http/Requests/RmaRequest.php | 56 +
beike/Shop/Http/Requests/UploadRequest.php | 39 +
.../Shop/Http/Requests/VerifyCodeRequest.php | 37 +
.../Resources/Account/AddressResource.php | 34 +
.../Shop/Http/Resources/Account/OrderList.php | 30 +
.../Resources/Account/RmaReasonDetail.php | 25 +
.../Http/Resources/Account/WishlistDetail.php | 38 +
beike/Shop/Http/Resources/BrandDetail.php | 32 +
beike/Shop/Http/Resources/CartDetail.php | 48 +
beike/Shop/Http/Resources/CategoryDetail.php | 32 +
.../Resources/Checkout/PaymentMethodItem.php | 30 +
.../Resources/Checkout/ShippingMethodItem.php | 29 +
.../Shop/Http/Resources/CustomerResource.php | 29 +
.../Http/Resources/PageCategoryDetail.php | 36 +
beike/Shop/Http/Resources/PageDetail.php | 46 +
beike/Shop/Http/Resources/ProductDetail.php | 84 +
beike/Shop/Http/Resources/ProductSimple.php | 60 +
beike/Shop/Http/Resources/RmaDetail.php | 48 +
beike/Shop/Http/Resources/SkuDetail.php | 41 +
.../Shop/Providers/PluginServiceProvider.php | 242 +
beike/Shop/Providers/ShopServiceProvider.php | 148 +
beike/Shop/Routes/shop.php | 109 +
beike/Shop/Services/AccountService.php | 107 +
beike/Shop/Services/AddressService.php | 50 +
beike/Shop/Services/CartService.php | 188 +
beike/Shop/Services/CheckoutService.php | 272 +
beike/Shop/Services/PaymentService.php | 66 +
beike/Shop/Services/RmaService.php | 50 +
beike/Shop/Services/TotalService.php | 118 +
.../TotalServices/CustomerDiscountService.php | 51 +
.../TotalServices/OrderTotalService.php | 38 +
.../TotalServices/ShippingService.php | 74 +
.../TotalServices/SubtotalService.php | 39 +
.../Services/TotalServices/TaxService.php | 52 +
beike/Shop/View/Components/AccountSidebar.php | 35 +
beike/Shop/View/Components/Alert.php | 23 +
beike/Shop/View/Components/Breadcrumb.php | 300 +
beike/Shop/View/Components/NoData.php | 26 +
bootstrap/app.php | 55 +
bootstrap/cache/.gitignore | 2 +
composer.json | 104 +
composer.lock | 11248 ++++++++++
config/app.php | 243 +
config/auth.php | 111 +
config/broadcasting.php | 64 +
config/cache.php | 110 +
config/cors.php | 34 +
config/database.php | 166 +
config/debugbar.php | 274 +
config/filesystems.php | 73 +
config/hashing.php | 52 +
config/horizon.php | 197 +
config/logging.php | 118 +
config/mail.php | 118 +
config/permission.php | 161 +
config/queue.php | 93 +
config/sanctum.php | 65 +
config/services.php | 33 +
config/session.php | 201 +
config/sitemap.php | 14 +
config/view.php | 37 +
database/.gitignore | 1 +
database/factories/AddressFactory.php | 30 +
.../Beike/Models/CartProductFactory.php | 32 +
database/factories/ProductFactory.php | 25 +
database/factories/ProductSkuFactory.php | 26 +
database/factories/UserFactory.php | 39 +
..._08_19_000000_create_failed_jobs_table.php | 38 +
.../2021_12_26_111435_create_tables.php | 475 +
..._08_01_033755_create_permission_tables.php | 151 +
...22_12_16_095559_create_order_shipments.php | 43 +
...2_22_022326_create_notifications_table.php | 35 +
.../2022_12_22_061843_order_add_field.php | 35 +
.../2022_12_28_171057_alter_cart_table.php | 40 +
...22_12_30_110019_create_product_related.php | 34 +
.../2022_12_30_165725_guest_checkout.php | 41 +
.../2023_01_03_111459_product_attribute.php | 88 +
...2023_01_06_104545_change_meta_keywords.php | 36 +
.../2023_01_10_115702_add_sales2_product.php | 40 +
...2023_02_09_021051_create_page_category.php | 65 +
database/seeders/AttributesSeeder.php | 340 +
database/seeders/BrandsSeeder.php | 139 +
database/seeders/CategoriesSeeder.php | 439 +
database/seeders/CountriesSeeder.php | 1794 ++
database/seeders/CurrenciesSeeder.php | 73 +
database/seeders/CustomerGroupsSeeder.php | 102 +
database/seeders/DatabaseSeeder.php | 59 +
database/seeders/LanguagesSeeder.php | 62 +
database/seeders/PagesSeeder.php | 193 +
database/seeders/PluginsSeeder.php | 77 +
database/seeders/ProductsSeeder.php | 2009 ++
database/seeders/SettingsSeeder.php | 78 +
database/seeders/ThemeSeeder.php | 1160 +
database/seeders/ZonesSeeder.php | 4110 ++++
index.php | 12 +
package-lock.json | 7505 +++++++
package.json | 24 +
phpunit.xml | 31 +
pint.json | 56 +
public/.htaccess | 7 +
public/build/beike/admin/css/app.css | 1666 ++
public/build/beike/admin/css/bootstrap.css | 16953 ++++++++++++++
public/build/beike/admin/css/design.css | 649 +
public/build/beike/admin/css/filemanager.css | 273 +
public/build/beike/admin/js/app.js | 3166 +++
public/build/beike/shop/default/css/app.css | 2347 ++
.../beike/shop/default/css/bootstrap.css | 18318 ++++++++++++++++
public/build/beike/shop/default/js/app.js | 2879 +++
public/cache/.gitignore | 2 +
public/catalog/.gitignore | 5 +
public/catalog/banner.png | Bin 0 -> 420235 bytes
public/catalog/placeholder.png | Bin 0 -> 7834 bytes
public/favicon.ico | 0
public/fonts/design/iconfont.json | 429 +
public/fonts/design/iconfont.ttf | Bin 0 -> 19000 bytes
public/fonts/design/iconfont.woff | Bin 0 -> 11628 bytes
public/fonts/design/iconfont.woff2 | Bin 0 -> 9888 bytes
public/fonts/iconfont/iconfont.json | 58 +
public/fonts/iconfont/iconfont.ttf | Bin 0 -> 8460 bytes
public/fonts/iconfont/iconfont.woff | Bin 0 -> 5884 bytes
public/fonts/poppins/Poppins-Bold.ttf | Bin 0 -> 142316 bytes
public/fonts/poppins/Poppins-Light.ttf | Bin 0 -> 147604 bytes
public/fonts/poppins/Poppins-Medium.ttf | Bin 0 -> 144632 bytes
public/fonts/poppins/Poppins-Regular.ttf | Bin 0 -> 146204 bytes
public/fonts/poppins/Poppins-SemiBold.ttf | Bin 0 -> 279164 bytes
public/htaccess.txt | 21 +
public/image/alipay.png | Bin 0 -> 8288 bytes
public/image/close.png | Bin 0 -> 1197 bytes
public/image/default-theme.jpg | Bin 0 -> 74344 bytes
public/image/favicon.png | Bin 0 -> 2309 bytes
public/image/login-bg.svg | 1 +
public/image/logo.png | Bin 0 -> 22981 bytes
public/image/no-data.svg | 97 +
public/image/placeholder.png | Bin 0 -> 7834 bytes
public/image/vip-icon.png | Bin 0 -> 13353 bytes
public/image/vip-info.webp | Bin 0 -> 155812 bytes
public/image/wechat.png | Bin 0 -> 8859 bytes
public/index.php | 79 +
public/install/css/app.css | 121 +
public/install/image/install-1.png | Bin 0 -> 324289 bytes
public/install/image/install-2.png | Bin 0 -> 183721 bytes
public/install/image/install-enter.jpg | Bin 0 -> 1129 bytes
public/mix-manifest.json | 11 +
public/nginx.htaccess | 0
public/plugin/.gitignore | 2 +
public/robots.txt | 2 +
public/upload/.gitignore | 2 +
public/vendor/axios/0.27.2/axios.min.js | 3 +
.../bootstrap/4.6.1/css/bootstrap.min.css | 7 +
.../4.6.1/js/bootstrap.bundle.min.js | 7 +
.../bootstrap/4.6.1/js/bootstrap.min.js | 7 +
.../bootstrap/5.1.3/css/bootstrap.min.css | 7 +
.../5.1.3/js/bootstrap.bundle.min.js | 6 +
.../bootstrap/5.1.3/js/bootstrap.min.js | 6 +
.../bootstrap/icon/bootstrap-icons.woff | Bin 0 -> 137216 bytes
.../bootstrap/icon/bootstrap-icons.woff2 | Bin 0 -> 102380 bytes
public/vendor/chart/chart.min.js | 13 +
public/vendor/clipboard/clipboard.min.js | 7 +
public/vendor/cookie/js.cookie.min.js | 1 +
public/vendor/cropper/cropper.min.css | 9 +
public/vendor/cropper/cropper.min.js | 10 +
public/vendor/element-ui/2.15.6/css.css | 1 +
.../element-ui/2.15.6/fonts/element-icons.ttf | Bin 0 -> 55956 bytes
.../2.15.6/fonts/element-icons.woff | Bin 0 -> 28200 bytes
public/vendor/element-ui/2.15.6/js.js | 1 +
.../element-ui/2.15.9/fonts/element-icons.ttf | Bin 0 -> 55956 bytes
.../2.15.9/fonts/element-icons.woff | Bin 0 -> 28200 bytes
public/vendor/element-ui/2.15.9/index.css | 1 +
public/vendor/element-ui/2.15.9/index.js | 1 +
public/vendor/element-ui/language/de.js | 143 +
public/vendor/element-ui/language/en.js | 142 +
public/vendor/element-ui/language/es.js | 141 +
public/vendor/element-ui/language/fr.js | 141 +
public/vendor/element-ui/language/it.js | 141 +
public/vendor/element-ui/language/ja.js | 142 +
public/vendor/element-ui/language/ru.js | 142 +
public/vendor/element-ui/language/zh_hk.js | 142 +
.../elevatezoom/jquery.elevateZoom.min.js | 65 +
public/vendor/highlight/atom-one-dark.min.css | 1 +
public/vendor/highlight/highlight.min.js | 1202 +
public/vendor/horizon/app-dark.css | 8 +
public/vendor/horizon/app.css | 8 +
public/vendor/horizon/app.js | 2 +
public/vendor/horizon/img/favicon.png | Bin 0 -> 648 bytes
public/vendor/horizon/img/horizon.svg | 4 +
public/vendor/horizon/img/sprite.svg | 806 +
public/vendor/horizon/mix-manifest.json | 8 +
public/vendor/jquery/jquery-2.1.1.min.js | 4 +
public/vendor/jquery/jquery-3.6.0.min.js | 2 +
.../vendor/jquery/jquery-ui/jquery-ui.min.css | 7 +
.../vendor/jquery/jquery-ui/jquery-ui.min.js | 6 +
public/vendor/layer/3.5.1/layer.js | 2 +
public/vendor/layer/3.5.1/mobile/layer.js | 2 +
.../vendor/layer/3.5.1/mobile/need/layer.css | 1 +
.../layer/3.5.1/theme/default/icon-ext.png | Bin 0 -> 5911 bytes
.../vendor/layer/3.5.1/theme/default/icon.png | Bin 0 -> 11493 bytes
.../layer/3.5.1/theme/default/layer.css | 1 +
.../layer/3.5.1/theme/default/loading-0.gif | Bin 0 -> 5793 bytes
.../layer/3.5.1/theme/default/loading-1.gif | Bin 0 -> 701 bytes
.../layer/3.5.1/theme/default/loading-2.gif | Bin 0 -> 1787 bytes
public/vendor/marked/marked.min.js | 6 +
public/vendor/qrcode/qrcode.min.js | 4 +
.../scrolltofixed/jquery-scrolltofixed-min.js | 1 +
public/vendor/sitemap/styles/google-news.xsl | 133 +
public/vendor/sitemap/styles/mobile.xsl | 123 +
public/vendor/sitemap/styles/sitemapindex.xsl | 125 +
public/vendor/sitemap/styles/xml.xsl | 133 +
public/vendor/sweetalert2/sweetalert2.min.css | 1 +
public/vendor/sweetalert2/sweetalert2.min.js | 5 +
public/vendor/swiper/swiper-bundle.min.css | 13 +
public/vendor/swiper/swiper-bundle.min.js | 13 +
.../tinymce/5.9.1/icons/default/icons.min.js | 1 +
.../tinymce/5.9.1/jquery.tinymce.min.js | 91 +
public/vendor/tinymce/5.9.1/langs/af_ZA.js | 230 +
public/vendor/tinymce/5.9.1/langs/ar.js | 262 +
public/vendor/tinymce/5.9.1/langs/az.js | 261 +
public/vendor/tinymce/5.9.1/langs/be.js | 261 +
public/vendor/tinymce/5.9.1/langs/bg_BG.js | 261 +
public/vendor/tinymce/5.9.1/langs/bn_BD.js | 261 +
public/vendor/tinymce/5.9.1/langs/ca.js | 261 +
public/vendor/tinymce/5.9.1/langs/cs.js | 261 +
public/vendor/tinymce/5.9.1/langs/cs_CZ.js | 260 +
public/vendor/tinymce/5.9.1/langs/cy.js | 230 +
public/vendor/tinymce/5.9.1/langs/da.js | 261 +
public/vendor/tinymce/5.9.1/langs/de.js | 261 +
public/vendor/tinymce/5.9.1/langs/de_AT.js | 261 +
public/vendor/tinymce/5.9.1/langs/dv.js | 230 +
public/vendor/tinymce/5.9.1/langs/el.js | 261 +
public/vendor/tinymce/5.9.1/langs/en_CA.js | 261 +
public/vendor/tinymce/5.9.1/langs/en_GB.js | 261 +
public/vendor/tinymce/5.9.1/langs/es.js | 261 +
public/vendor/tinymce/5.9.1/langs/es_MX.js | 261 +
public/vendor/tinymce/5.9.1/langs/et.js | 261 +
public/vendor/tinymce/5.9.1/langs/eu.js | 261 +
public/vendor/tinymce/5.9.1/langs/fa_IR.js | 262 +
public/vendor/tinymce/5.9.1/langs/fi.js | 261 +
public/vendor/tinymce/5.9.1/langs/fr.js | 261 +
public/vendor/tinymce/5.9.1/langs/ga.js | 261 +
public/vendor/tinymce/5.9.1/langs/gl.js | 253 +
public/vendor/tinymce/5.9.1/langs/he_IL.js | 262 +
public/vendor/tinymce/5.9.1/langs/hr.js | 253 +
public/vendor/tinymce/5.9.1/langs/hu_HU.js | 261 +
public/vendor/tinymce/5.9.1/langs/id.js | 261 +
public/vendor/tinymce/5.9.1/langs/it.js | 261 +
public/vendor/tinymce/5.9.1/langs/ja.js | 261 +
public/vendor/tinymce/5.9.1/langs/ka_GE.js | 230 +
public/vendor/tinymce/5.9.1/langs/kab.js | 261 +
public/vendor/tinymce/5.9.1/langs/kk.js | 230 +
public/vendor/tinymce/5.9.1/langs/km_KH.js | 253 +
public/vendor/tinymce/5.9.1/langs/ko_KR.js | 261 +
public/vendor/tinymce/5.9.1/langs/lt.js | 261 +
public/vendor/tinymce/5.9.1/langs/lv.js | 260 +
public/vendor/tinymce/5.9.1/langs/nb_NO.js | 261 +
public/vendor/tinymce/5.9.1/langs/nl.js | 261 +
public/vendor/tinymce/5.9.1/langs/pl.js | 261 +
public/vendor/tinymce/5.9.1/langs/pt_BR.js | 261 +
public/vendor/tinymce/5.9.1/langs/pt_PT.js | 261 +
public/vendor/tinymce/5.9.1/langs/ro.js | 230 +
public/vendor/tinymce/5.9.1/langs/ru.js | 261 +
public/vendor/tinymce/5.9.1/langs/sk.js | 253 +
public/vendor/tinymce/5.9.1/langs/sl_SI.js | 230 +
public/vendor/tinymce/5.9.1/langs/sr.js | 261 +
public/vendor/tinymce/5.9.1/langs/sv_SE.js | 261 +
public/vendor/tinymce/5.9.1/langs/ta.js | 261 +
public/vendor/tinymce/5.9.1/langs/ta_IN.js | 261 +
public/vendor/tinymce/5.9.1/langs/th_TH.js | 261 +
public/vendor/tinymce/5.9.1/langs/tr.js | 261 +
public/vendor/tinymce/5.9.1/langs/tr_TR.js | 261 +
public/vendor/tinymce/5.9.1/langs/ug.js | 260 +
public/vendor/tinymce/5.9.1/langs/uk.js | 261 +
public/vendor/tinymce/5.9.1/langs/uk_UA.js | 261 +
public/vendor/tinymce/5.9.1/langs/uz.js | 260 +
public/vendor/tinymce/5.9.1/langs/vi_VN.js | 260 +
public/vendor/tinymce/5.9.1/langs/zh_cn.js | 261 +
public/vendor/tinymce/5.9.1/langs/zh_hk.js | 261 +
public/vendor/tinymce/5.9.1/license.txt | 504 +
.../5.9.1/plugins/advlist/plugin.min.js | 9 +
.../5.9.1/plugins/anchor/plugin.min.js | 9 +
.../5.9.1/plugins/autolink/plugin.min.js | 9 +
.../5.9.1/plugins/autoresize/plugin.min.js | 9 +
.../5.9.1/plugins/autosave/plugin.min.js | 9 +
.../5.9.1/plugins/bbcode/plugin.min.js | 9 +
.../5.9.1/plugins/charmap/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/code/plugin.min.js | 9 +
.../5.9.1/plugins/codesample/plugin.min.js | 9 +
.../5.9.1/plugins/colorpicker/plugin.min.js | 9 +
.../5.9.1/plugins/contextmenu/plugin.min.js | 9 +
.../plugins/directionality/plugin.min.js | 9 +
.../5.9.1/plugins/emoticons/js/emojiimages.js | 9424 ++++++++
.../plugins/emoticons/js/emojiimages.min.js | 3 +
.../5.9.1/plugins/emoticons/js/emojis.js | 9423 ++++++++
.../5.9.1/plugins/emoticons/js/emojis.min.js | 2 +
.../5.9.1/plugins/emoticons/plugin.min.js | 9 +
.../5.9.1/plugins/fullpage/plugin.min.js | 9 +
.../5.9.1/plugins/fullscreen/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/help/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/hr/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/image/plugin.min.js | 9 +
.../5.9.1/plugins/imagetools/plugin.min.js | 9 +
.../5.9.1/plugins/importcss/plugin.min.js | 9 +
.../plugins/insertdatetime/plugin.min.js | 9 +
.../5.9.1/plugins/legacyoutput/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/link/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/lists/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/media/plugin.min.js | 9 +
.../5.9.1/plugins/nonbreaking/plugin.min.js | 9 +
.../5.9.1/plugins/noneditable/plugin.min.js | 9 +
.../5.9.1/plugins/pagebreak/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/paste/plugin.min.js | 9 +
.../5.9.1/plugins/preview/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/print/plugin.min.js | 9 +
.../5.9.1/plugins/quickbars/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/save/plugin.min.js | 9 +
.../5.9.1/plugins/searchreplace/plugin.min.js | 9 +
.../5.9.1/plugins/spellchecker/plugin.min.js | 9 +
.../5.9.1/plugins/tabfocus/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/table/plugin.min.js | 9 +
.../5.9.1/plugins/template/plugin.min.js | 9 +
.../5.9.1/plugins/textcolor/plugin.min.js | 9 +
.../5.9.1/plugins/textpattern/plugin.min.js | 9 +
.../tinymce/5.9.1/plugins/toc/plugin.min.js | 9 +
.../5.9.1/plugins/visualblocks/plugin.min.js | 9 +
.../5.9.1/plugins/visualchars/plugin.min.js | 9 +
.../5.9.1/plugins/wordcount/plugin.min.js | 9 +
.../5.9.1/skins/content/dark/content.min.css | 7 +
.../skins/content/default/content.min.css | 7 +
.../skins/content/document/content.min.css | 7 +
.../skins/content/writer/content.min.css | 7 +
.../ui/oxide-dark/content.inline.min.css | 7 +
.../5.9.1/skins/ui/oxide-dark/content.min.css | 7 +
.../ui/oxide-dark/content.mobile.min.css | 7 +
.../ui/oxide-dark/fonts/tinymce-mobile.woff | Bin 0 -> 4624 bytes
.../5.9.1/skins/ui/oxide-dark/skin.min.css | 7 +
.../skins/ui/oxide-dark/skin.mobile.min.css | 7 +
.../ui/oxide-dark/skin.shadowdom.min.css | 7 +
.../skins/ui/oxide/content.inline.min.css | 7 +
.../5.9.1/skins/ui/oxide/content.min.css | 7 +
.../skins/ui/oxide/content.mobile.min.css | 7 +
.../skins/ui/oxide/fonts/tinymce-mobile.woff | Bin 0 -> 4624 bytes
.../tinymce/5.9.1/skins/ui/oxide/skin.min.css | 7 +
.../5.9.1/skins/ui/oxide/skin.mobile.min.css | 7 +
.../skins/ui/oxide/skin.shadowdom.min.css | 7 +
.../tinymce/5.9.1/themes/mobile/theme.min.js | 9 +
.../tinymce/5.9.1/themes/silver/theme.min.js | 9 +
public/vendor/tinymce/5.9.1/tinymce.d.ts | 3028 +++
public/vendor/tinymce/5.9.1/tinymce.min.js | 9 +
.../vendor/tinymce/tinymce-vue/tinymce-vue.js | 349 +
.../tinymce/tinymce-vue/tinymce-vue.min.js | 1 +
public/vendor/vue/2.7/vue.js | 11841 ++++++++++
public/vendor/vue/2.7/vue.min.js | 11 +
public/vendor/vue/3/vue.global.js | 15934 ++++++++++++++
public/vendor/vue/Sortable.min.js | 2 +
public/vendor/vue/batch_select.js | 100 +
public/vendor/vue/vuedraggable.js | 407 +
public/vendor/zoom/jquery.zoom.min.js | 6 +
public/web.config | 28 +
resources/beike/admin/css/_autocomplete.scss | 37 +
.../beike/admin/css/_bootstrap-extra.scss | 241 +
resources/beike/admin/css/_dashboard.scss | 2 +
resources/beike/admin/css/_form.scss | 27 +
resources/beike/admin/css/_global.scss | 465 +
resources/beike/admin/css/_header.scss | 320 +
resources/beike/admin/css/_iconfont.scss | 24 +
resources/beike/admin/css/_marketing.scss | 46 +
resources/beike/admin/css/_page-category.scss | 16 +
resources/beike/admin/css/_page-pages.scss | 73 +
resources/beike/admin/css/_page-product.scss | 244 +
resources/beike/admin/css/_page-theme.scss | 47 +
resources/beike/admin/css/_sidebar.scss | 68 +
resources/beike/admin/css/_subscription.scss | 2 +
resources/beike/admin/css/_vue.scss | 13 +
resources/beike/admin/css/app.scss | 31 +
.../admin/css/bootstrap/bootstrap-icons.scss | 3401 +++
.../beike/admin/css/bootstrap/bootstrap.scss | 102 +
resources/beike/admin/css/design/app.scss | 815 +
resources/beike/admin/css/design/menu.scss | 101 +
resources/beike/admin/css/element-ui.scss | 56 +
.../beike/admin/css/filemanager/app.scss | 373 +
resources/beike/admin/css/login.scss | 95 +
resources/beike/admin/js/app.js | 120 +
resources/beike/admin/js/autocomplete.js | 135 +
.../beike/admin/js/bootstrap-validation.js | 46 +
resources/beike/admin/js/common.js | 150 +
resources/beike/admin/js/header.js | 15 +
.../admin/views/components/alert.blade.php | 5 +
.../admin/views/components/filter.blade.php | 34 +
.../views/components/form/error.blade.php | 3 +
.../views/components/form/image.blade.php | 11 +
.../components/form/input-locale.blade.php | 16 +
.../views/components/form/input.blade.php | 17 +
.../views/components/form/rich-text.blade.php | 29 +
.../admin/views/components/form/row.blade.php | 6 +
.../views/components/form/select.blade.php | 8 +
.../components/form/switch-radio.blade.php | 13 +
.../views/components/form/textarea.blade.php | 6 +
.../admin/views/components/header.blade.php | 169 +
.../admin/views/components/no-data.blade.php | 4 +
.../admin/views/components/sidebar.blade.php | 16 +
.../beike/admin/views/errors/401.blade.php | 5 +
.../beike/admin/views/errors/403.blade.php | 15 +
.../beike/admin/views/errors/404.blade.php | 5 +
.../beike/admin/views/errors/419.blade.php | 5 +
.../beike/admin/views/errors/429.blade.php | 5 +
.../beike/admin/views/errors/500.blade.php | 13 +
.../beike/admin/views/errors/503.blade.php | 5 +
.../beike/admin/views/errors/layout.blade.php | 53 +
.../admin/views/errors/minimal.blade.php | 34 +
.../admin/views/layouts/header.blade.php | 0
.../admin/views/layouts/master.blade.php | 70 +
.../views/pages/admin_roles/edit.blade.php | 144 +
.../views/pages/admin_roles/index.blade.php | 79 +
.../views/pages/admin_users/index.blade.php | 203 +
.../pages/attribute_group/index.blade.php | 166 +
.../views/pages/attributes/form.blade.php | 223 +
.../views/pages/attributes/index.blade.php | 187 +
.../admin/views/pages/brands/index.blade.php | 194 +
.../views/pages/categories/form-vue.blade.php | 92 +
.../views/pages/categories/form.blade.php | 76 +
.../views/pages/categories/index.blade.php | 59 +
.../admin/views/pages/country/index.blade.php | 188 +
.../views/pages/currencies/index.blade.php | 185 +
.../pages/customer_groups/index.blade.php | 224 +
.../views/pages/customers/form.blade.php | 316 +
.../views/pages/customers/index.blade.php | 278 +
.../views/pages/dashboard/index.blade.php | 0
.../component/image_selector.blade.php | 195 +
.../builder/component/link_selector.blade.php | 403 +
.../component/rich_text_i18n.blade.php | 154 +
.../builder/component/text_i18n.blade.php | 99 +
.../pages/design/builder/footer.blade.php | 268 +
.../pages/design/builder/index.blade.php | 275 +
.../views/pages/design/builder/menu.blade.php | 296 +
.../views/pages/design/module/brand.blade.php | 126 +
.../views/pages/design/module/icons.blade.php | 110 +
.../pages/design/module/image100.blade.php | 78 +
.../pages/design/module/image200.blade.php | 95 +
.../pages/design/module/image300.blade.php | 103 +
.../pages/design/module/image401.blade.php | 113 +
.../pages/design/module/product.blade.php | 139 +
.../pages/design/module/rich_text.blade.php | 57 +
.../pages/design/module/slideshow.blade.php | 131 +
.../pages/design/module/tab_product.blade.php | 179 +
.../admin/views/pages/file/index.blade.php | 40 +
.../views/pages/file_manager/index.blade.php | 605 +
.../beike/admin/views/pages/home.blade.php | 307 +
.../views/pages/languages/index.blade.php | 163 +
.../admin/views/pages/login/login.blade.php | 56 +
.../views/pages/marketing/index.blade.php | 209 +
.../views/pages/marketing/show.blade.php | 231 +
.../admin/views/pages/orders/form.blade.php | 375 +
.../admin/views/pages/orders/index.blade.php | 152 +
.../pages/page_categories/form.blade.php | 131 +
.../pages/page_categories/index.blade.php | 86 +
.../admin/views/pages/pages/form.blade.php | 212 +
.../admin/views/pages/pages/index.blade.php | 86 +
.../admin/views/pages/plugins/form.blade.php | 138 +
.../admin/views/pages/plugins/index.blade.php | 97 +
.../views/pages/products/form/form.blade.php | 952 +
.../views/pages/products/index.blade.php | 282 +
.../admin/views/pages/regions/index.blade.php | 226 +
.../views/pages/rma_reasons/index.blade.php | 159 +
.../admin/views/pages/rmas/index.blade.php | 57 +
.../admin/views/pages/rmas/info.blade.php | 160 +
.../beike/admin/views/pages/setting.blade.php | 298 +
.../views/pages/tax_classes/index.blade.php | 220 +
.../views/pages/tax_rates/index.blade.php | 195 +
.../admin/views/pages/theme/index.blade.php | 72 +
.../views/pages/user/forgotten.blade.php | 161 +
.../admin/views/pages/zones/index.blade.php | 204 +
.../admin/views/shared/vue-image.blade.php | 32 +
.../vendor/pagination/bootstrap-4.blade.php | 46 +
.../views/vendor/pagination/default.blade.php | 46 +
.../vendor/pagination/semantic-ui.blade.php | 36 +
.../pagination/simple-bootstrap-4.blade.php | 27 +
.../pagination/simple-default.blade.php | 19 +
.../pagination/simple-tailwind.blade.php | 25 +
.../vendor/pagination/tailwind.blade.php | 106 +
.../shop/default/css/account/account.scss | 63 +
resources/beike/shop/default/css/app.scss | 35 +
.../css/bootstrap/bootstrap-icons.scss | 3403 +++
.../shop/default/css/bootstrap/bootstrap.scss | 167 +
resources/beike/shop/default/css/cart.scss | 100 +
.../beike/shop/default/css/element-ui.scss | 13 +
resources/beike/shop/default/css/footer.scss | 97 +
resources/beike/shop/default/css/global.scss | 324 +
resources/beike/shop/default/css/header.scss | 400 +
resources/beike/shop/default/css/home.scss | 105 +
.../beike/shop/default/css/iconfont.scss | 23 +
resources/beike/shop/default/css/login.scss | 117 +
.../shop/default/css/module/module-brand.scss | 24 +
.../default/css/module/module-image-plus.scss | 50 +
.../css/module/module-tab-product.scss | 27 +
.../shop/default/css/module/slideshow.scss | 69 +
resources/beike/shop/default/css/news.scss | 13 +
.../beike/shop/default/css/order-success.scss | 77 +
.../default/css/page-account-address.scss | 107 +
.../shop/default/css/page-account-order.scss | 113 +
.../beike/shop/default/css/page-brands.scss | 67 +
.../shop/default/css/page-categories.scss | 230 +
.../beike/shop/default/css/page-checkout.scss | 220 +
.../beike/shop/default/css/page-list.scss | 50 +
.../beike/shop/default/css/page-product.scss | 265 +
.../beike/shop/default/css/product-style.scss | 129 +
resources/beike/shop/default/js/app.js | 52 +
.../shop/default/js/bootstrap-validation.js | 28 +
resources/beike/shop/default/js/common.js | 132 +
resources/beike/shop/default/js/header.js | 93 +
resources/beike/shop/default/js/product.js | 31 +
resources/js/app.js | 9 +
resources/js/bootstrap.js | 36 +
resources/js/http.js | 99 +
resources/lang/de/address.php | 25 +
resources/lang/de/admin/admin_roles.php | 20 +
resources/lang/de/admin/attribute.php | 30 +
resources/lang/de/admin/attribute_group.php | 22 +
resources/lang/de/admin/base.php | 14 +
resources/lang/de/admin/brand.php | 21 +
resources/lang/de/admin/builder.php | 255 +
resources/lang/de/admin/category.php | 22 +
resources/lang/de/admin/common.php | 85 +
resources/lang/de/admin/country.php | 18 +
resources/lang/de/admin/currency.php | 19 +
resources/lang/de/admin/customer.php | 39 +
resources/lang/de/admin/customer_group.php | 25 +
resources/lang/de/admin/dashboard.php | 24 +
resources/lang/de/admin/design_builder.php | 21 +
resources/lang/de/admin/file_manager.php | 37 +
resources/lang/de/admin/forgotten.php | 14 +
resources/lang/de/admin/language.php | 20 +
resources/lang/de/admin/login.php | 15 +
resources/lang/de/admin/marketing.php | 25 +
resources/lang/de/admin/order.php | 26 +
resources/lang/de/admin/page.php | 22 +
resources/lang/de/admin/page_category.php | 22 +
resources/lang/de/admin/plugin.php | 35 +
resources/lang/de/admin/product.php | 47 +
resources/lang/de/admin/region.php | 23 +
resources/lang/de/admin/rma.php | 30 +
resources/lang/de/admin/rma_reason.php | 17 +
resources/lang/de/admin/role.php | 19 +
resources/lang/de/admin/setting.php | 73 +
resources/lang/de/admin/tax_class.php | 22 +
resources/lang/de/admin/tax_rate.php | 26 +
resources/lang/de/admin/theme.php | 18 +
resources/lang/de/admin/user.php | 21 +
resources/lang/de/admin/zone.php | 21 +
resources/lang/de/auth.php | 19 +
resources/lang/de/brand.php | 16 +
resources/lang/de/cart.php | 16 +
resources/lang/de/category.php | 15 +
resources/lang/de/common.php | 95 +
resources/lang/de/currency.php | 23 +
resources/lang/de/customer.php | 17 +
resources/lang/de/customer_group.php | 15 +
resources/lang/de/mail.php | 27 +
resources/lang/de/order.php | 54 +
resources/lang/de/page.php | 14 +
resources/lang/de/page_category.php | 17 +
resources/lang/de/pagination.php | 6 +
resources/lang/de/passwords.php | 9 +
resources/lang/de/product.php | 27 +
resources/lang/de/rma.php | 31 +
resources/lang/de/role.php | 14 +
resources/lang/de/shop/account.php | 138 +
resources/lang/de/shop/brands.php | 14 +
resources/lang/de/shop/carts.php | 39 +
resources/lang/de/shop/checkout.php | 40 +
resources/lang/de/shop/common.php | 19 +
resources/lang/de/shop/currency.php | 14 +
resources/lang/de/shop/file.php | 14 +
resources/lang/de/shop/forgotten.php | 33 +
resources/lang/de/shop/login.php | 40 +
resources/lang/de/shop/order.php | 18 +
resources/lang/de/shop/products.php | 21 +
resources/lang/de/shop/steps.php | 18 +
resources/lang/de/shop/wishlist.php | 15 +
resources/lang/de/user.php | 14 +
resources/lang/de/validation.php | 198 +
resources/lang/en/address.php | 25 +
resources/lang/en/admin/admin_roles.php | 21 +
resources/lang/en/admin/attribute.php | 30 +
resources/lang/en/admin/attribute_group.php | 22 +
resources/lang/en/admin/base.php | 14 +
resources/lang/en/admin/brand.php | 21 +
resources/lang/en/admin/builder.php | 253 +
resources/lang/en/admin/category.php | 22 +
resources/lang/en/admin/common.php | 90 +
resources/lang/en/admin/country.php | 18 +
resources/lang/en/admin/currency.php | 19 +
resources/lang/en/admin/customer.php | 39 +
resources/lang/en/admin/customer_group.php | 25 +
resources/lang/en/admin/dashboard.php | 24 +
resources/lang/en/admin/design_builder.php | 21 +
resources/lang/en/admin/file_manager.php | 37 +
resources/lang/en/admin/forgotten.php | 14 +
resources/lang/en/admin/language.php | 20 +
resources/lang/en/admin/login.php | 15 +
resources/lang/en/admin/marketing.php | 37 +
resources/lang/en/admin/order.php | 26 +
resources/lang/en/admin/page.php | 22 +
resources/lang/en/admin/page_category.php | 22 +
resources/lang/en/admin/plugin.php | 35 +
resources/lang/en/admin/product.php | 47 +
resources/lang/en/admin/region.php | 23 +
resources/lang/en/admin/rma.php | 30 +
resources/lang/en/admin/rma_reason.php | 20 +
resources/lang/en/admin/role.php | 19 +
resources/lang/en/admin/setting.php | 74 +
resources/lang/en/admin/tax_class.php | 22 +
resources/lang/en/admin/tax_rate.php | 26 +
resources/lang/en/admin/theme.php | 18 +
resources/lang/en/admin/user.php | 21 +
resources/lang/en/admin/zone.php | 21 +
resources/lang/en/auth.php | 20 +
resources/lang/en/brand.php | 16 +
resources/lang/en/cart.php | 16 +
resources/lang/en/category.php | 15 +
resources/lang/en/common.php | 96 +
resources/lang/en/currency.php | 22 +
resources/lang/en/customer.php | 19 +
resources/lang/en/customer_group.php | 15 +
resources/lang/en/mail.php | 27 +
resources/lang/en/order.php | 54 +
resources/lang/en/page.php | 14 +
resources/lang/en/page_category.php | 18 +
resources/lang/en/pagination.php | 19 +
resources/lang/en/passwords.php | 22 +
resources/lang/en/product.php | 27 +
resources/lang/en/rma.php | 31 +
resources/lang/en/role.php | 14 +
resources/lang/en/shop/account.php | 138 +
resources/lang/en/shop/brands.php | 14 +
resources/lang/en/shop/carts.php | 40 +
resources/lang/en/shop/checkout.php | 40 +
resources/lang/en/shop/common.php | 19 +
resources/lang/en/shop/currency.php | 14 +
resources/lang/en/shop/file.php | 14 +
resources/lang/en/shop/forgotten.php | 33 +
resources/lang/en/shop/login.php | 40 +
resources/lang/en/shop/order.php | 18 +
resources/lang/en/shop/products.php | 21 +
resources/lang/en/shop/steps.php | 18 +
resources/lang/en/shop/wishlist.php | 15 +
resources/lang/en/user.php | 14 +
resources/lang/en/validation.php | 169 +
resources/lang/es/address.php | 25 +
resources/lang/es/admin/admin_roles.php | 20 +
resources/lang/es/admin/attribute.php | 30 +
resources/lang/es/admin/attribute_group.php | 22 +
resources/lang/es/admin/base.php | 14 +
resources/lang/es/admin/brand.php | 21 +
resources/lang/es/admin/builder.php | 255 +
resources/lang/es/admin/category.php | 22 +
resources/lang/es/admin/common.php | 85 +
resources/lang/es/admin/country.php | 18 +
resources/lang/es/admin/currency.php | 19 +
resources/lang/es/admin/customer.php | 39 +
resources/lang/es/admin/customer_group.php | 25 +
resources/lang/es/admin/dashboard.php | 24 +
resources/lang/es/admin/design_builder.php | 21 +
resources/lang/es/admin/file_manager.php | 37 +
resources/lang/es/admin/forgotten.php | 14 +
resources/lang/es/admin/language.php | 20 +
resources/lang/es/admin/login.php | 15 +
resources/lang/es/admin/marketing.php | 25 +
resources/lang/es/admin/order.php | 26 +
resources/lang/es/admin/order_shipping.php | 332 +
resources/lang/es/admin/page.php | 22 +
resources/lang/es/admin/page_category.php | 22 +
resources/lang/es/admin/plugin.php | 35 +
resources/lang/es/admin/product.php | 47 +
resources/lang/es/admin/region.php | 23 +
resources/lang/es/admin/rma.php | 30 +
resources/lang/es/admin/rma_reason.php | 17 +
resources/lang/es/admin/role.php | 19 +
resources/lang/es/admin/setting.php | 74 +
resources/lang/es/admin/tax_class.php | 22 +
resources/lang/es/admin/tax_rate.php | 26 +
resources/lang/es/admin/theme.php | 18 +
resources/lang/es/admin/user.php | 21 +
resources/lang/es/admin/zone.php | 21 +
resources/lang/es/auth.php | 19 +
resources/lang/es/brand.php | 16 +
resources/lang/es/cart.php | 16 +
resources/lang/es/category.php | 15 +
resources/lang/es/common.php | 95 +
resources/lang/es/currency.php | 23 +
resources/lang/es/customer.php | 17 +
resources/lang/es/customer_group.php | 15 +
resources/lang/es/mail.php | 27 +
resources/lang/es/order.php | 54 +
resources/lang/es/page.php | 14 +
resources/lang/es/page_category.php | 17 +
resources/lang/es/pagination.php | 6 +
resources/lang/es/passwords.php | 9 +
resources/lang/es/product.php | 27 +
resources/lang/es/rma.php | 31 +
resources/lang/es/role.php | 14 +
resources/lang/es/shop/account.php | 138 +
resources/lang/es/shop/brands.php | 14 +
resources/lang/es/shop/carts.php | 39 +
resources/lang/es/shop/checkout.php | 40 +
resources/lang/es/shop/common.php | 19 +
resources/lang/es/shop/currency.php | 14 +
resources/lang/es/shop/file.php | 14 +
resources/lang/es/shop/forgotten.php | 33 +
resources/lang/es/shop/login.php | 40 +
resources/lang/es/shop/order.php | 18 +
resources/lang/es/shop/products.php | 21 +
resources/lang/es/shop/steps.php | 18 +
resources/lang/es/shop/wishlist.php | 15 +
resources/lang/es/user.php | 14 +
resources/lang/es/validation.php | 194 +
resources/lang/fr/address.php | 25 +
resources/lang/fr/admin/admin_roles.php | 20 +
resources/lang/fr/admin/attribute.php | 30 +
resources/lang/fr/admin/attribute_group.php | 22 +
resources/lang/fr/admin/base.php | 14 +
resources/lang/fr/admin/brand.php | 21 +
resources/lang/fr/admin/builder.php | 255 +
resources/lang/fr/admin/category.php | 22 +
resources/lang/fr/admin/common.php | 85 +
resources/lang/fr/admin/country.php | 18 +
resources/lang/fr/admin/currency.php | 19 +
resources/lang/fr/admin/customer.php | 39 +
resources/lang/fr/admin/customer_group.php | 25 +
resources/lang/fr/admin/dashboard.php | 24 +
resources/lang/fr/admin/design_builder.php | 21 +
resources/lang/fr/admin/file_manager.php | 37 +
resources/lang/fr/admin/forgotten.php | 14 +
resources/lang/fr/admin/language.php | 20 +
resources/lang/fr/admin/login.php | 15 +
resources/lang/fr/admin/marketing.php | 25 +
resources/lang/fr/admin/order.php | 26 +
resources/lang/fr/admin/page.php | 22 +
resources/lang/fr/admin/page_category.php | 22 +
resources/lang/fr/admin/plugin.php | 35 +
resources/lang/fr/admin/product.php | 47 +
resources/lang/fr/admin/region.php | 23 +
resources/lang/fr/admin/rma.php | 30 +
resources/lang/fr/admin/rma_reason.php | 17 +
resources/lang/fr/admin/role.php | 19 +
resources/lang/fr/admin/setting.php | 73 +
resources/lang/fr/admin/tax_class.php | 22 +
resources/lang/fr/admin/tax_rate.php | 26 +
resources/lang/fr/admin/theme.php | 18 +
resources/lang/fr/admin/user.php | 21 +
resources/lang/fr/admin/zone.php | 21 +
resources/lang/fr/auth.php | 7 +
resources/lang/fr/brand.php | 16 +
resources/lang/fr/cart.php | 16 +
resources/lang/fr/category.php | 15 +
resources/lang/fr/common.php | 95 +
resources/lang/fr/currency.php | 23 +
resources/lang/fr/customer.php | 17 +
resources/lang/fr/customer_group.php | 15 +
resources/lang/fr/mail.php | 27 +
resources/lang/fr/order.php | 54 +
resources/lang/fr/page.php | 14 +
resources/lang/fr/page_category.php | 16 +
resources/lang/fr/pagination.php | 6 +
resources/lang/fr/passwords.php | 9 +
resources/lang/fr/product.php | 27 +
resources/lang/fr/rma.php | 31 +
resources/lang/fr/role.php | 14 +
resources/lang/fr/shop/account.php | 138 +
resources/lang/fr/shop/brands.php | 14 +
resources/lang/fr/shop/carts.php | 39 +
resources/lang/fr/shop/checkout.php | 40 +
resources/lang/fr/shop/common.php | 19 +
resources/lang/fr/shop/currency.php | 14 +
resources/lang/fr/shop/file.php | 14 +
resources/lang/fr/shop/forgotten.php | 33 +
resources/lang/fr/shop/login.php | 40 +
resources/lang/fr/shop/order.php | 18 +
resources/lang/fr/shop/products.php | 21 +
resources/lang/fr/shop/steps.php | 18 +
resources/lang/fr/shop/wishlist.php | 15 +
resources/lang/fr/user.php | 14 +
resources/lang/fr/validation.php | 198 +
resources/lang/it/address.php | 25 +
resources/lang/it/admin/admin_roles.php | 19 +
resources/lang/it/admin/attribute.php | 30 +
resources/lang/it/admin/attribute_group.php | 22 +
resources/lang/it/admin/base.php | 14 +
resources/lang/it/admin/brand.php | 21 +
resources/lang/it/admin/builder.php | 255 +
resources/lang/it/admin/category.php | 22 +
resources/lang/it/admin/common.php | 85 +
resources/lang/it/admin/country.php | 18 +
resources/lang/it/admin/currency.php | 19 +
resources/lang/it/admin/customer.php | 39 +
resources/lang/it/admin/customer_group.php | 25 +
resources/lang/it/admin/dashboard.php | 24 +
resources/lang/it/admin/design_builder.php | 21 +
resources/lang/it/admin/file_manager.php | 37 +
resources/lang/it/admin/forgotten.php | 14 +
resources/lang/it/admin/language.php | 20 +
resources/lang/it/admin/login.php | 15 +
resources/lang/it/admin/marketing.php | 25 +
resources/lang/it/admin/order.php | 26 +
resources/lang/it/admin/page.php | 22 +
resources/lang/it/admin/page_category.php | 22 +
resources/lang/it/admin/plugin.php | 35 +
resources/lang/it/admin/product.php | 47 +
resources/lang/it/admin/region.php | 23 +
resources/lang/it/admin/rma.php | 30 +
resources/lang/it/admin/rma_reason.php | 17 +
resources/lang/it/admin/role.php | 19 +
resources/lang/it/admin/setting.php | 73 +
resources/lang/it/admin/tax_class.php | 22 +
resources/lang/it/admin/tax_rate.php | 26 +
resources/lang/it/admin/theme.php | 18 +
resources/lang/it/admin/user.php | 21 +
resources/lang/it/admin/zone.php | 21 +
resources/lang/it/auth.php | 7 +
resources/lang/it/brand.php | 16 +
resources/lang/it/cart.php | 16 +
resources/lang/it/category.php | 15 +
resources/lang/it/common.php | 95 +
resources/lang/it/currency.php | 23 +
resources/lang/it/customer.php | 17 +
resources/lang/it/customer_group.php | 15 +
resources/lang/it/mail.php | 27 +
resources/lang/it/order.php | 54 +
resources/lang/it/page.php | 14 +
resources/lang/it/page_category.php | 18 +
resources/lang/it/pagination.php | 6 +
resources/lang/it/passwords.php | 9 +
resources/lang/it/product.php | 27 +
resources/lang/it/rma.php | 31 +
resources/lang/it/role.php | 14 +
resources/lang/it/shop/account.php | 138 +
resources/lang/it/shop/brands.php | 14 +
resources/lang/it/shop/carts.php | 39 +
resources/lang/it/shop/checkout.php | 40 +
resources/lang/it/shop/common.php | 19 +
resources/lang/it/shop/currency.php | 14 +
resources/lang/it/shop/file.php | 14 +
resources/lang/it/shop/forgotten.php | 33 +
resources/lang/it/shop/login.php | 40 +
resources/lang/it/shop/order.php | 18 +
resources/lang/it/shop/products.php | 21 +
resources/lang/it/shop/steps.php | 18 +
resources/lang/it/shop/wishlist.php | 15 +
resources/lang/it/user.php | 14 +
resources/lang/it/validation.php | 198 +
resources/lang/ja/address.php | 25 +
resources/lang/ja/admin/admin_roles.php | 20 +
resources/lang/ja/admin/attribute.php | 30 +
resources/lang/ja/admin/attribute_group.php | 22 +
resources/lang/ja/admin/base.php | 14 +
resources/lang/ja/admin/brand.php | 21 +
resources/lang/ja/admin/builder.php | 255 +
resources/lang/ja/admin/category.php | 22 +
resources/lang/ja/admin/common.php | 85 +
resources/lang/ja/admin/country.php | 18 +
resources/lang/ja/admin/currency.php | 19 +
resources/lang/ja/admin/customer.php | 39 +
resources/lang/ja/admin/customer_group.php | 25 +
resources/lang/ja/admin/dashboard.php | 24 +
resources/lang/ja/admin/design_builder.php | 21 +
resources/lang/ja/admin/file_manager.php | 37 +
resources/lang/ja/admin/forgotten.php | 14 +
resources/lang/ja/admin/language.php | 20 +
resources/lang/ja/admin/login.php | 15 +
resources/lang/ja/admin/marketing.php | 25 +
resources/lang/ja/admin/order.php | 26 +
resources/lang/ja/admin/page.php | 22 +
resources/lang/ja/admin/page_category.php | 22 +
resources/lang/ja/admin/plugin.php | 35 +
resources/lang/ja/admin/product.php | 47 +
resources/lang/ja/admin/region.php | 23 +
resources/lang/ja/admin/rma.php | 30 +
resources/lang/ja/admin/rma_reason.php | 17 +
resources/lang/ja/admin/role.php | 19 +
resources/lang/ja/admin/setting.php | 73 +
resources/lang/ja/admin/tax_class.php | 22 +
resources/lang/ja/admin/tax_rate.php | 26 +
resources/lang/ja/admin/theme.php | 18 +
resources/lang/ja/admin/user.php | 21 +
resources/lang/ja/admin/zone.php | 21 +
resources/lang/ja/auth.php | 20 +
resources/lang/ja/brand.php | 16 +
resources/lang/ja/cart.php | 16 +
resources/lang/ja/category.php | 15 +
resources/lang/ja/common.php | 95 +
resources/lang/ja/currency.php | 23 +
resources/lang/ja/customer.php | 17 +
resources/lang/ja/customer_group.php | 15 +
resources/lang/ja/mail.php | 27 +
resources/lang/ja/order.php | 54 +
resources/lang/ja/page.php | 14 +
resources/lang/ja/page_category.php | 17 +
resources/lang/ja/pagination.php | 6 +
resources/lang/ja/passwords.php | 9 +
resources/lang/ja/product.php | 27 +
resources/lang/ja/rma.php | 31 +
resources/lang/ja/role.php | 14 +
resources/lang/ja/shop/account.php | 138 +
resources/lang/ja/shop/brands.php | 14 +
resources/lang/ja/shop/carts.php | 39 +
resources/lang/ja/shop/checkout.php | 40 +
resources/lang/ja/shop/common.php | 19 +
resources/lang/ja/shop/currency.php | 14 +
resources/lang/ja/shop/file.php | 14 +
resources/lang/ja/shop/forgotten.php | 33 +
resources/lang/ja/shop/login.php | 40 +
resources/lang/ja/shop/order.php | 18 +
resources/lang/ja/shop/products.php | 21 +
resources/lang/ja/shop/steps.php | 18 +
resources/lang/ja/shop/wishlist.php | 15 +
resources/lang/ja/user.php | 14 +
resources/lang/ja/validation.php | 198 +
resources/lang/ru/address.php | 25 +
resources/lang/ru/admin/admin_roles.php | 20 +
resources/lang/ru/admin/attribute.php | 30 +
resources/lang/ru/admin/attribute_group.php | 22 +
resources/lang/ru/admin/base.php | 14 +
resources/lang/ru/admin/brand.php | 21 +
resources/lang/ru/admin/builder.php | 256 +
resources/lang/ru/admin/category.php | 22 +
resources/lang/ru/admin/common.php | 85 +
resources/lang/ru/admin/country.php | 18 +
resources/lang/ru/admin/currency.php | 19 +
resources/lang/ru/admin/customer.php | 39 +
resources/lang/ru/admin/customer_group.php | 25 +
resources/lang/ru/admin/dashboard.php | 24 +
resources/lang/ru/admin/design_builder.php | 21 +
resources/lang/ru/admin/file_manager.php | 37 +
resources/lang/ru/admin/forgotten.php | 14 +
resources/lang/ru/admin/language.php | 20 +
resources/lang/ru/admin/login.php | 15 +
resources/lang/ru/admin/marketing.php | 25 +
resources/lang/ru/admin/order.php | 26 +
resources/lang/ru/admin/page.php | 22 +
resources/lang/ru/admin/page_category.php | 22 +
resources/lang/ru/admin/plugin.php | 35 +
resources/lang/ru/admin/product.php | 47 +
resources/lang/ru/admin/region.php | 23 +
resources/lang/ru/admin/rma.php | 30 +
resources/lang/ru/admin/rma_reason.php | 17 +
resources/lang/ru/admin/role.php | 19 +
resources/lang/ru/admin/setting.php | 73 +
resources/lang/ru/admin/tax_class.php | 22 +
resources/lang/ru/admin/tax_rate.php | 26 +
resources/lang/ru/admin/theme.php | 18 +
resources/lang/ru/admin/user.php | 21 +
resources/lang/ru/admin/zone.php | 21 +
resources/lang/ru/auth.php | 7 +
resources/lang/ru/brand.php | 16 +
resources/lang/ru/cart.php | 16 +
resources/lang/ru/category.php | 15 +
resources/lang/ru/common.php | 95 +
resources/lang/ru/currency.php | 23 +
resources/lang/ru/customer.php | 17 +
resources/lang/ru/customer_group.php | 15 +
resources/lang/ru/mail.php | 27 +
resources/lang/ru/order.php | 54 +
resources/lang/ru/page.php | 14 +
resources/lang/ru/page_category.php | 17 +
resources/lang/ru/pagination.php | 6 +
resources/lang/ru/passwords.php | 9 +
resources/lang/ru/product.php | 27 +
resources/lang/ru/rma.php | 31 +
resources/lang/ru/role.php | 14 +
resources/lang/ru/shop/account.php | 138 +
resources/lang/ru/shop/brands.php | 14 +
resources/lang/ru/shop/carts.php | 39 +
resources/lang/ru/shop/checkout.php | 40 +
resources/lang/ru/shop/common.php | 19 +
resources/lang/ru/shop/currency.php | 14 +
resources/lang/ru/shop/file.php | 14 +
resources/lang/ru/shop/forgotten.php | 33 +
resources/lang/ru/shop/login.php | 40 +
resources/lang/ru/shop/order.php | 18 +
resources/lang/ru/shop/products.php | 21 +
resources/lang/ru/shop/steps.php | 18 +
resources/lang/ru/shop/wishlist.php | 15 +
resources/lang/ru/user.php | 14 +
resources/lang/ru/validation.php | 198 +
resources/lang/zh_cn/address.php | 25 +
resources/lang/zh_cn/admin/admin_roles.php | 21 +
resources/lang/zh_cn/admin/attribute.php | 30 +
.../lang/zh_cn/admin/attribute_group.php | 22 +
resources/lang/zh_cn/admin/base.php | 14 +
resources/lang/zh_cn/admin/brand.php | 21 +
resources/lang/zh_cn/admin/builder.php | 255 +
resources/lang/zh_cn/admin/category.php | 22 +
resources/lang/zh_cn/admin/common.php | 90 +
resources/lang/zh_cn/admin/country.php | 18 +
resources/lang/zh_cn/admin/currency.php | 19 +
resources/lang/zh_cn/admin/customer.php | 39 +
resources/lang/zh_cn/admin/customer_group.php | 25 +
resources/lang/zh_cn/admin/dashboard.php | 24 +
resources/lang/zh_cn/admin/design_builder.php | 21 +
resources/lang/zh_cn/admin/file_manager.php | 37 +
resources/lang/zh_cn/admin/forgotten.php | 14 +
resources/lang/zh_cn/admin/language.php | 20 +
resources/lang/zh_cn/admin/login.php | 15 +
resources/lang/zh_cn/admin/marketing.php | 37 +
resources/lang/zh_cn/admin/order.php | 26 +
resources/lang/zh_cn/admin/page.php | 22 +
resources/lang/zh_cn/admin/page_category.php | 22 +
resources/lang/zh_cn/admin/plugin.php | 35 +
resources/lang/zh_cn/admin/product.php | 47 +
resources/lang/zh_cn/admin/region.php | 23 +
resources/lang/zh_cn/admin/rma.php | 30 +
resources/lang/zh_cn/admin/rma_reason.php | 17 +
resources/lang/zh_cn/admin/role.php | 19 +
resources/lang/zh_cn/admin/setting.php | 72 +
resources/lang/zh_cn/admin/tax_class.php | 22 +
resources/lang/zh_cn/admin/tax_rate.php | 26 +
resources/lang/zh_cn/admin/theme.php | 18 +
resources/lang/zh_cn/admin/user.php | 21 +
resources/lang/zh_cn/admin/zone.php | 21 +
resources/lang/zh_cn/auth.php | 20 +
resources/lang/zh_cn/brand.php | 16 +
resources/lang/zh_cn/cart.php | 16 +
resources/lang/zh_cn/category.php | 15 +
resources/lang/zh_cn/common.php | 95 +
resources/lang/zh_cn/currency.php | 23 +
resources/lang/zh_cn/customer.php | 17 +
resources/lang/zh_cn/customer_group.php | 15 +
resources/lang/zh_cn/mail.php | 27 +
resources/lang/zh_cn/order.php | 55 +
resources/lang/zh_cn/page.php | 14 +
resources/lang/zh_cn/page_category.php | 17 +
resources/lang/zh_cn/pagination.php | 19 +
resources/lang/zh_cn/passwords.php | 22 +
resources/lang/zh_cn/product.php | 27 +
resources/lang/zh_cn/rma.php | 31 +
resources/lang/zh_cn/role.php | 14 +
resources/lang/zh_cn/shop/account.php | 138 +
resources/lang/zh_cn/shop/brands.php | 14 +
resources/lang/zh_cn/shop/carts.php | 40 +
resources/lang/zh_cn/shop/checkout.php | 40 +
resources/lang/zh_cn/shop/common.php | 19 +
resources/lang/zh_cn/shop/currency.php | 14 +
resources/lang/zh_cn/shop/file.php | 14 +
resources/lang/zh_cn/shop/forgotten.php | 33 +
resources/lang/zh_cn/shop/login.php | 40 +
resources/lang/zh_cn/shop/order.php | 18 +
resources/lang/zh_cn/shop/products.php | 21 +
resources/lang/zh_cn/shop/steps.php | 18 +
resources/lang/zh_cn/shop/wishlist.php | 15 +
resources/lang/zh_cn/user.php | 14 +
resources/lang/zh_cn/validation.php | 169 +
resources/lang/zh_hk/address.php | 25 +
resources/lang/zh_hk/admin/admin_roles.php | 20 +
resources/lang/zh_hk/admin/attribute.php | 30 +
.../lang/zh_hk/admin/attribute_group.php | 22 +
resources/lang/zh_hk/admin/base.php | 14 +
resources/lang/zh_hk/admin/brand.php | 21 +
resources/lang/zh_hk/admin/builder.php | 255 +
resources/lang/zh_hk/admin/category.php | 22 +
resources/lang/zh_hk/admin/common.php | 90 +
resources/lang/zh_hk/admin/country.php | 18 +
resources/lang/zh_hk/admin/currency.php | 19 +
resources/lang/zh_hk/admin/customer.php | 39 +
resources/lang/zh_hk/admin/customer_group.php | 25 +
resources/lang/zh_hk/admin/dashboard.php | 24 +
resources/lang/zh_hk/admin/design_builder.php | 21 +
resources/lang/zh_hk/admin/file_manager.php | 37 +
resources/lang/zh_hk/admin/forgotten.php | 14 +
resources/lang/zh_hk/admin/language.php | 20 +
resources/lang/zh_hk/admin/login.php | 15 +
resources/lang/zh_hk/admin/marketing.php | 37 +
resources/lang/zh_hk/admin/order.php | 26 +
resources/lang/zh_hk/admin/page.php | 22 +
resources/lang/zh_hk/admin/page_category.php | 22 +
resources/lang/zh_hk/admin/plugin.php | 35 +
resources/lang/zh_hk/admin/product.php | 47 +
resources/lang/zh_hk/admin/region.php | 23 +
resources/lang/zh_hk/admin/rma.php | 30 +
resources/lang/zh_hk/admin/rma_reason.php | 17 +
resources/lang/zh_hk/admin/role.php | 19 +
resources/lang/zh_hk/admin/setting.php | 73 +
resources/lang/zh_hk/admin/tax_class.php | 22 +
resources/lang/zh_hk/admin/tax_rate.php | 26 +
resources/lang/zh_hk/admin/theme.php | 18 +
resources/lang/zh_hk/admin/user.php | 21 +
resources/lang/zh_hk/admin/zone.php | 21 +
resources/lang/zh_hk/auth.php | 7 +
resources/lang/zh_hk/brand.php | 16 +
resources/lang/zh_hk/cart.php | 16 +
resources/lang/zh_hk/category.php | 15 +
resources/lang/zh_hk/common.php | 95 +
resources/lang/zh_hk/currency.php | 23 +
resources/lang/zh_hk/customer.php | 17 +
resources/lang/zh_hk/customer_group.php | 15 +
resources/lang/zh_hk/mail.php | 26 +
resources/lang/zh_hk/order.php | 53 +
resources/lang/zh_hk/page.php | 14 +
resources/lang/zh_hk/page_category.php | 17 +
resources/lang/zh_hk/pagination.php | 6 +
resources/lang/zh_hk/passwords.php | 9 +
resources/lang/zh_hk/product.php | 27 +
resources/lang/zh_hk/rma.php | 31 +
resources/lang/zh_hk/role.php | 14 +
resources/lang/zh_hk/shop/account.php | 137 +
resources/lang/zh_hk/shop/brands.php | 14 +
resources/lang/zh_hk/shop/carts.php | 39 +
resources/lang/zh_hk/shop/checkout.php | 40 +
resources/lang/zh_hk/shop/common.php | 19 +
resources/lang/zh_hk/shop/currency.php | 14 +
resources/lang/zh_hk/shop/file.php | 14 +
resources/lang/zh_hk/shop/forgotten.php | 33 +
resources/lang/zh_hk/shop/login.php | 40 +
resources/lang/zh_hk/shop/order.php | 18 +
resources/lang/zh_hk/shop/products.php | 21 +
resources/lang/zh_hk/shop/steps.php | 18 +
resources/lang/zh_hk/shop/wishlist.php | 15 +
resources/lang/zh_hk/user.php | 14 +
resources/lang/zh_hk/validation.php | 198 +
.../views/vendor/sitemap/google-news.php | 48 +
resources/views/vendor/sitemap/html.php | 17 +
resources/views/vendor/sitemap/ror-rdf.php | 18 +
resources/views/vendor/sitemap/ror-rss.php | 17 +
.../views/vendor/sitemap/sitemapindex.php | 14 +
resources/views/vendor/sitemap/txt.php | 5 +
resources/views/vendor/sitemap/xml-mobile.php | 12 +
resources/views/vendor/sitemap/xml.php | 118 +
.../views/vendor/unisharp/markdown.blade.php | 27 +
routes/api.php | 19 +
routes/channels.php | 18 +
routes/console.php | 19 +
routes/web.php | 7 +
server.php | 21 +
storage/app/.gitignore | 3 +
storage/debugbar/.gitignore | 2 +
storage/framework/.gitignore | 9 +
storage/framework/cache/.gitignore | 3 +
storage/framework/sessions/.gitignore | 2 +
storage/framework/testing/.gitignore | 2 +
storage/framework/views/.gitignore | 2 +
storage/installed | 1 +
storage/logs/.gitignore | 2 +
storage/upload/.gitignore | 2 +
tests/CreatesApplication.php | 22 +
tests/Feature/ExampleTest.php | 20 +
tests/TestCase.php | 10 +
tests/Unit/ExampleTest.php | 18 +
webpack.mix.js | 64 +
1464 files changed, 224942 insertions(+)
create mode 100644 .editorconfig
create mode 100644 .env
create mode 100644 .htaccess
create mode 100644 .styleci.yml
create mode 100644 404.html
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 app/Console/Kernel.php
create mode 100644 app/Exceptions/Handler.php
create mode 100644 app/Exceptions/RegisterAdminErrorViewPaths.php
create mode 100644 app/Http/Controllers/Controller.php
create mode 100644 app/Http/Kernel.php
create mode 100644 app/Http/Middleware/Authenticate.php
create mode 100644 app/Http/Middleware/CheckoutAuthenticate.php
create mode 100644 app/Http/Middleware/EncryptCookies.php
create mode 100644 app/Http/Middleware/PreventRequestsDuringMaintenance.php
create mode 100644 app/Http/Middleware/RedirectIfAuthenticated.php
create mode 100644 app/Http/Middleware/SetLocaleAdmin.php
create mode 100644 app/Http/Middleware/SetLocaleFromSession.php
create mode 100644 app/Http/Middleware/SetLocaleInstaller.php
create mode 100644 app/Http/Middleware/ShareViewData.php
create mode 100644 app/Http/Middleware/ShopAuthenticate.php
create mode 100644 app/Http/Middleware/TrimStrings.php
create mode 100644 app/Http/Middleware/TrustHosts.php
create mode 100644 app/Http/Middleware/TrustProxies.php
create mode 100644 app/Http/Middleware/VerifyCsrfToken.php
create mode 100644 app/Http/Requests/ContactRequest.php
create mode 100644 app/Providers/AppServiceProvider.php
create mode 100644 app/Providers/AuthServiceProvider.php
create mode 100644 app/Providers/BroadcastServiceProvider.php
create mode 100644 app/Providers/EventServiceProvider.php
create mode 100644 app/Providers/HorizonServiceProvider.php
create mode 100644 app/Providers/RouteServiceProvider.php
create mode 100644 artisan
create mode 100644 beike/Admin/Database/Seeders/ProductSeeder.php
create mode 100644 beike/Admin/Http/Controllers/AddressController.php
create mode 100644 beike/Admin/Http/Controllers/AdminRoleController.php
create mode 100644 beike/Admin/Http/Controllers/AdminUserController.php
create mode 100644 beike/Admin/Http/Controllers/AttributeController.php
create mode 100644 beike/Admin/Http/Controllers/AttributeGroupController.php
create mode 100644 beike/Admin/Http/Controllers/BrandController.php
create mode 100644 beike/Admin/Http/Controllers/CategoryController.php
create mode 100644 beike/Admin/Http/Controllers/Controller.php
create mode 100644 beike/Admin/Http/Controllers/CountryController.php
create mode 100644 beike/Admin/Http/Controllers/CurrencyController.php
create mode 100644 beike/Admin/Http/Controllers/CustomerController.php
create mode 100644 beike/Admin/Http/Controllers/CustomerGroupController.php
create mode 100644 beike/Admin/Http/Controllers/DesignController.php
create mode 100644 beike/Admin/Http/Controllers/DesignFooterController.php
create mode 100644 beike/Admin/Http/Controllers/DesignMenuController.php
create mode 100644 beike/Admin/Http/Controllers/EditController.php
create mode 100644 beike/Admin/Http/Controllers/FileManagerController.php
create mode 100644 beike/Admin/Http/Controllers/ForgottenController.php
create mode 100644 beike/Admin/Http/Controllers/HomeController.php
create mode 100644 beike/Admin/Http/Controllers/LanguageController.php
create mode 100644 beike/Admin/Http/Controllers/LoginController.php
create mode 100644 beike/Admin/Http/Controllers/LogoutController.php
create mode 100644 beike/Admin/Http/Controllers/MarketingController.php
create mode 100644 beike/Admin/Http/Controllers/OrderController.php
create mode 100644 beike/Admin/Http/Controllers/PageCategoryController.php
create mode 100644 beike/Admin/Http/Controllers/PagesController.php
create mode 100644 beike/Admin/Http/Controllers/PluginController.php
create mode 100644 beike/Admin/Http/Controllers/ProductController.php
create mode 100644 beike/Admin/Http/Controllers/RegionController.php
create mode 100644 beike/Admin/Http/Controllers/RmaController.php
create mode 100644 beike/Admin/Http/Controllers/RmaReasonController.php
create mode 100644 beike/Admin/Http/Controllers/SettingController.php
create mode 100644 beike/Admin/Http/Controllers/TaxClassController.php
create mode 100644 beike/Admin/Http/Controllers/TaxRateController.php
create mode 100644 beike/Admin/Http/Controllers/ThemeController.php
create mode 100644 beike/Admin/Http/Controllers/ZoneController.php
create mode 100644 beike/Admin/Http/Requests/AdminRoleRequest.php
create mode 100644 beike/Admin/Http/Requests/AdminUserRequest.php
create mode 100644 beike/Admin/Http/Requests/CategoryRequest.php
create mode 100644 beike/Admin/Http/Requests/CurrencyRequest.php
create mode 100644 beike/Admin/Http/Requests/CustomerGroupRequest.php
create mode 100644 beike/Admin/Http/Requests/CustomerRequest.php
create mode 100644 beike/Admin/Http/Requests/ForgottenRequest.php
create mode 100644 beike/Admin/Http/Requests/LoginRequest.php
create mode 100644 beike/Admin/Http/Requests/PageCategoryRequest.php
create mode 100644 beike/Admin/Http/Requests/PageRequest.php
create mode 100644 beike/Admin/Http/Requests/ProductRequest.php
create mode 100644 beike/Admin/Http/Requests/RmaRequest.php
create mode 100644 beike/Admin/Http/Requests/TaxRateRequest.php
create mode 100644 beike/Admin/Http/Requests/UploadRequest.php
create mode 100644 beike/Admin/Http/Requests/VerifyCodeRequest.php
create mode 100644 beike/Admin/Http/Resources/AddressResource.php
create mode 100644 beike/Admin/Http/Resources/AdminUserDetail.php
create mode 100644 beike/Admin/Http/Resources/AttributeDetailResource.php
create mode 100644 beike/Admin/Http/Resources/AttributeResource.php
create mode 100644 beike/Admin/Http/Resources/AttributeValueResource.php
create mode 100644 beike/Admin/Http/Resources/AutocompleteResource.php
create mode 100644 beike/Admin/Http/Resources/CategoryResource.php
create mode 100644 beike/Admin/Http/Resources/CustomerGroupDetail.php
create mode 100644 beike/Admin/Http/Resources/CustomerResource.php
create mode 100644 beike/Admin/Http/Resources/OrderSimple.php
create mode 100644 beike/Admin/Http/Resources/PageCategoryResource.php
create mode 100644 beike/Admin/Http/Resources/PluginResource.php
create mode 100644 beike/Admin/Http/Resources/ProductAttributeResource.php
create mode 100644 beike/Admin/Http/Resources/ProductResource.php
create mode 100644 beike/Admin/Http/Resources/RmaDetail.php
create mode 100644 beike/Admin/Http/Resources/RmaHistoryDetail.php
create mode 100644 beike/Admin/Http/Resources/RmaReasonDetail.php
create mode 100644 beike/Admin/Http/Resources/TaxClassDetail.php
create mode 100644 beike/Admin/Providers/AdminServiceProvider.php
create mode 100644 beike/Admin/Repositories/AdminRoleRepo.php
create mode 100644 beike/Admin/Repositories/AdminUserRepo.php
create mode 100644 beike/Admin/Repositories/AttributeGroupRepo.php
create mode 100644 beike/Admin/Repositories/AttributeRepo.php
create mode 100644 beike/Admin/Repositories/DashboardRepo.php
create mode 100644 beike/Admin/Repositories/PageRepo.php
create mode 100644 beike/Admin/Repositories/PermissionRepo.php
create mode 100644 beike/Admin/Repositories/RegionRepo.php
create mode 100644 beike/Admin/Repositories/Report/OrderReportRepo.php
create mode 100644 beike/Admin/Repositories/TaxClassRepo.php
create mode 100644 beike/Admin/Repositories/TaxRateRepo.php
create mode 100644 beike/Admin/Routes/admin.php
create mode 100644 beike/Admin/Services/AddressService.php
create mode 100644 beike/Admin/Services/CategoryService.php
create mode 100644 beike/Admin/Services/CustomerGroupService.php
create mode 100644 beike/Admin/Services/CustomerService.php
create mode 100644 beike/Admin/Services/FileManagerService.php
create mode 100644 beike/Admin/Services/LanguageService.php
create mode 100644 beike/Admin/Services/MarketingService.php
create mode 100644 beike/Admin/Services/ProductService.php
create mode 100644 beike/Admin/Services/UserService.php
create mode 100644 beike/Admin/View/Components/Alert.php
create mode 100644 beike/Admin/View/Components/Filter.php
create mode 100644 beike/Admin/View/Components/Form/Image.php
create mode 100644 beike/Admin/View/Components/Form/Input.php
create mode 100644 beike/Admin/View/Components/Form/InputLocale.php
create mode 100644 beike/Admin/View/Components/Form/RichText.php
create mode 100644 beike/Admin/View/Components/Form/Select.php
create mode 100644 beike/Admin/View/Components/Form/SwitchRadio.php
create mode 100644 beike/Admin/View/Components/Form/Textarea.php
create mode 100644 beike/Admin/View/Components/Header.php
create mode 100644 beike/Admin/View/Components/NoData.php
create mode 100644 beike/Admin/View/Components/Sidebar.php
create mode 100644 beike/Admin/View/DesignBuilders/Brand.php
create mode 100644 beike/Admin/View/DesignBuilders/Icons.php
create mode 100644 beike/Admin/View/DesignBuilders/Image100.php
create mode 100644 beike/Admin/View/DesignBuilders/Image200.php
create mode 100644 beike/Admin/View/DesignBuilders/Image300.php
create mode 100644 beike/Admin/View/DesignBuilders/Image401.php
create mode 100644 beike/Admin/View/DesignBuilders/Product.php
create mode 100644 beike/Admin/View/DesignBuilders/RichText.php
create mode 100644 beike/Admin/View/DesignBuilders/SlideShow.php
create mode 100644 beike/Admin/View/DesignBuilders/TabProduct.php
create mode 100644 beike/Config/beike.php
create mode 100644 beike/Console/Commands/ChangeRootPassword.php
create mode 100644 beike/Console/Commands/FetchCurrencyRate.php
create mode 100644 beike/Console/Commands/GenerateDatabaseDict.php
create mode 100644 beike/Console/Commands/GenerateSitemap.php
create mode 100644 beike/Console/Commands/MakeRootAdminUser.php
create mode 100644 beike/Console/Commands/MigrateFromOpenCart.php
create mode 100644 beike/Helpers.php
create mode 100644 beike/Hook/Callback.php
create mode 100644 beike/Hook/Console/HookListeners.php
create mode 100644 beike/Hook/Facades/Hook.php
create mode 100644 beike/Hook/Hook.php
create mode 100644 beike/Hook/HookServiceProvider.php
create mode 100644 beike/Installer/Controllers/DatabaseController.php
create mode 100644 beike/Installer/Controllers/EnvironmentController.php
create mode 100644 beike/Installer/Controllers/FinalController.php
create mode 100644 beike/Installer/Controllers/PermissionsController.php
create mode 100644 beike/Installer/Controllers/RequirementsController.php
create mode 100644 beike/Installer/Controllers/WelcomeController.php
create mode 100644 beike/Installer/Helpers/DatabaseManager.php
create mode 100644 beike/Installer/Helpers/EnvironmentManager.php
create mode 100644 beike/Installer/Helpers/FinalInstallManager.php
create mode 100644 beike/Installer/Helpers/InstalledFileManager.php
create mode 100644 beike/Installer/Helpers/MigrationsHelper.php
create mode 100644 beike/Installer/Helpers/PermissionsChecker.php
create mode 100644 beike/Installer/Helpers/RequirementsChecker.php
create mode 100644 beike/Installer/Helpers/functions.php
create mode 100644 beike/Installer/Lang/en/installer_messages.php
create mode 100644 beike/Installer/Lang/zh_cn/installer_messages.php
create mode 100644 beike/Installer/Providers/InstallerServiceProvider.php
create mode 100644 beike/Installer/Routes/installer.php
create mode 100644 beike/Installer/Views/environment-wizard.blade.php
create mode 100644 beike/Installer/Views/finished.blade.php
create mode 100644 beike/Installer/Views/layouts/master.blade.php
create mode 100644 beike/Installer/Views/permissions.blade.php
create mode 100644 beike/Installer/Views/requirements.blade.php
create mode 100644 beike/Installer/Views/welcome.blade.php
create mode 100644 beike/Installer/assets/scss/_install-1.scss
create mode 100644 beike/Installer/assets/scss/_steps.scss
create mode 100644 beike/Installer/assets/scss/app.scss
create mode 100644 beike/Installer/config.php
create mode 100644 beike/Libraries/Breadcrumb.php
create mode 100644 beike/Libraries/Notification.php
create mode 100644 beike/Libraries/Tax.php
create mode 100644 beike/Libraries/Url.php
create mode 100644 beike/Mail/CustomerForgotten.php
create mode 100644 beike/Mail/CustomerNewOrder.php
create mode 100644 beike/Mail/CustomerRegistration.php
create mode 100644 beike/Mail/CustomerUpdateOrder.php
create mode 100644 beike/Mail/UserForgotten.php
create mode 100644 beike/Models/Address.php
create mode 100644 beike/Models/AdminUser.php
create mode 100644 beike/Models/Attribute.php
create mode 100644 beike/Models/AttributeDescription.php
create mode 100644 beike/Models/AttributeGroup.php
create mode 100644 beike/Models/AttributeGroupDescription.php
create mode 100644 beike/Models/AttributeValue.php
create mode 100644 beike/Models/AttributeValueDescription.php
create mode 100644 beike/Models/Base.php
create mode 100644 beike/Models/Brand.php
create mode 100644 beike/Models/Cart.php
create mode 100644 beike/Models/CartProduct.php
create mode 100644 beike/Models/Category.php
create mode 100644 beike/Models/CategoryDescription.php
create mode 100644 beike/Models/CategoryPath.php
create mode 100644 beike/Models/Country.php
create mode 100644 beike/Models/Currency.php
create mode 100644 beike/Models/Customer.php
create mode 100644 beike/Models/CustomerGroup.php
create mode 100644 beike/Models/CustomerGroupDescription.php
create mode 100644 beike/Models/CustomerWishlist.php
create mode 100644 beike/Models/Language.php
create mode 100644 beike/Models/Order.php
create mode 100644 beike/Models/OrderHistory.php
create mode 100644 beike/Models/OrderProduct.php
create mode 100644 beike/Models/OrderShipment.php
create mode 100644 beike/Models/OrderTotal.php
create mode 100644 beike/Models/Page.php
create mode 100644 beike/Models/PageCategory.php
create mode 100644 beike/Models/PageCategoryDescription.php
create mode 100644 beike/Models/PageDescription.php
create mode 100644 beike/Models/PageProduct.php
create mode 100644 beike/Models/Plugin.php
create mode 100644 beike/Models/Product.php
create mode 100644 beike/Models/ProductAttribute.php
create mode 100644 beike/Models/ProductCategory.php
create mode 100644 beike/Models/ProductDescription.php
create mode 100644 beike/Models/ProductRelation.php
create mode 100644 beike/Models/ProductSku.php
create mode 100644 beike/Models/Region.php
create mode 100644 beike/Models/RegionZone.php
create mode 100644 beike/Models/Rma.php
create mode 100644 beike/Models/RmaHistory.php
create mode 100644 beike/Models/RmaReason.php
create mode 100644 beike/Models/Setting.php
create mode 100644 beike/Models/TaxClass.php
create mode 100644 beike/Models/TaxRate.php
create mode 100644 beike/Models/TaxRule.php
create mode 100644 beike/Models/VerifyCode.php
create mode 100644 beike/Models/Zone.php
create mode 100644 beike/Notifications/AdminForgottenNotification.php
create mode 100644 beike/Notifications/ForgottenNotification.php
create mode 100644 beike/Notifications/NewOrderNotification.php
create mode 100644 beike/Notifications/RegistrationNotification.php
create mode 100644 beike/Notifications/UpdateOrderNotification.php
create mode 100644 beike/Plugin/Asset.php
create mode 100644 beike/Plugin/Manager.php
create mode 100644 beike/Plugin/Plugin.php
create mode 100644 beike/Repositories/AddressRepo.php
create mode 100644 beike/Repositories/BrandRepo.php
create mode 100644 beike/Repositories/CartRepo.php
create mode 100644 beike/Repositories/CategoryRepo.php
create mode 100644 beike/Repositories/CountryRepo.php
create mode 100644 beike/Repositories/CurrencyRepo.php
create mode 100644 beike/Repositories/CustomerGroupRepo.php
create mode 100644 beike/Repositories/CustomerRepo.php
create mode 100644 beike/Repositories/FooterRepo.php
create mode 100644 beike/Repositories/LanguageRepo.php
create mode 100644 beike/Repositories/MenuRepo.php
create mode 100644 beike/Repositories/OrderHistoryRepo.php
create mode 100644 beike/Repositories/OrderProductRepo.php
create mode 100644 beike/Repositories/OrderRepo.php
create mode 100644 beike/Repositories/OrderTotalRepo.php
create mode 100644 beike/Repositories/PageCategoryRepo.php
create mode 100644 beike/Repositories/PageRepo.php
create mode 100644 beike/Repositories/PluginRepo.php
create mode 100644 beike/Repositories/ProductRepo.php
create mode 100644 beike/Repositories/RmaReasonRepo.php
create mode 100644 beike/Repositories/RmaRepo.php
create mode 100644 beike/Repositories/SettingRepo.php
create mode 100644 beike/Repositories/SystemSettingRepo.php
create mode 100644 beike/Repositories/ThemeRepo.php
create mode 100644 beike/Repositories/UserRepo.php
create mode 100644 beike/Repositories/VerifyCodeRepo.php
create mode 100644 beike/Repositories/ZoneRepo.php
create mode 100644 beike/Services/CurrencyService.php
create mode 100644 beike/Services/DesignService.php
create mode 100644 beike/Services/ImageService.php
create mode 100644 beike/Services/ShipmentService.php
create mode 100644 beike/Services/ShippingMethodService.php
create mode 100644 beike/Services/SitemapService.php
create mode 100644 beike/Services/StateMachineService.php
create mode 100644 beike/Shop/Http/Controllers/Account/AccountController.php
create mode 100644 beike/Shop/Http/Controllers/Account/AddressController.php
create mode 100644 beike/Shop/Http/Controllers/Account/EditController.php
create mode 100644 beike/Shop/Http/Controllers/Account/ForgottenController.php
create mode 100644 beike/Shop/Http/Controllers/Account/LoginController.php
create mode 100644 beike/Shop/Http/Controllers/Account/LogoutController.php
create mode 100644 beike/Shop/Http/Controllers/Account/OrderController.php
create mode 100644 beike/Shop/Http/Controllers/Account/RegisterController.php
create mode 100644 beike/Shop/Http/Controllers/Account/RmaController.php
create mode 100644 beike/Shop/Http/Controllers/Account/WishlistController.php
create mode 100644 beike/Shop/Http/Controllers/BrandController.php
create mode 100644 beike/Shop/Http/Controllers/CartController.php
create mode 100644 beike/Shop/Http/Controllers/CategoryController.php
create mode 100644 beike/Shop/Http/Controllers/CheckoutController.php
create mode 100644 beike/Shop/Http/Controllers/Controller.php
create mode 100644 beike/Shop/Http/Controllers/CurrencyController.php
create mode 100644 beike/Shop/Http/Controllers/FileController.php
create mode 100644 beike/Shop/Http/Controllers/HomeController.php
create mode 100644 beike/Shop/Http/Controllers/LanguageController.php
create mode 100644 beike/Shop/Http/Controllers/PageCategoryController.php
create mode 100644 beike/Shop/Http/Controllers/PageController.php
create mode 100644 beike/Shop/Http/Controllers/PluginController.php
create mode 100644 beike/Shop/Http/Controllers/ProductController.php
create mode 100644 beike/Shop/Http/Controllers/ZoneController.php
create mode 100644 beike/Shop/Http/Requests/AddressRequest.php
create mode 100644 beike/Shop/Http/Requests/CartRequest.php
create mode 100644 beike/Shop/Http/Requests/EditRequest.php
create mode 100644 beike/Shop/Http/Requests/ForgottenRequest.php
create mode 100644 beike/Shop/Http/Requests/LoginRequest.php
create mode 100644 beike/Shop/Http/Requests/RegisterRequest.php
create mode 100644 beike/Shop/Http/Requests/RmaRequest.php
create mode 100644 beike/Shop/Http/Requests/UploadRequest.php
create mode 100644 beike/Shop/Http/Requests/VerifyCodeRequest.php
create mode 100644 beike/Shop/Http/Resources/Account/AddressResource.php
create mode 100644 beike/Shop/Http/Resources/Account/OrderList.php
create mode 100644 beike/Shop/Http/Resources/Account/RmaReasonDetail.php
create mode 100644 beike/Shop/Http/Resources/Account/WishlistDetail.php
create mode 100644 beike/Shop/Http/Resources/BrandDetail.php
create mode 100644 beike/Shop/Http/Resources/CartDetail.php
create mode 100644 beike/Shop/Http/Resources/CategoryDetail.php
create mode 100644 beike/Shop/Http/Resources/Checkout/PaymentMethodItem.php
create mode 100644 beike/Shop/Http/Resources/Checkout/ShippingMethodItem.php
create mode 100644 beike/Shop/Http/Resources/CustomerResource.php
create mode 100644 beike/Shop/Http/Resources/PageCategoryDetail.php
create mode 100644 beike/Shop/Http/Resources/PageDetail.php
create mode 100644 beike/Shop/Http/Resources/ProductDetail.php
create mode 100644 beike/Shop/Http/Resources/ProductSimple.php
create mode 100644 beike/Shop/Http/Resources/RmaDetail.php
create mode 100644 beike/Shop/Http/Resources/SkuDetail.php
create mode 100644 beike/Shop/Providers/PluginServiceProvider.php
create mode 100644 beike/Shop/Providers/ShopServiceProvider.php
create mode 100644 beike/Shop/Routes/shop.php
create mode 100644 beike/Shop/Services/AccountService.php
create mode 100644 beike/Shop/Services/AddressService.php
create mode 100644 beike/Shop/Services/CartService.php
create mode 100644 beike/Shop/Services/CheckoutService.php
create mode 100644 beike/Shop/Services/PaymentService.php
create mode 100644 beike/Shop/Services/RmaService.php
create mode 100644 beike/Shop/Services/TotalService.php
create mode 100644 beike/Shop/Services/TotalServices/CustomerDiscountService.php
create mode 100644 beike/Shop/Services/TotalServices/OrderTotalService.php
create mode 100644 beike/Shop/Services/TotalServices/ShippingService.php
create mode 100644 beike/Shop/Services/TotalServices/SubtotalService.php
create mode 100644 beike/Shop/Services/TotalServices/TaxService.php
create mode 100644 beike/Shop/View/Components/AccountSidebar.php
create mode 100644 beike/Shop/View/Components/Alert.php
create mode 100644 beike/Shop/View/Components/Breadcrumb.php
create mode 100644 beike/Shop/View/Components/NoData.php
create mode 100644 bootstrap/app.php
create mode 100644 bootstrap/cache/.gitignore
create mode 100644 composer.json
create mode 100644 composer.lock
create mode 100644 config/app.php
create mode 100644 config/auth.php
create mode 100644 config/broadcasting.php
create mode 100644 config/cache.php
create mode 100644 config/cors.php
create mode 100644 config/database.php
create mode 100644 config/debugbar.php
create mode 100644 config/filesystems.php
create mode 100644 config/hashing.php
create mode 100644 config/horizon.php
create mode 100644 config/logging.php
create mode 100644 config/mail.php
create mode 100644 config/permission.php
create mode 100644 config/queue.php
create mode 100644 config/sanctum.php
create mode 100644 config/services.php
create mode 100644 config/session.php
create mode 100644 config/sitemap.php
create mode 100644 config/view.php
create mode 100644 database/.gitignore
create mode 100644 database/factories/AddressFactory.php
create mode 100644 database/factories/Beike/Models/CartProductFactory.php
create mode 100644 database/factories/ProductFactory.php
create mode 100644 database/factories/ProductSkuFactory.php
create mode 100644 database/factories/UserFactory.php
create mode 100644 database/migrations/2019_08_19_000000_create_failed_jobs_table.php
create mode 100644 database/migrations/2021_12_26_111435_create_tables.php
create mode 100644 database/migrations/2022_08_01_033755_create_permission_tables.php
create mode 100644 database/migrations/2022_12_16_095559_create_order_shipments.php
create mode 100644 database/migrations/2022_12_22_022326_create_notifications_table.php
create mode 100644 database/migrations/2022_12_22_061843_order_add_field.php
create mode 100644 database/migrations/2022_12_28_171057_alter_cart_table.php
create mode 100644 database/migrations/2022_12_30_110019_create_product_related.php
create mode 100644 database/migrations/2022_12_30_165725_guest_checkout.php
create mode 100644 database/migrations/2023_01_03_111459_product_attribute.php
create mode 100644 database/migrations/2023_01_06_104545_change_meta_keywords.php
create mode 100644 database/migrations/2023_01_10_115702_add_sales2_product.php
create mode 100644 database/migrations/2023_02_09_021051_create_page_category.php
create mode 100644 database/seeders/AttributesSeeder.php
create mode 100644 database/seeders/BrandsSeeder.php
create mode 100644 database/seeders/CategoriesSeeder.php
create mode 100644 database/seeders/CountriesSeeder.php
create mode 100644 database/seeders/CurrenciesSeeder.php
create mode 100644 database/seeders/CustomerGroupsSeeder.php
create mode 100644 database/seeders/DatabaseSeeder.php
create mode 100644 database/seeders/LanguagesSeeder.php
create mode 100644 database/seeders/PagesSeeder.php
create mode 100644 database/seeders/PluginsSeeder.php
create mode 100644 database/seeders/ProductsSeeder.php
create mode 100644 database/seeders/SettingsSeeder.php
create mode 100644 database/seeders/ThemeSeeder.php
create mode 100644 database/seeders/ZonesSeeder.php
create mode 100644 index.php
create mode 100644 package-lock.json
create mode 100644 package.json
create mode 100644 phpunit.xml
create mode 100644 pint.json
create mode 100644 public/.htaccess
create mode 100644 public/build/beike/admin/css/app.css
create mode 100644 public/build/beike/admin/css/bootstrap.css
create mode 100644 public/build/beike/admin/css/design.css
create mode 100644 public/build/beike/admin/css/filemanager.css
create mode 100644 public/build/beike/admin/js/app.js
create mode 100644 public/build/beike/shop/default/css/app.css
create mode 100644 public/build/beike/shop/default/css/bootstrap.css
create mode 100644 public/build/beike/shop/default/js/app.js
create mode 100644 public/cache/.gitignore
create mode 100644 public/catalog/.gitignore
create mode 100644 public/catalog/banner.png
create mode 100644 public/catalog/placeholder.png
create mode 100644 public/favicon.ico
create mode 100644 public/fonts/design/iconfont.json
create mode 100644 public/fonts/design/iconfont.ttf
create mode 100644 public/fonts/design/iconfont.woff
create mode 100644 public/fonts/design/iconfont.woff2
create mode 100644 public/fonts/iconfont/iconfont.json
create mode 100644 public/fonts/iconfont/iconfont.ttf
create mode 100644 public/fonts/iconfont/iconfont.woff
create mode 100644 public/fonts/poppins/Poppins-Bold.ttf
create mode 100644 public/fonts/poppins/Poppins-Light.ttf
create mode 100644 public/fonts/poppins/Poppins-Medium.ttf
create mode 100644 public/fonts/poppins/Poppins-Regular.ttf
create mode 100644 public/fonts/poppins/Poppins-SemiBold.ttf
create mode 100644 public/htaccess.txt
create mode 100644 public/image/alipay.png
create mode 100644 public/image/close.png
create mode 100644 public/image/default-theme.jpg
create mode 100644 public/image/favicon.png
create mode 100644 public/image/login-bg.svg
create mode 100644 public/image/logo.png
create mode 100644 public/image/no-data.svg
create mode 100644 public/image/placeholder.png
create mode 100644 public/image/vip-icon.png
create mode 100644 public/image/vip-info.webp
create mode 100644 public/image/wechat.png
create mode 100644 public/index.php
create mode 100644 public/install/css/app.css
create mode 100644 public/install/image/install-1.png
create mode 100644 public/install/image/install-2.png
create mode 100644 public/install/image/install-enter.jpg
create mode 100644 public/mix-manifest.json
create mode 100644 public/nginx.htaccess
create mode 100644 public/plugin/.gitignore
create mode 100644 public/robots.txt
create mode 100644 public/upload/.gitignore
create mode 100644 public/vendor/axios/0.27.2/axios.min.js
create mode 100644 public/vendor/bootstrap/4.6.1/css/bootstrap.min.css
create mode 100644 public/vendor/bootstrap/4.6.1/js/bootstrap.bundle.min.js
create mode 100644 public/vendor/bootstrap/4.6.1/js/bootstrap.min.js
create mode 100644 public/vendor/bootstrap/5.1.3/css/bootstrap.min.css
create mode 100644 public/vendor/bootstrap/5.1.3/js/bootstrap.bundle.min.js
create mode 100644 public/vendor/bootstrap/5.1.3/js/bootstrap.min.js
create mode 100644 public/vendor/bootstrap/icon/bootstrap-icons.woff
create mode 100644 public/vendor/bootstrap/icon/bootstrap-icons.woff2
create mode 100644 public/vendor/chart/chart.min.js
create mode 100644 public/vendor/clipboard/clipboard.min.js
create mode 100644 public/vendor/cookie/js.cookie.min.js
create mode 100644 public/vendor/cropper/cropper.min.css
create mode 100644 public/vendor/cropper/cropper.min.js
create mode 100644 public/vendor/element-ui/2.15.6/css.css
create mode 100644 public/vendor/element-ui/2.15.6/fonts/element-icons.ttf
create mode 100644 public/vendor/element-ui/2.15.6/fonts/element-icons.woff
create mode 100644 public/vendor/element-ui/2.15.6/js.js
create mode 100644 public/vendor/element-ui/2.15.9/fonts/element-icons.ttf
create mode 100644 public/vendor/element-ui/2.15.9/fonts/element-icons.woff
create mode 100644 public/vendor/element-ui/2.15.9/index.css
create mode 100644 public/vendor/element-ui/2.15.9/index.js
create mode 100644 public/vendor/element-ui/language/de.js
create mode 100644 public/vendor/element-ui/language/en.js
create mode 100644 public/vendor/element-ui/language/es.js
create mode 100644 public/vendor/element-ui/language/fr.js
create mode 100644 public/vendor/element-ui/language/it.js
create mode 100644 public/vendor/element-ui/language/ja.js
create mode 100644 public/vendor/element-ui/language/ru.js
create mode 100644 public/vendor/element-ui/language/zh_hk.js
create mode 100644 public/vendor/elevatezoom/jquery.elevateZoom.min.js
create mode 100644 public/vendor/highlight/atom-one-dark.min.css
create mode 100644 public/vendor/highlight/highlight.min.js
create mode 100644 public/vendor/horizon/app-dark.css
create mode 100644 public/vendor/horizon/app.css
create mode 100644 public/vendor/horizon/app.js
create mode 100644 public/vendor/horizon/img/favicon.png
create mode 100644 public/vendor/horizon/img/horizon.svg
create mode 100644 public/vendor/horizon/img/sprite.svg
create mode 100644 public/vendor/horizon/mix-manifest.json
create mode 100644 public/vendor/jquery/jquery-2.1.1.min.js
create mode 100644 public/vendor/jquery/jquery-3.6.0.min.js
create mode 100644 public/vendor/jquery/jquery-ui/jquery-ui.min.css
create mode 100644 public/vendor/jquery/jquery-ui/jquery-ui.min.js
create mode 100644 public/vendor/layer/3.5.1/layer.js
create mode 100644 public/vendor/layer/3.5.1/mobile/layer.js
create mode 100644 public/vendor/layer/3.5.1/mobile/need/layer.css
create mode 100644 public/vendor/layer/3.5.1/theme/default/icon-ext.png
create mode 100644 public/vendor/layer/3.5.1/theme/default/icon.png
create mode 100644 public/vendor/layer/3.5.1/theme/default/layer.css
create mode 100644 public/vendor/layer/3.5.1/theme/default/loading-0.gif
create mode 100644 public/vendor/layer/3.5.1/theme/default/loading-1.gif
create mode 100644 public/vendor/layer/3.5.1/theme/default/loading-2.gif
create mode 100644 public/vendor/marked/marked.min.js
create mode 100644 public/vendor/qrcode/qrcode.min.js
create mode 100644 public/vendor/scrolltofixed/jquery-scrolltofixed-min.js
create mode 100644 public/vendor/sitemap/styles/google-news.xsl
create mode 100644 public/vendor/sitemap/styles/mobile.xsl
create mode 100644 public/vendor/sitemap/styles/sitemapindex.xsl
create mode 100644 public/vendor/sitemap/styles/xml.xsl
create mode 100644 public/vendor/sweetalert2/sweetalert2.min.css
create mode 100644 public/vendor/sweetalert2/sweetalert2.min.js
create mode 100644 public/vendor/swiper/swiper-bundle.min.css
create mode 100644 public/vendor/swiper/swiper-bundle.min.js
create mode 100644 public/vendor/tinymce/5.9.1/icons/default/icons.min.js
create mode 100644 public/vendor/tinymce/5.9.1/jquery.tinymce.min.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/af_ZA.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ar.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/az.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/be.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/bg_BG.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/bn_BD.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ca.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/cs.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/cs_CZ.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/cy.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/da.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/de.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/de_AT.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/dv.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/el.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/en_CA.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/en_GB.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/es.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/es_MX.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/et.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/eu.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/fa_IR.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/fi.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/fr.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ga.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/gl.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/he_IL.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/hr.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/hu_HU.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/id.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/it.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ja.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ka_GE.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/kab.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/kk.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/km_KH.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ko_KR.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/lt.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/lv.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/nb_NO.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/nl.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/pl.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/pt_BR.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/pt_PT.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ro.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ru.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/sk.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/sl_SI.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/sr.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/sv_SE.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ta.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ta_IN.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/th_TH.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/tr.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/tr_TR.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/ug.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/uk.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/uk_UA.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/uz.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/vi_VN.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/zh_cn.js
create mode 100644 public/vendor/tinymce/5.9.1/langs/zh_hk.js
create mode 100644 public/vendor/tinymce/5.9.1/license.txt
create mode 100644 public/vendor/tinymce/5.9.1/plugins/advlist/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/anchor/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/autolink/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/autoresize/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/autosave/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/bbcode/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/charmap/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/code/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/codesample/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/colorpicker/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/contextmenu/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/directionality/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/emoticons/js/emojiimages.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/emoticons/js/emojiimages.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/emoticons/js/emojis.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/emoticons/js/emojis.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/emoticons/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/fullpage/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/fullscreen/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/help/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/hr/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/image/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/imagetools/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/importcss/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/insertdatetime/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/legacyoutput/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/link/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/lists/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/media/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/nonbreaking/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/noneditable/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/pagebreak/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/paste/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/preview/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/print/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/quickbars/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/save/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/searchreplace/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/spellchecker/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/tabfocus/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/table/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/template/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/textcolor/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/textpattern/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/toc/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/visualblocks/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/visualchars/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/plugins/wordcount/plugin.min.js
create mode 100644 public/vendor/tinymce/5.9.1/skins/content/dark/content.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/content/default/content.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/content/document/content.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/content/writer/content.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide-dark/content.inline.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide-dark/content.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide-dark/content.mobile.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide-dark/fonts/tinymce-mobile.woff
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide-dark/skin.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide-dark/skin.mobile.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide-dark/skin.shadowdom.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide/content.inline.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide/content.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide/content.mobile.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide/fonts/tinymce-mobile.woff
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide/skin.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide/skin.mobile.min.css
create mode 100644 public/vendor/tinymce/5.9.1/skins/ui/oxide/skin.shadowdom.min.css
create mode 100644 public/vendor/tinymce/5.9.1/themes/mobile/theme.min.js
create mode 100644 public/vendor/tinymce/5.9.1/themes/silver/theme.min.js
create mode 100644 public/vendor/tinymce/5.9.1/tinymce.d.ts
create mode 100644 public/vendor/tinymce/5.9.1/tinymce.min.js
create mode 100644 public/vendor/tinymce/tinymce-vue/tinymce-vue.js
create mode 100644 public/vendor/tinymce/tinymce-vue/tinymce-vue.min.js
create mode 100644 public/vendor/vue/2.7/vue.js
create mode 100644 public/vendor/vue/2.7/vue.min.js
create mode 100644 public/vendor/vue/3/vue.global.js
create mode 100644 public/vendor/vue/Sortable.min.js
create mode 100644 public/vendor/vue/batch_select.js
create mode 100644 public/vendor/vue/vuedraggable.js
create mode 100644 public/vendor/zoom/jquery.zoom.min.js
create mode 100644 public/web.config
create mode 100644 resources/beike/admin/css/_autocomplete.scss
create mode 100644 resources/beike/admin/css/_bootstrap-extra.scss
create mode 100644 resources/beike/admin/css/_dashboard.scss
create mode 100644 resources/beike/admin/css/_form.scss
create mode 100644 resources/beike/admin/css/_global.scss
create mode 100644 resources/beike/admin/css/_header.scss
create mode 100644 resources/beike/admin/css/_iconfont.scss
create mode 100644 resources/beike/admin/css/_marketing.scss
create mode 100644 resources/beike/admin/css/_page-category.scss
create mode 100644 resources/beike/admin/css/_page-pages.scss
create mode 100644 resources/beike/admin/css/_page-product.scss
create mode 100644 resources/beike/admin/css/_page-theme.scss
create mode 100644 resources/beike/admin/css/_sidebar.scss
create mode 100644 resources/beike/admin/css/_subscription.scss
create mode 100644 resources/beike/admin/css/_vue.scss
create mode 100644 resources/beike/admin/css/app.scss
create mode 100644 resources/beike/admin/css/bootstrap/bootstrap-icons.scss
create mode 100644 resources/beike/admin/css/bootstrap/bootstrap.scss
create mode 100644 resources/beike/admin/css/design/app.scss
create mode 100644 resources/beike/admin/css/design/menu.scss
create mode 100644 resources/beike/admin/css/element-ui.scss
create mode 100644 resources/beike/admin/css/filemanager/app.scss
create mode 100644 resources/beike/admin/css/login.scss
create mode 100644 resources/beike/admin/js/app.js
create mode 100644 resources/beike/admin/js/autocomplete.js
create mode 100644 resources/beike/admin/js/bootstrap-validation.js
create mode 100644 resources/beike/admin/js/common.js
create mode 100644 resources/beike/admin/js/header.js
create mode 100644 resources/beike/admin/views/components/alert.blade.php
create mode 100644 resources/beike/admin/views/components/filter.blade.php
create mode 100644 resources/beike/admin/views/components/form/error.blade.php
create mode 100644 resources/beike/admin/views/components/form/image.blade.php
create mode 100644 resources/beike/admin/views/components/form/input-locale.blade.php
create mode 100644 resources/beike/admin/views/components/form/input.blade.php
create mode 100644 resources/beike/admin/views/components/form/rich-text.blade.php
create mode 100644 resources/beike/admin/views/components/form/row.blade.php
create mode 100644 resources/beike/admin/views/components/form/select.blade.php
create mode 100644 resources/beike/admin/views/components/form/switch-radio.blade.php
create mode 100644 resources/beike/admin/views/components/form/textarea.blade.php
create mode 100644 resources/beike/admin/views/components/header.blade.php
create mode 100644 resources/beike/admin/views/components/no-data.blade.php
create mode 100644 resources/beike/admin/views/components/sidebar.blade.php
create mode 100644 resources/beike/admin/views/errors/401.blade.php
create mode 100644 resources/beike/admin/views/errors/403.blade.php
create mode 100644 resources/beike/admin/views/errors/404.blade.php
create mode 100644 resources/beike/admin/views/errors/419.blade.php
create mode 100644 resources/beike/admin/views/errors/429.blade.php
create mode 100644 resources/beike/admin/views/errors/500.blade.php
create mode 100644 resources/beike/admin/views/errors/503.blade.php
create mode 100644 resources/beike/admin/views/errors/layout.blade.php
create mode 100644 resources/beike/admin/views/errors/minimal.blade.php
create mode 100644 resources/beike/admin/views/layouts/header.blade.php
create mode 100644 resources/beike/admin/views/layouts/master.blade.php
create mode 100644 resources/beike/admin/views/pages/admin_roles/edit.blade.php
create mode 100644 resources/beike/admin/views/pages/admin_roles/index.blade.php
create mode 100644 resources/beike/admin/views/pages/admin_users/index.blade.php
create mode 100644 resources/beike/admin/views/pages/attribute_group/index.blade.php
create mode 100644 resources/beike/admin/views/pages/attributes/form.blade.php
create mode 100644 resources/beike/admin/views/pages/attributes/index.blade.php
create mode 100644 resources/beike/admin/views/pages/brands/index.blade.php
create mode 100644 resources/beike/admin/views/pages/categories/form-vue.blade.php
create mode 100644 resources/beike/admin/views/pages/categories/form.blade.php
create mode 100644 resources/beike/admin/views/pages/categories/index.blade.php
create mode 100644 resources/beike/admin/views/pages/country/index.blade.php
create mode 100644 resources/beike/admin/views/pages/currencies/index.blade.php
create mode 100644 resources/beike/admin/views/pages/customer_groups/index.blade.php
create mode 100644 resources/beike/admin/views/pages/customers/form.blade.php
create mode 100644 resources/beike/admin/views/pages/customers/index.blade.php
create mode 100644 resources/beike/admin/views/pages/dashboard/index.blade.php
create mode 100644 resources/beike/admin/views/pages/design/builder/component/image_selector.blade.php
create mode 100644 resources/beike/admin/views/pages/design/builder/component/link_selector.blade.php
create mode 100644 resources/beike/admin/views/pages/design/builder/component/rich_text_i18n.blade.php
create mode 100644 resources/beike/admin/views/pages/design/builder/component/text_i18n.blade.php
create mode 100644 resources/beike/admin/views/pages/design/builder/footer.blade.php
create mode 100644 resources/beike/admin/views/pages/design/builder/index.blade.php
create mode 100644 resources/beike/admin/views/pages/design/builder/menu.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/brand.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/icons.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/image100.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/image200.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/image300.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/image401.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/product.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/rich_text.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/slideshow.blade.php
create mode 100644 resources/beike/admin/views/pages/design/module/tab_product.blade.php
create mode 100644 resources/beike/admin/views/pages/file/index.blade.php
create mode 100644 resources/beike/admin/views/pages/file_manager/index.blade.php
create mode 100644 resources/beike/admin/views/pages/home.blade.php
create mode 100644 resources/beike/admin/views/pages/languages/index.blade.php
create mode 100644 resources/beike/admin/views/pages/login/login.blade.php
create mode 100644 resources/beike/admin/views/pages/marketing/index.blade.php
create mode 100644 resources/beike/admin/views/pages/marketing/show.blade.php
create mode 100644 resources/beike/admin/views/pages/orders/form.blade.php
create mode 100644 resources/beike/admin/views/pages/orders/index.blade.php
create mode 100644 resources/beike/admin/views/pages/page_categories/form.blade.php
create mode 100644 resources/beike/admin/views/pages/page_categories/index.blade.php
create mode 100644 resources/beike/admin/views/pages/pages/form.blade.php
create mode 100644 resources/beike/admin/views/pages/pages/index.blade.php
create mode 100644 resources/beike/admin/views/pages/plugins/form.blade.php
create mode 100644 resources/beike/admin/views/pages/plugins/index.blade.php
create mode 100644 resources/beike/admin/views/pages/products/form/form.blade.php
create mode 100644 resources/beike/admin/views/pages/products/index.blade.php
create mode 100644 resources/beike/admin/views/pages/regions/index.blade.php
create mode 100644 resources/beike/admin/views/pages/rma_reasons/index.blade.php
create mode 100644 resources/beike/admin/views/pages/rmas/index.blade.php
create mode 100644 resources/beike/admin/views/pages/rmas/info.blade.php
create mode 100644 resources/beike/admin/views/pages/setting.blade.php
create mode 100644 resources/beike/admin/views/pages/tax_classes/index.blade.php
create mode 100644 resources/beike/admin/views/pages/tax_rates/index.blade.php
create mode 100644 resources/beike/admin/views/pages/theme/index.blade.php
create mode 100644 resources/beike/admin/views/pages/user/forgotten.blade.php
create mode 100644 resources/beike/admin/views/pages/zones/index.blade.php
create mode 100644 resources/beike/admin/views/shared/vue-image.blade.php
create mode 100644 resources/beike/admin/views/vendor/pagination/bootstrap-4.blade.php
create mode 100644 resources/beike/admin/views/vendor/pagination/default.blade.php
create mode 100644 resources/beike/admin/views/vendor/pagination/semantic-ui.blade.php
create mode 100644 resources/beike/admin/views/vendor/pagination/simple-bootstrap-4.blade.php
create mode 100644 resources/beike/admin/views/vendor/pagination/simple-default.blade.php
create mode 100644 resources/beike/admin/views/vendor/pagination/simple-tailwind.blade.php
create mode 100644 resources/beike/admin/views/vendor/pagination/tailwind.blade.php
create mode 100644 resources/beike/shop/default/css/account/account.scss
create mode 100644 resources/beike/shop/default/css/app.scss
create mode 100644 resources/beike/shop/default/css/bootstrap/bootstrap-icons.scss
create mode 100644 resources/beike/shop/default/css/bootstrap/bootstrap.scss
create mode 100644 resources/beike/shop/default/css/cart.scss
create mode 100644 resources/beike/shop/default/css/element-ui.scss
create mode 100644 resources/beike/shop/default/css/footer.scss
create mode 100644 resources/beike/shop/default/css/global.scss
create mode 100644 resources/beike/shop/default/css/header.scss
create mode 100644 resources/beike/shop/default/css/home.scss
create mode 100644 resources/beike/shop/default/css/iconfont.scss
create mode 100644 resources/beike/shop/default/css/login.scss
create mode 100644 resources/beike/shop/default/css/module/module-brand.scss
create mode 100644 resources/beike/shop/default/css/module/module-image-plus.scss
create mode 100644 resources/beike/shop/default/css/module/module-tab-product.scss
create mode 100644 resources/beike/shop/default/css/module/slideshow.scss
create mode 100644 resources/beike/shop/default/css/news.scss
create mode 100644 resources/beike/shop/default/css/order-success.scss
create mode 100644 resources/beike/shop/default/css/page-account-address.scss
create mode 100644 resources/beike/shop/default/css/page-account-order.scss
create mode 100644 resources/beike/shop/default/css/page-brands.scss
create mode 100644 resources/beike/shop/default/css/page-categories.scss
create mode 100644 resources/beike/shop/default/css/page-checkout.scss
create mode 100644 resources/beike/shop/default/css/page-list.scss
create mode 100644 resources/beike/shop/default/css/page-product.scss
create mode 100644 resources/beike/shop/default/css/product-style.scss
create mode 100644 resources/beike/shop/default/js/app.js
create mode 100644 resources/beike/shop/default/js/bootstrap-validation.js
create mode 100644 resources/beike/shop/default/js/common.js
create mode 100644 resources/beike/shop/default/js/header.js
create mode 100644 resources/beike/shop/default/js/product.js
create mode 100644 resources/js/app.js
create mode 100644 resources/js/bootstrap.js
create mode 100644 resources/js/http.js
create mode 100644 resources/lang/de/address.php
create mode 100644 resources/lang/de/admin/admin_roles.php
create mode 100644 resources/lang/de/admin/attribute.php
create mode 100644 resources/lang/de/admin/attribute_group.php
create mode 100644 resources/lang/de/admin/base.php
create mode 100644 resources/lang/de/admin/brand.php
create mode 100644 resources/lang/de/admin/builder.php
create mode 100644 resources/lang/de/admin/category.php
create mode 100644 resources/lang/de/admin/common.php
create mode 100644 resources/lang/de/admin/country.php
create mode 100644 resources/lang/de/admin/currency.php
create mode 100644 resources/lang/de/admin/customer.php
create mode 100644 resources/lang/de/admin/customer_group.php
create mode 100644 resources/lang/de/admin/dashboard.php
create mode 100644 resources/lang/de/admin/design_builder.php
create mode 100644 resources/lang/de/admin/file_manager.php
create mode 100644 resources/lang/de/admin/forgotten.php
create mode 100644 resources/lang/de/admin/language.php
create mode 100644 resources/lang/de/admin/login.php
create mode 100644 resources/lang/de/admin/marketing.php
create mode 100644 resources/lang/de/admin/order.php
create mode 100644 resources/lang/de/admin/page.php
create mode 100644 resources/lang/de/admin/page_category.php
create mode 100644 resources/lang/de/admin/plugin.php
create mode 100644 resources/lang/de/admin/product.php
create mode 100644 resources/lang/de/admin/region.php
create mode 100644 resources/lang/de/admin/rma.php
create mode 100644 resources/lang/de/admin/rma_reason.php
create mode 100644 resources/lang/de/admin/role.php
create mode 100644 resources/lang/de/admin/setting.php
create mode 100644 resources/lang/de/admin/tax_class.php
create mode 100644 resources/lang/de/admin/tax_rate.php
create mode 100644 resources/lang/de/admin/theme.php
create mode 100644 resources/lang/de/admin/user.php
create mode 100644 resources/lang/de/admin/zone.php
create mode 100644 resources/lang/de/auth.php
create mode 100644 resources/lang/de/brand.php
create mode 100644 resources/lang/de/cart.php
create mode 100644 resources/lang/de/category.php
create mode 100644 resources/lang/de/common.php
create mode 100644 resources/lang/de/currency.php
create mode 100644 resources/lang/de/customer.php
create mode 100644 resources/lang/de/customer_group.php
create mode 100644 resources/lang/de/mail.php
create mode 100644 resources/lang/de/order.php
create mode 100644 resources/lang/de/page.php
create mode 100644 resources/lang/de/page_category.php
create mode 100644 resources/lang/de/pagination.php
create mode 100644 resources/lang/de/passwords.php
create mode 100644 resources/lang/de/product.php
create mode 100644 resources/lang/de/rma.php
create mode 100644 resources/lang/de/role.php
create mode 100644 resources/lang/de/shop/account.php
create mode 100644 resources/lang/de/shop/brands.php
create mode 100644 resources/lang/de/shop/carts.php
create mode 100644 resources/lang/de/shop/checkout.php
create mode 100644 resources/lang/de/shop/common.php
create mode 100644 resources/lang/de/shop/currency.php
create mode 100644 resources/lang/de/shop/file.php
create mode 100644 resources/lang/de/shop/forgotten.php
create mode 100644 resources/lang/de/shop/login.php
create mode 100644 resources/lang/de/shop/order.php
create mode 100644 resources/lang/de/shop/products.php
create mode 100644 resources/lang/de/shop/steps.php
create mode 100644 resources/lang/de/shop/wishlist.php
create mode 100644 resources/lang/de/user.php
create mode 100644 resources/lang/de/validation.php
create mode 100644 resources/lang/en/address.php
create mode 100644 resources/lang/en/admin/admin_roles.php
create mode 100644 resources/lang/en/admin/attribute.php
create mode 100644 resources/lang/en/admin/attribute_group.php
create mode 100644 resources/lang/en/admin/base.php
create mode 100644 resources/lang/en/admin/brand.php
create mode 100644 resources/lang/en/admin/builder.php
create mode 100644 resources/lang/en/admin/category.php
create mode 100644 resources/lang/en/admin/common.php
create mode 100644 resources/lang/en/admin/country.php
create mode 100644 resources/lang/en/admin/currency.php
create mode 100644 resources/lang/en/admin/customer.php
create mode 100644 resources/lang/en/admin/customer_group.php
create mode 100644 resources/lang/en/admin/dashboard.php
create mode 100644 resources/lang/en/admin/design_builder.php
create mode 100644 resources/lang/en/admin/file_manager.php
create mode 100644 resources/lang/en/admin/forgotten.php
create mode 100644 resources/lang/en/admin/language.php
create mode 100644 resources/lang/en/admin/login.php
create mode 100644 resources/lang/en/admin/marketing.php
create mode 100644 resources/lang/en/admin/order.php
create mode 100644 resources/lang/en/admin/page.php
create mode 100644 resources/lang/en/admin/page_category.php
create mode 100644 resources/lang/en/admin/plugin.php
create mode 100644 resources/lang/en/admin/product.php
create mode 100644 resources/lang/en/admin/region.php
create mode 100644 resources/lang/en/admin/rma.php
create mode 100644 resources/lang/en/admin/rma_reason.php
create mode 100644 resources/lang/en/admin/role.php
create mode 100644 resources/lang/en/admin/setting.php
create mode 100644 resources/lang/en/admin/tax_class.php
create mode 100644 resources/lang/en/admin/tax_rate.php
create mode 100644 resources/lang/en/admin/theme.php
create mode 100644 resources/lang/en/admin/user.php
create mode 100644 resources/lang/en/admin/zone.php
create mode 100644 resources/lang/en/auth.php
create mode 100644 resources/lang/en/brand.php
create mode 100644 resources/lang/en/cart.php
create mode 100644 resources/lang/en/category.php
create mode 100644 resources/lang/en/common.php
create mode 100644 resources/lang/en/currency.php
create mode 100644 resources/lang/en/customer.php
create mode 100644 resources/lang/en/customer_group.php
create mode 100644 resources/lang/en/mail.php
create mode 100644 resources/lang/en/order.php
create mode 100644 resources/lang/en/page.php
create mode 100644 resources/lang/en/page_category.php
create mode 100644 resources/lang/en/pagination.php
create mode 100644 resources/lang/en/passwords.php
create mode 100644 resources/lang/en/product.php
create mode 100644 resources/lang/en/rma.php
create mode 100644 resources/lang/en/role.php
create mode 100644 resources/lang/en/shop/account.php
create mode 100644 resources/lang/en/shop/brands.php
create mode 100644 resources/lang/en/shop/carts.php
create mode 100644 resources/lang/en/shop/checkout.php
create mode 100644 resources/lang/en/shop/common.php
create mode 100644 resources/lang/en/shop/currency.php
create mode 100644 resources/lang/en/shop/file.php
create mode 100644 resources/lang/en/shop/forgotten.php
create mode 100644 resources/lang/en/shop/login.php
create mode 100644 resources/lang/en/shop/order.php
create mode 100644 resources/lang/en/shop/products.php
create mode 100644 resources/lang/en/shop/steps.php
create mode 100644 resources/lang/en/shop/wishlist.php
create mode 100644 resources/lang/en/user.php
create mode 100644 resources/lang/en/validation.php
create mode 100644 resources/lang/es/address.php
create mode 100644 resources/lang/es/admin/admin_roles.php
create mode 100644 resources/lang/es/admin/attribute.php
create mode 100644 resources/lang/es/admin/attribute_group.php
create mode 100644 resources/lang/es/admin/base.php
create mode 100644 resources/lang/es/admin/brand.php
create mode 100644 resources/lang/es/admin/builder.php
create mode 100644 resources/lang/es/admin/category.php
create mode 100644 resources/lang/es/admin/common.php
create mode 100644 resources/lang/es/admin/country.php
create mode 100644 resources/lang/es/admin/currency.php
create mode 100644 resources/lang/es/admin/customer.php
create mode 100644 resources/lang/es/admin/customer_group.php
create mode 100644 resources/lang/es/admin/dashboard.php
create mode 100644 resources/lang/es/admin/design_builder.php
create mode 100644 resources/lang/es/admin/file_manager.php
create mode 100644 resources/lang/es/admin/forgotten.php
create mode 100644 resources/lang/es/admin/language.php
create mode 100644 resources/lang/es/admin/login.php
create mode 100644 resources/lang/es/admin/marketing.php
create mode 100644 resources/lang/es/admin/order.php
create mode 100644 resources/lang/es/admin/order_shipping.php
create mode 100644 resources/lang/es/admin/page.php
create mode 100644 resources/lang/es/admin/page_category.php
create mode 100644 resources/lang/es/admin/plugin.php
create mode 100644 resources/lang/es/admin/product.php
create mode 100644 resources/lang/es/admin/region.php
create mode 100644 resources/lang/es/admin/rma.php
create mode 100644 resources/lang/es/admin/rma_reason.php
create mode 100644 resources/lang/es/admin/role.php
create mode 100644 resources/lang/es/admin/setting.php
create mode 100644 resources/lang/es/admin/tax_class.php
create mode 100644 resources/lang/es/admin/tax_rate.php
create mode 100644 resources/lang/es/admin/theme.php
create mode 100644 resources/lang/es/admin/user.php
create mode 100644 resources/lang/es/admin/zone.php
create mode 100644 resources/lang/es/auth.php
create mode 100644 resources/lang/es/brand.php
create mode 100644 resources/lang/es/cart.php
create mode 100644 resources/lang/es/category.php
create mode 100644 resources/lang/es/common.php
create mode 100644 resources/lang/es/currency.php
create mode 100644 resources/lang/es/customer.php
create mode 100644 resources/lang/es/customer_group.php
create mode 100644 resources/lang/es/mail.php
create mode 100644 resources/lang/es/order.php
create mode 100644 resources/lang/es/page.php
create mode 100644 resources/lang/es/page_category.php
create mode 100644 resources/lang/es/pagination.php
create mode 100644 resources/lang/es/passwords.php
create mode 100644 resources/lang/es/product.php
create mode 100644 resources/lang/es/rma.php
create mode 100644 resources/lang/es/role.php
create mode 100644 resources/lang/es/shop/account.php
create mode 100644 resources/lang/es/shop/brands.php
create mode 100644 resources/lang/es/shop/carts.php
create mode 100644 resources/lang/es/shop/checkout.php
create mode 100644 resources/lang/es/shop/common.php
create mode 100644 resources/lang/es/shop/currency.php
create mode 100644 resources/lang/es/shop/file.php
create mode 100644 resources/lang/es/shop/forgotten.php
create mode 100644 resources/lang/es/shop/login.php
create mode 100644 resources/lang/es/shop/order.php
create mode 100644 resources/lang/es/shop/products.php
create mode 100644 resources/lang/es/shop/steps.php
create mode 100644 resources/lang/es/shop/wishlist.php
create mode 100644 resources/lang/es/user.php
create mode 100644 resources/lang/es/validation.php
create mode 100644 resources/lang/fr/address.php
create mode 100644 resources/lang/fr/admin/admin_roles.php
create mode 100644 resources/lang/fr/admin/attribute.php
create mode 100644 resources/lang/fr/admin/attribute_group.php
create mode 100644 resources/lang/fr/admin/base.php
create mode 100644 resources/lang/fr/admin/brand.php
create mode 100644 resources/lang/fr/admin/builder.php
create mode 100644 resources/lang/fr/admin/category.php
create mode 100644 resources/lang/fr/admin/common.php
create mode 100644 resources/lang/fr/admin/country.php
create mode 100644 resources/lang/fr/admin/currency.php
create mode 100644 resources/lang/fr/admin/customer.php
create mode 100644 resources/lang/fr/admin/customer_group.php
create mode 100644 resources/lang/fr/admin/dashboard.php
create mode 100644 resources/lang/fr/admin/design_builder.php
create mode 100644 resources/lang/fr/admin/file_manager.php
create mode 100644 resources/lang/fr/admin/forgotten.php
create mode 100644 resources/lang/fr/admin/language.php
create mode 100644 resources/lang/fr/admin/login.php
create mode 100644 resources/lang/fr/admin/marketing.php
create mode 100644 resources/lang/fr/admin/order.php
create mode 100644 resources/lang/fr/admin/page.php
create mode 100644 resources/lang/fr/admin/page_category.php
create mode 100644 resources/lang/fr/admin/plugin.php
create mode 100644 resources/lang/fr/admin/product.php
create mode 100644 resources/lang/fr/admin/region.php
create mode 100644 resources/lang/fr/admin/rma.php
create mode 100644 resources/lang/fr/admin/rma_reason.php
create mode 100644 resources/lang/fr/admin/role.php
create mode 100644 resources/lang/fr/admin/setting.php
create mode 100644 resources/lang/fr/admin/tax_class.php
create mode 100644 resources/lang/fr/admin/tax_rate.php
create mode 100644 resources/lang/fr/admin/theme.php
create mode 100644 resources/lang/fr/admin/user.php
create mode 100644 resources/lang/fr/admin/zone.php
create mode 100644 resources/lang/fr/auth.php
create mode 100644 resources/lang/fr/brand.php
create mode 100644 resources/lang/fr/cart.php
create mode 100644 resources/lang/fr/category.php
create mode 100644 resources/lang/fr/common.php
create mode 100644 resources/lang/fr/currency.php
create mode 100644 resources/lang/fr/customer.php
create mode 100644 resources/lang/fr/customer_group.php
create mode 100644 resources/lang/fr/mail.php
create mode 100644 resources/lang/fr/order.php
create mode 100644 resources/lang/fr/page.php
create mode 100644 resources/lang/fr/page_category.php
create mode 100644 resources/lang/fr/pagination.php
create mode 100644 resources/lang/fr/passwords.php
create mode 100644 resources/lang/fr/product.php
create mode 100644 resources/lang/fr/rma.php
create mode 100644 resources/lang/fr/role.php
create mode 100644 resources/lang/fr/shop/account.php
create mode 100644 resources/lang/fr/shop/brands.php
create mode 100644 resources/lang/fr/shop/carts.php
create mode 100644 resources/lang/fr/shop/checkout.php
create mode 100644 resources/lang/fr/shop/common.php
create mode 100644 resources/lang/fr/shop/currency.php
create mode 100644 resources/lang/fr/shop/file.php
create mode 100644 resources/lang/fr/shop/forgotten.php
create mode 100644 resources/lang/fr/shop/login.php
create mode 100644 resources/lang/fr/shop/order.php
create mode 100644 resources/lang/fr/shop/products.php
create mode 100644 resources/lang/fr/shop/steps.php
create mode 100644 resources/lang/fr/shop/wishlist.php
create mode 100644 resources/lang/fr/user.php
create mode 100644 resources/lang/fr/validation.php
create mode 100644 resources/lang/it/address.php
create mode 100644 resources/lang/it/admin/admin_roles.php
create mode 100644 resources/lang/it/admin/attribute.php
create mode 100644 resources/lang/it/admin/attribute_group.php
create mode 100644 resources/lang/it/admin/base.php
create mode 100644 resources/lang/it/admin/brand.php
create mode 100644 resources/lang/it/admin/builder.php
create mode 100644 resources/lang/it/admin/category.php
create mode 100644 resources/lang/it/admin/common.php
create mode 100644 resources/lang/it/admin/country.php
create mode 100644 resources/lang/it/admin/currency.php
create mode 100644 resources/lang/it/admin/customer.php
create mode 100644 resources/lang/it/admin/customer_group.php
create mode 100644 resources/lang/it/admin/dashboard.php
create mode 100644 resources/lang/it/admin/design_builder.php
create mode 100644 resources/lang/it/admin/file_manager.php
create mode 100644 resources/lang/it/admin/forgotten.php
create mode 100644 resources/lang/it/admin/language.php
create mode 100644 resources/lang/it/admin/login.php
create mode 100644 resources/lang/it/admin/marketing.php
create mode 100644 resources/lang/it/admin/order.php
create mode 100644 resources/lang/it/admin/page.php
create mode 100644 resources/lang/it/admin/page_category.php
create mode 100644 resources/lang/it/admin/plugin.php
create mode 100644 resources/lang/it/admin/product.php
create mode 100644 resources/lang/it/admin/region.php
create mode 100644 resources/lang/it/admin/rma.php
create mode 100644 resources/lang/it/admin/rma_reason.php
create mode 100644 resources/lang/it/admin/role.php
create mode 100644 resources/lang/it/admin/setting.php
create mode 100644 resources/lang/it/admin/tax_class.php
create mode 100644 resources/lang/it/admin/tax_rate.php
create mode 100644 resources/lang/it/admin/theme.php
create mode 100644 resources/lang/it/admin/user.php
create mode 100644 resources/lang/it/admin/zone.php
create mode 100644 resources/lang/it/auth.php
create mode 100644 resources/lang/it/brand.php
create mode 100644 resources/lang/it/cart.php
create mode 100644 resources/lang/it/category.php
create mode 100644 resources/lang/it/common.php
create mode 100644 resources/lang/it/currency.php
create mode 100644 resources/lang/it/customer.php
create mode 100644 resources/lang/it/customer_group.php
create mode 100644 resources/lang/it/mail.php
create mode 100644 resources/lang/it/order.php
create mode 100644 resources/lang/it/page.php
create mode 100644 resources/lang/it/page_category.php
create mode 100644 resources/lang/it/pagination.php
create mode 100644 resources/lang/it/passwords.php
create mode 100644 resources/lang/it/product.php
create mode 100644 resources/lang/it/rma.php
create mode 100644 resources/lang/it/role.php
create mode 100644 resources/lang/it/shop/account.php
create mode 100644 resources/lang/it/shop/brands.php
create mode 100644 resources/lang/it/shop/carts.php
create mode 100644 resources/lang/it/shop/checkout.php
create mode 100644 resources/lang/it/shop/common.php
create mode 100644 resources/lang/it/shop/currency.php
create mode 100644 resources/lang/it/shop/file.php
create mode 100644 resources/lang/it/shop/forgotten.php
create mode 100644 resources/lang/it/shop/login.php
create mode 100644 resources/lang/it/shop/order.php
create mode 100644 resources/lang/it/shop/products.php
create mode 100644 resources/lang/it/shop/steps.php
create mode 100644 resources/lang/it/shop/wishlist.php
create mode 100644 resources/lang/it/user.php
create mode 100644 resources/lang/it/validation.php
create mode 100644 resources/lang/ja/address.php
create mode 100644 resources/lang/ja/admin/admin_roles.php
create mode 100644 resources/lang/ja/admin/attribute.php
create mode 100644 resources/lang/ja/admin/attribute_group.php
create mode 100644 resources/lang/ja/admin/base.php
create mode 100644 resources/lang/ja/admin/brand.php
create mode 100644 resources/lang/ja/admin/builder.php
create mode 100644 resources/lang/ja/admin/category.php
create mode 100644 resources/lang/ja/admin/common.php
create mode 100644 resources/lang/ja/admin/country.php
create mode 100644 resources/lang/ja/admin/currency.php
create mode 100644 resources/lang/ja/admin/customer.php
create mode 100644 resources/lang/ja/admin/customer_group.php
create mode 100644 resources/lang/ja/admin/dashboard.php
create mode 100644 resources/lang/ja/admin/design_builder.php
create mode 100644 resources/lang/ja/admin/file_manager.php
create mode 100644 resources/lang/ja/admin/forgotten.php
create mode 100644 resources/lang/ja/admin/language.php
create mode 100644 resources/lang/ja/admin/login.php
create mode 100644 resources/lang/ja/admin/marketing.php
create mode 100644 resources/lang/ja/admin/order.php
create mode 100644 resources/lang/ja/admin/page.php
create mode 100644 resources/lang/ja/admin/page_category.php
create mode 100644 resources/lang/ja/admin/plugin.php
create mode 100644 resources/lang/ja/admin/product.php
create mode 100644 resources/lang/ja/admin/region.php
create mode 100644 resources/lang/ja/admin/rma.php
create mode 100644 resources/lang/ja/admin/rma_reason.php
create mode 100644 resources/lang/ja/admin/role.php
create mode 100644 resources/lang/ja/admin/setting.php
create mode 100644 resources/lang/ja/admin/tax_class.php
create mode 100644 resources/lang/ja/admin/tax_rate.php
create mode 100644 resources/lang/ja/admin/theme.php
create mode 100644 resources/lang/ja/admin/user.php
create mode 100644 resources/lang/ja/admin/zone.php
create mode 100644 resources/lang/ja/auth.php
create mode 100644 resources/lang/ja/brand.php
create mode 100644 resources/lang/ja/cart.php
create mode 100644 resources/lang/ja/category.php
create mode 100644 resources/lang/ja/common.php
create mode 100644 resources/lang/ja/currency.php
create mode 100644 resources/lang/ja/customer.php
create mode 100644 resources/lang/ja/customer_group.php
create mode 100644 resources/lang/ja/mail.php
create mode 100644 resources/lang/ja/order.php
create mode 100644 resources/lang/ja/page.php
create mode 100644 resources/lang/ja/page_category.php
create mode 100644 resources/lang/ja/pagination.php
create mode 100644 resources/lang/ja/passwords.php
create mode 100644 resources/lang/ja/product.php
create mode 100644 resources/lang/ja/rma.php
create mode 100644 resources/lang/ja/role.php
create mode 100644 resources/lang/ja/shop/account.php
create mode 100644 resources/lang/ja/shop/brands.php
create mode 100644 resources/lang/ja/shop/carts.php
create mode 100644 resources/lang/ja/shop/checkout.php
create mode 100644 resources/lang/ja/shop/common.php
create mode 100644 resources/lang/ja/shop/currency.php
create mode 100644 resources/lang/ja/shop/file.php
create mode 100644 resources/lang/ja/shop/forgotten.php
create mode 100644 resources/lang/ja/shop/login.php
create mode 100644 resources/lang/ja/shop/order.php
create mode 100644 resources/lang/ja/shop/products.php
create mode 100644 resources/lang/ja/shop/steps.php
create mode 100644 resources/lang/ja/shop/wishlist.php
create mode 100644 resources/lang/ja/user.php
create mode 100644 resources/lang/ja/validation.php
create mode 100644 resources/lang/ru/address.php
create mode 100644 resources/lang/ru/admin/admin_roles.php
create mode 100644 resources/lang/ru/admin/attribute.php
create mode 100644 resources/lang/ru/admin/attribute_group.php
create mode 100644 resources/lang/ru/admin/base.php
create mode 100644 resources/lang/ru/admin/brand.php
create mode 100644 resources/lang/ru/admin/builder.php
create mode 100644 resources/lang/ru/admin/category.php
create mode 100644 resources/lang/ru/admin/common.php
create mode 100644 resources/lang/ru/admin/country.php
create mode 100644 resources/lang/ru/admin/currency.php
create mode 100644 resources/lang/ru/admin/customer.php
create mode 100644 resources/lang/ru/admin/customer_group.php
create mode 100644 resources/lang/ru/admin/dashboard.php
create mode 100644 resources/lang/ru/admin/design_builder.php
create mode 100644 resources/lang/ru/admin/file_manager.php
create mode 100644 resources/lang/ru/admin/forgotten.php
create mode 100644 resources/lang/ru/admin/language.php
create mode 100644 resources/lang/ru/admin/login.php
create mode 100644 resources/lang/ru/admin/marketing.php
create mode 100644 resources/lang/ru/admin/order.php
create mode 100644 resources/lang/ru/admin/page.php
create mode 100644 resources/lang/ru/admin/page_category.php
create mode 100644 resources/lang/ru/admin/plugin.php
create mode 100644 resources/lang/ru/admin/product.php
create mode 100644 resources/lang/ru/admin/region.php
create mode 100644 resources/lang/ru/admin/rma.php
create mode 100644 resources/lang/ru/admin/rma_reason.php
create mode 100644 resources/lang/ru/admin/role.php
create mode 100644 resources/lang/ru/admin/setting.php
create mode 100644 resources/lang/ru/admin/tax_class.php
create mode 100644 resources/lang/ru/admin/tax_rate.php
create mode 100644 resources/lang/ru/admin/theme.php
create mode 100644 resources/lang/ru/admin/user.php
create mode 100644 resources/lang/ru/admin/zone.php
create mode 100644 resources/lang/ru/auth.php
create mode 100644 resources/lang/ru/brand.php
create mode 100644 resources/lang/ru/cart.php
create mode 100644 resources/lang/ru/category.php
create mode 100644 resources/lang/ru/common.php
create mode 100644 resources/lang/ru/currency.php
create mode 100644 resources/lang/ru/customer.php
create mode 100644 resources/lang/ru/customer_group.php
create mode 100644 resources/lang/ru/mail.php
create mode 100644 resources/lang/ru/order.php
create mode 100644 resources/lang/ru/page.php
create mode 100644 resources/lang/ru/page_category.php
create mode 100644 resources/lang/ru/pagination.php
create mode 100644 resources/lang/ru/passwords.php
create mode 100644 resources/lang/ru/product.php
create mode 100644 resources/lang/ru/rma.php
create mode 100644 resources/lang/ru/role.php
create mode 100644 resources/lang/ru/shop/account.php
create mode 100644 resources/lang/ru/shop/brands.php
create mode 100644 resources/lang/ru/shop/carts.php
create mode 100644 resources/lang/ru/shop/checkout.php
create mode 100644 resources/lang/ru/shop/common.php
create mode 100644 resources/lang/ru/shop/currency.php
create mode 100644 resources/lang/ru/shop/file.php
create mode 100644 resources/lang/ru/shop/forgotten.php
create mode 100644 resources/lang/ru/shop/login.php
create mode 100644 resources/lang/ru/shop/order.php
create mode 100644 resources/lang/ru/shop/products.php
create mode 100644 resources/lang/ru/shop/steps.php
create mode 100644 resources/lang/ru/shop/wishlist.php
create mode 100644 resources/lang/ru/user.php
create mode 100644 resources/lang/ru/validation.php
create mode 100644 resources/lang/zh_cn/address.php
create mode 100644 resources/lang/zh_cn/admin/admin_roles.php
create mode 100644 resources/lang/zh_cn/admin/attribute.php
create mode 100644 resources/lang/zh_cn/admin/attribute_group.php
create mode 100644 resources/lang/zh_cn/admin/base.php
create mode 100644 resources/lang/zh_cn/admin/brand.php
create mode 100644 resources/lang/zh_cn/admin/builder.php
create mode 100644 resources/lang/zh_cn/admin/category.php
create mode 100644 resources/lang/zh_cn/admin/common.php
create mode 100644 resources/lang/zh_cn/admin/country.php
create mode 100644 resources/lang/zh_cn/admin/currency.php
create mode 100644 resources/lang/zh_cn/admin/customer.php
create mode 100644 resources/lang/zh_cn/admin/customer_group.php
create mode 100644 resources/lang/zh_cn/admin/dashboard.php
create mode 100644 resources/lang/zh_cn/admin/design_builder.php
create mode 100644 resources/lang/zh_cn/admin/file_manager.php
create mode 100644 resources/lang/zh_cn/admin/forgotten.php
create mode 100644 resources/lang/zh_cn/admin/language.php
create mode 100644 resources/lang/zh_cn/admin/login.php
create mode 100644 resources/lang/zh_cn/admin/marketing.php
create mode 100644 resources/lang/zh_cn/admin/order.php
create mode 100644 resources/lang/zh_cn/admin/page.php
create mode 100644 resources/lang/zh_cn/admin/page_category.php
create mode 100644 resources/lang/zh_cn/admin/plugin.php
create mode 100644 resources/lang/zh_cn/admin/product.php
create mode 100644 resources/lang/zh_cn/admin/region.php
create mode 100644 resources/lang/zh_cn/admin/rma.php
create mode 100644 resources/lang/zh_cn/admin/rma_reason.php
create mode 100644 resources/lang/zh_cn/admin/role.php
create mode 100644 resources/lang/zh_cn/admin/setting.php
create mode 100644 resources/lang/zh_cn/admin/tax_class.php
create mode 100644 resources/lang/zh_cn/admin/tax_rate.php
create mode 100644 resources/lang/zh_cn/admin/theme.php
create mode 100644 resources/lang/zh_cn/admin/user.php
create mode 100644 resources/lang/zh_cn/admin/zone.php
create mode 100644 resources/lang/zh_cn/auth.php
create mode 100644 resources/lang/zh_cn/brand.php
create mode 100644 resources/lang/zh_cn/cart.php
create mode 100644 resources/lang/zh_cn/category.php
create mode 100644 resources/lang/zh_cn/common.php
create mode 100644 resources/lang/zh_cn/currency.php
create mode 100644 resources/lang/zh_cn/customer.php
create mode 100644 resources/lang/zh_cn/customer_group.php
create mode 100644 resources/lang/zh_cn/mail.php
create mode 100644 resources/lang/zh_cn/order.php
create mode 100644 resources/lang/zh_cn/page.php
create mode 100644 resources/lang/zh_cn/page_category.php
create mode 100644 resources/lang/zh_cn/pagination.php
create mode 100644 resources/lang/zh_cn/passwords.php
create mode 100644 resources/lang/zh_cn/product.php
create mode 100644 resources/lang/zh_cn/rma.php
create mode 100644 resources/lang/zh_cn/role.php
create mode 100644 resources/lang/zh_cn/shop/account.php
create mode 100644 resources/lang/zh_cn/shop/brands.php
create mode 100644 resources/lang/zh_cn/shop/carts.php
create mode 100644 resources/lang/zh_cn/shop/checkout.php
create mode 100644 resources/lang/zh_cn/shop/common.php
create mode 100644 resources/lang/zh_cn/shop/currency.php
create mode 100644 resources/lang/zh_cn/shop/file.php
create mode 100644 resources/lang/zh_cn/shop/forgotten.php
create mode 100644 resources/lang/zh_cn/shop/login.php
create mode 100644 resources/lang/zh_cn/shop/order.php
create mode 100644 resources/lang/zh_cn/shop/products.php
create mode 100644 resources/lang/zh_cn/shop/steps.php
create mode 100644 resources/lang/zh_cn/shop/wishlist.php
create mode 100644 resources/lang/zh_cn/user.php
create mode 100644 resources/lang/zh_cn/validation.php
create mode 100644 resources/lang/zh_hk/address.php
create mode 100644 resources/lang/zh_hk/admin/admin_roles.php
create mode 100644 resources/lang/zh_hk/admin/attribute.php
create mode 100644 resources/lang/zh_hk/admin/attribute_group.php
create mode 100644 resources/lang/zh_hk/admin/base.php
create mode 100644 resources/lang/zh_hk/admin/brand.php
create mode 100644 resources/lang/zh_hk/admin/builder.php
create mode 100644 resources/lang/zh_hk/admin/category.php
create mode 100644 resources/lang/zh_hk/admin/common.php
create mode 100644 resources/lang/zh_hk/admin/country.php
create mode 100644 resources/lang/zh_hk/admin/currency.php
create mode 100644 resources/lang/zh_hk/admin/customer.php
create mode 100644 resources/lang/zh_hk/admin/customer_group.php
create mode 100644 resources/lang/zh_hk/admin/dashboard.php
create mode 100644 resources/lang/zh_hk/admin/design_builder.php
create mode 100644 resources/lang/zh_hk/admin/file_manager.php
create mode 100644 resources/lang/zh_hk/admin/forgotten.php
create mode 100644 resources/lang/zh_hk/admin/language.php
create mode 100644 resources/lang/zh_hk/admin/login.php
create mode 100644 resources/lang/zh_hk/admin/marketing.php
create mode 100644 resources/lang/zh_hk/admin/order.php
create mode 100644 resources/lang/zh_hk/admin/page.php
create mode 100644 resources/lang/zh_hk/admin/page_category.php
create mode 100644 resources/lang/zh_hk/admin/plugin.php
create mode 100644 resources/lang/zh_hk/admin/product.php
create mode 100644 resources/lang/zh_hk/admin/region.php
create mode 100644 resources/lang/zh_hk/admin/rma.php
create mode 100644 resources/lang/zh_hk/admin/rma_reason.php
create mode 100644 resources/lang/zh_hk/admin/role.php
create mode 100644 resources/lang/zh_hk/admin/setting.php
create mode 100644 resources/lang/zh_hk/admin/tax_class.php
create mode 100644 resources/lang/zh_hk/admin/tax_rate.php
create mode 100644 resources/lang/zh_hk/admin/theme.php
create mode 100644 resources/lang/zh_hk/admin/user.php
create mode 100644 resources/lang/zh_hk/admin/zone.php
create mode 100644 resources/lang/zh_hk/auth.php
create mode 100644 resources/lang/zh_hk/brand.php
create mode 100644 resources/lang/zh_hk/cart.php
create mode 100644 resources/lang/zh_hk/category.php
create mode 100644 resources/lang/zh_hk/common.php
create mode 100644 resources/lang/zh_hk/currency.php
create mode 100644 resources/lang/zh_hk/customer.php
create mode 100644 resources/lang/zh_hk/customer_group.php
create mode 100644 resources/lang/zh_hk/mail.php
create mode 100644 resources/lang/zh_hk/order.php
create mode 100644 resources/lang/zh_hk/page.php
create mode 100644 resources/lang/zh_hk/page_category.php
create mode 100644 resources/lang/zh_hk/pagination.php
create mode 100644 resources/lang/zh_hk/passwords.php
create mode 100644 resources/lang/zh_hk/product.php
create mode 100644 resources/lang/zh_hk/rma.php
create mode 100644 resources/lang/zh_hk/role.php
create mode 100644 resources/lang/zh_hk/shop/account.php
create mode 100644 resources/lang/zh_hk/shop/brands.php
create mode 100644 resources/lang/zh_hk/shop/carts.php
create mode 100644 resources/lang/zh_hk/shop/checkout.php
create mode 100644 resources/lang/zh_hk/shop/common.php
create mode 100644 resources/lang/zh_hk/shop/currency.php
create mode 100644 resources/lang/zh_hk/shop/file.php
create mode 100644 resources/lang/zh_hk/shop/forgotten.php
create mode 100644 resources/lang/zh_hk/shop/login.php
create mode 100644 resources/lang/zh_hk/shop/order.php
create mode 100644 resources/lang/zh_hk/shop/products.php
create mode 100644 resources/lang/zh_hk/shop/steps.php
create mode 100644 resources/lang/zh_hk/shop/wishlist.php
create mode 100644 resources/lang/zh_hk/user.php
create mode 100644 resources/lang/zh_hk/validation.php
create mode 100644 resources/views/vendor/sitemap/google-news.php
create mode 100644 resources/views/vendor/sitemap/html.php
create mode 100644 resources/views/vendor/sitemap/ror-rdf.php
create mode 100644 resources/views/vendor/sitemap/ror-rss.php
create mode 100644 resources/views/vendor/sitemap/sitemapindex.php
create mode 100644 resources/views/vendor/sitemap/txt.php
create mode 100644 resources/views/vendor/sitemap/xml-mobile.php
create mode 100644 resources/views/vendor/sitemap/xml.php
create mode 100644 resources/views/vendor/unisharp/markdown.blade.php
create mode 100644 routes/api.php
create mode 100644 routes/channels.php
create mode 100644 routes/console.php
create mode 100644 routes/web.php
create mode 100644 server.php
create mode 100644 storage/app/.gitignore
create mode 100644 storage/debugbar/.gitignore
create mode 100644 storage/framework/.gitignore
create mode 100644 storage/framework/cache/.gitignore
create mode 100644 storage/framework/sessions/.gitignore
create mode 100644 storage/framework/testing/.gitignore
create mode 100644 storage/framework/views/.gitignore
create mode 100644 storage/installed
create mode 100644 storage/logs/.gitignore
create mode 100644 storage/upload/.gitignore
create mode 100644 tests/CreatesApplication.php
create mode 100644 tests/Feature/ExampleTest.php
create mode 100644 tests/TestCase.php
create mode 100644 tests/Unit/ExampleTest.php
create mode 100644 webpack.mix.js
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..787d50ea
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,21 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{js,scss,blade.php}]
+indent_size = 2
+
+[*.{yml,yaml}]
+indent_size = 2
+
+[docker-compose.yml]
+indent_size = 4
diff --git a/.env b/.env
new file mode 100644
index 00000000..db4e8122
--- /dev/null
+++ b/.env
@@ -0,0 +1,28 @@
+APP_NAME='BeikeShop'
+APP_ENV=
+APP_KEY=base64:PItUypiY6FmV8oQTVIcIHyNQJAuuS36FmEs8exQbYAw=
+APP_DEBUG=false
+APP_LOG_LEVEL=
+APP_URL=http://43.153.17.83
+
+BEIKE_API_URL=https://beikeshop.com
+
+DB_CONNECTION=mysql
+DB_HOST=127.0.0.1
+DB_PORT=3306
+DB_DATABASE=wyyl
+DB_USERNAME=wyyl
+DB_PASSWORD='wyyl@2023'
+
+BROADCAST_DRIVER=log
+CACHE_DRIVER=file
+SESSION_DRIVER=file
+QUEUE_CONNECTION=sync
+
+MAIL_DRIVER=
+MAIL_HOST=
+MAIL_PORT=
+MAIL_USERNAME=
+MAIL_PASSWORD=
+MAIL_ENCRYPTION=
+
diff --git a/.htaccess b/.htaccess
new file mode 100644
index 00000000..3aec5e27
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,21 @@
+
+
+
+请保留我公司版权信息,如要移除,需要我公司授权。
+
+
+## BeikeShop系统亮点
+- **全新!支持ChatGPT:BeikeShop1.3.2 集成ChatGPT,打造高效智能化跨境电商系统**
+- 开源免费:BeikeShop以开源方式发布,OSL-3.0协议允许用户自由使用、修改。
+- 轻量级框架:BeikeShop基于Laravel框架开发,具有高效、灵活、易用等特点。
+- 灵活的插件机制:BeikeShop提供灵活的Hook插件机制,可以方便地扩展和定制系统功能。
+- 多语言多货币支持:支持多种语言/货币切换,可灵活扩展其他语言/货币。
+- 多种支付方式:支持 PayPal、Stripe、Alipay、WeChat Pay 等多种支付方式,覆盖全球主要外贸国家
+- 快速搭建:向VIP提供一键安装脚本,帮助用户快速搭建起一个稳定、高效、易用的跨境电商独立站。
+
+
+
+
+
+
+
+
+
+## 安装教程(面向非开发者)
+1. 下载BeikeShop
+1. 上传到你的服务器并解压
+1. 将解压文件夹下的 public 设置为网站根目录
+1. 通过浏览器访问网站根据提示完成安装
+1. BeikeShop详细安装指引
+1. 如需升级请下载最新版覆盖到服务器后网站根目录运行`composer install && php artisan migrate`
+
+## 安装教程(面向开发者)
+1. 打开命令行克隆代码 `git clone https://gitee.com/beikeshop/beikeshop.git`
+1. 命令行进入 `beikeshop` 目录, 执行 `composer install` 安装第三方包
+1. 接着执行 `cp .env.example .env` 创建配置文件
+1. 接着执行 `npm install`(node 版本需16+) 以及 `npm run dev` 编译前端 js 和 css 文件
+1. 将项目文件夹下的 `public` 设置为网站根目录
+1. 通过浏览器访问网站, 根据提示完成安装
+1. 如需升级请在服务器端网站根目录运行`git pull && composer install && php artisan migrate`
+
+## 参与贡献
+1. Fork 本仓库
+1. 新建 feature-xxx 分支
+1. 提交代码
+1. 新建 Merge Request
+
+## QQ交流群:
+群1: 639108380
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
new file mode 100644
index 00000000..3c8d77dd
--- /dev/null
+++ b/app/Console/Kernel.php
@@ -0,0 +1,32 @@
+command('inspire')->hourly();
+ }
+
+ /**
+ * Register the commands for the application.
+ *
+ * @return void
+ */
+ protected function commands()
+ {
+ $this->load(__DIR__ . '/Commands');
+
+ require base_path('routes/console.php');
+ }
+}
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
new file mode 100644
index 00000000..0dc01dda
--- /dev/null
+++ b/app/Exceptions/Handler.php
@@ -0,0 +1,75 @@
+reportable(function (Throwable $e) {
+ //
+ });
+ }
+
+ /**
+ * Convert the given exception to an array.
+ *
+ * @param \Throwable $e
+ * @return array
+ */
+ protected function convertExceptionToArray(Throwable $e)
+ {
+
+ return config('app.debug') ? [
+ 'message' => $e->getMessage(),
+ 'exception' => get_class($e),
+ 'file' => $e->getFile(),
+ 'line' => $e->getLine(),
+ 'trace' => collect($e->getTrace())->map(fn ($trace) => Arr::except($trace, ['args']))->all(),
+ ] : [
+ 'message' => $this->isHttpException($e) ? $e->getMessage() : 'Server Error',
+ ];
+ }
+
+ /**
+ * 自定义错误信息页面, 前台与后台不同, 需要分开定义
+ */
+ protected function registerErrorViewPaths()
+ {
+ if (is_admin()) {
+ (new RegisterAdminErrorViewPaths())();
+ } else {
+ (new RegisterErrorViewPaths())();
+ }
+ }
+}
diff --git a/app/Exceptions/RegisterAdminErrorViewPaths.php b/app/Exceptions/RegisterAdminErrorViewPaths.php
new file mode 100644
index 00000000..3cfa6d56
--- /dev/null
+++ b/app/Exceptions/RegisterAdminErrorViewPaths.php
@@ -0,0 +1,23 @@
+map(function ($path) {
+ return "{$path}/errors";
+ })->all());
+ }
+ }
+}
diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php
new file mode 100644
index 00000000..a0a2a8a3
--- /dev/null
+++ b/app/Http/Controllers/Controller.php
@@ -0,0 +1,13 @@
+ locale => share_data => error_page
+ * @var array
+ */
+ protected $middlewareGroups = [
+ 'shop' => [
+ \App\Http\Middleware\EncryptCookies::class,
+ \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+ \Illuminate\Session\Middleware\StartSession::class,
+ // \Illuminate\Session\Middleware\AuthenticateSession::class,
+ \App\Http\Middleware\SetLocaleFromSession::class,
+ \App\Http\Middleware\ShareViewData::class,
+ \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+ \App\Http\Middleware\VerifyCsrfToken::class,
+ \Illuminate\Routing\Middleware\SubstituteBindings::class,
+ ],
+ 'admin' => [
+ \App\Http\Middleware\EncryptCookies::class,
+ \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+ \Illuminate\Session\Middleware\StartSession::class,
+ \App\Http\Middleware\SetLocaleAdmin::class,
+ \App\Http\Middleware\ShareViewData::class,
+ \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+ \App\Http\Middleware\VerifyCsrfToken::class,
+ \Illuminate\Routing\Middleware\SubstituteBindings::class,
+ ],
+ 'installer' => [
+ \App\Http\Middleware\EncryptCookies::class,
+ \Illuminate\Session\Middleware\StartSession::class,
+ \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+ ],
+
+ 'web' => [
+ \App\Http\Middleware\EncryptCookies::class,
+ \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+ \Illuminate\Session\Middleware\StartSession::class,
+ // \Illuminate\Session\Middleware\AuthenticateSession::class,
+ \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+ \App\Http\Middleware\VerifyCsrfToken::class,
+ \Illuminate\Routing\Middleware\SubstituteBindings::class,
+ ],
+ 'api' => [
+ // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
+ 'throttle:api',
+ \Illuminate\Routing\Middleware\SubstituteBindings::class,
+ ],
+ ];
+
+ /**
+ * The application's route middleware.
+ *
+ * These middleware may be assigned to groups or used individually.
+ *
+ * @var array
+ */
+ protected $routeMiddleware = [
+ 'admin_auth' => \App\Http\Middleware\Authenticate::class,
+ 'shop_auth' => \App\Http\Middleware\ShopAuthenticate::class,
+ 'checkout_auth' => \App\Http\Middleware\CheckoutAuthenticate::class,
+ 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
+ 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
+ 'can' => \Illuminate\Auth\Middleware\Authorize::class,
+ 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
+ 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
+ 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
+ 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
+ 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
+ ];
+}
diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php
new file mode 100644
index 00000000..7f26ada0
--- /dev/null
+++ b/app/Http/Middleware/Authenticate.php
@@ -0,0 +1,22 @@
+expectsJson()) {
+ // 后台
+ return admin_route('login.show');
+ }
+ }
+}
diff --git a/app/Http/Middleware/CheckoutAuthenticate.php b/app/Http/Middleware/CheckoutAuthenticate.php
new file mode 100644
index 00000000..7a82cf0c
--- /dev/null
+++ b/app/Http/Middleware/CheckoutAuthenticate.php
@@ -0,0 +1,72 @@
+authenticate($request, $guards);
+
+ $customer = current_customer();
+ if ($customer->status != 1) {
+ Auth::guard(Customer::AUTH_GUARD)->logout();
+
+ return redirect(shop_route('login.index'));
+ }
+
+ return $next($request);
+ }
+
+ /**
+ * Get the path the user should be redirected to when they are not authenticated.
+ *
+ * @param Request $request
+ */
+ protected function redirectTo($request)
+ {
+ if (! $request->expectsJson()) {
+ return shop_route('login.index');
+ }
+ }
+
+ /**
+ * Handle an unauthenticated user.
+ *
+ * @param Request $request
+ * @param array $guards
+ * @return void
+ *
+ * @throws AuthenticationException
+ */
+ protected function unauthenticated($request, array $guards)
+ {
+ if (system_setting('base.guest_checkout', 1)) {
+ return;
+ }
+
+ throw new AuthenticationException(
+ trans('common.unauthenticated'), $guards, $this->redirectTo($request)
+ );
+ }
+}
diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php
new file mode 100644
index 00000000..033136ad
--- /dev/null
+++ b/app/Http/Middleware/EncryptCookies.php
@@ -0,0 +1,17 @@
+check()) {
+ return redirect(RouteServiceProvider::HOME);
+ }
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/SetLocaleAdmin.php b/app/Http/Middleware/SetLocaleAdmin.php
new file mode 100644
index 00000000..30c03c9b
--- /dev/null
+++ b/app/Http/Middleware/SetLocaleAdmin.php
@@ -0,0 +1,29 @@
+locale ?? 'zh_cn';
+ if (in_array($currentLocale, admin_languages())) {
+ App::setLocale($currentLocale);
+ } else {
+ App::setLocale('en');
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/SetLocaleFromSession.php b/app/Http/Middleware/SetLocaleFromSession.php
new file mode 100644
index 00000000..06feb132
--- /dev/null
+++ b/app/Http/Middleware/SetLocaleFromSession.php
@@ -0,0 +1,31 @@
+toArray())) {
+ App::setLocale($sessionLocale);
+ } else {
+ $configLocale = system_setting('base.locale');
+ App::setLocale($configLocale);
+ session(['locale' => $configLocale]);
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/SetLocaleInstaller.php b/app/Http/Middleware/SetLocaleInstaller.php
new file mode 100644
index 00000000..97955f2d
--- /dev/null
+++ b/app/Http/Middleware/SetLocaleInstaller.php
@@ -0,0 +1,35 @@
+getEnvContent();
+
+ if ($locale && in_array($locale, $languages)) {
+ App::setLocale($locale);
+ } else {
+ App::setLocale('zh_cn');
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/ShareViewData.php b/app/Http/Middleware/ShareViewData.php
new file mode 100644
index 00000000..60291c70
--- /dev/null
+++ b/app/Http/Middleware/ShareViewData.php
@@ -0,0 +1,75 @@
+
+ * @created 2022-08-03 15:46:13
+ * @modified 2022-08-03 15:46:13
+ */
+
+namespace App\Http\Middleware;
+
+use Beike\Repositories\FooterRepo;
+use Beike\Repositories\LanguageRepo;
+use Beike\Repositories\MenuRepo;
+use Closure;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\View;
+
+class ShareViewData
+{
+ public function handle(Request $request, Closure $next)
+ {
+ $this->loadShopShareViewData();
+
+ return $next($request);
+ }
+
+ /**
+ * @throws \Exception
+ */
+ protected function loadShopShareViewData()
+ {
+ if (is_admin()) {
+ $adminLanguages = $this->handleAdminLanguages();
+ $loggedAdminUser = current_user();
+ if ($loggedAdminUser) {
+ $currentLanguage = $loggedAdminUser->locale ?: 'en';
+ View::share('admin_languages', $adminLanguages);
+ View::share('admin_language', collect($adminLanguages)->where('code', $currentLanguage)->first());
+ }
+ } else {
+ View::share('design', request('design') == 1);
+ View::share('languages', LanguageRepo::enabled());
+ View::share('shop_base_url', shop_route('home.index'));
+ View::share('footer_content', hook_filter('footer.content', FooterRepo::handleFooterData()));
+ View::share('menu_content', hook_filter('menu.content', MenuRepo::handleMenuData()));
+ }
+ }
+
+ /**
+ * 处理后台语言包列表
+ *
+ * @return array
+ */
+ private function handleAdminLanguages(): array
+ {
+ $items = [];
+ $languages = admin_languages();
+ foreach ($languages as $language) {
+ $path = lang_path("{$language}/admin/base.php");
+ if (file_exists($path)) {
+ $baseData = require_once $path;
+ }
+ $name = $baseData['name'] ?? '';
+ $items[] = [
+ 'code' => $language,
+ 'name' => $name,
+ ];
+ }
+
+ return $items;
+ }
+}
diff --git a/app/Http/Middleware/ShopAuthenticate.php b/app/Http/Middleware/ShopAuthenticate.php
new file mode 100644
index 00000000..ad363db3
--- /dev/null
+++ b/app/Http/Middleware/ShopAuthenticate.php
@@ -0,0 +1,64 @@
+authenticate($request, $guards);
+
+ $customer = current_customer();
+ if ($customer->status != 1) {
+ Auth::guard(Customer::AUTH_GUARD)->logout();
+
+ return redirect(shop_route('login.index'));
+ }
+
+ return $next($request);
+ }
+
+ /**
+ * Get the path the user should be redirected to when they are not authenticated.
+ *
+ * @param Request $request
+ */
+ protected function redirectTo($request)
+ {
+ if (! $request->expectsJson()) {
+ return shop_route('login.index');
+ }
+ }
+
+ /**
+ * Handle an unauthenticated user.
+ *
+ * @param Request $request
+ * @param array $guards
+ * @return void
+ *
+ * @throws AuthenticationException
+ */
+ protected function unauthenticated($request, array $guards)
+ {
+ throw new AuthenticationException(
+ trans('common.unauthenticated'), $guards, $this->redirectTo($request)
+ );
+ }
+}
diff --git a/app/Http/Middleware/TrimStrings.php b/app/Http/Middleware/TrimStrings.php
new file mode 100644
index 00000000..a8a252df
--- /dev/null
+++ b/app/Http/Middleware/TrimStrings.php
@@ -0,0 +1,19 @@
+allSubdomainsOfApplicationUrl(),
+ ];
+ }
+}
diff --git a/app/Http/Middleware/TrustProxies.php b/app/Http/Middleware/TrustProxies.php
new file mode 100644
index 00000000..beb5d137
--- /dev/null
+++ b/app/Http/Middleware/TrustProxies.php
@@ -0,0 +1,28 @@
+ 'required|string|max:100|min:10',
+ ];
+ }
+}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
new file mode 100644
index 00000000..4843b8de
--- /dev/null
+++ b/app/Providers/AppServiceProvider.php
@@ -0,0 +1,31 @@
+ 'App\Policies\ModelPolicy',
+ ];
+
+ /**
+ * Register any authentication / authorization services.
+ *
+ * @return void
+ */
+ public function boot()
+ {
+ $this->registerPolicies();
+
+ Gate::before(function ($user, $ability) {
+ return $user->id == 1;
+ });
+ }
+}
diff --git a/app/Providers/BroadcastServiceProvider.php b/app/Providers/BroadcastServiceProvider.php
new file mode 100644
index 00000000..395c518b
--- /dev/null
+++ b/app/Providers/BroadcastServiceProvider.php
@@ -0,0 +1,21 @@
+ [
+ // SendEmailVerificationNotification::class,
+ // ],
+ ];
+
+ /**
+ * Register any events for your application.
+ *
+ * @return void
+ */
+ public function boot()
+ {
+ //
+ }
+}
diff --git a/app/Providers/HorizonServiceProvider.php b/app/Providers/HorizonServiceProvider.php
new file mode 100644
index 00000000..251266a9
--- /dev/null
+++ b/app/Providers/HorizonServiceProvider.php
@@ -0,0 +1,42 @@
+email, [
+
+ ]);
+ });
+ }
+}
diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php
new file mode 100644
index 00000000..3bd3c81e
--- /dev/null
+++ b/app/Providers/RouteServiceProvider.php
@@ -0,0 +1,63 @@
+configureRateLimiting();
+
+ $this->routes(function () {
+ Route::prefix('api')
+ ->middleware('api')
+ ->namespace($this->namespace)
+ ->group(base_path('routes/api.php'));
+
+ Route::middleware('web')
+ ->namespace($this->namespace)
+ ->group(base_path('routes/web.php'));
+ });
+ }
+
+ /**
+ * Configure the rate limiters for the application.
+ *
+ * @return void
+ */
+ protected function configureRateLimiting()
+ {
+ RateLimiter::for('api', function (Request $request) {
+ return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
+ });
+ }
+}
diff --git a/artisan b/artisan
new file mode 100644
index 00000000..67a3329b
--- /dev/null
+++ b/artisan
@@ -0,0 +1,53 @@
+#!/usr/bin/env php
+make(Illuminate\Contracts\Console\Kernel::class);
+
+$status = $kernel->handle(
+ $input = new Symfony\Component\Console\Input\ArgvInput,
+ new Symfony\Component\Console\Output\ConsoleOutput
+);
+
+/*
+|--------------------------------------------------------------------------
+| Shutdown The Application
+|--------------------------------------------------------------------------
+|
+| Once Artisan has finished running, we will fire off the shutdown events
+| so that any final work may be done by the application before we shut
+| down the process. This is the last thing to happen to the request.
+|
+*/
+
+$kernel->terminate($input, $status);
+
+exit($status);
diff --git a/beike/Admin/Database/Seeders/ProductSeeder.php b/beike/Admin/Database/Seeders/ProductSeeder.php
new file mode 100644
index 00000000..b7921331
--- /dev/null
+++ b/beike/Admin/Database/Seeders/ProductSeeder.php
@@ -0,0 +1,62 @@
+addMinute();
+ $productId = DB::table('products')->insertGetId([
+ 'image' => $faker->imageUrl(100, 100),
+ 'video' => '',
+ 'position' => 0,
+ 'active' => 1,
+ 'variables' => null,
+ 'created_at' => $time,
+ 'updated_at' => $time,
+ ]);
+
+ $descriptions = [];
+ foreach (locales() as $locale) {
+ $descriptions[] = [
+ 'product_id' => $productId,
+ 'locale' => $locale['code'],
+ 'name' => $faker->words(5, true),
+ 'content' => $faker->paragraphs(6, true),
+ 'meta_title' => $faker->words(10, true),
+ 'meta_description' => $faker->sentence(10),
+ 'meta_keywords' => $faker->words(10, true),
+ 'created_at' => $time,
+ 'updated_at' => $time,
+ ];
+ }
+ DB::table('product_descriptions')->insert($descriptions);
+
+ $costPrice = $faker->numberBetween(100, 500);
+ DB::table('product_skus')->insert([
+ 'product_id' => $productId,
+ 'variants' => null,
+ 'position' => 0,
+ 'image' => $faker->imageUrl(100, 100),
+ 'model' => $faker->isbn10(),
+ 'sku' => $faker->isbn10(),
+ 'price' => $costPrice + 10,
+ 'origin_price' => $costPrice + 50,
+ 'cost_price' => $costPrice,
+ 'quantity' => $faker->numberBetween(100, 1000),
+ 'is_default' => 1,
+ 'created_at' => $time,
+ 'updated_at' => $time,
+ ]);
+ }
+ }
+}
diff --git a/beike/Admin/Http/Controllers/AddressController.php b/beike/Admin/Http/Controllers/AddressController.php
new file mode 100644
index 00000000..1a96193d
--- /dev/null
+++ b/beike/Admin/Http/Controllers/AddressController.php
@@ -0,0 +1,68 @@
+
+ * @created 2022-06-28 20:17:04
+ * @modified 2022-06-28 20:17:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Resources\AddressResource;
+use Beike\Admin\Services\AddressService;
+use Beike\Repositories\AddressRepo;
+use Illuminate\Http\Request;
+
+class AddressController extends Controller
+{
+ public function index(Request $request, int $customerId)
+ {
+ $addresses = AddressRepo::listByCustomer($customerId);
+ $data = [
+ 'addresses' => AddressResource::collection($addresses),
+ ];
+
+ return hook_filter('admin.address.index.data', $data);
+ }
+
+ public function store(Request $request, int $customerId)
+ {
+ $requestData = $request->all();
+
+ $beforeData = [
+ 'customer_id' => $customerId,
+ 'data' => $requestData,
+ ];
+ hook_action('admin.address.store.before', $beforeData);
+ $address = AddressService::addForCustomer($customerId, $requestData);
+ hook_action('admin.address.store.after', $address);
+
+ return json_success(trans('common.created_success'), $address);
+ }
+
+ public function update(Request $request, int $customerId, int $addressId)
+ {
+ $requestData = $request->all();
+ $beforeData = [
+ 'customer_id' => $customerId,
+ 'address_id' => $addressId,
+ 'data' => $requestData,
+ ];
+ hook_action('admin.address.update.before', $beforeData);
+ $address = AddressService::update($addressId, $request->all());
+ hook_action('admin.address.update.after', $address);
+
+ return json_success(trans('common.updated_success'), $address);
+ }
+
+ public function destroy(Request $request, int $customerId, int $addressId)
+ {
+ AddressRepo::delete($addressId);
+ hook_action('admin.address.destroy.after', $addressId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/AdminRoleController.php b/beike/Admin/Http/Controllers/AdminRoleController.php
new file mode 100644
index 00000000..f49a2dd7
--- /dev/null
+++ b/beike/Admin/Http/Controllers/AdminRoleController.php
@@ -0,0 +1,88 @@
+
+ * @created 2022-08-01 11:44:54
+ * @modified 2022-08-01 11:44:54
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Requests\AdminRoleRequest;
+use Beike\Admin\Repositories\AdminRoleRepo;
+use Beike\Admin\Repositories\PermissionRepo;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
+use Spatie\Permission\Models\Role;
+
+class AdminRoleController extends Controller
+{
+ public function index()
+ {
+ $data = [
+ 'roles' => Role::query()->get(),
+ ];
+ $data = hook_filter('admin.admin_role.index.data', $data);
+
+ return view('admin::pages.admin_roles.index', $data);
+ }
+
+ public function create(Request $request)
+ {
+ $permissionRepo = (new PermissionRepo());
+ $data = [
+ 'core_permissions' => $permissionRepo->getRoleCorePermissions(),
+ 'plugin_permissions' => $permissionRepo->getRolePluginPermissions(),
+ ];
+
+ $data = hook_filter('admin.admin_role.create.data', $data);
+
+ return view('admin::pages.admin_roles.edit', $data);
+ }
+
+ public function edit(Request $request, int $id)
+ {
+ Cache::forget('spatie.permission.cache');
+ $role = Role::query()->findOrFail($id);
+ $permissionRepo = (new PermissionRepo())->setRole($role);
+ $data = [
+ 'core_permissions' => $permissionRepo->getRoleCorePermissions(),
+ 'plugin_permissions' => $permissionRepo->getRolePluginPermissions(),
+ 'role' => $role,
+ ];
+ $data = hook_filter('admin.admin_role.edit.data', $data);
+
+ return view('admin::pages.admin_roles.edit', $data);
+ }
+
+ /**
+ * 保存后台用户角色
+ *
+ * @param AdminRoleRequest $request
+ * @return array
+ * @throws \Exception
+ */
+ public function store(AdminRoleRequest $request): array
+ {
+ $adminUser = AdminRoleRepo::createAdminRole($request->toArray());
+
+ return json_success(trans('common.created_success'), $adminUser);
+ }
+
+ public function update(Request $request, int $adminUserId)
+ {
+ $adminUser = AdminRoleRepo::updateAdminRole($request->toArray());
+
+ return json_success(trans('common.updated_success'), $adminUser);
+ }
+
+ public function destroy(Request $request, int $adminUserId)
+ {
+ AdminRoleRepo::deleteAdminRole($adminUserId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/AdminUserController.php b/beike/Admin/Http/Controllers/AdminUserController.php
new file mode 100644
index 00000000..8bfedabb
--- /dev/null
+++ b/beike/Admin/Http/Controllers/AdminUserController.php
@@ -0,0 +1,70 @@
+
+ * @created 2022-08-01 11:44:54
+ * @modified 2022-08-01 11:44:54
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Requests\AdminUserRequest;
+use Beike\Admin\Repositories\AdminUserRepo;
+use Illuminate\Http\Request;
+use Spatie\Permission\Models\Role;
+
+class AdminUserController extends Controller
+{
+ /**
+ * 获取后台用户列表
+ *
+ * @return mixed
+ */
+ public function index()
+ {
+ $data = [
+ 'admin_users' => AdminUserRepo::getAdminUsers(),
+ 'admin_roles' => Role::query()->get(),
+ ];
+ $data = hook_filter('admin.admin_user.index.data', $data);
+
+ return view('admin::pages.admin_users.index', $data);
+ }
+
+ /**
+ * 创建后台管理员
+ *
+ * @param AdminUserRequest $request
+ * @return array
+ */
+ public function store(AdminUserRequest $request)
+ {
+ $adminUser = AdminUserRepo::createAdminUser($request->toArray());
+
+ return json_success(trans('common.created_success'), $adminUser);
+ }
+
+ /**
+ * 更新后台管理员
+ *
+ * @param AdminUserRequest $request
+ * @param int $adminUserId
+ * @return array
+ */
+ public function update(AdminUserRequest $request, int $adminUserId)
+ {
+ $adminUser = AdminUserRepo::updateAdminUser($adminUserId, $request->toArray());
+
+ return json_success(trans('common.updated_success'), $adminUser);
+ }
+
+ public function destroy(Request $request, int $adminUserId)
+ {
+ AdminUserRepo::deleteAdminUser($adminUserId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/AttributeController.php b/beike/Admin/Http/Controllers/AttributeController.php
new file mode 100644
index 00000000..a630b26b
--- /dev/null
+++ b/beike/Admin/Http/Controllers/AttributeController.php
@@ -0,0 +1,151 @@
+
+ * @created 2023-01-04 19:45:41
+ * @modified 2023-01-04 19:45:41
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Resources\AttributeDetailResource;
+use Beike\Admin\Http\Resources\AttributeResource;
+use Beike\Admin\Http\Resources\AttributeValueResource;
+use Beike\Admin\Http\Resources\AutocompleteResource;
+use Beike\Admin\Repositories\AttributeGroupRepo;
+use Beike\Admin\Repositories\AttributeRepo;
+use Exception;
+use Illuminate\Http\Request;
+
+class AttributeController extends Controller
+{
+ public function index(Request $request)
+ {
+ try {
+ $attributes = AttributeRepo::getList();
+ $data = [
+ 'attribute_list' => $attributes,
+ 'attribute_list_format' => AttributeResource::collection($attributes),
+ 'attribute_group' => AttributeGroupRepo::getList(),
+ ];
+ $data = hook_filter('admin.attribute.index.data', $data);
+ if ($request->expectsJson()) {
+ return json_success(trans('success'), $data);
+ }
+ } catch (Exception $e) {
+ return view('admin::pages.attributes.index', $data)->withErrors(['error' => $e->getMessage()]);
+ }
+
+ return view('admin::pages.attributes.index', $data);
+ }
+
+ public function show(Request $request, int $id)
+ {
+ try {
+ $data = [
+ 'attribute' => (new AttributeDetailResource(AttributeRepo::find($id)))->jsonSerialize(),
+ 'attribute_group' => AttributeGroupRepo::getList(),
+ ];
+ $data = hook_filter('admin.attribute.show.data', $data);
+ } catch (Exception $e) {
+ return view('admin::pages.attributes.form', $data)->withErrors(['error' => $e->getMessage()]);
+ }
+
+ return view('admin::pages.attributes.form', $data);
+ }
+
+ public function store(Request $request)
+ {
+ try {
+ $requestData = json_decode($request->getContent(), true);
+ $item = AttributeRepo::create($requestData);
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.created_success'), $item);
+ }
+
+ public function update(Request $request, int $id)
+ {
+ try {
+ $requestData = json_decode($request->getContent(), true);
+ $item = AttributeRepo::update($id, $requestData);
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.updated_success'), $item);
+ }
+
+ public function storeValue(Request $request, int $id)
+ {
+ try {
+ $requestData = json_decode($request->getContent(), true);
+ $item = AttributeRepo::createValue(array_merge($requestData, ['attribute_id' => $id]));
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.created_success'), new AttributeValueResource($item));
+ }
+
+ public function updateValue(Request $request, int $id, int $value_id)
+ {
+ try {
+ $requestData = json_decode($request->getContent(), true);
+ $item = AttributeRepo::updateValue($value_id, $requestData);
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.updated_success'), new AttributeValueResource($item));
+ }
+
+ public function destroyValue(Request $request, int $id, int $value_id)
+ {
+ try {
+ AttributeRepo::deleteValue($value_id);
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ public function destroy(Request $request, int $id)
+ {
+ try {
+ AttributeRepo::delete($id);
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ public function autocomplete(Request $request): array
+ {
+ try {
+ $items = AttributeRepo::autocomplete($request->get('name') ?? '', 0);
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.get_success'), AutocompleteResource::collection($items));
+ }
+
+ public function autocompleteValue(Request $request, int $id): array
+ {
+ try {
+ $items = AttributeRepo::autocompleteValue($id, $request->get('name') ?? '');
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.get_success'), AutocompleteResource::collection($items));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/AttributeGroupController.php b/beike/Admin/Http/Controllers/AttributeGroupController.php
new file mode 100644
index 00000000..1102a508
--- /dev/null
+++ b/beike/Admin/Http/Controllers/AttributeGroupController.php
@@ -0,0 +1,68 @@
+
+ * @created 2023-01-04 19:45:41
+ * @modified 2023-01-04 19:45:41
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Repositories\AttributeGroupRepo;
+use Exception;
+use Illuminate\Http\Request;
+
+class AttributeGroupController extends Controller
+{
+ public function index()
+ {
+ try {
+ $data = [
+ 'attribute_groups' => AttributeGroupRepo::getList(),
+ ];
+ $data = hook_filter('admin.attribute_group.index.data', $data);
+ } catch (Exception $e) {
+ return view('admin::pages.attribute_group.index', $data)->withErrors(['error' => $e->getMessage()]);
+ }
+
+ return view('admin::pages.attribute_group.index', $data);
+ }
+
+ public function store(Request $request)
+ {
+ try {
+ $requestData = json_decode($request->getContent(), true);
+ $item = AttributeGroupRepo::create($requestData);
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.created_success'), $item);
+ }
+
+ public function update(Request $request, int $id)
+ {
+ try {
+ $requestData = json_decode($request->getContent(), true);
+ $item = AttributeGroupRepo::update($id, $requestData);
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.updated_success'), $item);
+ }
+
+ public function destroy(Request $request, int $id)
+ {
+ try {
+ AttributeGroupRepo::delete($id);
+ } catch (Exception $e) {
+ return json_fail($e->getMessage(), []);
+ }
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/BrandController.php b/beike/Admin/Http/Controllers/BrandController.php
new file mode 100644
index 00000000..2163e2b6
--- /dev/null
+++ b/beike/Admin/Http/Controllers/BrandController.php
@@ -0,0 +1,129 @@
+
+ * @created 2022-07-27 21:17:04
+ * @modified 2022-07-27 21:17:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Models\Brand;
+use Beike\Repositories\BrandRepo;
+use Exception;
+use Illuminate\Http\Request;
+
+class BrandController extends Controller
+{
+ /**
+ * 显示品牌列表
+ * @param Request $request
+ * @return mixed
+ */
+ public function index(Request $request)
+ {
+ $brands = BrandRepo::list($request->only('name', 'first', 'status'));
+ $data = [
+ 'brands' => $brands,
+ ];
+ $data = hook_filter('admin.brand.index.data', $data);
+ if ($request->expectsJson()) {
+ return json_success(trans('common.success'), $data);
+ }
+
+ return view('admin::pages.brands.index', $data);
+ }
+
+ /**
+ * 创建品牌
+ *
+ * @param Request $request
+ * @return array
+ */
+ public function store(Request $request): array
+ {
+ $requestData = $request->all();
+ $data = [
+ 'request_data' => $requestData,
+ ];
+
+ hook_action('admin.brand.store.before', $data);
+ $brand = BrandRepo::create($requestData);
+ hook_action('admin.brand.store.after', ['brand' => $brand, 'request_data' => $requestData]);
+
+ return json_success(trans('common.created_success'), $brand);
+ }
+
+ /**
+ * @param Request $request
+ * @param Brand $brand
+ * @return array
+ * @throws Exception
+ */
+ public function update(Request $request, Brand $brand): array
+ {
+ $requestData = $request->all();
+ $data = [
+ 'brand_id' => $brand,
+ 'request_data' => $requestData,
+ ];
+ hook_action('admin.brand.update.before', $data);
+ $brand = BrandRepo::update($brand, $requestData);
+ hook_action('admin.brand.update.after', $data);
+
+ return json_success(trans('common.updated_success'), $brand);
+ }
+
+ /**
+ * @param Request $request
+ * @param Brand $brand
+ * @return array
+ */
+ public function destroy(Request $request, Brand $brand): array
+ {
+ hook_action('admin.brand.destroy.before', $brand);
+ BrandRepo::delete($brand);
+ hook_action('admin.brand.destroy.after', $brand);
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ /**
+ * @param Request $request
+ * @return array
+ */
+ public function autocomplete(Request $request): array
+ {
+ $brands = BrandRepo::autocomplete($request->get('name') ?? '', 0);
+
+ return json_success(trans('common.get_success'), $brands);
+ }
+
+ /**
+ * @param int $id
+ * @return array
+ */
+ public function name(int $id): array
+ {
+ $name = BrandRepo::getName($id);
+
+ return json_success(trans('common.get_success'), $name);
+ }
+
+ /**
+ * 根据商品ID批量获取商品名称
+ *
+ * @param Request $request
+ * @return array
+ */
+ public function getNames(Request $request): array
+ {
+ $ids = explode(',', $request->get('ids'));
+ $name = BrandRepo::getNames($ids);
+
+ return json_success(trans('common.get_success'), $name);
+ }
+}
diff --git a/beike/Admin/Http/Controllers/CategoryController.php b/beike/Admin/Http/Controllers/CategoryController.php
new file mode 100644
index 00000000..e80f2288
--- /dev/null
+++ b/beike/Admin/Http/Controllers/CategoryController.php
@@ -0,0 +1,108 @@
+ CategoryResource::collection($categories),
+ ];
+ $data = hook_filter('admin.category.index.data', $data);
+
+ return view('admin::pages.categories.index', $data);
+ }
+
+ public function create(Request $request)
+ {
+ return $this->form($request);
+ }
+
+ public function store(CategoryRequest $request)
+ {
+ return $this->save($request);
+ }
+
+ public function edit(Request $request, Category $category)
+ {
+ return $this->form($request, $category);
+ }
+
+ public function update(CategoryRequest $request, Category $category)
+ {
+ return $this->save($request, $category);
+ }
+
+ /**
+ * 删除分类
+ * @param Request $request
+ * @param Category $category
+ * @return array
+ * @throws \Exception
+ */
+ public function destroy(Request $request, Category $category): array
+ {
+ CategoryRepo::delete($category);
+ hook_action('admin.category.destroy.after', $category);
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ public function name(int $id)
+ {
+ $name = CategoryRepo::getName($id);
+
+ return json_success(trans('common.get_success'), $name);
+ }
+
+ protected function form(Request $request, Category $category = null)
+ {
+ if ($category) {
+ $descriptions = $category->descriptions->keyBy('locale');
+ }
+
+ $data = [
+ 'category' => $category ?? new Category(),
+ 'languages' => LanguageRepo::all(),
+ 'descriptions' => $descriptions ?? null,
+ 'categories' => CategoryRepo::flatten(locale()),
+ '_redirect' => $this->getRedirect(),
+ ];
+ $data = hook_filter('admin.category.form.data', $data);
+
+ return view('admin::pages.categories.form', $data);
+ }
+
+ protected function save(Request $request, ?Category $category = null)
+ {
+ $requestData = $request->all();
+ $category = (new CategoryService())->createOrUpdate($requestData, $category);
+ $data = [
+ 'category' => $category,
+ 'request_data' => $requestData,
+ ];
+
+ hook_action('admin.category.save.after', $data);
+
+ return redirect($this->getRedirect())->with('success', 'Category created successfully');
+ }
+
+ public function autocomplete(Request $request)
+ {
+ $categories = CategoryRepo::autocomplete($request->get('name') ?? '');
+
+ return json_success(trans('common.get_success'), $categories);
+ }
+}
diff --git a/beike/Admin/Http/Controllers/Controller.php b/beike/Admin/Http/Controllers/Controller.php
new file mode 100644
index 00000000..b746357b
--- /dev/null
+++ b/beike/Admin/Http/Controllers/Controller.php
@@ -0,0 +1,89 @@
+defaultRoute)) {
+ $this->defaultRoute = $this->getDefaultRoute();
+ }
+
+ return request('_redirect') ?? request()->header('referer', admin_route($this->defaultRoute));
+ }
+
+ /**
+ * 获取当前管理界面列表页路由
+ * @return string
+ */
+ private function getDefaultRoute(): string
+ {
+ $currentRouteName = Route::getCurrentRoute()->getName();
+ $names = explode('.', $currentRouteName);
+ $name = $names[1] ?? '';
+
+ return "{$name}.index";
+ }
+
+ /**
+ * 导出CSV
+ *
+ * @param $fileName
+ * @param $items
+ * @param string $module
+ * @return BinaryFileResponse
+ * @throws \Exception
+ */
+ protected function downloadCsv($fileName, $items, string $module = ''): BinaryFileResponse
+ {
+ $module = $module ?: $fileName;
+ $charset = app()->getLocale() == 'zh-hk' ? 'BIG5' : 'GBK';
+
+ if (empty($items)) {
+ throw new \Exception(trans('common.empty_items'));
+ }
+ if (! str_contains($fileName, '.csv')) {
+ $fileName = $fileName . '-' . date('YmdHis') . '.csv';
+ }
+ $headers = [
+ 'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
+ 'Content-type' => 'application/octet-stream',
+ // 'Content-type' => 'text/csv',
+ 'Content-Disposition' => "attachment; filename={$fileName}",
+ 'Content-Transfer-Encoding' => 'binary',
+ 'Expires' => '0',
+ 'Pragma' => 'public',
+ ];
+
+ $columns = array_keys($items[0]);
+ foreach ($columns as $index => $column) {
+ $columns[$index] = iconv('UTF-8', "{$charset}//IGNORE", trans("$module.{$column}"));
+ }
+ foreach ($items as $index => $item) {
+ foreach ($item as $field => $value) {
+ $items[$index][$field] = iconv('UTF-8', "{$charset}//IGNORE", $value);
+ }
+ }
+
+ $filePath = storage_path('app/' . $fileName);
+ $file = fopen($filePath, 'w');
+ fputcsv($file, $columns);
+ foreach ($items as $item) {
+ fputcsv($file, $item);
+ }
+ fclose($file);
+
+ return response()->download($filePath, $fileName, $headers);
+ }
+}
diff --git a/beike/Admin/Http/Controllers/CountryController.php b/beike/Admin/Http/Controllers/CountryController.php
new file mode 100644
index 00000000..1d69afbb
--- /dev/null
+++ b/beike/Admin/Http/Controllers/CountryController.php
@@ -0,0 +1,60 @@
+
+ * @created 2022-08-29 16:17:04
+ * @modified 2022-08-29 16:17:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Repositories\CountryRepo;
+use Illuminate\Http\Request;
+
+class CountryController extends Controller
+{
+ public function index(Request $request)
+ {
+ $countries = CountryRepo::list($request->only('name', 'code', 'status'));
+
+ $data = [
+ 'country' => $countries,
+ ];
+ $data = hook_filter('admin.country.index.data', $data);
+ if ($request->expectsJson()) {
+ return json_success(trans('common.success'), $data);
+ }
+
+ return view('admin::pages.country.index', $data);
+ }
+
+ public function store(Request $request)
+ {
+ $country = CountryRepo::create($request->only('name', 'code', 'sort_order', 'status'));
+
+ hook_action('admin.country.store.after', $country);
+
+ return json_success(trans('common.created_success'), $country);
+ }
+
+ public function update(Request $request, int $id)
+ {
+ $country = CountryRepo::update($id, $request->only('name', 'code', 'sort_order', 'status'));
+
+ hook_action('admin.country.store.after', $country);
+
+ return json_success(trans('common.updated_success'), $country);
+ }
+
+ public function destroy(int $id)
+ {
+ CountryRepo::delete($id);
+
+ hook_action('admin.country.destroy.after', $id);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/CurrencyController.php b/beike/Admin/Http/Controllers/CurrencyController.php
new file mode 100644
index 00000000..f38adc76
--- /dev/null
+++ b/beike/Admin/Http/Controllers/CurrencyController.php
@@ -0,0 +1,74 @@
+
+ * @created 2022-06-30 16:17:04
+ * @modified 2022-06-30 16:17:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Requests\CurrencyRequest;
+use Beike\Repositories\CurrencyRepo;
+use Illuminate\Http\Request;
+
+class CurrencyController extends Controller
+{
+ protected string $defaultRoute = 'currencies.index';
+
+ public function index(Request $request)
+ {
+ $currencies = CurrencyRepo::all();
+
+ $data = [
+ 'currencies' => $currencies,
+ ];
+ $data = hook_filter('admin.currency.index.data', $data);
+
+ return view('admin::pages.currencies.index', $data);
+ }
+
+ public function store(CurrencyRequest $request)
+ {
+ $data = [
+ 'name' => $request->get('name', ''),
+ 'code' => $request->get('code', ''),
+ 'symbol_left' => $request->get('symbol_left', ''),
+ 'symbol_right' => $request->get('symbol_right', ''),
+ 'decimal_place' => (float) $request->get('decimal_place', 0),
+ 'value' => (float) $request->get('value', 1),
+ 'status' => (int) $request->get('status', 0),
+ ];
+ $currency = CurrencyRepo::create($data);
+ hook_action('admin.currency.store.after', $currency);
+
+ return json_success(trans('common.created_success'), $currency);
+ }
+
+ public function update(CurrencyRequest $request, int $id)
+ {
+ $data = [
+ 'name' => $request->get('name', ''),
+ 'code' => $request->get('code', ''),
+ 'symbol_left' => $request->get('symbol_left', ''),
+ 'symbol_right' => $request->get('symbol_right', ''),
+ 'decimal_place' => (float) $request->get('decimal_place', 0),
+ 'value' => (float) $request->get('value', 1),
+ 'status' => (int) $request->get('status', 0),
+ ];
+ $currency = CurrencyRepo::update($id, $data);
+
+ return json_success(trans('common.updated_success'), $currency);
+ }
+
+ public function destroy(Request $request, int $currencyId)
+ {
+ CurrencyRepo::delete($currencyId);
+ hook_action('admin.currency.destroy.after', $currencyId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/CustomerController.php b/beike/Admin/Http/Controllers/CustomerController.php
new file mode 100644
index 00000000..8177d07d
--- /dev/null
+++ b/beike/Admin/Http/Controllers/CustomerController.php
@@ -0,0 +1,141 @@
+
+ * @created 2022-06-28 16:17:04
+ * @modified 2022-06-28 16:17:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Requests\CustomerRequest;
+use Beike\Admin\Http\Resources\AddressResource;
+use Beike\Admin\Http\Resources\CustomerGroupDetail;
+use Beike\Admin\Http\Resources\CustomerResource;
+use Beike\Admin\Services\CustomerService;
+use Beike\Repositories\AddressRepo;
+use Beike\Repositories\CountryRepo;
+use Beike\Repositories\CustomerGroupRepo;
+use Beike\Repositories\CustomerRepo;
+use Illuminate\Http\Request;
+
+class CustomerController extends Controller
+{
+ public function index(Request $request)
+ {
+ $customers = CustomerRepo::list($request->only(['name', 'email', 'status', 'from', 'customer_group_id']));
+
+ $data = [
+ 'customers' => $customers,
+ 'customers_format' => CustomerResource::collection($customers)->jsonSerialize(),
+ 'customer_groups' => CustomerGroupDetail::collection(CustomerGroupRepo::list())->jsonSerialize(),
+ 'type' => 'customer',
+ ];
+ $data = hook_filter('admin.customer.index.data', $data);
+ if ($request->expectsJson()) {
+ return json_success(trans('success'), $data);
+ }
+
+ return view('admin::pages.customers.index', $data);
+ }
+
+ public function trashed(Request $request)
+ {
+ $customers = CustomerRepo::list(array_merge($request->only(['name', 'email', 'status', 'from', 'customer_group_id']), ['only_trashed' => true]));
+
+ $data = [
+ 'customers' => $customers,
+ 'customers_format' => CustomerResource::collection($customers)->jsonSerialize(),
+ 'customer_groups' => CustomerGroupDetail::collection(CustomerGroupRepo::list())->jsonSerialize(),
+ 'type' => 'trashed',
+ ];
+ $data = hook_filter('admin.customer.trashed.data', $data);
+ if ($request->expectsJson()) {
+ return json_success(trans('success'), $data);
+ }
+
+ return view('admin::pages.customers.index', $data);
+ }
+
+ public function store(CustomerRequest $request)
+ {
+ $requestData = $request->all();
+
+ hook_action('admin.customer.store.before', ['request_data' => $requestData]);
+
+ $customer = CustomerService::create($requestData);
+
+ hook_action('admin.customer.store.after', ['customer_id' => $customer->id, 'request_data' => $requestData]);
+
+ return json_success(trans('common.success'), new CustomerResource($customer));
+ }
+
+ public function edit(Request $request, int $customerId)
+ {
+ $addresses = AddressRepo::listByCustomer($customerId);
+ $customer = CustomerRepo::find($customerId);
+ $data = [
+ 'customer' => $customer,
+ 'customer_groups' => CustomerGroupDetail::collection(CustomerGroupRepo::list())->jsonSerialize(),
+ 'addresses' => AddressResource::collection($addresses)->jsonSerialize(),
+ 'countries' => CountryRepo::all(),
+ 'country_id' => system_setting('base.country_id'),
+ '_redirect' => $this->getRedirect(),
+ ];
+ $data = hook_filter('admin.customer.edit.data', $data);
+
+ return view('admin::pages.customers.form', $data);
+ }
+
+ public function update(CustomerRequest $request, int $customerId)
+ {
+ $requestData = $request->all();
+ $password = $requestData['password'] ?? '';
+ if (empty($password)) {
+ unset($requestData['password']);
+ }
+
+ hook_action('admin.customer.update.before', ['customer_id' => $customerId, 'request_data' => $requestData]);
+
+ $customer = CustomerRepo::update($customerId, $requestData);
+
+ hook_action('admin.customer.update.after', ['customer_id' => $customerId, 'request_data' => $requestData]);
+
+ return json_success(trans('common.updated_success'), $customer);
+ }
+
+ public function destroy(Request $request, int $customerId)
+ {
+ CustomerRepo::delete($customerId);
+ hook_action('admin.customer.destroy.after', $customerId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ public function restore(Request $request, int $customerId)
+ {
+ CustomerRepo::restore($customerId);
+ hook_action('admin.customer.restore.after', $customerId);
+
+ return json_success(trans('common.restored_success'));
+ }
+
+ public function forceDelete(Request $request, int $customerId)
+ {
+ CustomerRepo::forceDelete($customerId);
+ hook_action('admin.customer.force_delete.after', $customerId);
+
+ return json_success(trans('common.success'));
+ }
+
+ public function forceDeleteAll(Request $request)
+ {
+ CustomerRepo::forceDeleteAll();
+ hook_action('admin.customer.force_delete_all.after', ['module' => 'customer']);
+
+ return json_success(trans('common.success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/CustomerGroupController.php b/beike/Admin/Http/Controllers/CustomerGroupController.php
new file mode 100644
index 00000000..bfbaaa81
--- /dev/null
+++ b/beike/Admin/Http/Controllers/CustomerGroupController.php
@@ -0,0 +1,65 @@
+
+ * @created 2022-06-30 21:17:04
+ * @modified 2022-06-30 21:17:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Requests\CustomerGroupRequest;
+use Beike\Admin\Services\CustomerGroupService;
+use Beike\Repositories\CustomerGroupRepo;
+use Beike\Repositories\LanguageRepo;
+use Illuminate\Http\Request;
+
+class CustomerGroupController extends Controller
+{
+ protected string $defaultRoute = 'customer_groups.index';
+
+ public function index(Request $request)
+ {
+ $customers = CustomerGroupRepo::list();
+
+ $data = [
+ 'customer_groups' => $customers,
+ 'languages' => LanguageRepo::all(),
+ ];
+ $data = hook_filter('admin.customer_group.index.data', $data);
+
+ return view('admin::pages.customer_groups.index', $data);
+ }
+
+ public function store(CustomerGroupRequest $request)
+ {
+ $customerGroup = CustomerGroupService::create($request->all());
+ $customerGroup->load('descriptions', 'description');
+
+ hook_action('admin.customer_group.store.after', $customerGroup);
+
+ return json_success(trans('common.created_success'), $customerGroup);
+ }
+
+ public function update(CustomerGroupRequest $request, int $id)
+ {
+ $customerGroup = CustomerGroupService::update($id, $request->all());
+ $customerGroup->load('descriptions', 'description');
+
+ hook_action('admin.customer_group.update.after', $customerGroup);
+
+ return json_success(trans('common.updated_success'), $customerGroup);
+ }
+
+ public function destroy(Request $request, int $id)
+ {
+ CustomerGroupRepo::delete($id);
+
+ hook_action('admin.customer_group.destroy.after', $id);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/DesignController.php b/beike/Admin/Http/Controllers/DesignController.php
new file mode 100644
index 00000000..c56edc32
--- /dev/null
+++ b/beike/Admin/Http/Controllers/DesignController.php
@@ -0,0 +1,82 @@
+ [
+ 'editor-slide_show', 'editor-image401', 'editor-tab_product', 'editor-product', 'editor-image100',
+ 'editor-brand', 'editor-icons', 'editor-rich_text', 'editor-image200', 'editor-image300',
+ ],
+ 'design_settings' => system_setting('base.design_setting'),
+ ];
+
+ $data = hook_filter('admin.design.index.data', $data);
+
+ return view('admin::pages.design.builder.index', $data);
+ }
+
+ /**
+ * 预览模块显示结果
+ *
+ * @param Request $request
+ * @return View
+ * @throws \Exception
+ */
+ public function preview(Request $request): View
+ {
+ $module = json_decode($request->getContent(), true);
+ $moduleId = $module['module_id'] ?? '';
+ $moduleCode = $module['code'] ?? '';
+ $content = $module['content'] ?? '';
+ $viewPath = $module['view_path'] ?? '';
+
+ if (empty($viewPath)) {
+ $viewPath = "design.{$moduleCode}";
+ }
+
+ $viewData = [
+ 'code' => $moduleCode,
+ 'module_id' => $moduleId,
+ 'view_path' => $viewPath,
+ 'content' => DesignService::handleModuleContent($moduleCode, $content),
+ 'design' => (bool) $request->get('design'),
+ ];
+
+ $viewData = hook_filter('admin.design.preview.data', $viewData);
+
+ return view($viewPath, $viewData);
+ }
+
+ /**
+ * 更新所有数据
+ *
+ * @param Request $request
+ * @return array
+ * @throws \Throwable
+ */
+ public function update(Request $request): array
+ {
+ $content = json_decode($request->getContent(), true);
+ $moduleData = DesignService::handleRequestModules($content);
+ SettingRepo::storeValue('design_setting', $moduleData);
+
+ hook_action('admin.design.update.after', $moduleData);
+
+ return json_success(trans('common.updated_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/DesignFooterController.php b/beike/Admin/Http/Controllers/DesignFooterController.php
new file mode 100644
index 00000000..ccbfd311
--- /dev/null
+++ b/beike/Admin/Http/Controllers/DesignFooterController.php
@@ -0,0 +1,65 @@
+ system_setting('base.footer_setting'),
+ ];
+ $data = hook_filter('admin.design_footer.index.data', $data);
+
+ return view('admin::pages.design.builder.footer', $data);
+ }
+
+ /**
+ * 预览模块显示结果
+ *
+ * @param Request $request
+ * @return View
+ * @throws \Exception
+ */
+ public function preview(Request $request): View
+ {
+ $content = json_decode($request->getContent(), true);
+ $viewPath = 'layout.footer';
+
+ $viewData = [
+ 'view_path' => $viewPath,
+ 'footer_content' => FooterRepo::handleFooterData($content),
+ 'design' => (bool) $request->get('design'),
+ ];
+ $viewData = hook_filter('admin.design_footer.index.data', $viewData);
+
+ return view($viewPath, $viewData);
+ }
+
+ /**
+ * 更新所有数据
+ *
+ * @param Request $request
+ * @return array
+ * @throws \Throwable
+ */
+ public function update(Request $request): array
+ {
+ $content = json_decode($request->getContent(), true);
+
+ SettingRepo::storeValue('footer_setting', $content);
+
+ return json_success(trans('common.updated_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/DesignMenuController.php b/beike/Admin/Http/Controllers/DesignMenuController.php
new file mode 100644
index 00000000..bef9fba2
--- /dev/null
+++ b/beike/Admin/Http/Controllers/DesignMenuController.php
@@ -0,0 +1,42 @@
+ system_setting('base.menu_setting', []),
+ ];
+ $data = hook_filter('admin.design_menu.index.data', $data);
+
+ return view('admin::pages.design.builder.menu', $data);
+ }
+
+ /**
+ * 更新所有数据
+ *
+ * @param Request $request
+ * @return array
+ * @throws \Throwable
+ */
+ public function update(Request $request): array
+ {
+ $content = json_decode($request->getContent(), true);
+
+ SettingRepo::storeValue('menu_setting', $content);
+
+ return json_success(trans('common.updated_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/EditController.php b/beike/Admin/Http/Controllers/EditController.php
new file mode 100644
index 00000000..4c7a76b5
--- /dev/null
+++ b/beike/Admin/Http/Controllers/EditController.php
@@ -0,0 +1,25 @@
+update($request->only('email', 'name', 'password'));
+
+ return redirect()->back()->withErrors(['email' => 'Invalid credentials']);
+ }
+
+ public function locale(Request $request)
+ {
+ $user = current_user();
+ $user->update($request->only('locale'));
+
+ return redirect()->back();
+ }
+}
diff --git a/beike/Admin/Http/Controllers/FileManagerController.php b/beike/Admin/Http/Controllers/FileManagerController.php
new file mode 100644
index 00000000..924e71b6
--- /dev/null
+++ b/beike/Admin/Http/Controllers/FileManagerController.php
@@ -0,0 +1,134 @@
+getDirectories();
+ $data = hook_filter('admin.file_manager.index.data', $data);
+
+ return view('admin::pages.file_manager.index', ['directories' => $data]);
+ }
+
+ /**
+ * 获取某个文件夹下面的文件列表
+ *
+ * @param Request $request
+ * @return array
+ * @throws \Exception
+ */
+ public function getFiles(Request $request): array
+ {
+ $baseFolder = $request->get('base_folder');
+ $page = (int) $request->get('page');
+ $perPage = (int) $request->get('per_page');
+
+ $data = (new FileManagerService)->getFiles($baseFolder, $page, $perPage);
+
+ return hook_filter('admin.file_manager.files.data', $data);
+ }
+
+ /**
+ * 获取文件夹列表
+ * @param Request $request
+ * @return mixed
+ * @throws \Exception
+ */
+ public function getDirectories(Request $request)
+ {
+ $baseFolder = $request->get('base_folder');
+
+ $data = (new FileManagerService)->getDirectories($baseFolder);
+
+ return hook_filter('admin.file_manager.directories.data', $data);
+ }
+
+ /**
+ * 创建文件夹
+ * POST /admin/file_manager
+ * @throws \Exception
+ */
+ public function createDirectory(Request $request): array
+ {
+ $folderName = $request->get('name');
+ (new FileManagerService)->createDirectory($folderName);
+
+ return json_success(trans('common.created_success'));
+ }
+
+ /**
+ * 文件或文件夹改名
+ * PUT /admin/file_manager/rename
+ * @throws \Exception
+ */
+ public function rename(Request $request): array
+ {
+ $originPath = $request->get('origin_name');
+ $newPath = $request->get('new_name');
+ (new FileManagerService)->updateName($originPath, $newPath);
+
+ return json_success(trans('common.updated_success'));
+ }
+
+ /**
+ * 删除文件或文件夹
+ * DELETE /admin/file_manager/files {"path":"/xx/yy", "files":["1.jpg", "2.png"]}
+ * @throws \Exception
+ */
+ public function destroyFiles(Request $request): array
+ {
+ $requestData = json_decode($request->getContent(), true);
+ $basePath = $requestData['path'] ?? '';
+ $files = $requestData['files'] ?? [];
+ (new FileManagerService)->deleteFiles($basePath, $files);
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ /**
+ * 删除文件夹
+ *
+ * @param Request $request
+ * @return array
+ * @throws \Exception
+ */
+ public function destroyDirectories(Request $request): array
+ {
+ $folderName = $request->get('name');
+ (new FileManagerService)->deleteDirectoryOrFile($folderName);
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ /**
+ * 上传文件
+ * POST /admin/file_manager/upload
+ *
+ * @param UploadRequest $request
+ * @return array
+ */
+ public function uploadFiles(UploadRequest $request): array
+ {
+ $file = $request->file('file');
+ $savePath = $request->get('path');
+
+ $originName = $file->getClientOriginalName();
+ $filePath = $file->storeAs($savePath, $originName, 'catalog');
+
+ return [
+ 'name' => $originName,
+ 'url' => asset('catalog/' . $filePath),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Controllers/ForgottenController.php b/beike/Admin/Http/Controllers/ForgottenController.php
new file mode 100644
index 00000000..906682c5
--- /dev/null
+++ b/beike/Admin/Http/Controllers/ForgottenController.php
@@ -0,0 +1,53 @@
+
+ * @created 2022-07-14 11:39:08
+ * @modified 2022-07-14 11:39:08
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Requests\ForgottenRequest;
+use Beike\Admin\Http\Requests\VerifyCodeRequest;
+use Beike\Admin\Services\UserService;
+use Illuminate\Http\Request;
+
+class ForgottenController
+{
+ /**
+ * 找回密码页面
+ * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
+ */
+ public function index()
+ {
+ return view('admin::pages.user.forgotten');
+ }
+
+ /**
+ * 接收email地址,生成验证码发送到邮件地址
+ * @param Request $request
+ * @return array
+ */
+ public function sendVerifyCode(VerifyCodeRequest $request)
+ {
+ UserService::sendVerifyCodeForForgotten($request->get('email'));
+
+ return json_success(trans('admin/forgotten.verify_code_sent'));
+ }
+
+ /**
+ * 接收验证码和新密码、确认密码,验证验证码是否正确、密码和确认密码是否相等,然后修改密码
+ * @param Request $request
+ * @return array
+ */
+ public function changePassword(ForgottenRequest $request)
+ {
+ UserService::verifyAndChangePassword($request->get('code'), $request->get('email'), $request->get('password'));
+
+ return json_success(trans('common.updated_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/HomeController.php b/beike/Admin/Http/Controllers/HomeController.php
new file mode 100644
index 00000000..1f6f55cb
--- /dev/null
+++ b/beike/Admin/Http/Controllers/HomeController.php
@@ -0,0 +1,27 @@
+ DashboardRepo::getCustomerViewData(),
+ 'orders' => DashboardRepo::getOrderData(),
+ 'customers' => DashboardRepo::getCustomerData(),
+ 'order_totals' => DashboardRepo::getTotalData(),
+ 'order_trends' => [
+ 'latest_month' => OrderReportRepo::getLatestMonth(),
+ 'latest_week' => OrderReportRepo::getLatestWeek(),
+ 'latest_year' => OrderReportRepo::getLatestYear(),
+ ],
+ ];
+
+ return view('admin::pages.home', $data);
+ }
+}
diff --git a/beike/Admin/Http/Controllers/LanguageController.php b/beike/Admin/Http/Controllers/LanguageController.php
new file mode 100644
index 00000000..e6f9302c
--- /dev/null
+++ b/beike/Admin/Http/Controllers/LanguageController.php
@@ -0,0 +1,74 @@
+
+ * @created 2022-07-05 16:37:04
+ * @created 2022-07-05 16:37:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Services\LanguageService;
+use Beike\Repositories\LanguageRepo;
+use Exception;
+use Illuminate\Http\Request;
+
+class LanguageController extends Controller
+{
+ /**
+ * 语言列表
+ * @return mixed
+ */
+ public function index()
+ {
+ $languages = LanguageService::all();
+
+ $data = [
+ 'languages' => $languages,
+ ];
+ $data = hook_filter('admin.language.index.data', $data);
+
+ return view('admin::pages.languages.index', $data);
+ }
+
+ /**
+ * 新建语言
+ * @param Request $request
+ * @return array
+ */
+ public function store(Request $request): array
+ {
+ $language = LanguageService::create($request->only('name', 'code'));
+
+ return json_success(trans('common.created_success'), $language);
+ }
+
+ /**
+ * @param Request $request
+ * @param int $id
+ * @return array
+ * @throws Exception
+ */
+ public function update(Request $request, int $id): array
+ {
+ $language = LanguageRepo::update($id, $request->except('status'));
+
+ return json_success(trans('common.updated_success'), $language);
+ }
+
+ /**
+ * 删除语言
+ *
+ * @param int $currencyId
+ * @return array
+ */
+ public function destroy(int $id): array
+ {
+ LanguageService::delete($id);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/LoginController.php b/beike/Admin/Http/Controllers/LoginController.php
new file mode 100644
index 00000000..9de1416a
--- /dev/null
+++ b/beike/Admin/Http/Controllers/LoginController.php
@@ -0,0 +1,37 @@
+
+ * @created 2022-12-21 14:22:26
+ * @modified 2022-12-21 14:22:26
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use App\Http\Controllers\Controller;
+use Beike\Admin\Http\Requests\LoginRequest;
+use Beike\Models\AdminUser;
+
+class LoginController extends Controller
+{
+ public function show()
+ {
+ if (auth(AdminUser::AUTH_GUARD)->check()) {
+ return redirect()->back();
+ }
+
+ return view('admin::pages.login.login', \request()->only('admin_email', 'admin_password'));
+ }
+
+ public function store(LoginRequest $loginRequest)
+ {
+ if (auth(AdminUser::AUTH_GUARD)->attempt($loginRequest->validated())) {
+ return redirect(admin_route('home.index'));
+ }
+
+ return redirect()->back()->with(['error' => trans('auth.failed')])->withInput();
+ }
+}
diff --git a/beike/Admin/Http/Controllers/LogoutController.php b/beike/Admin/Http/Controllers/LogoutController.php
new file mode 100644
index 00000000..9cd16dcc
--- /dev/null
+++ b/beike/Admin/Http/Controllers/LogoutController.php
@@ -0,0 +1,18 @@
+logout();
+
+ return redirect(admin_route('login.show'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/MarketingController.php b/beike/Admin/Http/Controllers/MarketingController.php
new file mode 100644
index 00000000..fbd67013
--- /dev/null
+++ b/beike/Admin/Http/Controllers/MarketingController.php
@@ -0,0 +1,100 @@
+
+ * @created 2022-09-26 11:49:34
+ * @modified 2022-09-26 11:49:34
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Services\MarketingService;
+use Beike\Repositories\PluginRepo;
+use Illuminate\Http\Request;
+
+class MarketingController
+{
+ /**
+ * @param Request $request
+ * @return mixed
+ */
+ public function index(Request $request)
+ {
+ $filters = [
+ 'type' => $request->get('type'),
+ 'keyword' => $request->get('keyword'),
+ 'page' => $request->get('page'),
+ ];
+ $plugins = MarketingService::getInstance()->getList($filters);
+ $data = [
+ 'plugins' => $plugins,
+ 'domain' => str_replace(['http://', 'https://'], '', config('app.url')),
+ 'types' => PluginRepo::getTypes(),
+ ];
+ $data = hook_filter('admin.marketing.index.data', $data);
+ if ($request->expectsJson()) {
+ return json_success(trans('common.success'), $data);
+ }
+
+ return view('admin::pages.marketing.index', $data);
+ }
+
+ /**
+ * 获取单个插件详情
+ */
+ public function show(Request $request)
+ {
+ try {
+ $pluginCode = $request->code;
+ $plugin = MarketingService::getInstance()->getPlugin($pluginCode);
+ $data = [
+ 'domain' => str_replace(['http://', 'https://'], '', config('app.url')),
+ 'plugin' => $plugin,
+ ];
+
+ $data = hook_filter('admin.marketing.show.data', $data);
+
+ if ($request->expectsJson()) {
+ return $data;
+ }
+
+ return view('admin::pages.marketing.show', $data);
+ } catch (\Exception $e) {
+ return redirect(admin_route('marketing.index'))->withErrors(['error' => $e->getMessage()]);
+ }
+ }
+
+ /**
+ * 下单购买插件
+ */
+ public function buy(Request $request)
+ {
+ try {
+ $postData = $request->getContent();
+ $pluginCode = $request->code;
+ $result = MarketingService::getInstance()->buy($pluginCode, $postData);
+
+ return json_success('获取成功', $result);
+ } catch (\Exception $e) {
+ return json_fail($e->getMessage());
+ }
+ }
+
+ /**
+ * 下载插件安装包到本地
+ */
+ public function download(Request $request)
+ {
+ try {
+ $pluginCode = $request->code;
+ MarketingService::getInstance()->download($pluginCode);
+
+ return json_success('下载解压成功, 请去插件列表安装');
+ } catch (\Exception $e) {
+ return json_fail($e->getMessage());
+ }
+ }
+}
diff --git a/beike/Admin/Http/Controllers/OrderController.php b/beike/Admin/Http/Controllers/OrderController.php
new file mode 100644
index 00000000..07ca08a7
--- /dev/null
+++ b/beike/Admin/Http/Controllers/OrderController.php
@@ -0,0 +1,123 @@
+
+ * @created 2022-07-05 10:45:26
+ * @modified 2022-07-05 10:45:26
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Resources\OrderSimple;
+use Beike\Models\Order;
+use Beike\Models\OrderShipment;
+use Beike\Repositories\OrderRepo;
+use Beike\Services\ShipmentService;
+use Beike\Services\StateMachineService;
+use Beike\Shop\Http\Resources\Account\OrderList;
+use Illuminate\Http\Request;
+
+class OrderController extends Controller
+{
+ /**
+ * 获取订单列表
+ *
+ * @param Request $request
+ * @return mixed
+ * @throws \Exception
+ */
+ public function index(Request $request)
+ {
+ $orders = OrderRepo::filterOrders($request->all());
+ $data = [
+ 'orders' => OrderList::collection($orders),
+ 'statuses' => StateMachineService::getAllStatuses(),
+ ];
+ $data = hook_filter('admin.order.index.data', $data);
+
+ return view('admin::pages.orders.index', $data);
+ }
+
+ /**
+ * 导出订单列表
+ *
+ * @param Request $request
+ * @return mixed
+ * @throws \Exception
+ */
+ public function export(Request $request)
+ {
+ try {
+ $orders = OrderRepo::filterAll($request->all());
+ $items = OrderSimple::collection($orders)->jsonSerialize();
+ $items = hook_filter('admin.order.export.data', $items);
+
+ return $this->downloadCsv('orders', $items, 'order');
+ } catch (\Exception $e) {
+ return redirect(admin_route('orders.index'))->withErrors(['error' => $e->getMessage()]);
+ }
+ }
+
+ /**
+ * 查看单个订单
+ *
+ * @param Request $request
+ * @param Order $order
+ * @return mixed
+ * @throws \Exception
+ */
+ public function show(Request $request, Order $order)
+ {
+ $order->load(['orderTotals', 'orderHistories', 'orderShipments']);
+ $data = hook_filter('admin.order.show.data', ['order' => $order, 'html_items' => []]);
+ $data['statuses'] = StateMachineService::getInstance($order)->nextBackendStatuses();
+ $data = hook_filter('admin.order.show.data', $data);
+
+ return view('admin::pages.orders.form', $data);
+ }
+
+ /**
+ * 更新订单状态,添加订单更新日志
+ *
+ * @param Request $request
+ * @param Order $order
+ * @return array
+ * @throws \Throwable
+ */
+ public function updateStatus(Request $request, Order $order)
+ {
+ $status = $request->get('status');
+ $comment = $request->get('comment');
+ $notify = $request->get('notify');
+
+ $shipment = ShipmentService::handleShipment(\request('express_code'), \request('express_number'));
+
+ $stateMachine = new StateMachineService($order);
+ $stateMachine->setShipment($shipment)->changeStatus($status, $comment, $notify);
+
+ $orderStatusData = $request->all();
+
+ hook_action('admin.order.update_status.after', $orderStatusData);
+
+ return json_success(trans('common.updated_success'));
+ }
+
+ /**
+ * 更新发货信息
+ */
+ public function updateShipment(Request $request, Order $order, int $orderShipmentId): array
+ {
+ $data = $request->all();
+ $orderShipment = OrderShipment::query()->where('order_id', $order->id)->findOrFail($orderShipmentId);
+ ShipmentService::updateShipment($orderShipment, $data);
+ hook_action('admin.order.update_shipment.after', [
+ 'request_data' => $data,
+ 'shipment' => $orderShipment,
+ ]);
+
+ return json_success(trans('common.updated_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/PageCategoryController.php b/beike/Admin/Http/Controllers/PageCategoryController.php
new file mode 100644
index 00000000..934da06c
--- /dev/null
+++ b/beike/Admin/Http/Controllers/PageCategoryController.php
@@ -0,0 +1,153 @@
+
+ * @created 2023-02-09 10:21:27
+ * @modified 2023-02-09 10:21:27
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Requests\PageCategoryRequest;
+use Beike\Admin\Http\Resources\PageCategoryResource;
+use Beike\Models\PageCategory;
+use Beike\Repositories\PageCategoryRepo;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
+
+class PageCategoryController extends Controller
+{
+ /**
+ * 显示文章分类列表
+ *
+ * @return mixed
+ */
+ public function index()
+ {
+ $pageCategoryList = PageCategoryRepo::getList();
+ $data = [
+ 'page_categories' => $pageCategoryList,
+ 'page_categories_format' => PageCategoryResource::collection($pageCategoryList)->jsonSerialize(),
+ ];
+
+ $data = hook_filter('admin.page_category.index.data', $data);
+
+ return view('admin::pages.page_categories.index', $data);
+ }
+
+ /**
+ * 创建文章分类
+ *
+ * @return mixed
+ */
+ public function create(): mixed
+ {
+ return view('admin::pages.page_categories.form', ['page_category' => new PageCategory()]);
+ }
+
+ /**
+ * 保存新建
+ *
+ * @param PageCategoryRequest $request
+ * @return RedirectResponse
+ * @throws \Throwable
+ */
+ public function store(PageCategoryRequest $request)
+ {
+ try {
+ $requestData = $request->all();
+ hook_action('admin.page_category.store.before', $requestData);
+ $pageCategory = PageCategoryRepo::createOrUpdate($requestData);
+
+ hook_action('admin.page_category.store.after', ['page_category' => $pageCategory, 'request_data' => $requestData]);
+
+ return redirect(admin_route('page_categories.index'));
+ } catch (\Exception $e) {
+ return redirect(admin_route('page_categories.index'))->withErrors(['error' => $e->getMessage()]);
+ }
+ }
+
+ /**
+ * @param Request $request
+ * @param PageCategory $pageCategory
+ * @return mixed
+ */
+ public function edit(Request $request, PageCategory $pageCategory)
+ {
+ $pageCategory->load(['descriptions', 'parent.description']);
+ $descriptions = $pageCategory->descriptions->keyBy('locale')->toArray();
+ $data = [
+ 'page_category' => $pageCategory,
+ 'descriptions' => $descriptions,
+ ];
+
+ $data = hook_filter('admin.page_category.edit.data', $data);
+
+ return view('admin::pages.page_categories.form', $data);
+ }
+
+ /**
+ * 保存更新
+ *
+ * @param PageCategoryRequest $request
+ * @param PageCategory $pageCategory
+ * @return RedirectResponse
+ * @throws \Throwable
+ */
+ public function update(PageCategoryRequest $request, PageCategory $pageCategory)
+ {
+ try {
+ $requestData = $request->all();
+ $requestData['id'] = $pageCategory->id;
+ hook_action('admin.page_category.update.before', $requestData);
+ $pageCategory = PageCategoryRepo::createOrUpdate($requestData);
+ hook_action('admin.page_category.update.after', ['page_category' => $pageCategory, 'request_data' => $requestData]);
+
+ return redirect()->to(admin_route('page_categories.index'));
+ } catch (\Exception $e) {
+ return redirect(admin_route('page_categories.index'))->withErrors(['error' => $e->getMessage()]);
+ }
+ }
+
+ /**
+ * 删除单页
+ *
+ * @param Request $request
+ * @param int $pageId
+ * @return array
+ */
+ public function destroy(Request $request, int $pageId): array
+ {
+ PageCategoryRepo::deleteById($pageId);
+ hook_action('admin.page_category.store.after', $pageId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ /**
+ * 搜索页面标题自动完成
+ * @param Request $request
+ * @return array
+ */
+ public function autocomplete(Request $request): array
+ {
+ $products = PageCategoryRepo::autocomplete($request->get('name') ?? '');
+
+ return json_success(trans('common.get_success'), $products);
+ }
+
+ /**
+ * 获取单页名称
+ * @param PageCategory $pageCategory
+ * @return array
+ */
+ public function name(PageCategory $pageCategory): array
+ {
+ $name = $pageCategory->description->title ?? '';
+
+ return json_success(trans('common.get_success'), $name);
+ }
+}
diff --git a/beike/Admin/Http/Controllers/PagesController.php b/beike/Admin/Http/Controllers/PagesController.php
new file mode 100644
index 00000000..5aa3fa47
--- /dev/null
+++ b/beike/Admin/Http/Controllers/PagesController.php
@@ -0,0 +1,145 @@
+
+ * @created 2022-08-08 15:07:33
+ * @modified 2022-08-08 15:07:33
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Requests\PageRequest;
+use Beike\Admin\Repositories\PageRepo;
+use Beike\Models\Page;
+use Beike\Shop\Http\Resources\PageDetail;
+use Beike\Shop\Http\Resources\ProductSimple;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
+
+class PagesController extends Controller
+{
+ /**
+ * 显示单页列表
+ *
+ * @return mixed
+ */
+ public function index()
+ {
+ $pageList = PageRepo::getList();
+ $data = [
+ 'pages' => $pageList,
+ 'pages_format' => PageDetail::collection($pageList)->jsonSerialize(),
+ ];
+
+ return view('admin::pages.pages.index', $data);
+ }
+
+ /**
+ * 创建页面
+ *
+ * @return mixed
+ */
+ public function create()
+ {
+ return view('admin::pages.pages.form', ['page' => new Page()]);
+ }
+
+ /**
+ * 保存新建
+ *
+ * @param PageRequest $request
+ * @return RedirectResponse
+ */
+ public function store(PageRequest $request)
+ {
+ try {
+ $requestData = $request->all();
+ $page = PageRepo::createOrUpdate($requestData);
+ hook_action('admin.page.store.after', ['request_data' => $requestData, 'page' => $page]);
+
+ return redirect(admin_route('pages.index'));
+ } catch (\Exception $e) {
+ return redirect(admin_route('pages.index'))->withErrors(['error' => $e->getMessage()]);
+ }
+ }
+
+ /**
+ * @param Request $request
+ * @param Page $page
+ * @return mixed
+ */
+ public function edit(Request $request, Page $page)
+ {
+ $page->load(['products.description', 'category.description']);
+
+ $data = [
+ 'page' => $page,
+ 'products' => ProductSimple::collection($page->products)->jsonSerialize(),
+ 'descriptions' => PageRepo::getDescriptionsByLocale($page->id),
+ ];
+
+ return view('admin::pages.pages.form', $data);
+ }
+
+ /**
+ * 保存更新
+ *
+ * @param PageRequest $request
+ * @param int $pageId
+ * @return RedirectResponse
+ */
+ public function update(PageRequest $request, int $pageId)
+ {
+ try {
+ $requestData = $request->all();
+ $requestData['id'] = $pageId;
+ $page = PageRepo::createOrUpdate($requestData);
+ hook_action('admin.page.update.after', ['request_data' => $requestData, 'page' => $page]);
+
+ return redirect()->to(admin_route('pages.index'));
+ } catch (\Exception $e) {
+ return redirect(admin_route('pages.index'))->withErrors(['error' => $e->getMessage()]);
+ }
+ }
+
+ /**
+ * 删除单页
+ *
+ * @param Request $request
+ * @param int $pageId
+ * @return array
+ */
+ public function destroy(Request $request, int $pageId): array
+ {
+ PageRepo::deleteById($pageId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ /**
+ * 搜索页面标题自动完成
+ * @param Request $request
+ * @return array
+ */
+ public function autocomplete(Request $request): array
+ {
+ $products = PageRepo::autocomplete($request->get('name') ?? '');
+
+ return json_success(trans('common.get_success'), $products);
+ }
+
+ /**
+ * 获取单页名称
+ * @param Page $page
+ * @return array
+ */
+ public function name(Page $page): array
+ {
+ $name = $page->description->title ?? '';
+
+ return json_success(trans('common.get_success'), $name);
+ }
+}
diff --git a/beike/Admin/Http/Controllers/PluginController.php b/beike/Admin/Http/Controllers/PluginController.php
new file mode 100644
index 00000000..6a688225
--- /dev/null
+++ b/beike/Admin/Http/Controllers/PluginController.php
@@ -0,0 +1,137 @@
+
+ * @created 2022-06-29 16:02:15
+ * @modified 2022-06-29 16:02:15
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Resources\PluginResource;
+use Beike\Repositories\PluginRepo;
+use Beike\Repositories\SettingRepo;
+use Exception;
+use Illuminate\Contracts\View\View;
+use Illuminate\Http\Request;
+
+class PluginController extends Controller
+{
+ /**
+ * @throws Exception
+ */
+ public function index()
+ {
+ $plugins = app('plugin')->getPlugins();
+ $data['plugins'] = array_values(PluginResource::collection($plugins)->jsonSerialize());
+ $data = hook_filter('admin.plugin.index.data', $data);
+
+ return view('admin::pages.plugins.index', $data);
+ }
+
+ /**
+ * 上传插件
+ */
+ public function import(Request $request): array
+ {
+ $zipFile = $request->file('file');
+ app('plugin')->import($zipFile);
+
+ return json_success(trans('common.success'));
+ }
+
+ /**
+ * @param Request $request
+ * @param $code
+ * @return array
+ * @throws Exception
+ */
+ public function install(Request $request, $code): array
+ {
+ $plugin = app('plugin')->getPluginOrFail($code);
+ PluginRepo::installPlugin($plugin);
+
+ return json_success(trans('common.success'));
+ }
+
+ /**
+ * @param Request $request
+ * @param $code
+ * @return array
+ * @throws Exception
+ */
+ public function uninstall(Request $request, $code): array
+ {
+ $plugin = app('plugin')->getPluginOrFail($code);
+ PluginRepo::uninstallPlugin($plugin);
+
+ return json_success(trans('common.success'));
+ }
+
+ /**
+ * @param Request $request
+ * @param $code
+ * @return View
+ * @throws Exception
+ */
+ public function edit(Request $request, $code): View
+ {
+ $plugin = app('plugin')->getPluginOrFail($code);
+ $columnView = $plugin->getColumnView();
+ $view = $columnView ?: 'admin::pages.plugins.form';
+
+ $data = [
+ 'view' => $view,
+ 'plugin' => $plugin,
+ ];
+
+ $data = hook_filter('admin.plugin.edit.data', $data);
+
+ return view($view, $data);
+ }
+
+ /**
+ * @param Request $request
+ * @param $code
+ * @return mixed
+ * @throws Exception
+ */
+ public function update(Request $request, $code)
+ {
+ $fields = $request->all();
+ $plugin = app('plugin')->getPluginOrFail($code);
+ if (method_exists($plugin, 'validate')) {
+ $validator = $plugin->validate($fields);
+ if ($validator->fails()) {
+ return back()->withErrors($validator)->withInput();
+ }
+ }
+
+ $data = ['plugin_code' => $code, 'fields' => $fields];
+ hook_action('plugin.update.before', $data);
+
+ SettingRepo::update('plugin', $code, $fields);
+
+ hook_action('plugin.update.after', $data);
+
+ return redirect($this->getRedirect())->with('success', trans('common.updated_success'));
+ }
+
+ /**
+ * @param Request $request
+ * @param $code
+ * @return array
+ * @throws Exception
+ */
+ public function updateStatus(Request $request, $code): array
+ {
+ app('plugin')->getPluginOrFail($code);
+ $status = $request->get('status');
+ SettingRepo::update('plugin', $code, ['status' => $status]);
+
+ return json_success(trans('common.updated_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/ProductController.php b/beike/Admin/Http/Controllers/ProductController.php
new file mode 100644
index 00000000..2435c2ee
--- /dev/null
+++ b/beike/Admin/Http/Controllers/ProductController.php
@@ -0,0 +1,215 @@
+all();
+ $productList = ProductRepo::list($requestData);
+ $products = ProductResource::collection($productList);
+ $productsFormat = $products->jsonSerialize();
+
+ $data = [
+ 'categories' => CategoryRepo::flatten(locale()),
+ 'products_format' => $productsFormat,
+ 'products' => $products,
+ 'type' => 'products',
+ ];
+
+ $data = hook_filter('admin.product.index.data', $data);
+
+ if ($request->expectsJson()) {
+ return $productsFormat;
+ }
+
+ return view('admin::pages.products.index', $data);
+ }
+
+ public function trashed(Request $request)
+ {
+ $requestData = $request->all();
+ $requestData['trashed'] = true;
+ $productList = ProductRepo::list($requestData);
+ $products = ProductResource::collection($productList);
+ $productsFormat = $products->jsonSerialize();
+
+ $data = [
+ 'categories' => CategoryRepo::flatten(locale()),
+ 'products_format' => $productsFormat,
+ 'products' => $products,
+ 'type' => 'trashed',
+ ];
+
+ $data = hook_filter('admin.product.trashed.data', $data);
+
+ if ($request->expectsJson()) {
+ return $products;
+ }
+
+ return view('admin::pages.products.index', $data);
+ }
+
+ public function create(Request $request)
+ {
+ return $this->form($request, new Product());
+ }
+
+ public function store(ProductRequest $request)
+ {
+ try {
+ $requestData = $request->all();
+ $product = (new ProductService)->create($requestData);
+
+ $data = [
+ 'request_data' => $requestData,
+ 'product' => $product,
+ ];
+
+ hook_action('admin.product.store.after', $data);
+
+ return redirect()->to(admin_route('products.index'))
+ ->with('success', trans('common.created_success'));
+ } catch (\Exception $e) {
+ return redirect(admin_route('products.create'))
+ ->withInput()
+ ->withErrors(['error' => $e->getMessage()]);
+ }
+ }
+
+ public function edit(Request $request, Product $product)
+ {
+ return $this->form($request, $product);
+ }
+
+ public function update(ProductRequest $request, Product $product)
+ {
+ try {
+ $requestData = $request->all();
+ $product = (new ProductService)->update($product, $requestData);
+
+ $data = [
+ 'request_data' => $requestData,
+ 'product' => $product,
+ ];
+ hook_action('admin.product.update.after', $data);
+
+ return redirect()->to($this->getRedirect())->with('success', trans('common.updated_success'));
+ } catch (\Exception $e) {
+ return redirect(admin_route('products.edit', $product))->withErrors(['error' => $e->getMessage()]);
+ }
+ }
+
+ public function destroy(Request $request, Product $product)
+ {
+ $product->delete();
+ hook_action('admin.product.destroy.after', $product);
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ public function restore(Request $request)
+ {
+ $productId = $request->id ?? 0;
+ Product::withTrashed()->find($productId)->restore();
+
+ hook_action('admin.product.restore.after', $productId);
+
+ return ['success' => true];
+ }
+
+ protected function form(Request $request, Product $product)
+ {
+ if ($product->id) {
+ $descriptions = $product->descriptions->keyBy('locale');
+ $categoryIds = $product->categories->pluck('id')->toArray();
+ $product->load('brand', 'attributes');
+ }
+
+ $product = hook_filter('admin.product.form.product', $product);
+ $taxClasses = TaxClassRepo::getList();
+ array_unshift($taxClasses, ['title' => trans('admin/builder.text_no'), 'id' => 0]);
+
+ $data = [
+ 'product' => $product,
+ 'descriptions' => $descriptions ?? [],
+ 'category_ids' => $categoryIds ?? [],
+ 'product_attributes' => ProductAttributeResource::collection($product->attributes),
+ 'relations' => ProductResource::collection($product->relations)->resource,
+ 'languages' => LanguageRepo::all(),
+ 'tax_classes' => $taxClasses,
+ 'source' => [
+ 'categories' => CategoryRepo::flatten(locale()),
+ ],
+ '_redirect' => $this->getRedirect(),
+ ];
+
+ $data = hook_filter('admin.product.form.data', $data);
+
+ return view('admin::pages.products.form.form', $data);
+ }
+
+ public function name(int $id)
+ {
+ $name = ProductRepo::getName($id);
+
+ return json_success(trans('common.get_success'), $name);
+ }
+
+ /**
+ * 根据商品ID批量获取商品名称
+ *
+ * @param Request $request
+ * @return array
+ */
+ public function getNames(Request $request): array
+ {
+ $productIds = explode(',', $request->get('product_ids'));
+ $name = ProductRepo::getNames($productIds);
+
+ return json_success(trans('common.get_success'), $name);
+ }
+
+ public function autocomplete(Request $request)
+ {
+ $products = ProductRepo::autocomplete($request->get('name') ?? '');
+
+ return json_success(trans('common.get_success'), $products);
+ }
+
+ public function updateStatus(Request $request)
+ {
+ ProductRepo::updateStatusByIds($request->get('ids'), $request->get('status'));
+
+ return json_success(trans('common.updated_success'), []);
+ }
+
+ public function destroyByIds(Request $request)
+ {
+ $productIds = $request->get('ids');
+ ProductRepo::DeleteByIds($productIds);
+
+ hook_action('admin.product.destroy_by_ids.after', $productIds);
+
+ return json_success(trans('common.deleted_success'), []);
+ }
+
+ public function trashedClear()
+ {
+ ProductRepo::forceDeleteTrashed();
+ }
+}
diff --git a/beike/Admin/Http/Controllers/RegionController.php b/beike/Admin/Http/Controllers/RegionController.php
new file mode 100644
index 00000000..4d0ee061
--- /dev/null
+++ b/beike/Admin/Http/Controllers/RegionController.php
@@ -0,0 +1,55 @@
+
+ * @created 2022-07-26 20:01:02
+ * @modified 2022-07-26 20:01:02
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Repositories\RegionRepo;
+use Beike\Repositories\CountryRepo;
+use Illuminate\Http\Request;
+
+class RegionController
+{
+ public function index()
+ {
+ $data = [
+ 'regions' => RegionRepo::getList(),
+ 'countries' => CountryRepo::all(),
+ ];
+
+ $data = hook_filter('admin.region.index.data', $data);
+
+ return view('admin::pages.regions.index', $data);
+ }
+
+ public function store(Request $request)
+ {
+ $requestData = json_decode($request->getContent(), true);
+ $region = RegionRepo::createOrUpdate($requestData);
+
+ return json_success(trans('common.created_success'), $region);
+ }
+
+ public function update(Request $request, int $regionId)
+ {
+ $requestData = json_decode($request->getContent(), true);
+ $requestData['id'] = $regionId;
+ $region = RegionRepo::createOrUpdate($requestData);
+
+ return json_success(trans('common.updated_success'), $region);
+ }
+
+ public function destroy(Request $request, int $regionId)
+ {
+ RegionRepo::deleteById($regionId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/RmaController.php b/beike/Admin/Http/Controllers/RmaController.php
new file mode 100644
index 00000000..4f7bf2a6
--- /dev/null
+++ b/beike/Admin/Http/Controllers/RmaController.php
@@ -0,0 +1,74 @@
+
+ * @created 2022-08-03 21:17:04
+ * @modified 2022-08-03 21:17:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Resources\RmaDetail;
+use Beike\Admin\Http\Resources\RmaHistoryDetail;
+use Beike\Repositories\RmaRepo;
+use Illuminate\Http\Request;
+
+class RmaController extends Controller
+{
+ public function index(Request $request)
+ {
+ $rmas = RmaRepo::list($request->only('name', 'email', 'telephone', 'product_name', 'sku', 'type', 'status'));
+ $data = [
+ 'rmas' => $rmas,
+ 'rmas_format' => RmaDetail::collection($rmas)->jsonSerialize(),
+ ];
+
+ $data = hook_filter('admin.rma.index.data', $data);
+
+ return view('admin::pages.rmas.index', $data);
+ }
+
+ /**
+ * @param int $id
+ * @return mixed
+ */
+ public function show(int $id)
+ {
+ $rma = RmaRepo::find($id);
+ $data = [
+ 'rma' => (new RmaDetail($rma))->jsonSerialize(),
+ 'histories' => RmaHistoryDetail::collection($rma->histories)->jsonSerialize(),
+ 'statuses' => RmaRepo::getStatuses(),
+ 'types' => RmaRepo::getTypes(),
+ ];
+
+ $data = hook_filter('admin.rma.show.data', $data);
+
+ return view('admin::pages.rmas.info', $data);
+ }
+
+ public function addHistory(Request $request, int $id)
+ {
+ RmaRepo::addHistory($id, $request->only('status', 'notify', 'comment'));
+ $data = [
+ 'rma' => (new RmaDetail(RmaRepo::find($id)))->jsonSerialize(),
+ 'statuses' => RmaRepo::getStatuses(),
+ ];
+
+ hook_filter('admin.rma.add_history.data', $data);
+
+ return json_success(trans('common.updated_success'), $data);
+ }
+
+ public function destroy(int $id): array
+ {
+ RmaRepo::delete($id);
+
+ hook_action('admin.rma.destroy.after', $id);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/RmaReasonController.php b/beike/Admin/Http/Controllers/RmaReasonController.php
new file mode 100644
index 00000000..45306424
--- /dev/null
+++ b/beike/Admin/Http/Controllers/RmaReasonController.php
@@ -0,0 +1,63 @@
+
+ * @created 2022-08-03 21:17:04
+ * @modified 2022-08-03 21:17:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Resources\RmaReasonDetail;
+use Beike\Repositories\LanguageRepo;
+use Beike\Repositories\RmaReasonRepo;
+use Exception;
+use Illuminate\Http\Request;
+
+class RmaReasonController extends Controller
+{
+ public function index(Request $request)
+ {
+ $rmaReasons = RmaReasonRepo::list($request->only('name'));
+
+ $data = [
+ 'languages' => LanguageRepo::all(),
+ 'rmaReasons' => RmaReasonDetail::collection($rmaReasons)->jsonSerialize(),
+ ];
+
+ $data = hook_filter('admin.rma_reason.index.data', $data);
+
+ if ($request->expectsJson()) {
+ return json_success(trans('common.success'), $data);
+ }
+
+ return view('admin::pages.rma_reasons.index', $data);
+ }
+
+ public function store(Request $request): array
+ {
+ $rmaReason = RmaReasonRepo::create($request->only('name'));
+
+ return json_success(trans('common.created_success'), $rmaReason);
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function update(Request $request, int $id): array
+ {
+ $rmaReason = RmaReasonRepo::update($id, $request->only('name'));
+
+ return json_success(trans('common.updated_success'), $rmaReason);
+ }
+
+ public function destroy(int $id): array
+ {
+ RmaReasonRepo::delete($id);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/SettingController.php b/beike/Admin/Http/Controllers/SettingController.php
new file mode 100644
index 00000000..1c2a5ce9
--- /dev/null
+++ b/beike/Admin/Http/Controllers/SettingController.php
@@ -0,0 +1,76 @@
+
+ * @created 2022-06-29 16:02:15
+ * @modified 2022-06-29 16:02:15
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Resources\CustomerGroupDetail;
+use Beike\Repositories\CountryRepo;
+use Beike\Repositories\CurrencyRepo;
+use Beike\Repositories\CustomerGroupRepo;
+use Beike\Repositories\SettingRepo;
+use Beike\Repositories\ThemeRepo;
+use Illuminate\Http\Request;
+
+class SettingController extends Controller
+{
+ /**
+ * 显示系统设置页面
+ *
+ * @return mixed
+ */
+ public function index()
+ {
+ $themes = ThemeRepo::getAllThemes();
+
+ $tax_address = [
+ ['value' => 'shipping', 'label' => trans('admin/setting.shipping_address')],
+ ['value' => 'payment', 'label' => trans('admin/setting.payment_address')],
+ ];
+
+ $data = [
+ 'countries' => CountryRepo::listEnabled(),
+ 'currencies' => CurrencyRepo::listEnabled(),
+ 'tax_address' => $tax_address,
+ 'customer_groups' => CustomerGroupDetail::collection(CustomerGroupRepo::list())->jsonSerialize(),
+ 'themes' => $themes,
+ ];
+
+ $data = hook_filter('admin.setting.index.data', $data);
+
+ return view('admin::pages.setting', $data);
+ }
+
+ /**
+ * 更新系统设置
+ *
+ * @throws \Throwable
+ */
+ public function store(Request $request)
+ {
+ $settings = $request->all();
+ foreach ($settings as $key => $value) {
+ SettingRepo::storeValue($key, $value);
+ }
+
+ $oldAdminName = admin_name();
+ $newAdminName = $settings['admin_name'] ?: 'admin';
+ $settingUrl = str_replace($oldAdminName, $newAdminName, admin_route('settings.index'));
+
+ return redirect($settingUrl)->with('success', trans('common.updated_success'));
+ }
+
+ public function storeDeveloperToken(Request $request)
+ {
+ SettingRepo::storeValue('developer_token', $request->get('developer_token'));
+
+ return json_success(trans('common.updated_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/TaxClassController.php b/beike/Admin/Http/Controllers/TaxClassController.php
new file mode 100644
index 00000000..80c6fadd
--- /dev/null
+++ b/beike/Admin/Http/Controllers/TaxClassController.php
@@ -0,0 +1,56 @@
+
+ * @created 2022-07-26 19:45:41
+ * @modified 2022-07-26 19:45:41
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Repositories\TaxClassRepo;
+use Beike\Models\TaxRate;
+use Illuminate\Http\Request;
+
+class TaxClassController extends Controller
+{
+ public function index()
+ {
+ $data = [
+ 'tax_classes' => TaxClassRepo::getList(),
+ 'all_tax_rates' => TaxRate::all(),
+ 'bases' => TaxClassRepo::BASE_TYPES,
+ ];
+
+ $data = hook_filter('admin.tax_class.index.data', $data);
+
+ return view('admin::pages.tax_classes.index', $data);
+ }
+
+ public function store(Request $request)
+ {
+ $requestData = json_decode($request->getContent(), true);
+ $taxClass = TaxClassRepo::createOrUpdate($requestData);
+
+ return json_success(trans('common.created_success'), $taxClass);
+ }
+
+ public function update(Request $request, int $taxClassId)
+ {
+ $requestData = json_decode($request->getContent(), true);
+ $requestData['id'] = $taxClassId;
+ $taxClass = TaxClassRepo::createOrUpdate($requestData);
+
+ return json_success(trans('common.updated_success'), $taxClass);
+ }
+
+ public function destroy(Request $request, int $taxClassId)
+ {
+ TaxClassRepo::deleteById($taxClassId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/TaxRateController.php b/beike/Admin/Http/Controllers/TaxRateController.php
new file mode 100644
index 00000000..f3357453
--- /dev/null
+++ b/beike/Admin/Http/Controllers/TaxRateController.php
@@ -0,0 +1,58 @@
+
+ * @created 2022-07-26 20:00:13
+ * @modified 2022-07-26 20:00:13
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Admin\Http\Requests\TaxRateRequest;
+use Beike\Admin\Repositories\TaxRateRepo;
+use Beike\Models\Region;
+use Illuminate\Http\Request;
+
+class TaxRateController
+{
+ public function index()
+ {
+ $data = [
+ 'tax_rates' => TaxRateRepo::getList(),
+ 'regions' => Region::all(),
+ ];
+
+ $data = hook_filter('admin.tax_rate.index.data', $data);
+
+ return view('admin::pages.tax_rates.index', $data);
+ }
+
+ public function store(TaxRateRequest $request)
+ {
+ $requestData = json_decode($request->getContent(), true);
+ $taxRate = TaxRateRepo::createOrUpdate($requestData);
+ $taxRate->load('region');
+
+ return json_success(trans('common.created_success'), $taxRate);
+ }
+
+ public function update(TaxRateRequest $request, int $taxRateId)
+ {
+ $requestData = json_decode($request->getContent(), true);
+ $requestData['id'] = $taxRateId;
+ $taxRate = TaxRateRepo::createOrUpdate($requestData);
+ $taxRate->load('region');
+
+ return json_success(trans('common.updated_success'), $taxRate);
+ }
+
+ public function destroy(Request $request, int $taxRateId)
+ {
+ TaxRateRepo::deleteById($taxRateId);
+
+ return json_success(trans('common.deleted_success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/ThemeController.php b/beike/Admin/Http/Controllers/ThemeController.php
new file mode 100644
index 00000000..b8db8687
--- /dev/null
+++ b/beike/Admin/Http/Controllers/ThemeController.php
@@ -0,0 +1,83 @@
+
+ * @created 2023-03-16 12:00:13
+ * @modified 2023-03-16 12:00:13
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Repositories\PluginRepo;
+use Beike\Repositories\SettingRepo;
+use Database\Seeders\ThemeSeeder;
+use Illuminate\Http\Request;
+
+class ThemeController extends Controller
+{
+ /**
+ * Themes index
+ *
+ * @return mixed
+ * @throws \Exception
+ */
+ public function index()
+ {
+ $currentTheme = system_setting('base.theme');
+ $themes = PluginRepo::getEnabledThemes();
+
+ $data['themes'][] = [
+ 'name' => trans('admin/theme.theme_name'),
+ 'code' => 'default',
+ 'demo' => true,
+ 'image' => image_origin('image/default-theme.jpg'),
+ 'status' => $currentTheme == 'default',
+ ];
+
+ foreach ($themes as $theme) {
+ $themeCode = $theme->code;
+ $plugin = $theme->plugin;
+ $imagePath = $plugin->theme ?? 'image/theme.jpg';
+ $data['themes'][] = [
+ 'name' => $plugin->getLocaleName(),
+ 'code' => $themeCode,
+ 'demo' => true,
+ 'image' => plugin_asset($themeCode, $imagePath),
+ 'status' => $currentTheme == $themeCode,
+ ];
+ }
+
+ return view('admin::pages.theme.index', $data);
+ }
+
+ /**
+ * Enable theme
+ *
+ * @param Request $request
+ * @param $themeCode
+ * @return mixed
+ * @throws \Exception
+ */
+ public function update(Request $request, $themeCode)
+ {
+ $importDemo = $request->get('import_demo');
+ if ($importDemo) {
+ if ($themeCode == 'default') {
+ $seeder = new ThemeSeeder();
+ $seeder->run();
+ } else {
+ $plugin = plugin($themeCode);
+ if ($plugin) {
+ PluginRepo::runSeeder($plugin);
+ }
+ }
+ }
+
+ SettingRepo::update('system', 'base', ['theme' => $themeCode]);
+
+ return json_success(trans('common.success'));
+ }
+}
diff --git a/beike/Admin/Http/Controllers/ZoneController.php b/beike/Admin/Http/Controllers/ZoneController.php
new file mode 100644
index 00000000..2428fa14
--- /dev/null
+++ b/beike/Admin/Http/Controllers/ZoneController.php
@@ -0,0 +1,69 @@
+
+ * @created 2022-06-30 16:17:04
+ * @modified 2022-06-30 16:17:04
+ */
+
+namespace Beike\Admin\Http\Controllers;
+
+use Beike\Repositories\CountryRepo;
+use Beike\Repositories\ZoneRepo;
+use Illuminate\Http\Request;
+
+class ZoneController extends Controller
+{
+ public function index(Request $request)
+ {
+ $zones = ZoneRepo::list($request->only('name', 'code', 'status'));
+
+ $data = [
+ 'zones' => $zones,
+ 'countries' => CountryRepo::all(),
+ ];
+
+ $data = hook_filter('admin.zone.index.data', $data);
+
+ if ($request->expectsJson()) {
+ return json_success(trans('common.success'), $data);
+ }
+
+ return view('admin::pages.zones.index', $data);
+ }
+
+ public function store(Request $request)
+ {
+ $zone = ZoneRepo::create($request->only('country_id', 'name', 'code', 'sort_order', 'status'));
+
+ return json_success(trans('common.created_success'), $zone);
+ }
+
+ public function update(Request $request, int $id)
+ {
+ $zone = ZoneRepo::update($id, $request->only('country_id', 'name', 'code', 'sort_order', 'status'));
+
+ return json_success(trans('common.updated_success'), $zone);
+ }
+
+ public function destroy(int $id)
+ {
+ ZoneRepo::delete($id);
+
+ return json_success(trans('common.deleted_success'));
+ }
+
+ public function listByCountry(Request $request, int $countryId)
+ {
+ ZoneRepo::listByCountry($countryId);
+
+ $data = [
+ 'zones' => ZoneRepo::listByCountry($countryId),
+ ];
+
+ return json_success(trans('common.success'), $data);
+ }
+}
diff --git a/beike/Admin/Http/Requests/AdminRoleRequest.php b/beike/Admin/Http/Requests/AdminRoleRequest.php
new file mode 100644
index 00000000..5489fa47
--- /dev/null
+++ b/beike/Admin/Http/Requests/AdminRoleRequest.php
@@ -0,0 +1,46 @@
+
+ * @created 2022-08-12 17:48:08
+ * @modified 2022-08-12 17:48:08
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class AdminRoleRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules(): array
+ {
+ return [
+ 'name' => 'required|string|max:10',
+ ];
+ }
+
+ public function attributes()
+ {
+ return [
+ 'name' => trans('role.name'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/AdminUserRequest.php b/beike/Admin/Http/Requests/AdminUserRequest.php
new file mode 100644
index 00000000..e8a7aeb6
--- /dev/null
+++ b/beike/Admin/Http/Requests/AdminUserRequest.php
@@ -0,0 +1,50 @@
+
+ * @created 2022-08-15 18:58:20
+ * @modified 2022-08-15 18:58:20
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class AdminUserRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules(): array
+ {
+ if (! $this->id) {
+ $rules['email'] = 'required|email:rfc|unique:admin_users,email';
+ } else {
+ $rules['email'] = 'required|email:rfc|unique:admin_users,email,' . $this->id;
+ }
+
+ return $rules;
+ }
+
+ public function attributes()
+ {
+ return [
+ 'email' => trans('user.email'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/CategoryRequest.php b/beike/Admin/Http/Requests/CategoryRequest.php
new file mode 100644
index 00000000..8f427699
--- /dev/null
+++ b/beike/Admin/Http/Requests/CategoryRequest.php
@@ -0,0 +1,37 @@
+ 'required|max:255',
+ ];
+ }
+
+ public function attributes()
+ {
+ return [
+ 'descriptions.*.name' => trans('category.name'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/CurrencyRequest.php b/beike/Admin/Http/Requests/CurrencyRequest.php
new file mode 100644
index 00000000..1511bcdd
--- /dev/null
+++ b/beike/Admin/Http/Requests/CurrencyRequest.php
@@ -0,0 +1,47 @@
+ 'required',
+ 'code' => 'required|max:16',
+ 'symbol_left' => 'max:16',
+ 'symbol_right' => 'max:16',
+ 'value' => 'required',
+ 'decimal_place' => 'required|max:1',
+ ];
+ }
+
+ public function attributes()
+ {
+ return [
+ 'name' => trans('currency.name'),
+ 'code' => trans('currency.code'),
+ 'symbol_left' => trans('currency.symbol_left'),
+ 'symbol_right' => trans('currency.symbol_right'),
+ 'value' => trans('currency.value'),
+ 'decimal_place' => trans('currency.decimal_place'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/CustomerGroupRequest.php b/beike/Admin/Http/Requests/CustomerGroupRequest.php
new file mode 100644
index 00000000..b79322b5
--- /dev/null
+++ b/beike/Admin/Http/Requests/CustomerGroupRequest.php
@@ -0,0 +1,48 @@
+
+ * @created 2022-07-01 14:17:04
+ * @modified 2022-07-01 14:17:04
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class CustomerGroupRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize()
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+ 'name.*' => 'required|max:64',
+ 'level' => 'required|max:16',
+ ];
+ }
+
+ public function attributes()
+ {
+ return [
+ 'descriptions.*.name' => trans('customer_group.name'),
+ 'level' => trans('customer_group.level'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/CustomerRequest.php b/beike/Admin/Http/Requests/CustomerRequest.php
new file mode 100644
index 00000000..51bc8da5
--- /dev/null
+++ b/beike/Admin/Http/Requests/CustomerRequest.php
@@ -0,0 +1,58 @@
+
+ * @created 2022-07-01 15:17:04
+ * @modified 2022-07-01 15:17:04
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class CustomerRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize()
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ $rules = [
+ 'name' => 'required|max:64',
+ 'email' => 'required|email:rfc|unique:customers',
+ 'customer_group_id' => 'required|exists:customer_groups,id',
+ ];
+ if (! $this->id) {
+ $rules['password'] = 'required|max:64';
+ } else {
+ $rules['email'] = 'required|email:rfc|unique:customers,email,' . $this->id;
+ }
+
+ return $rules;
+ }
+
+ public function attributes()
+ {
+ return [
+ 'name' => trans('customer.name'),
+ 'email' => trans('customer.email'),
+ 'password' => trans('customer.password'),
+ 'customer_group_id' => trans('customer.customer_group_id'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/ForgottenRequest.php b/beike/Admin/Http/Requests/ForgottenRequest.php
new file mode 100644
index 00000000..9f74aafc
--- /dev/null
+++ b/beike/Admin/Http/Requests/ForgottenRequest.php
@@ -0,0 +1,37 @@
+ 'required|confirmed',
+ ];
+ }
+
+ public function attributes()
+ {
+ return [
+ 'password' => trans('customer.password'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/LoginRequest.php b/beike/Admin/Http/Requests/LoginRequest.php
new file mode 100644
index 00000000..93febce2
--- /dev/null
+++ b/beike/Admin/Http/Requests/LoginRequest.php
@@ -0,0 +1,31 @@
+
+ */
+ public function rules(): array
+ {
+ return [
+ 'email' => ['required', 'email'],
+ 'password' => 'required',
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/PageCategoryRequest.php b/beike/Admin/Http/Requests/PageCategoryRequest.php
new file mode 100644
index 00000000..be7676f3
--- /dev/null
+++ b/beike/Admin/Http/Requests/PageCategoryRequest.php
@@ -0,0 +1,49 @@
+
+ * @created 2023-02-10 16:04:14
+ * @modified 2023-02-10 16:04:14
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class PageCategoryRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules(): array
+ {
+ return [
+ 'descriptions.*.locale' => 'required|string',
+ 'descriptions.*.title' => 'required|string|min:3|max:32',
+ 'descriptions.*.summary' => 'string',
+ ];
+ }
+
+ public function attributes()
+ {
+ return [
+ 'title' => trans('page_category.title'),
+ 'summary' => trans('page_category.summary'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/PageRequest.php b/beike/Admin/Http/Requests/PageRequest.php
new file mode 100644
index 00000000..95234e77
--- /dev/null
+++ b/beike/Admin/Http/Requests/PageRequest.php
@@ -0,0 +1,51 @@
+
+ * @created 2022-08-15 18:58:20
+ * @modified 2022-08-15 18:58:20
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class PageRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules(): array
+ {
+ $rules = [
+ 'descriptions.*.title' => 'required|string|min:3|max:128',
+ 'descriptions.*.content' => 'required|string',
+ 'descriptions.*.locale' => 'required|string',
+ ];
+
+ return $rules;
+ }
+
+ public function attributes()
+ {
+ return [
+ 'title' => trans('page.title'),
+ 'content' => trans('page.content'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/ProductRequest.php b/beike/Admin/Http/Requests/ProductRequest.php
new file mode 100644
index 00000000..eb036a6b
--- /dev/null
+++ b/beike/Admin/Http/Requests/ProductRequest.php
@@ -0,0 +1,56 @@
+
+ * @created 2022-08-19 21:58:20
+ * @modified 2022-08-19 21:58:20
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class ProductRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules(): array
+ {
+ return [
+ 'descriptions.*.name' => 'required|string|min:3|max:128',
+ 'brand_id' => 'int',
+ 'skus.*.sku' => 'required|string',
+ 'skus.*.price' => 'required|numeric',
+ 'skus.*.origin_price' => 'required|numeric',
+ 'skus.*.cost_price' => 'numeric',
+ ];
+ }
+
+ public function attributes()
+ {
+ return [
+ 'descriptions.*.name' => trans('product.name'),
+ 'brand_id' => trans('product.brand'),
+ 'skus.*.sku' => trans('product.sku'),
+ 'skus.*.price' => trans('product.price'),
+ 'skus.*.origin_price' => trans('product.origin_price'),
+ 'skus.*.cost_price' => trans('product.cost_price'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/RmaRequest.php b/beike/Admin/Http/Requests/RmaRequest.php
new file mode 100644
index 00000000..671eab1f
--- /dev/null
+++ b/beike/Admin/Http/Requests/RmaRequest.php
@@ -0,0 +1,60 @@
+
+ * @created 2022-08-03 11:17:04
+ * @modified 2022-08-03 11:17:04
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class RmaRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize()
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ $rules = [
+ 'order_id' => 'required|exists:orders,id',
+ 'order_product_id' => 'required|exists:order_products,id',
+ 'customer_id' => 'required|exists:customers,id',
+ 'quantity' => 'required',
+ 'opened' => 'required',
+ 'rma_reason_id' => 'required|exists:rma_reasons,id',
+ 'type' => 'required',
+ ];
+
+ return $rules;
+ }
+
+ public function attributes()
+ {
+ return [
+ 'order_id' => trans('rma.order_id'),
+ 'order_product_id' => trans('rma.order_product_id'),
+ 'customer_id' => trans('rma.customer_id'),
+ 'quantity' => trans('rma.quantity'),
+ 'opened' => trans('rma.opened'),
+ 'rma_reason_id' => trans('rma.rma_reason_id'),
+ 'type' => trans('rma.type'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/TaxRateRequest.php b/beike/Admin/Http/Requests/TaxRateRequest.php
new file mode 100644
index 00000000..2d6915b2
--- /dev/null
+++ b/beike/Admin/Http/Requests/TaxRateRequest.php
@@ -0,0 +1,57 @@
+
+ * @created 2022-08-12 17:48:08
+ * @modified 2022-08-12 17:48:08
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class TaxRateRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules(): array
+ {
+ $rule = [
+ 'name' => 'required|string|max:10',
+ 'rate' => 'required|numeric',
+ 'type' => 'required|in:percent,flat',
+ 'region_id' => 'required|int',
+ ];
+
+ if ($this->type == 'percent') {
+ $rule['rate'] = 'required|numeric|gt:0|lt:100';
+ }
+
+ return $rule;
+ }
+
+ public function attributes()
+ {
+ return [
+ 'name' => trans('validation.attributes.tax_rate.name'),
+ 'rate' => trans('validation.attributes.tax_rate.rate'),
+ 'type' => trans('validation.attributes.tax_rate.type'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/UploadRequest.php b/beike/Admin/Http/Requests/UploadRequest.php
new file mode 100644
index 00000000..46c98c17
--- /dev/null
+++ b/beike/Admin/Http/Requests/UploadRequest.php
@@ -0,0 +1,39 @@
+
+ * @created 2022-07-22 14:51:27
+ * @modified 2022-07-22 14:51:27
+ */
+
+namespace Beike\Admin\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class UploadRequest extends FormRequest
+{
+ /**
+ * Determine if the user is authorized to make this request.
+ *
+ * @return bool
+ */
+ public function authorize()
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+ 'file' => 'required|image|mimes:jpg,png,jpeg,gif,svg|max:2048',
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Requests/VerifyCodeRequest.php b/beike/Admin/Http/Requests/VerifyCodeRequest.php
new file mode 100644
index 00000000..f39d3c46
--- /dev/null
+++ b/beike/Admin/Http/Requests/VerifyCodeRequest.php
@@ -0,0 +1,37 @@
+ 'required|email:rfc|exists:admin_users,email',
+ ];
+ }
+
+ public function attributes()
+ {
+ return [
+ 'email' => trans('shop/login.email_address'),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Resources/AddressResource.php b/beike/Admin/Http/Resources/AddressResource.php
new file mode 100644
index 00000000..feaa85ab
--- /dev/null
+++ b/beike/Admin/Http/Resources/AddressResource.php
@@ -0,0 +1,32 @@
+ $this->name,
+ 'phone' => $this->phone,
+ 'country_id' => $this->country_id,
+ 'country' => $this->country->name,
+ 'zone_id' => $this->zone_id,
+ 'zone' => $this->zone,
+ 'city' => $this->city,
+ 'zipcode' => $this->zipcode,
+ 'address_1' => $this->address_1,
+ 'address_2' => $this->address_2,
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Http/Resources/AdminUserDetail.php b/beike/Admin/Http/Resources/AdminUserDetail.php
new file mode 100644
index 00000000..a7311719
--- /dev/null
+++ b/beike/Admin/Http/Resources/AdminUserDetail.php
@@ -0,0 +1,31 @@
+
+ * @created 2022-08-12 15:56:28
+ * @modified 2022-08-12 15:56:28
+ */
+
+namespace Beike\Admin\Http\Resources;
+
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class AdminUserDetail extends JsonResource
+{
+ public function toArray($request): array
+ {
+ return [
+ 'id' => $this->id,
+ 'name' => $this->name,
+ 'email' => $this->email,
+ 'locale' => $this->locale,
+ 'roles' => $this->roles,
+ 'roles_name' => $this->roles->pluck('name')->toArray(),
+ 'created_at' => time_format($this->created_at),
+ 'updated_at' => time_format($this->updated_at),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Resources/AttributeDetailResource.php b/beike/Admin/Http/Resources/AttributeDetailResource.php
new file mode 100644
index 00000000..76ceaea4
--- /dev/null
+++ b/beike/Admin/Http/Resources/AttributeDetailResource.php
@@ -0,0 +1,30 @@
+ $this->id,
+ 'attribute_group_id' => $this->attribute_group_id,
+ 'name' => $this->description->name ?? '',
+ 'sort_order' => $this->sort_order,
+ 'attribute_group_name' => $this->attributeGroup->description->name ?? '',
+ 'created_at' => time_format($this->created_at),
+ 'values' => AttributeValueResource::collection($this->values),
+ 'descriptions' => $this->descriptions,
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Http/Resources/AttributeResource.php b/beike/Admin/Http/Resources/AttributeResource.php
new file mode 100644
index 00000000..13e22bb3
--- /dev/null
+++ b/beike/Admin/Http/Resources/AttributeResource.php
@@ -0,0 +1,27 @@
+ $this->id,
+ 'name' => $this->description->name ?? '',
+ 'sort_order' => $this->sort_order,
+ 'attribute_group_name' => $this->attributeGroup->description->name ?? '',
+ 'created_at' => time_format($this->created_at),
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Http/Resources/AttributeValueResource.php b/beike/Admin/Http/Resources/AttributeValueResource.php
new file mode 100644
index 00000000..e2b9b4a2
--- /dev/null
+++ b/beike/Admin/Http/Resources/AttributeValueResource.php
@@ -0,0 +1,28 @@
+ $this->id,
+ 'attribute_id' => $this->attribute_id,
+ 'name' => $this->description->name,
+ 'description' => $this->description,
+ 'descriptions' => $this->descriptions,
+ 'created_at' => time_format($this->created_at),
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Http/Resources/AutocompleteResource.php b/beike/Admin/Http/Resources/AutocompleteResource.php
new file mode 100644
index 00000000..52e37da1
--- /dev/null
+++ b/beike/Admin/Http/Resources/AutocompleteResource.php
@@ -0,0 +1,24 @@
+ $this->id,
+ 'name' => $this->description->name ?? '',
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Http/Resources/CategoryResource.php b/beike/Admin/Http/Resources/CategoryResource.php
new file mode 100644
index 00000000..85020f3d
--- /dev/null
+++ b/beike/Admin/Http/Resources/CategoryResource.php
@@ -0,0 +1,29 @@
+ $this->id,
+ 'name' => $this->description->name ?? '',
+ 'parent_id' => $this->parent_id,
+ 'position' => $this->position,
+ 'active' => $this->active,
+ 'url_edit' => admin_route('categories.edit', $this),
+ 'children' => self::collection($this->children),
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Http/Resources/CustomerGroupDetail.php b/beike/Admin/Http/Resources/CustomerGroupDetail.php
new file mode 100644
index 00000000..fbb7aac3
--- /dev/null
+++ b/beike/Admin/Http/Resources/CustomerGroupDetail.php
@@ -0,0 +1,31 @@
+ $this->id,
+ 'total' => $this->total,
+ 'reward_point_factor' => $this->reward_point_factor,
+ 'use_point_factor' => $this->use_point_factor,
+ 'discount_factor' => $this->discount_factor,
+ 'level' => $this->level,
+ 'name' => $this->description->name ?? '',
+ 'description' => $this->description->description ?? '',
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Http/Resources/CustomerResource.php b/beike/Admin/Http/Resources/CustomerResource.php
new file mode 100644
index 00000000..08777bc4
--- /dev/null
+++ b/beike/Admin/Http/Resources/CustomerResource.php
@@ -0,0 +1,39 @@
+ $this->id,
+ 'name' => $this->name,
+ 'email' => $this->email,
+ 'status' => $this->status,
+ 'created_at' => time_format($this->created_at),
+ 'avatar' => image_resize($this->avatar),
+ 'from' => $this->from,
+ 'customer_group_name' => $this->customerGroup->description->name ?? '',
+ 'edit' => admin_route('customers.edit', $this->id),
+ 'delete' => admin_route('customers.destroy', $this->id),
+ ];
+
+ $params = [
+ 'object' => $this,
+ 'data' => $data,
+ ];
+
+ return hook_filter('resource.customer', $params)['data'];
+ }
+}
diff --git a/beike/Admin/Http/Resources/OrderSimple.php b/beike/Admin/Http/Resources/OrderSimple.php
new file mode 100644
index 00000000..057978fb
--- /dev/null
+++ b/beike/Admin/Http/Resources/OrderSimple.php
@@ -0,0 +1,33 @@
+
+ * @created 2022-08-24 10:51:53
+ * @modified 2022-08-24 10:51:53
+ */
+
+namespace Beike\Admin\Http\Resources;
+
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class OrderSimple extends JsonResource
+{
+ public function toArray($request): array
+ {
+ $data = [
+ 'id' => $this->id,
+ 'number' => $this->number,
+ 'customer_name' => $this->customer_name,
+ 'email' => $this->email,
+ 'telephone' => $this->telephone,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ 'status_format' => $this->status_format,
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Http/Resources/PageCategoryResource.php b/beike/Admin/Http/Resources/PageCategoryResource.php
new file mode 100644
index 00000000..693f0027
--- /dev/null
+++ b/beike/Admin/Http/Resources/PageCategoryResource.php
@@ -0,0 +1,36 @@
+
+ * @created 2023-02-10 09:20:33
+ * @modified 2023-02-10 09:20:33
+ */
+
+namespace Beike\Admin\Http\Resources;
+
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class PageCategoryResource extends JsonResource
+{
+ public function toArray($request): array
+ {
+ $description = $this->description;
+
+ return [
+ 'id' => $this->id,
+ 'active' => $this->active,
+ 'title' => $description->title,
+ 'title_format' => sub_string($description->title, 64),
+ 'summary' => $description->summary,
+ 'summary_format' => sub_string($description->summary, 128),
+ 'meta_title' => $description->meta_title,
+ 'meta_description' => $description->meta_description,
+ 'meta_keywords' => $description->meta_keywords,
+ 'created_at' => time_format($this->created_at),
+ 'updated_at' => time_format($this->updated_at),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Resources/PluginResource.php b/beike/Admin/Http/Resources/PluginResource.php
new file mode 100644
index 00000000..aa22d381
--- /dev/null
+++ b/beike/Admin/Http/Resources/PluginResource.php
@@ -0,0 +1,35 @@
+ $this->code,
+ 'name' => $this->getLocaleName(),
+ 'description' => $this->getLocaleDescription(),
+ 'path' => $this->path,
+ 'version' => $this->version,
+ 'dir_name' => $this->dirName,
+ 'type' => $this->type,
+ 'type_format' => trans('admin/plugin.' . $this->type),
+ 'icon' => plugin_resize($this->code, $this->icon),
+ 'author' => $this->author,
+ 'status' => $this->getStatus(),
+ 'installed' => $this->getInstalled(),
+ 'edit_url' => $this->getEditUrl(),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Resources/ProductAttributeResource.php b/beike/Admin/Http/Resources/ProductAttributeResource.php
new file mode 100644
index 00000000..00b4cc9a
--- /dev/null
+++ b/beike/Admin/Http/Resources/ProductAttributeResource.php
@@ -0,0 +1,33 @@
+load('attribute', 'attributeValue');
+ $data = [
+ 'attribute' => [
+ 'id' => $this->attribute_id,
+ 'name' => $this->attribute->description->name,
+ ],
+ 'attribute_value' => [
+ 'id' => $this->attribute_value_id,
+ 'name' => $this->attributeValue->description->name,
+ ],
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Http/Resources/ProductResource.php b/beike/Admin/Http/Resources/ProductResource.php
new file mode 100644
index 00000000..b75a0cab
--- /dev/null
+++ b/beike/Admin/Http/Resources/ProductResource.php
@@ -0,0 +1,38 @@
+masterSku;
+
+ $data = [
+ 'id' => $this->id,
+ 'images' => array_map(function ($image) {
+ return image_resize($image);
+ }, $this->images ?? []),
+ 'name' => $this->description->name ?? '',
+ 'price_formatted' => currency_format($masterSku->price),
+ 'active' => $this->active,
+ 'position' => $this->position,
+ 'url' => $this->url,
+ 'created_at' => time_format($this->created_at),
+ 'deleted_at' => $this->deleted_at ? time_format($this->deleted_at) : '',
+ 'url_edit' => admin_route('products.edit', $this->id),
+ ];
+
+ return hook_filter('resource.product', $data);
+ }
+}
diff --git a/beike/Admin/Http/Resources/RmaDetail.php b/beike/Admin/Http/Resources/RmaDetail.php
new file mode 100644
index 00000000..92b2d00d
--- /dev/null
+++ b/beike/Admin/Http/Resources/RmaDetail.php
@@ -0,0 +1,42 @@
+
+ * @created 2022-08-31 11:56:28
+ * @modified 2022-08-31 11:56:28
+ */
+
+namespace Beike\Admin\Http\Resources;
+
+use Beike\Repositories\RmaRepo;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class RmaDetail extends JsonResource
+{
+ public function toArray($request): array
+ {
+ $types = RmaRepo::getTypes();
+ $statuses = RmaRepo::getStatuses();
+
+ return [
+ 'id' => $this->id,
+ 'order_product_id' => $this->order_product_id,
+ 'quantity' => $this->quantity,
+ 'opened' => $this->opened,
+ 'type' => $types[$this->type],
+ 'comment' => $this->comment,
+ 'status' => $statuses[$this->status],
+ 'created_at' => time_format($this->created_at),
+ 'email' => $this->email,
+ 'telephone' => $this->telephone,
+ 'product_name' => $this->product_name,
+ 'name' => $this->name,
+ 'sku' => $this->sku,
+ 'reason' => $this->reason ? (json_decode($this->reason->name, true)[locale()] ?? '') : '',
+ 'type_text' => $this->type_text,
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Resources/RmaHistoryDetail.php b/beike/Admin/Http/Resources/RmaHistoryDetail.php
new file mode 100644
index 00000000..3d3f5482
--- /dev/null
+++ b/beike/Admin/Http/Resources/RmaHistoryDetail.php
@@ -0,0 +1,32 @@
+
+ * @created 2022-09-30 11:56:28
+ * @modified 2022-09-30 11:56:28
+ */
+
+namespace Beike\Admin\Http\Resources;
+
+use Beike\Repositories\RmaRepo;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class RmaHistoryDetail extends JsonResource
+{
+ public function toArray($request): array
+ {
+ $statuses = RmaRepo::getStatuses();
+
+ return [
+ 'id' => $this->id,
+ 'rma_id' => $this->rma_id,
+ 'status' => $statuses[$this->status],
+ 'created_at' => time_format($this->created_at),
+ 'notify' => $this->notify,
+ 'comment' => $this->comment,
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Resources/RmaReasonDetail.php b/beike/Admin/Http/Resources/RmaReasonDetail.php
new file mode 100644
index 00000000..5216383c
--- /dev/null
+++ b/beike/Admin/Http/Resources/RmaReasonDetail.php
@@ -0,0 +1,26 @@
+
+ * @created 2022-08-31 11:56:28
+ * @modified 2022-08-31 11:56:28
+ */
+
+namespace Beike\Admin\Http\Resources;
+
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class RmaReasonDetail extends JsonResource
+{
+ public function toArray($request): array
+ {
+ return [
+ 'id' => $this->id,
+ 'name' => json_decode($this->name, true)[locale()] ?? '',
+ 'names' => json_decode($this->name, true),
+ ];
+ }
+}
diff --git a/beike/Admin/Http/Resources/TaxClassDetail.php b/beike/Admin/Http/Resources/TaxClassDetail.php
new file mode 100644
index 00000000..e928a248
--- /dev/null
+++ b/beike/Admin/Http/Resources/TaxClassDetail.php
@@ -0,0 +1,30 @@
+
+ * @created 2022-08-12 15:56:28
+ * @modified 2022-08-12 15:56:28
+ */
+
+namespace Beike\Admin\Http\Resources;
+
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class TaxClassDetail extends JsonResource
+{
+ public function toArray($request): array
+ {
+ return [
+ 'id' => $this->id,
+ 'title' => $this->title,
+ 'description' => sub_string($this->description),
+ 'created_at' => time_format($this->created_at),
+ 'updated_at' => time_format($this->updated_at),
+ 'tax_rates' => $this->taxRates->toArray(),
+ 'tax_rules' => $this->taxRules->toArray(),
+ ];
+ }
+}
diff --git a/beike/Admin/Providers/AdminServiceProvider.php b/beike/Admin/Providers/AdminServiceProvider.php
new file mode 100644
index 00000000..7c8f1610
--- /dev/null
+++ b/beike/Admin/Providers/AdminServiceProvider.php
@@ -0,0 +1,197 @@
+
+ * @created 2022-08-08 08:08:08
+ * @modified 2022-08-08 08:08:08
+ */
+
+namespace Beike\Admin\Providers;
+
+use Beike\Admin\View\Components\Alert;
+use Beike\Admin\View\Components\Filter;
+use Beike\Admin\View\Components\Form\Image;
+use Beike\Admin\View\Components\Form\Input;
+use Beike\Admin\View\Components\Form\InputLocale;
+use Beike\Admin\View\Components\Form\RichText;
+use Beike\Admin\View\Components\Form\Select;
+use Beike\Admin\View\Components\Form\SwitchRadio;
+use Beike\Admin\View\Components\Form\Textarea;
+use Beike\Admin\View\Components\Header;
+use Beike\Admin\View\Components\NoData;
+use Beike\Admin\View\Components\Sidebar;
+use Beike\Console\Commands\ChangeRootPassword;
+use Beike\Console\Commands\FetchCurrencyRate;
+use Beike\Console\Commands\GenerateDatabaseDict;
+use Beike\Console\Commands\GenerateSitemap;
+use Beike\Console\Commands\MakeRootAdminUser;
+use Beike\Console\Commands\MigrateFromOpenCart;
+use Beike\Models\AdminUser;
+use Illuminate\Support\Facades\Config;
+use Illuminate\Support\Facades\View;
+use Illuminate\Support\ServiceProvider;
+use Illuminate\Support\Str;
+use Illuminate\View\FileViewFinder;
+
+class AdminServiceProvider extends ServiceProvider
+{
+ /**
+ * @throws \Exception
+ */
+ public function boot()
+ {
+ $uri = request()->getRequestUri();
+ if (is_installer()) {
+ return;
+ }
+
+ $this->loadCommands();
+ $this->publishResources();
+
+ load_settings();
+ $this->loadRoutesFrom(__DIR__ . '/../Routes/admin.php');
+
+ $adminName = admin_name();
+ if (! Str::startsWith($uri, "/{$adminName}")) {
+ return;
+ }
+
+ $this->mergeConfigFrom(__DIR__ . '/../../Config/beike.php', 'beike');
+ $this->loadViewsFrom(resource_path('/beike/admin/views'), 'admin');
+ $this->loadThemeViewPath();
+
+ $this->app->booted(function () {
+ $this->loadShareViewData();
+ });
+
+ $this->loadAdminViewComponents();
+
+ $this->registerGuard();
+
+ Config::set('filesystems.disks.catalog', [
+ 'driver' => 'local',
+ 'root' => public_path('catalog'),
+ ]);
+
+ $this->loadDesignComponents();
+ }
+
+ /**
+ * 加载后台命令行脚本
+ */
+ protected function loadCommands()
+ {
+ if ($this->app->runningInConsole()) {
+ $this->commands([
+ ChangeRootPassword::class,
+ FetchCurrencyRate::class,
+ GenerateDatabaseDict::class,
+ GenerateSitemap::class,
+ MakeRootAdminUser::class,
+ MigrateFromOpenCart::class,
+ ]);
+ }
+ }
+
+ /**
+ * 注册后台用户 guard
+ */
+ protected function registerGuard()
+ {
+ Config::set('auth.guards.' . AdminUser::AUTH_GUARD, [
+ 'driver' => 'session',
+ 'provider' => 'admin_users',
+ ]);
+
+ Config::set('auth.providers.admin_users', [
+ 'driver' => 'eloquent',
+ 'model' => AdminUser::class,
+ ]);
+ }
+
+ /**
+ * 加载主题模板, 用于装修预览
+ */
+ protected function loadThemeViewPath()
+ {
+ $this->app->singleton('view.finder', function ($app) {
+ $paths = $app['config']['view.paths'];
+ if ($theme = system_setting('base.theme')) {
+ $customTheme[] = base_path("themes/{$theme}");
+ $paths = array_merge($customTheme, $paths);
+ }
+
+ return new FileViewFinder($app['files'], $paths);
+ });
+ }
+
+ /**
+ * 后台UI组件
+ */
+ protected function loadAdminViewComponents()
+ {
+ $this->loadViewComponentsAs('admin', [
+ 'header' => Header::class,
+ 'sidebar' => Sidebar::class,
+ 'filter' => Filter::class,
+ 'alert' => Alert::class,
+ 'form-input-locale' => InputLocale::class,
+ 'form-switch' => SwitchRadio::class,
+ 'form-input' => Input::class,
+ 'form-select' => Select::class,
+ 'form-image' => Image::class,
+ 'form-textarea' => Textarea::class,
+ 'form-rich-text' => RichText::class,
+ 'no-data' => NoData::class,
+ ]);
+ }
+
+ /**
+ * seeder 数据
+ */
+ protected function publishResources()
+ {
+ $this->publishes([
+ __DIR__ . '/../Database/Seeders/ProductSeeder.php' => database_path('seeders/ProductSeeder.php'),
+ ], 'beike-seeders');
+ }
+
+ /**
+ * 加载首页 page builder 相关组件
+ *
+ * @throws \Exception
+ */
+ protected function loadDesignComponents()
+ {
+ $viewPath = base_path() . '/beike/Admin/View';
+ $builderPath = $viewPath . '/DesignBuilders/';
+
+ $builders = glob($builderPath . '*');
+ foreach ($builders as $builder) {
+ $builderName = basename($builder, '.php');
+ $aliasName = Str::snake($builderName);
+ $componentName = Str::studly($builderName);
+ $classBaseName = "\\Beike\\Admin\\View\\DesignBuilders\\{$componentName}";
+
+ if (! class_exists($classBaseName)) {
+ throw new \Exception("请先定义自定义模板类 {$classBaseName}");
+ }
+ $this->loadViewComponentsAs('editor', [
+ $aliasName => $classBaseName,
+ ]);
+ }
+ }
+
+ /**
+ * 后台公共数据
+ */
+ protected function loadShareViewData()
+ {
+ View::share('languages', languages());
+ View::share('admin_base_url', admin_route('home.index'));
+ View::share('shop_base_url', shop_route('home.index'));
+ }
+}
diff --git a/beike/Admin/Repositories/AdminRoleRepo.php b/beike/Admin/Repositories/AdminRoleRepo.php
new file mode 100644
index 00000000..a8bfcaa2
--- /dev/null
+++ b/beike/Admin/Repositories/AdminRoleRepo.php
@@ -0,0 +1,91 @@
+
+ * @created 2022-08-01 21:12:11
+ * @modified 2022-08-01 21:12:11
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Spatie\Permission\Models\Permission;
+use Spatie\Permission\Models\Role;
+
+class AdminRoleRepo
+{
+ /**
+ * 创建新角色
+ *
+ * @param $data
+ * @return Role
+ * @throws \Exception
+ */
+ public static function createAdminRole($data): Role
+ {
+ $adminRole = Role::findOrCreate($data['name'], 'web_admin');
+ $permissions = array_merge($data['core_permissions'], $data['plugin_permissions']);
+ self::syncPermissions($adminRole, $permissions);
+
+ return $adminRole;
+ }
+
+ /**
+ * 编辑新角色
+ *
+ * @param $data
+ * @return Role
+ * @throws \Exception
+ */
+ public static function updateAdminRole($data): Role
+ {
+ $adminRole = Role::findById($data['id']);
+ $adminRole->update([
+ 'name' => $data['name'],
+ 'guard_name' => 'web_admin',
+ ]);
+
+ $permissions = array_merge($data['core_permissions'], $data['plugin_permissions']);
+ self::syncPermissions($adminRole, $permissions);
+
+ return $adminRole;
+ }
+
+ /**
+ * 同步所有权限
+ *
+ * @param Role $adminRole
+ * @param $permissions
+ * @throws \Exception
+ */
+ private static function syncPermissions(Role $adminRole, $permissions)
+ {
+ $items = [];
+ foreach ($permissions as $groupedPermissions) {
+ foreach ($groupedPermissions['permissions'] as $groupedPermission) {
+ if ($groupedPermission['selected']) {
+ $code = $groupedPermission['code'];
+ Permission::findOrCreate($code);
+ $items[] = $code;
+ }
+ }
+ }
+ if (empty($items)) {
+ throw new \Exception(trans('admin/role.select_one_at_least'));
+ }
+ $adminRole->syncPermissions($items);
+ }
+
+ /**
+ * 删除角色
+ *
+ * @param $adminRoleId
+ */
+ public static function deleteAdminRole($adminRoleId)
+ {
+ $adminRole = Role::query()->find($adminRoleId);
+ $adminRole->delete();
+ }
+}
diff --git a/beike/Admin/Repositories/AdminUserRepo.php b/beike/Admin/Repositories/AdminUserRepo.php
new file mode 100644
index 00000000..22fcf442
--- /dev/null
+++ b/beike/Admin/Repositories/AdminUserRepo.php
@@ -0,0 +1,95 @@
+
+ * @created 2022-08-01 20:30:44
+ * @modified 2022-08-01 20:30:44
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Beike\Admin\Http\Resources\AdminUserDetail;
+use Beike\Models\AdminUser;
+use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
+
+class AdminUserRepo
+{
+ /**
+ * 获取后台用户管理员列表
+ */
+ public static function getAdminUsers(): array
+ {
+ $builder = AdminUser::query()->with(['roles']);
+ $adminUsers = $builder->get();
+
+ return AdminUserDetail::collection($adminUsers)->jsonSerialize();
+ }
+
+ /**
+ * 创建后台管理员用户
+ *
+ * @param $data
+ * @return AdminUser
+ */
+ public static function createAdminUser($data): AdminUser
+ {
+ $adminUser = new AdminUser([
+ 'name' => $data['name'],
+ 'email' => $data['email'],
+ 'password' => bcrypt($data['password']),
+ 'locale' => $data['locale'],
+ 'active' => true,
+ ]);
+ $adminUser->save();
+
+ if (isset($data['roles'])) {
+ $adminUser->assignRole($data['roles']);
+ }
+
+ return $adminUser;
+ }
+
+ /**
+ * 更新后台管理员用户
+ *
+ * @param $adminUserId
+ * @param $data
+ * @return mixed
+ */
+ public static function updateAdminUser($adminUserId, $data)
+ {
+ $password = $data['password'] ?? '';
+ $adminUser = AdminUser::query()->findOrFail($adminUserId);
+ $userData = [
+ 'name' => $data['name'],
+ 'email' => $data['email'],
+ 'locale' => $data['locale'],
+ 'active' => true,
+ ];
+ if ($password) {
+ $userData['password'] = bcrypt($password);
+ }
+ $adminUser->update($userData);
+ $adminUser->syncRoles($data['roles']);
+
+ return $adminUser;
+ }
+
+ /**
+ * 删除后台用户
+ *
+ * @param $adminUserId
+ * @throws \Exception
+ */
+ public static function deleteAdminUser($adminUserId)
+ {
+ if ($adminUserId == 1) {
+ throw new NotAcceptableHttpException(trans('admin/customer.cannot_delete_root'));
+ }
+ $adminUser = AdminUser::query()->find($adminUserId);
+ $adminUser->delete();
+ }
+}
diff --git a/beike/Admin/Repositories/AttributeGroupRepo.php b/beike/Admin/Repositories/AttributeGroupRepo.php
new file mode 100644
index 00000000..e66aeba3
--- /dev/null
+++ b/beike/Admin/Repositories/AttributeGroupRepo.php
@@ -0,0 +1,78 @@
+
+ * @created 2023-01-04 19:45:41
+ * @modified 2023-01-04 19:45:41
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Beike\Models\AttributeGroup;
+
+class AttributeGroupRepo
+{
+ public static function getList()
+ {
+ return AttributeGroup::query()->orderByDesc('id')->with('description', 'descriptions')->get();
+ }
+
+ public static function create($data)
+ {
+ $attributeGroup = AttributeGroup::query()->create([
+ 'sort_order' => $data['sort_order'],
+ ]);
+
+ $descriptions = [];
+ foreach ($data['name'] as $locale => $name) {
+ $descriptions[] = [
+ 'locale' => $locale,
+ 'name' => $name,
+ ];
+ }
+ $attributeGroup->descriptions()->createMany($descriptions);
+
+ $attributeGroup->load('description', 'descriptions');
+
+ return $attributeGroup;
+ }
+
+ public static function update($id, $data)
+ {
+ $attributeGroup = AttributeGroup::query()->updateOrCreate(['id' => $id], [
+ 'sort_order' => $data['sort_order'],
+ ]);
+
+ $descriptions = [];
+ foreach ($data['name'] as $locale => $name) {
+ $descriptions[] = [
+ 'locale' => $locale,
+ 'name' => $name,
+ ];
+ }
+ $attributeGroup->descriptions()->delete();
+ $attributeGroup->descriptions()->createMany($descriptions);
+
+ $attributeGroup->load('description', 'descriptions');
+
+ return $attributeGroup;
+ }
+
+ public static function find($id)
+ {
+ return AttributeGroup::query()->find($id);
+ }
+
+ public static function delete($id)
+ {
+ $group = AttributeGroup::query()->findOrFail($id);
+ if ($group->attributes->count()) {
+ throw new \Exception(trans('admin/attribute_group.error_cannot_delete_attribute_used', ['attributes' => implode(', ', $group->attributes->pluck('id')->toArray())]));
+ }
+ $group->descriptions()->delete();
+ $group->delete();
+ }
+}
diff --git a/beike/Admin/Repositories/AttributeRepo.php b/beike/Admin/Repositories/AttributeRepo.php
new file mode 100644
index 00000000..76515a52
--- /dev/null
+++ b/beike/Admin/Repositories/AttributeRepo.php
@@ -0,0 +1,141 @@
+
+ * @created 2023-01-04 19:45:41
+ * @modified 2023-01-04 19:45:41
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Beike\Models\Attribute;
+use Beike\Models\AttributeValue;
+use Beike\Models\ProductAttribute;
+
+class AttributeRepo
+{
+ public static function getList()
+ {
+ return Attribute::query()->orderByDesc('id')->paginate()->withQueryString();
+ }
+
+ public static function create($data)
+ {
+ $attribute = Attribute::query()->create([
+ 'attribute_group_id' => $data['attribute_group_id'],
+ 'sort_order' => $data['sort_order'],
+ ]);
+
+ $descriptions = [];
+ foreach ($data['name'] as $locale => $name) {
+ $descriptions[] = [
+ 'locale' => $locale,
+ 'name' => $name,
+ ];
+ }
+ $attribute->descriptions()->createMany($descriptions);
+
+ return $attribute;
+ }
+
+ public static function update($id, $data)
+ {
+ $attribute = Attribute::query()->updateOrCreate(['id' => $id], [
+ 'attribute_group_id' => $data['attribute_group_id'],
+ 'sort_order' => $data['sort_order'],
+ ]);
+
+ $descriptions = [];
+ foreach ($data['name'] as $locale => $name) {
+ $descriptions[] = [
+ 'locale' => $locale,
+ 'name' => $name,
+ ];
+ }
+ $attribute->descriptions()->delete();
+ $attribute->descriptions()->createMany($descriptions);
+
+ return $attribute;
+ }
+
+ public static function createValue($data)
+ {
+ $attributeValue = AttributeValue::query()->create([
+ 'attribute_id' => $data['attribute_id'],
+ ]);
+
+ $descriptions = [];
+ foreach ($data['name'] as $locale => $name) {
+ $descriptions[] = [
+ 'locale' => $locale,
+ 'name' => $name,
+ ];
+ }
+ $attributeValue->descriptions()->createMany($descriptions);
+
+ return $attributeValue;
+ }
+
+ public static function updateValue($id, $data)
+ {
+ $attributeValue = AttributeValue::query()->findOrFail($id);
+
+ $descriptions = [];
+ foreach ($data['name'] as $locale => $name) {
+ $descriptions[] = [
+ 'locale' => $locale,
+ 'name' => $name,
+ ];
+ }
+ $attributeValue->descriptions()->delete();
+ $attributeValue->descriptions()->createMany($descriptions);
+
+ return $attributeValue;
+ }
+
+ public static function deleteValue($id)
+ {
+ AttributeValue::query()->findOrFail($id)->delete();
+ }
+
+ public static function find($id)
+ {
+ return Attribute::query()->with('values.descriptions')->find($id);
+ }
+
+ public static function delete($id)
+ {
+ $productIds = ProductAttribute::query()->where('attribute_id', $id)->pluck('product_id')->toArray();
+ if ($productIds) {
+ throw new \Exception(trans('admin/attribute.error_cannot_delete_product_used', ['product_ids' => implode(', ', $productIds)]));
+ }
+ $attribute = Attribute::query()->findOrFail($id);
+ $attribute->descriptions()->delete();
+ $attribute->values()->delete();
+ $attribute->delete();
+ }
+
+ public static function autocomplete($name)
+ {
+ $builder = Attribute::query()->with('description')
+ ->whereHas('description', function ($query) use ($name) {
+ $query->where('name', 'like', "{$name}%");
+ });
+
+ return $builder->limit(10)->get();
+ }
+
+ public static function autocompleteValue($attributeId, $name)
+ {
+ $builder = AttributeValue::query()->with('description')
+ ->where('attribute_id', $attributeId)
+ ->whereHas('description', function ($query) use ($name) {
+ $query->where('name', 'like', "{$name}%");
+ });
+
+ return $builder->limit(10)->get();
+ }
+}
diff --git a/beike/Admin/Repositories/DashboardRepo.php b/beike/Admin/Repositories/DashboardRepo.php
new file mode 100644
index 00000000..a963e354
--- /dev/null
+++ b/beike/Admin/Repositories/DashboardRepo.php
@@ -0,0 +1,120 @@
+
+ * @created 2022-08-03 18:16:53
+ * @modified 2022-08-03 18:16:53
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Beike\Models\Product;
+use Beike\Repositories\CustomerRepo;
+use Beike\Repositories\OrderRepo;
+
+class DashboardRepo
+{
+ /**
+ * 获取商品总数
+ *
+ * @return array
+ */
+ public static function getProductData(): array
+ {
+ return [
+ 'total' => quantity_format(Product::query()->count()),
+ 'percentage' => 0,
+ ];
+ }
+
+ /**
+ * 获取客户访问统计今日昨日比较
+ * @return array
+ * @todo
+ */
+ public static function getCustomerViewData(): array
+ {
+ $today = 10;
+ $yesterday = 8;
+ $difference = $today - $yesterday;
+ if ($difference && $yesterday) {
+ $percentage = round(($difference / $yesterday) * 100);
+ } else {
+ $percentage = 0;
+ }
+
+ return [
+ 'total' => $today,
+ 'percentage' => $percentage,
+ ];
+ }
+
+ /**
+ * 获取订单基础统计, 总数和今日昨日比较
+ *
+ * @return array
+ */
+ public static function getOrderData(): array
+ {
+ $today = OrderRepo::getListBuilder(['start' => today()->subDay(), 'end' => today()])->count();
+ $yesterday = OrderRepo::getListBuilder(['start' => today()->subDays(2), 'end' => today()->subDay()])->count();
+ $difference = $today - $yesterday;
+ if ($difference && $yesterday) {
+ $percentage = round(($difference / $yesterday) * 100);
+ } else {
+ $percentage = 0;
+ }
+
+ return [
+ 'total' => $today,
+ 'percentage' => $percentage,
+ ];
+ }
+
+ /**
+ * 获取客户注册今日昨日比较
+ *
+ * @return array
+ */
+ public static function getCustomerData(): array
+ {
+ $today = CustomerRepo::getListBuilder(['start' => today()->subDay(), 'end' => today()])->count();
+ $yesterday = CustomerRepo::getListBuilder(['start' => today()->subDays(2), 'end' => today()->subDay()])->count();
+ $difference = $today - $yesterday;
+ if ($difference && $yesterday) {
+ $percentage = round(($difference / $yesterday) * 100);
+ } else {
+ $percentage = 0;
+ }
+
+ return [
+ 'total' => $today,
+ 'percentage' => $percentage,
+ ];
+ }
+
+ /**
+ * 获取订单总额基础统计, 总数和今日昨日比较
+ *
+ * @return array
+ */
+ public static function getTotalData(): array
+ {
+ $today = OrderRepo::getListBuilder(['start' => today()->subDay(), 'end' => today()])->sum('total');
+ $yesterday = OrderRepo::getListBuilder(['start' => today()->subDays(2), 'end' => today()->subDay()])->sum('total');
+ $difference = $today - $yesterday;
+ if ($difference && $yesterday) {
+ $percentage = round(($difference / $yesterday) * 100);
+ } else {
+ $percentage = 0;
+ }
+
+ return [
+ 'total' => currency_format($today),
+ 'percentage' => $percentage,
+ ];
+ }
+}
diff --git a/beike/Admin/Repositories/PageRepo.php b/beike/Admin/Repositories/PageRepo.php
new file mode 100644
index 00000000..a6c1fb98
--- /dev/null
+++ b/beike/Admin/Repositories/PageRepo.php
@@ -0,0 +1,132 @@
+
+ * @created 2022-07-26 21:08:07
+ * @modified 2022-07-26 21:08:07
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Beike\Models\Page;
+use Illuminate\Contracts\Pagination\LengthAwarePaginator;
+use Illuminate\Support\Facades\DB;
+
+class PageRepo
+{
+ /**
+ * 获取列表页数据
+ *
+ * @return LengthAwarePaginator
+ */
+ public static function getList(): LengthAwarePaginator
+ {
+ $builder = Page::query()->with([
+ 'description',
+ ])->orderByDesc('updated_at');
+
+ return $builder->paginate(perPage());
+ }
+
+ public static function findByPageId($pageId)
+ {
+ $page = Page::query()->findOrFail($pageId);
+ $page->load(['descriptions']);
+
+ return $page;
+ }
+
+ public static function getDescriptionsByLocale($pageId)
+ {
+ $page = self::findByPageId($pageId);
+
+ return $page->descriptions->keyBy('locale')->toArray();
+ }
+
+ public static function createOrUpdate($data)
+ {
+ try {
+ DB::beginTransaction();
+ $region = self::pushPage($data);
+ DB::commit();
+
+ return $region;
+ } catch (\Exception $e) {
+ DB::rollBack();
+
+ throw $e;
+ }
+ }
+
+ public static function pushPage($data)
+ {
+ $id = $data['id'] ?? 0;
+ if ($id) {
+ $page = Page::query()->findOrFail($id);
+ } else {
+ $page = new Page();
+ }
+ $page->fill([
+ 'page_category_id' => (int) ($data['page_category_id'] ?? 0),
+ 'position' => (int) ($data['position'] ?? 0),
+ 'active' => (bool) ($data['active'] ?? true),
+ 'author' => $data['author'] ?? '',
+ 'views' => (int) ($data['views'] ?? 0),
+ ]);
+
+ $page->saveOrFail();
+
+ $page->descriptions()->delete();
+ $page->descriptions()->createMany($data['descriptions']);
+
+ $products = $data['products'] ?? [];
+ if ($products) {
+ $items = [];
+ foreach ($products as $item) {
+ $items[] = [
+ 'product_id' => $item,
+ ];
+ }
+ $page->pageProducts()->delete();
+ $page->pageProducts()->createMany($items);
+ }
+
+ $page->load(['descriptions', 'pageProducts']);
+
+ return $page;
+ }
+
+ public static function deleteById($id)
+ {
+ $page = Page::query()->findOrFail($id);
+ $page->descriptions()->delete();
+ $page->delete();
+ }
+
+ /**
+ * 页面内容自动完成
+ *
+ * @param $name
+ * @return array
+ */
+ public static function autocomplete($name): array
+ {
+ $pages = Page::query()->with('description')
+ ->whereHas('description', function ($query) use ($name) {
+ $query->where('title', 'like', "{$name}%");
+ })->limit(10)->get();
+ $results = [];
+ foreach ($pages as $page) {
+ $results[] = [
+ 'id' => $page->id,
+ 'name' => $page->description->title,
+ 'status' => $page->active,
+ ];
+ }
+
+ return $results;
+ }
+}
diff --git a/beike/Admin/Repositories/PermissionRepo.php b/beike/Admin/Repositories/PermissionRepo.php
new file mode 100644
index 00000000..96103f58
--- /dev/null
+++ b/beike/Admin/Repositories/PermissionRepo.php
@@ -0,0 +1,485 @@
+
+ * @created 2022-08-01 20:49:45
+ * @modified 2022-08-01 20:49:45
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Beike\Models\AdminUser;
+use Spatie\Permission\Exceptions\PermissionDoesNotExist;
+use Spatie\Permission\Models\Role;
+
+class PermissionRepo
+{
+ private ?AdminUser $adminUser = null;
+
+ private ?Role $adminRole = null;
+
+ public function setUser($user): self
+ {
+ $this->adminUser = $user;
+
+ return $this;
+ }
+
+ public function setRole($role): self
+ {
+ $this->adminRole = $role;
+
+ return $this;
+ }
+
+ /**
+ * 所有权限列表
+ *
+ * @return array
+ * @throws \Exception
+ */
+ public function getRoleCorePermissions(): array
+ {
+ $corePermissions = [
+ ['title' => trans('admin/common.order'), 'permissions' => $this->getOrderPermissions()],
+ ['title' => trans('admin/common.rma'), 'permissions' => $this->getRmaPermissions()],
+ ['title' => trans('admin/common.rma_reason'), 'permissions' => $this->getRmaReasonPermissions()],
+ ['title' => trans('admin/common.product'), 'permissions' => $this->getProductPermissions()],
+ ['title' => trans('admin/common.category'), 'permissions' => $this->getCategoryPermissions()],
+ ['title' => trans('admin/common.brand'), 'permissions' => $this->getBrandPermissions()],
+ ['title' => trans('admin/common.attribute'), 'permissions' => $this->getAttributePermissions()],
+ ['title' => trans('admin/common.attribute_group'), 'permissions' => $this->getAttributeGroupPermissions()],
+ ['title' => trans('admin/common.customer'), 'permissions' => $this->getCustomerPermissions()],
+ ['title' => trans('admin/common.customer_group'), 'permissions' => $this->getCustomerGroupPermissions()],
+ ['title' => trans('admin/common.page'), 'permissions' => $this->getPagePermissions()],
+ ['title' => trans('admin/common.page_category'), 'permissions' => $this->getPageCategoryPermissions()],
+ ['title' => trans('admin/common.setting'), 'permissions' => $this->getSettingPermissions()],
+
+ ['title' => trans('admin/common.plugin'), 'permissions' => $this->getPluginPermissions()],
+ ['title' => trans('admin/common.marketing'), 'permissions' => $this->getMarketingPermissions()],
+ ['title' => trans('admin/common.admin_user'), 'permissions' => $this->getAdminUserPermissions()],
+ ['title' => trans('admin/common.admin_role'), 'permissions' => $this->getAdminRolePermissions()],
+ ['title' => trans('admin/common.region'), 'permissions' => $this->getRegionPermissions()],
+ ['title' => trans('admin/common.tax_rate'), 'permissions' => $this->getTaxRatePermissions()],
+ ['title' => trans('admin/common.tax_class'), 'permissions' => $this->getTaxClassPermissions()],
+ ['title' => trans('admin/common.currency'), 'permissions' => $this->getCurrencyPermissions()],
+ ['title' => trans('admin/common.language'), 'permissions' => $this->getLanguagePermissions()],
+ ['title' => trans('admin/common.file_manager'), 'permissions' => $this->getFileManagerPermissions()],
+ ['title' => trans('admin/common.zone'), 'permissions' => $this->getZonePermissions()],
+ ['title' => trans('admin/common.country'), 'permissions' => $this->getCountryPermissions()],
+ ];
+
+ $corePermissions = hook_filter('role.permissions.all', $corePermissions);
+
+ return $corePermissions;
+ }
+
+ /**
+ * 插件权限
+ *
+ * @return array
+ * @throws \Exception
+ */
+ public function getRolePluginPermissions(): array
+ {
+ $pluginPermissions = hook_filter('role.permissions.plugin', []);
+
+ $pluginPermissions = $this->handlePluginPermission($pluginPermissions);
+
+ return $pluginPermissions;
+ }
+
+ /**
+ * 订单权限列表
+ *
+ * @return array
+ */
+ private function getOrderPermissions(): array
+ {
+ $routes = ['orders_index', 'orders_export', 'orders_show', 'orders_update_status'];
+ $items = $this->getPermissionList('order', $routes);
+
+ return hook_filter('role.order_permissions', $items);
+ }
+
+ /**
+ * 售后(退换货)权限列表
+ *
+ * @return array
+ */
+ private function getRmaPermissions(): array
+ {
+ $routes = ['rmas_index', 'rmas_show', 'rmas_update', 'rmas_delete'];
+ $items = $this->getPermissionList('rma', $routes);
+
+ return hook_filter('role.rma_permissions', $items);
+ }
+
+ /**
+ * 售后(退换货)原因权限列表
+ *
+ * @return array
+ */
+ private function getRmaReasonPermissions(): array
+ {
+ $routes = ['rma_reasons_index', 'rma_reasons_create', 'rma_reasons_update', 'rma_reasons_delete'];
+ $items = $this->getPermissionList('rma_reason', $routes);
+
+ return hook_filter('role.rma_reason_permissions', $items);
+ }
+
+ /**
+ * 商品权限列表
+ *
+ * @return array
+ */
+ private function getProductPermissions(): array
+ {
+ $routes = ['products_index', 'products_create', 'products_show', 'products_update', 'products_delete', 'products_trashed', 'products_restore'];
+ $items = $this->getPermissionList('product', $routes);
+
+ return hook_filter('role.product_permissions', $items);
+ }
+
+ /**
+ * 分类权限列表
+ *
+ * @return array
+ */
+ private function getCategoryPermissions(): array
+ {
+ $routes = ['categories_index', 'categories_create', 'categories_show', 'categories_update', 'categories_delete'];
+ $items = $this->getPermissionList('category', $routes);
+
+ return hook_filter('role.category_permissions', $items);
+ }
+
+ /**
+ * 品牌权限列表
+ *
+ * @return array
+ */
+ private function getBrandPermissions(): array
+ {
+ $routes = ['brands_index', 'brands_create', 'brands_show', 'brands_update', 'brands_delete'];
+ $items = $this->getPermissionList('brand', $routes);
+
+ return hook_filter('role.brand_permissions', $items);
+ }
+
+ /**
+ * 属性权限列表
+ *
+ * @return array
+ */
+ private function getAttributePermissions(): array
+ {
+ $routes = ['attributes_index', 'attributes_create', 'attributes_show', 'attributes_update', 'attributes_delete'];
+ $items = $this->getPermissionList('attribute', $routes);
+
+ return hook_filter('role.attribute_permissions', $items);
+ }
+
+ /**
+ * 属性组权限列表
+ *
+ * @return array
+ */
+ private function getAttributeGroupPermissions(): array
+ {
+ $routes = ['attribute_groups_index', 'attribute_groups_create', 'attribute_groups_update', 'attribute_groups_delete'];
+ $items = $this->getPermissionList('attribute_group', $routes);
+
+ return hook_filter('role.attribute_group_permissions', $items);
+ }
+
+ /**
+ * 客户权限列表
+ *
+ * @return array
+ */
+ private function getCustomerPermissions(): array
+ {
+ $routes = ['customers_index', 'customers_create', 'customers_show', 'customers_update', 'customers_delete'];
+ $items = $this->getPermissionList('customer', $routes);
+
+ return hook_filter('role.customer_permissions', $items);
+ }
+
+ /**
+ * 客户组权限列表
+ *
+ * @return array
+ */
+ private function getCustomerGroupPermissions(): array
+ {
+ $routes = ['customer_groups_index', 'customer_groups_create', 'customer_groups_show', 'customer_groups_update', 'customer_groups_delete'];
+ $items = $this->getPermissionList('customer_group', $routes);
+
+ return hook_filter('role.customer_group_permissions', $items);
+ }
+
+ /**
+ * 设置权限列表
+ *
+ * @return array
+ */
+ private function getSettingPermissions(): array
+ {
+ $routes = ['settings_index', 'settings_update', 'design_index', 'design_footer_index', 'design_menu_index'];
+ $items = $this->getPermissionList('setting', $routes);
+
+ return hook_filter('role.setting_permissions', $items);
+ }
+
+ /**
+ * 文章管理列表
+ * @return array
+ */
+ private function getPagePermissions(): array
+ {
+ $routes = ['pages_index', 'pages_create', 'pages_show', 'pages_update', 'pages_delete'];
+ $items = $this->getPermissionList('page', $routes);
+
+ return hook_filter('role.page_permissions', $items);
+ }
+
+ /**
+ * 文章分类管理列表
+ * @return array
+ */
+ private function getPageCategoryPermissions(): array
+ {
+ $routes = ['page_categories_index', 'page_categories_create', 'page_categories_show', 'page_categories_update', 'page_categories_delete'];
+ $items = $this->getPermissionList('page_category', $routes);
+
+ return hook_filter('role.page_category_permissions', $items);
+ }
+
+ /**
+ * 插件权限列表
+ *
+ * @return array
+ */
+ private function getPluginPermissions(): array
+ {
+ $routes = ['plugins_index', 'plugins_import', 'plugins_update', 'plugins_show', 'plugins_install', 'plugins_update_status', 'plugins_uninstall'];
+ $items = $this->getPermissionList('plugin', $routes);
+
+ return hook_filter('role.plugin_permissions', $items);
+ }
+
+ /**
+ * 插件权限列表
+ *
+ * @return array
+ */
+ private function getMarketingPermissions(): array
+ {
+ $routes = ['marketing_index', 'marketing_show', 'marketing_buy', 'marketing_download'];
+ $items = $this->getPermissionList('marketing', $routes);
+
+ return hook_filter('role.marketing_permissions', $items);
+ }
+
+ /**
+ * 后台管理员权限列表
+ *
+ * @return array
+ */
+ private function getAdminUserPermissions(): array
+ {
+ $routes = ['admin_users_index', 'admin_users_create', 'admin_users_show', 'admin_users_update', 'admin_users_delete'];
+ $items = $this->getPermissionList('user', $routes);
+
+ return hook_filter('role.user_permissions', $items);
+ }
+
+ /**
+ * 后台管理员权限列表
+ *
+ * @return array
+ */
+ private function getAdminRolePermissions(): array
+ {
+ $routes = ['admin_roles_index', 'admin_roles_create', 'admin_roles_show', 'admin_roles_update', 'admin_roles_delete'];
+ $items = $this->getPermissionList('role', $routes);
+
+ return hook_filter('role.role_permissions', $items);
+ }
+
+ /**
+ * 区域分组权限列表
+ *
+ * @return array
+ */
+ private function getRegionPermissions(): array
+ {
+ $routes = ['regions_index', 'regions_create', 'regions_show', 'regions_update', 'regions_delete'];
+ $items = $this->getPermissionList('region', $routes);
+
+ return hook_filter('role.region_permissions', $items);
+ }
+
+ /**
+ * 获取税率权限列表
+ *
+ * @return array[]
+ */
+ private function getTaxRatePermissions(): array
+ {
+ $routes = ['tax_rates_index', 'tax_rates_create', 'tax_rates_show', 'tax_rates_update', 'tax_rates_delete'];
+ $items = $this->getPermissionList('tax_rate', $routes);
+
+ return hook_filter('role.tax_rate_permissions', $items);
+ }
+
+ /**
+ * 获取税类权限列表
+ *
+ * @return array[]
+ */
+ private function getTaxClassPermissions(): array
+ {
+ $routes = ['tax_classes_index', 'tax_classes_create', 'tax_classes_show', 'tax_classes_update', 'tax_classes_delete'];
+ $items = $this->getPermissionList('tax_class', $routes);
+
+ return hook_filter('role.tax_class_permissions', $items);
+ }
+
+ /**
+ * 获取汇率权限列表
+ *
+ * @return array[]
+ */
+ private function getCurrencyPermissions(): array
+ {
+ $routes = ['currencies_index', 'currencies_create', 'currencies_show', 'currencies_update', 'currencies_delete'];
+ $items = $this->getPermissionList('currency', $routes);
+
+ return hook_filter('role.currency_permissions', $items);
+ }
+
+ /**
+ * 获取语言权限列表
+ *
+ * @return array[]
+ */
+ private function getLanguagePermissions(): array
+ {
+ $routes = ['languages_index', 'languages_create', 'languages_update', 'languages_delete'];
+ $items = $this->getPermissionList('language', $routes);
+
+ return hook_filter('role.language_permissions', $items);
+ }
+
+ /**
+ * 获取文件管理器权限列表
+ *
+ * @return array[]
+ */
+ private function getFileManagerPermissions(): array
+ {
+ $routes = ['file_manager_create', 'file_manager_show', 'file_manager_update', 'file_manager_delete'];
+ $items = $this->getPermissionList('file_manager', $routes);
+
+ return hook_filter('role.file_manager_permissions', $items);
+ }
+
+ /**
+ * 获取省份权限列表
+ *
+ * @return array[]
+ */
+ private function getZonePermissions(): array
+ {
+ $routes = ['zones_create', 'zones_index', 'zones_update', 'zones_delete'];
+ $items = $this->getPermissionList('zone', $routes);
+
+ return hook_filter('role.zone_permissions', $items);
+ }
+
+ /**
+ * 获取国家权限列表
+ *
+ * @return array[]
+ */
+ private function getCountryPermissions(): array
+ {
+ $routes = ['countries_create', 'countries_index', 'countries_update', 'countries_delete'];
+ $items = $this->getPermissionList('country', $routes);
+
+ return hook_filter('role.country_permissions', $items);
+ }
+
+ /**
+ * 处理第三方插件权限
+ *
+ * @param $pluginPermissions
+ * @return array
+ * @throws \Exception
+ */
+ private function handlePluginPermission($pluginPermissions): array
+ {
+ if (empty($pluginPermissions)) {
+ return [];
+ }
+
+ foreach ($pluginPermissions as $index => $pluginPermission) {
+ $itemPermissions = $pluginPermission['permissions'] ?? [];
+ if (empty($itemPermissions)) {
+ throw new \Exception('Empty plugin permission!');
+ }
+ foreach ($itemPermissions as $ipIndex => $itemPermission) {
+ $code = $itemPermission['code'] ?? '';
+ if (empty($code)) {
+ throw new \Exception('Empty plugin permission code!');
+ }
+ $pluginPermissions[$index]['permissions'][$ipIndex]['selected'] = $this->hasPermission($code);
+ }
+ }
+
+ return $pluginPermissions;
+ }
+
+ /**
+ * 根据模块和路由返回权限列表
+ *
+ * @param $module
+ * @param $routes
+ * @return array
+ */
+ private function getPermissionList($module, $routes): array
+ {
+ $items = [];
+ foreach ($routes as $route) {
+ $items[] = ['code' => $route, 'name' => trans("admin/{$module}.{$route}"), 'selected' => $this->hasPermission($route)];
+ }
+
+ return $items;
+ }
+
+ /**
+ * 判断当前用户或者角色是否有权限
+ *
+ * @param $permission
+ * @return bool
+ */
+ private function hasPermission($permission): bool
+ {
+ try {
+ if ($this->adminRole) {
+ return $this->adminRole->hasPermissionTo($permission);
+ } elseif ($this->adminUser) {
+ return $this->adminUser->can($permission);
+ }
+ } catch (PermissionDoesNotExist $exception) {
+ return false;
+ }
+
+ return false;
+ }
+}
diff --git a/beike/Admin/Repositories/RegionRepo.php b/beike/Admin/Repositories/RegionRepo.php
new file mode 100644
index 00000000..c5b13a1b
--- /dev/null
+++ b/beike/Admin/Repositories/RegionRepo.php
@@ -0,0 +1,77 @@
+
+ * @created 2022-07-27 10:48:25
+ * @modified 2022-07-27 10:48:25
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Beike\Models\Region;
+use Illuminate\Support\Facades\DB;
+
+class RegionRepo
+{
+ public static function getList()
+ {
+ return Region::query()->with('regionZones.zone')->get();
+ }
+
+ public static function createOrUpdate($data)
+ {
+ try {
+ DB::beginTransaction();
+ $region = self::pushRegion($data);
+ DB::commit();
+
+ return $region;
+ } catch (\Exception $e) {
+ DB::rollBack();
+
+ throw $e;
+ }
+ }
+
+ public static function pushRegion($data)
+ {
+ $id = $data['id'] ?? 0;
+ if ($id) {
+ $region = Region::query()->findOrFail($id);
+ } else {
+ $region = new Region();
+ }
+ $region->fill([
+ 'name' => $data['name'],
+ 'description' => $data['description'],
+ ]);
+ $region->saveOrFail();
+
+ $newRegionZones = [];
+ foreach ($data['region_zones'] as $regionZone) {
+ if ($regionZone['country_id']) {
+ $newRegionZones[] = [
+ 'country_id' => (int) $regionZone['country_id'],
+ 'zone_id' => (int) $regionZone['zone_id'],
+ ];
+ }
+ }
+ if ($newRegionZones) {
+ $region->regionZones()->delete();
+ $region->regionZones()->createMany($newRegionZones);
+ }
+ $region->load(['regionZones']);
+
+ return $region;
+ }
+
+ public static function deleteById($id)
+ {
+ $region = Region::query()->findOrFail($id);
+ $region->regionZones()->delete();
+ $region->delete();
+ }
+}
diff --git a/beike/Admin/Repositories/Report/OrderReportRepo.php b/beike/Admin/Repositories/Report/OrderReportRepo.php
new file mode 100644
index 00000000..0d2d50e3
--- /dev/null
+++ b/beike/Admin/Repositories/Report/OrderReportRepo.php
@@ -0,0 +1,143 @@
+
+ * @created 2022-08-05 14:33:49
+ * @modified 2022-08-05 14:33:49
+ */
+
+namespace Beike\Admin\Repositories\Report;
+
+use Beike\Repositories\OrderRepo;
+use Carbon\Carbon;
+use Carbon\CarbonPeriod;
+use Illuminate\Support\Facades\DB;
+
+class OrderReportRepo
+{
+ /**
+ * 获取最近一个月每日销售订单数
+ * @return mixed
+ */
+ public static function getLatestMonth()
+ {
+ $orderTotals = OrderRepo::getListBuilder(['start' => today()->subMonth(), 'end' => today()])
+ ->select(DB::raw('DATE(created_at) as date, count(*) as total'))
+ ->groupBy('date')
+ ->get()
+ ->keyBy('date');
+
+ $orderAmounts = OrderRepo::getListBuilder(['start' => today()->subMonth(), 'end' => today()])
+ ->select(DB::raw('DATE(created_at) as date, sum(total) as amount'))
+ ->groupBy('date')
+ ->get()
+ ->keyBy('date');
+
+ $dates = $totals = $amounts = [];
+ $period = CarbonPeriod::create(today()->subMonth(), today()->subDay())->toArray();
+ foreach ($period as $date) {
+ $dateFormat = $date->format('Y-m-d');
+ $orderTotal = $orderTotals[$dateFormat] ?? null;
+ $orderAmount = $orderAmounts[$dateFormat] ?? null;
+
+ $dates[] = $dateFormat;
+ $totals[] = $orderTotal ? $orderTotal->total : 0;
+ $amounts[] = $orderAmount ? $orderAmount->amount : 0;
+ }
+
+ $data = [
+ 'period' => $dates,
+ 'totals' => $totals,
+ 'amounts' => $amounts,
+ ];
+
+ return hook_filter('dashboard.order_report_month', $data);
+ }
+
+ /**
+ * 获取最近一周每日销售订单数
+ */
+ public static function getLatestWeek()
+ {
+ $orderTotals = OrderRepo::getListBuilder(['start' => today()->subWeek(), 'end' => today()])
+ ->select(DB::raw('DATE(created_at) as date, count(*) as total'))
+ ->groupBy('date')
+ ->get()
+ ->keyBy('date');
+
+ $orderAmounts = OrderRepo::getListBuilder(['start' => today()->subWeek(), 'end' => today()])
+ ->select(DB::raw('DATE(created_at) as date, sum(total) as amount'))
+ ->groupBy('date')
+ ->get()
+ ->keyBy('date');
+
+ $dates = $totals = $amounts = [];
+ $period = CarbonPeriod::create(today()->subWeek(), today()->subDay())->toArray();
+ foreach ($period as $date) {
+ $dateFormat = $date->format('Y-m-d');
+ $orderTotal = $orderTotals[$dateFormat] ?? null;
+ $orderAmount = $orderAmounts[$dateFormat] ?? null;
+
+ $dates[] = $dateFormat;
+ $totals[] = $orderTotal ? $orderTotal->total : 0;
+ $amounts[] = $orderAmount ? $orderAmount->amount : 0;
+ }
+
+ $data = [
+ 'period' => $dates,
+ 'totals' => $totals,
+ 'amounts' => $amounts,
+ ];
+
+ return hook_filter('dashboard.order_report_week', $data);
+ }
+
+ /**
+ * 获取最近一年每月销售订单数
+ */
+ public static function getLatestYear()
+ {
+ $orderTotals = OrderRepo::getListBuilder(['start' => today()->subYear(), 'end' => today()])
+ ->select(DB::raw('YEAR(created_at) as year, MONTH(created_at) as month, count(*) as total'))
+ ->groupBy(['year', 'month'])
+ ->get();
+ $orderMonthTotals = [];
+ foreach ($orderTotals as $orderTotal) {
+ $key = Carbon::create($orderTotal->year, $orderTotal->month)->format('Y-m');
+ $orderMonthTotals[$key] = $orderTotal['total'];
+ }
+
+ $orderAmounts = OrderRepo::getListBuilder(['start' => today()->subYear(), 'end' => today()])
+ ->select(DB::raw('YEAR(created_at) as year, MONTH(created_at) as month, sum(total) as amount'))
+ ->groupBy(['year', 'month'])
+ ->get();
+ $orderMonthAmounts = [];
+ foreach ($orderAmounts as $orderAmount) {
+ $key = Carbon::create($orderAmount->year, $orderAmount->month)->format('Y-m');
+ $orderMonthAmounts[$key] = $orderAmount['amount'];
+ }
+
+ $dates = $totals = $amounts = [];
+ $period = CarbonPeriod::create(today()->subYear()->endOfMonth(), '1 month', today()->endOfMonth())->toArray();
+ foreach ($period as $date) {
+ $dateFormat = $date->format('Y-m');
+ $orderTotal = $orderMonthTotals[$dateFormat] ?? null;
+ $orderAmount = $orderMonthAmounts[$dateFormat] ?? null;
+
+ $dates[] = $dateFormat;
+ $totals[] = $orderTotal ?: 0;
+ $amounts[] = $orderAmount ?: 0;
+ }
+
+ $data = [
+ 'period' => $dates,
+ 'totals' => $totals,
+ 'amounts' => $amounts,
+ ];
+
+ return hook_filter('dashboard.order_report_year', $data);
+ }
+}
diff --git a/beike/Admin/Repositories/TaxClassRepo.php b/beike/Admin/Repositories/TaxClassRepo.php
new file mode 100644
index 00000000..8df54501
--- /dev/null
+++ b/beike/Admin/Repositories/TaxClassRepo.php
@@ -0,0 +1,66 @@
+
+ * @created 2022-07-26 21:08:07
+ * @modified 2022-07-26 21:08:07
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Beike\Admin\Http\Resources\TaxClassDetail;
+use Beike\Models\TaxClass;
+
+class TaxClassRepo
+{
+ public const BASE_TYPES = ['store', 'payment', 'shipping'];
+
+ public static function getList()
+ {
+ $taxClass = TaxClass::query()->with([
+ 'taxRates.region',
+ 'taxRules',
+ ])->get();
+
+ return TaxClassDetail::collection($taxClass)->jsonSerialize();
+ }
+
+ public static function createOrUpdate($data)
+ {
+ $id = $data['id'] ?? 0;
+ if ($id) {
+ $taxClass = TaxClass::query()->findOrFail($id);
+ } else {
+ $taxClass = new TaxClass();
+ }
+ $taxClass->fill([
+ 'title' => $data['title'],
+ 'description' => $data['description'],
+ ]);
+ $taxClass->saveOrFail();
+
+ $rules = [];
+ foreach ($data['tax_rules'] as $rule) {
+ $rules[] = [
+ 'tax_rate_id' => $rule['tax_rate_id'],
+ 'based' => $rule['based'],
+ 'priority' => (int) $rule['priority'],
+ ];
+ }
+ $taxClass->taxRules()->delete();
+ $taxClass->taxRules()->createMany($rules);
+ $taxClass->load(['taxRules']);
+
+ return $taxClass;
+ }
+
+ public static function deleteById($id)
+ {
+ $taxClass = TaxClass::query()->findOrFail($id);
+ $taxClass->taxRules()->delete();
+ $taxClass->delete();
+ }
+}
diff --git a/beike/Admin/Repositories/TaxRateRepo.php b/beike/Admin/Repositories/TaxRateRepo.php
new file mode 100644
index 00000000..341e370f
--- /dev/null
+++ b/beike/Admin/Repositories/TaxRateRepo.php
@@ -0,0 +1,56 @@
+
+ * @created 2022-07-27 11:21:14
+ * @modified 2022-07-27 11:21:14
+ */
+
+namespace Beike\Admin\Repositories;
+
+use Beike\Models\TaxRate;
+
+class TaxRateRepo
+{
+ public static function getList()
+ {
+ return TaxRate::query()->with([
+ 'region',
+ ])->get();
+ }
+
+ public static function createOrUpdate($data)
+ {
+ $id = $data['id'] ?? 0;
+ if ($id) {
+ $taxRate = TaxRate::query()->findOrFail($id);
+ } else {
+ $taxRate = new TaxRate();
+ }
+ $taxRate->fill([
+ 'region_id' => $data['region_id'],
+ 'name' => $data['name'],
+ 'rate' => $data['rate'],
+ 'type' => $data['type'],
+ ]);
+ $taxRate->saveOrFail();
+
+ return $taxRate;
+ }
+
+ public static function deleteById($id)
+ {
+ $taxRate = TaxRate::query()->findOrFail($id);
+ $taxRate->delete();
+ }
+
+ public static function getNameByRateId($taxRateId)
+ {
+ $taxRate = TaxRate::query()->findOrFail($taxRateId);
+
+ return $taxRate->name;
+ }
+}
diff --git a/beike/Admin/Routes/admin.php b/beike/Admin/Routes/admin.php
new file mode 100644
index 00000000..5abfda76
--- /dev/null
+++ b/beike/Admin/Routes/admin.php
@@ -0,0 +1,246 @@
+middleware(['admin'])
+ ->name("{$adminName}.")
+ ->group(function () {
+ Route::get('login', [Controllers\LoginController::class, 'show'])->name('login.show');
+ Route::post('login', [Controllers\LoginController::class, 'store'])->name('login.store');
+
+ Route::get('forgotten', [ForgottenController::class, 'index'])->name('forgotten.index');
+ Route::post('forgotten/send_code', [ForgottenController::class, 'sendVerifyCode'])->name('forgotten.send_code');
+ Route::post('forgotten/password', [ForgottenController::class, 'changePassword'])->name('forgotten.password');
+
+ Route::middleware('admin_auth:' . \Beike\Models\AdminUser::AUTH_GUARD)
+ ->group(function () {
+ Route::get('/', [Controllers\HomeController::class, 'index'])->name('home.index');
+
+ // 属性
+ Route::middleware('can:attributes_update')->post('attributes/{id}/values', [Controllers\AttributeController::class, 'storeValue'])->name('attributes.values.store');
+ Route::middleware('can:attributes_show')->get('attributes/{id}/values/autocomplete', [Controllers\AttributeController::class, 'autocompleteValue'])->name('attributes.values.autocomplete');
+ Route::middleware('can:attributes_update')->put('attributes/{id}/values/{value_id}', [Controllers\AttributeController::class, 'updateValue'])->name('attributes.values.update');
+ Route::middleware('can:attributes_update')->delete('attributes/{id}/values/{value_id}', [Controllers\AttributeController::class, 'destroyValue'])->name('attributes.values.destroy');
+ Route::middleware('can:attributes_index')->get('attributes', [Controllers\AttributeController::class, 'index'])->name('attributes.index');
+ Route::middleware('can:attributes_show')->get('attributes/autocomplete', [Controllers\AttributeController::class, 'autocomplete'])->name('attributes.autocomplete');
+ Route::middleware('can:attributes_show')->get('attributes/{id}', [Controllers\AttributeController::class, 'show'])->name('attributes.show');
+ Route::middleware('can:attributes_create')->post('attributes', [Controllers\AttributeController::class, 'store'])->name('attributes.store');
+ Route::middleware('can:attributes_update')->put('attributes/{id}', [Controllers\AttributeController::class, 'update'])->name('attributes.update');
+ Route::middleware('can:attributes_delete')->delete('attributes/{id}', [Controllers\AttributeController::class, 'destroy'])->name('attributes.destroy');
+
+ // 属性组
+ Route::middleware('can:attribute_groups_index')->get('attribute_groups', [Controllers\AttributeGroupController::class, 'index'])->name('attribute_groups.index');
+ Route::middleware('can:attribute_groups_create')->post('attribute_groups', [Controllers\AttributeGroupController::class, 'store'])->name('attribute_groups.store');
+ Route::middleware('can:attribute_groups_update')->put('attribute_groups/{id}', [Controllers\AttributeGroupController::class, 'update'])->name('attribute_groups.update');
+ Route::middleware('can:attribute_groups_delete')->delete('attribute_groups/{id}', [Controllers\AttributeGroupController::class, 'destroy'])->name('attribute_groups.destroy');
+
+ // 商品品牌
+ Route::middleware('can:brands_index')->get('brands/names', [Controllers\BrandController::class, 'getNames'])->name('brands.names');
+ Route::middleware('can:brands_index')->get('brands/autocomplete', [Controllers\BrandController::class, 'autocomplete'])->name('brands.autocomplete');
+ Route::middleware('can:brands_show')->get('brands/{id}/name', [Controllers\BrandController::class, 'name'])->name('brands.name');
+ Route::middleware('can:brands_index')->get('brands', [Controllers\BrandController::class, 'index'])->name('brands.index');
+ Route::middleware('can:brands_create')->post('brands', [Controllers\BrandController::class, 'store'])->name('brands.store');
+ Route::middleware('can:brands_update')->put('brands/{brand}', [Controllers\BrandController::class, 'update'])->name('brands.update');
+ Route::middleware('can:brands_delete')->delete('brands/{brand}', [Controllers\BrandController::class, 'destroy'])->name('brands.destroy');
+
+ // 商品分类
+ Route::middleware('can:categories_index')->get('categories/autocomplete', [Controllers\CategoryController::class, 'autocomplete'])->name('categories.autocomplete');
+ Route::middleware('can:categories_show')->get('categories/{category}/name', [Controllers\CategoryController::class, 'name'])->name('categories.name');
+ Route::middleware('can:categories_index')->get('categories', [Controllers\CategoryController::class, 'index'])->name('categories.index');
+ Route::middleware('can:categories_create')->get('categories/create', [Controllers\CategoryController::class, 'create'])->name('categories.create');
+ Route::middleware('can:categories_create')->post('categories', [Controllers\CategoryController::class, 'store'])->name('categories.store');
+ Route::middleware('can:categories_update')->get('categories/{category}/edit', [Controllers\CategoryController::class, 'edit'])->name('categories.edit');
+ Route::middleware('can:categories_update')->put('categories/{category}', [Controllers\CategoryController::class, 'update'])->name('categories.update');
+ Route::middleware('can:categories_delete')->delete('categories/{category}', [Controllers\CategoryController::class, 'destroy'])->name('categories.destroy');
+
+ // 国家
+ Route::middleware('can:countries_index')->get('countries', [Controllers\CountryController::class, 'index'])->name('countries.index');
+ Route::middleware('can:countries_create')->post('countries', [Controllers\CountryController::class, 'store'])->name('countries.store');
+ Route::middleware('can:countries_update')->put('countries/{id}', [Controllers\CountryController::class, 'update'])->name('countries.update');
+ Route::middleware('can:countries_delete')->delete('countries/{id}', [Controllers\CountryController::class, 'destroy'])->name('countries.destroy');
+
+ // 省份
+ Route::middleware('can:zones_index')->get('zones', [Controllers\ZoneController::class, 'index'])->name('zones.index');
+ Route::middleware('can:zones_create')->post('zones', [Controllers\ZoneController::class, 'store'])->name('zones.store');
+ Route::middleware('can:zones_update')->put('zones/{id}', [Controllers\ZoneController::class, 'update'])->name('zones.update');
+ Route::middleware('can:zones_delete')->delete('zones/{id}', [Controllers\ZoneController::class, 'destroy'])->name('zones.destroy');
+
+ // 客户
+ Route::middleware('can:customers_index')->get('customers/trashed', [Controllers\CustomerController::class, 'trashed'])->name('customers.trashed');
+ Route::middleware('can:customers_index')->get('customers', [Controllers\CustomerController::class, 'index'])->name('customers.index');
+ Route::middleware('can:customers_create')->post('customers', [Controllers\CustomerController::class, 'store'])->name('customers.store');
+ Route::middleware('can:customers_show')->get('customers/{id}/edit', [Controllers\CustomerController::class, 'edit'])->name('customers.edit');
+ Route::middleware('can:customers_update')->put('customers/{id}', [Controllers\CustomerController::class, 'update'])->name('customers.update');
+ Route::middleware('can:customers_create')->delete('customers/{id}/restore', [Controllers\CustomerController::class, 'restore'])->name('customers.restore');
+ Route::middleware('can:customers_delete')->delete('customers/{id}', [Controllers\CustomerController::class, 'destroy'])->name('customers.destroy');
+ Route::middleware('can:customers_delete')->delete('customers/{id}/force', [Controllers\CustomerController::class, 'forceDelete'])->name('customers.force_delete');
+ Route::middleware('can:customers_delete')->post('customers/force_delete_all', [Controllers\CustomerController::class, 'forceDeleteAll'])->name('customers.force_delete_all');
+
+ // 客户地址
+ Route::middleware('can:customers_show')->get('customers/{customer_id}/addresses', [Controllers\AddressController::class, 'index'])->name('customers.addresses.index');
+ Route::middleware('can:customers_update')->post('customers/{customer_id}/addresses', [Controllers\AddressController::class, 'store'])->name('customers.addresses.store');
+ Route::middleware('can:customers_update')->put('customers/{customer_id}/addresses/{id}', [Controllers\AddressController::class, 'update'])->name('customers.addresses.update');
+ Route::middleware('can:customers_update')->delete('customers/{customer_id}/addresses/{id}', [Controllers\AddressController::class, 'destroy'])->name('customers.addresses.destroy');
+
+ Route::get('countries/{country_id}/zones', [Controllers\ZoneController::class, 'listByCountry'])->name('countries.zones.index');
+
+ // 客户组
+ Route::middleware('can:customer_groups_index')->get('customer_groups', [Controllers\CustomerGroupController::class, 'index'])->name('customer_groups.index');
+ Route::middleware('can:customer_groups_create')->post('customer_groups', [Controllers\CustomerGroupController::class, 'store'])->name('customer_groups.store');
+ Route::middleware('can:customer_groups_update')->put('customer_groups/{id}', [Controllers\CustomerGroupController::class, 'update'])->name('customer_groups.update');
+ Route::middleware('can:customer_groups_delete')->delete('customer_groups/{id}', [Controllers\CustomerGroupController::class, 'destroy'])->name('customer_groups.destroy');
+
+ // 货币
+ Route::middleware('can:currencies_index')->get('currencies', [Controllers\CurrencyController::class, 'index'])->name('currencies.index');
+ Route::middleware('can:currencies_create')->post('currencies', [Controllers\CurrencyController::class, 'store'])->name('currencies.store');
+ Route::middleware('can:currencies_update')->put('currencies/{id}', [Controllers\CurrencyController::class, 'update'])->name('currencies.update');
+ Route::middleware('can:currencies_delete')->delete('currencies/{id}', [Controllers\CurrencyController::class, 'destroy'])->name('currencies.destroy');
+
+ // 页面装修
+ Route::middleware('can:design_index')->get('design/builder', [Controllers\DesignController::class, 'index'])->name('design.index');
+ Route::middleware('can:design_index')->put('design/builder', [Controllers\DesignController::class, 'update'])->name('design.update');
+ Route::middleware('can:design_index')->post('design/builder/preview', [Controllers\DesignController::class, 'preview'])->name('design.module.preview');
+
+ Route::middleware('can:design_footer_index')->get('design_footer/builder', [Controllers\DesignFooterController::class, 'index'])->name('design_footer.index');
+ Route::middleware('can:design_footer_index')->put('design_footer/builder', [Controllers\DesignFooterController::class, 'update'])->name('design_footer.update');
+ Route::middleware('can:design_footer_index')->post('design_footer/builder/preview', [Controllers\DesignFooterController::class, 'preview'])->name('design_footer.module.preview');
+
+ Route::middleware('can:design_menu_index')->get('design_menu/builder', [Controllers\DesignMenuController::class, 'index'])->name('design_menu.index');
+ Route::middleware('can:design_menu_index')->put('design_menu/builder', [Controllers\DesignMenuController::class, 'update'])->name('design_menu.update');
+
+ // 模板主题
+ Route::middleware('can:theme_index')->get('themes', [Controllers\ThemeController::class, 'index'])->name('theme.index');
+ Route::middleware('can:theme_update')->put('themes/{code}', [Controllers\ThemeController::class, 'update'])->name('theme.update');
+
+ Route::put('edit', [Controllers\EditController::class, 'update'])->name('edit');
+ Route::get('edit/locale', [Controllers\EditController::class, 'locale'])->name('edit.locale');
+
+ // 图片库
+ Route::middleware('can:file_manager_show')->get('file_manager', [Controllers\FileManagerController::class, 'index'])->name('file_manager.index');
+ Route::middleware('can:file_manager_show')->get('file_manager/files', [Controllers\FileManagerController::class, 'getFiles'])->name('file_manager.get_files');
+ Route::middleware('can:file_manager_show')->get('file_manager/directories', [Controllers\FileManagerController::class, 'getDirectories'])->name('file_manager.get_directories');
+ Route::middleware('can:file_manager_create')->post('file_manager/directories', [Controllers\FileManagerController::class, 'createDirectory'])->name('file_manager.create_directory');
+ Route::middleware('can:file_manager_create')->post('file_manager/upload', [Controllers\FileManagerController::class, 'uploadFiles'])->name('file_manager.upload');
+ Route::middleware('can:file_manager_update')->post('file_manager/rename', [Controllers\FileManagerController::class, 'rename'])->name('file_manager.rename');
+ Route::middleware('can:file_manager_delete')->delete('file_manager/files', [Controllers\FileManagerController::class, 'destroyFiles'])->name('file_manager.delete_files');
+ Route::middleware('can:file_manager_delete')->delete('file_manager/directories', [Controllers\FileManagerController::class, 'destroyDirectories'])->name('file_manager.delete_directories');
+
+ Route::get('logout', [Controllers\LogoutController::class, 'index'])->name('logout.index');
+
+ // 语言管理
+ Route::middleware('can:languages_index')->get('languages', [Controllers\LanguageController::class, 'index'])->name('languages.index');
+ Route::middleware('can:languages_create')->post('languages', [Controllers\LanguageController::class, 'store'])->name('languages.store');
+ Route::middleware('can:languages_update')->put('languages/{id}', [Controllers\LanguageController::class, 'update'])->name('languages.update');
+ Route::middleware('can:languages_delete')->delete('languages/{id}', [Controllers\LanguageController::class, 'destroy'])->name('languages.destroy');
+
+ // 订单
+ Route::middleware('can:orders_index')->get('orders', [Controllers\OrderController::class, 'index'])->name('orders.index');
+ Route::middleware('can:orders_export')->get('orders/export', [Controllers\OrderController::class, 'export'])->name('orders.export');
+ Route::middleware('can:orders_show')->get('orders/{order}', [Controllers\OrderController::class, 'show'])->name('orders.show');
+ Route::middleware('can:orders_update_status')->put('orders/{order}/status', [Controllers\OrderController::class, 'updateStatus'])->name('orders.update_status');
+ Route::middleware('can:orders_update_status')->put('orders/{order}/shipments/{shipment}', [Controllers\OrderController::class, 'updateShipment'])->name('orders.update_shipment');
+
+ // 插件
+ Route::middleware('can:plugins_index')->get('plugins', [Controllers\PluginController::class, 'index'])->name('plugins.index');
+ Route::middleware('can:plugins_import')->post('plugins/import', [Controllers\PluginController::class, 'import'])->name('plugins.import');
+ Route::middleware('can:plugins_show')->get('plugins/{code}/edit', [Controllers\PluginController::class, 'edit'])->name('plugins.edit');
+ Route::middleware('can:plugins_update')->put('plugins/{code}', [Controllers\PluginController::class, 'update'])->name('plugins.update');
+ Route::middleware('can:plugins_update_status')->put('plugins/{code}/status', [Controllers\PluginController::class, 'updateStatus'])->name('plugins.update_status');
+ Route::middleware('can:plugins_install')->post('plugins/{code}/install', [Controllers\PluginController::class, 'install'])->name('plugins.install');
+ Route::middleware('can:plugins_uninstall')->post('plugins/{code}/uninstall', [Controllers\PluginController::class, 'uninstall'])->name('plugins.uninstall');
+
+ // 插件市场
+ Route::middleware('can:marketing_index')->get('marketing', [Controllers\MarketingController::class, 'index'])->name('marketing.index');
+ Route::middleware('can:marketing_show')->get('marketing/{code}', [Controllers\MarketingController::class, 'show'])->name('marketing.show');
+ Route::middleware('can:marketing_buy')->post('marketing/{code}/buy', [Controllers\MarketingController::class, 'buy'])->name('marketing.buy');
+ Route::middleware('can:marketing_download')->post('marketing/{code}/download', [Controllers\MarketingController::class, 'download'])->name('marketing.download');
+
+ // 文章
+ Route::middleware('can:pages_index')->get('pages', [Controllers\PagesController::class, 'index'])->name('pages.index');
+ Route::middleware('can:pages_index')->get('pages/autocomplete', [Controllers\PagesController::class, 'autocomplete'])->name('pages.autocomplete');
+ Route::middleware('can:pages_create')->get('pages/create', [Controllers\PagesController::class, 'create'])->name('pages.create');
+ Route::middleware('can:pages_show')->get('pages/{page}/edit', [Controllers\PagesController::class, 'edit'])->name('pages.edit');
+ Route::middleware('can:pages_show')->get('pages/{page}/name', [Controllers\PagesController::class, 'name'])->name('pages.name');
+ Route::middleware('can:pages_create')->post('pages', [Controllers\PagesController::class, 'store'])->name('pages.store');
+ Route::middleware('can:pages_update')->put('pages/{page}', [Controllers\PagesController::class, 'update'])->name('pages.update');
+ Route::middleware('can:pages_delete')->delete('pages/{page}', [Controllers\PagesController::class, 'destroy'])->name('pages.destroy');
+
+ // 文章分类
+ Route::middleware('can:page_categories_index')->get('page_categories', [Controllers\PageCategoryController::class, 'index'])->name('page_categories.index');
+ Route::middleware('can:page_categories_index')->get('page_categories/autocomplete', [Controllers\PageCategoryController::class, 'autocomplete'])->name('page_categories.autocomplete');
+ Route::middleware('can:page_categories_create')->get('page_categories/create', [Controllers\PageCategoryController::class, 'create'])->name('page_categories.create');
+ Route::middleware('can:page_categories_show')->get('page_categories/{page_category}/edit', [Controllers\PageCategoryController::class, 'edit'])->name('page_categories.edit');
+ Route::middleware('can:page_categories_show')->get('page_categories/{page_category}/name', [Controllers\PageCategoryController::class, 'name'])->name('page_categories.name');
+ Route::middleware('can:page_categories_create')->post('page_categories', [Controllers\PageCategoryController::class, 'store'])->name('page_categories.store');
+ Route::middleware('can:page_categories_update')->put('page_categories/{page_category}', [Controllers\PageCategoryController::class, 'update'])->name('page_categories.update');
+ Route::middleware('can:page_categories_delete')->delete('page_categories/{page_category}', [Controllers\PageCategoryController::class, 'destroy'])->name('page_categories.destroy');
+
+ // 商品
+ Route::middleware('can:products_restore')->put('products/restore', [Controllers\ProductController::class, 'restore']);
+ Route::middleware('can:products_trashed')->get('products/trashed', [Controllers\ProductController::class, 'trashed'])->name('products.trashed');
+ Route::middleware('can:products_trashed')->post('products/trashed/clear', [Controllers\ProductController::class, 'trashedClear'])->name('products.trashed.clear');
+ Route::middleware('can:products_show')->get('products/{id}/name', [Controllers\ProductController::class, 'name'])->name('products.name');
+ Route::middleware('can:products_index')->get('products/names', [Controllers\ProductController::class, 'getNames'])->name('products.names');
+ Route::middleware('can:products_index')->get('products/autocomplete', [Controllers\ProductController::class, 'autocomplete'])->name('products.autocomplete');
+
+ Route::middleware('can:products_update')->post('products/status', [Controllers\ProductController::class, 'updateStatus'])->name('products.update_status');
+ Route::middleware('can:products_delete')->delete('products/delete', [Controllers\ProductController::class, 'destroyByIds'])->name('products.batch_delete');
+ Route::middleware('can:products_index')->get('products', [Controllers\ProductController::class, 'index'])->name('products.index');
+ Route::middleware('can:products_create')->get('products/create', [Controllers\ProductController::class, 'create'])->name('products.create');
+ Route::middleware('can:products_create')->post('products', [Controllers\ProductController::class, 'store'])->name('products.store');
+ Route::middleware('can:products_update')->get('products/{product}/edit', [Controllers\ProductController::class, 'edit'])->name('products.edit');
+ Route::middleware('can:products_update')->put('products/{product}', [Controllers\ProductController::class, 'update'])->name('products.update');
+ Route::middleware('can:products_delete')->delete('products/{product}', [Controllers\ProductController::class, 'destroy'])->name('products.destroy');
+
+ // 区域组
+ Route::middleware('can:regions_index')->get('regions', [Controllers\RegionController::class, 'index'])->name('regions.index');
+ Route::middleware('can:regions_create')->post('regions', [Controllers\RegionController::class, 'store'])->name('regions.store');
+ Route::middleware('can:regions_update')->put('regions/{id}', [Controllers\RegionController::class, 'update'])->name('regions.update');
+ Route::middleware('can:regions_delete')->delete('regions/{id}', [Controllers\RegionController::class, 'destroy'])->name('regions.destroy');
+
+ // RMA
+ Route::middleware('can:rmas_update')->post('rmas/history/{id}', [Controllers\RmaController::class, 'addHistory'])->name('rmas.add_history');
+ Route::middleware('can:rmas_index')->get('rmas', [Controllers\RmaController::class, 'index'])->name('rmas.index');
+ Route::middleware('can:rmas_show')->get('rmas/{id}', [Controllers\RmaController::class, 'show'])->name('rmas.show');
+ Route::middleware('can:rmas_delete')->delete('rmas/{id}', [Controllers\RmaController::class, 'destroy'])->name('rmas.destroy');
+
+ Route::middleware('can:rma_reasons_index')->get('rma_reasons', [Controllers\RmaReasonController::class, 'index'])->name('rma_reasons.index');
+ Route::middleware('can:rma_reasons_create')->post('rma_reasons', [Controllers\RmaReasonController::class, 'store'])->name('rma_reasons.store');
+ Route::middleware('can:rma_reasons_update')->put('rma_reasons/{id}', [Controllers\RmaReasonController::class, 'update'])->name('rma_reasons.update');
+ Route::middleware('can:rma_reasons_delete')->delete('rma_reasons/{id}', [Controllers\RmaReasonController::class, 'destroy'])->name('rma_reasons.destroy');
+
+ Route::middleware('can:settings_index')->get('settings', [Controllers\SettingController::class, 'index'])->name('settings.index');
+ Route::middleware('can:settings_update')->post('settings', [Controllers\SettingController::class, 'store'])->name('settings.store');
+ Route::middleware('can:settings_update')->post('settings/store_token', [Controllers\SettingController::class, 'storeDeveloperToken'])->name('settings.store_token');
+
+ // 税类
+ Route::middleware('can:tax_classes_index')->get('tax_classes', [Controllers\TaxClassController::class, 'index'])->name('tax_classes.index');
+ Route::middleware('can:tax_classes_create')->post('tax_classes', [Controllers\TaxClassController::class, 'store'])->name('tax_classes.store');
+ Route::middleware('can:tax_classes_update')->put('tax_classes/{tax_class}', [Controllers\TaxClassController::class, 'update'])->name('tax_classes.update');
+ Route::middleware('can:tax_classes_delete')->delete('tax_classes/{tax_class}', [Controllers\TaxClassController::class, 'destroy'])->name('tax_classes.destroy');
+
+ // 税费
+ Route::middleware('can:tax_rates_index')->get('tax_rates', [Controllers\TaxRateController::class, 'index'])->name('tax_rates.index');
+ Route::middleware('can:tax_rates_create')->post('tax_rates', [Controllers\TaxRateController::class, 'store'])->name('tax_rates.store');
+ Route::middleware('can:tax_rates_update')->put('tax_rates/{tax_rate}', [Controllers\TaxRateController::class, 'update'])->name('tax_rates.update');
+ Route::middleware('can:tax_rates_delete')->delete('tax_rates/{tax_rate}', [Controllers\TaxRateController::class, 'destroy'])->name('tax_rates.destroy');
+
+ // 后台用户
+ Route::middleware('can:admin_users_index')->get('admin_users', [Controllers\AdminUserController::class, 'index'])->name('admin_users.index');
+ Route::middleware('can:admin_users_create')->post('admin_users', [Controllers\AdminUserController::class, 'store'])->name('admin_users.store');
+ Route::middleware('can:admin_users_update')->put('admin_users/{user_id}', [Controllers\AdminUserController::class, 'update'])->name('admin_users.update');
+ Route::middleware('can:admin_users_delete')->delete('admin_users/{user_id}', [Controllers\AdminUserController::class, 'destroy'])->name('admin_users.destroy');
+
+ // 后台用户组
+ Route::middleware('can:admin_roles_index')->get('admin_roles', [Controllers\AdminRoleController::class, 'index'])->name('admin_roles.index');
+ Route::middleware('can:admin_roles_create')->get('admin_roles/create', [Controllers\AdminRoleController::class, 'create'])->name('admin_roles.create');
+ Route::middleware('can:admin_roles_create')->post('admin_roles', [Controllers\AdminRoleController::class, 'store'])->name('admin_roles.store');
+ Route::middleware('can:admin_roles_show')->get('admin_roles/{role_id}/edit', [Controllers\AdminRoleController::class, 'edit'])->name('admin_roles.edit');
+ Route::middleware('can:admin_roles_update')->put('admin_roles/{role_id}', [Controllers\AdminRoleController::class, 'update'])->name('admin_roles.update');
+ Route::middleware('can:admin_roles_delete')->delete('admin_roles/{role_id}', [Controllers\AdminRoleController::class, 'destroy'])->name('admin_roles.destroy');
+ });
+ });
diff --git a/beike/Admin/Services/AddressService.php b/beike/Admin/Services/AddressService.php
new file mode 100644
index 00000000..197198d2
--- /dev/null
+++ b/beike/Admin/Services/AddressService.php
@@ -0,0 +1,57 @@
+
+ * @created 2022-07-04 11:15:25
+ * @modified 2022-07-04 11:15:25
+ */
+
+namespace Beike\Admin\Services;
+
+use Beike\Repositories\AddressRepo;
+use Beike\Repositories\ZoneRepo;
+
+class AddressService
+{
+ public static function addForCustomer($customerId, $data)
+ {
+ $data = self::getParams($data);
+ $data['customer_id'] = $customerId;
+ $address = AddressRepo::create($data);
+
+ return $address;
+ }
+
+ public static function update($addressId, $data)
+ {
+ $data = self::getParams($data);
+ $address = AddressRepo::update($addressId, $data);
+
+ return $address;
+ }
+
+ /**
+ * @param $data
+ * @return array
+ */
+ public static function getParams($data): array
+ {
+ $data = [
+ 'name' => $data['name'] ?? '',
+ 'phone' => $data['phone'] ?? '',
+ 'country_id' => (int) $data['country_id'] ?? 0,
+ 'zone_id' => (int) $data['zone_id'] ?? 0,
+ 'zone' => ZoneRepo::find($data['zone_id'])->name,
+ 'city_id' => (int) $data['city_id'] ?? 0,
+ 'city' => $data['city'] ?? '',
+ 'zipcode' => $data['zipcode'] ?? '',
+ 'address_1' => $data['address_1'] ?? '',
+ 'address_2' => $data['address_2'] ?? '',
+ ];
+
+ return $data;
+ }
+}
diff --git a/beike/Admin/Services/CategoryService.php b/beike/Admin/Services/CategoryService.php
new file mode 100644
index 00000000..ed3115a1
--- /dev/null
+++ b/beike/Admin/Services/CategoryService.php
@@ -0,0 +1,182 @@
+
+ * @created 2022-05-07 15:15:25
+ * @modified 2022-05-07 15:15:25
+ */
+
+namespace Beike\Admin\Services;
+
+use Beike\Models\Category;
+use Beike\Models\CategoryPath;
+use Illuminate\Support\Facades\DB;
+
+class CategoryService
+{
+ public function createOrUpdate(array $data, ?Category $category)
+ {
+ $isUpdating = $category !== null;
+ if ($category === null) {
+ $category = new Category();
+ }
+
+ try {
+ DB::beginTransaction();
+
+ $category->fill($data);
+ $category->save();
+
+ $descriptions = [];
+ foreach ($data['descriptions'] as $locale => $description) {
+ $descriptions[] = [
+ 'locale' => $locale,
+ 'name' => $description['name'],
+ 'content' => $description['content'] ?? '',
+ 'meta_title' => $description['meta_title'] ?? '',
+ 'meta_description' => $description['meta_description'] ?? '',
+ 'meta_keywords' => $description['meta_keywords'] ?? '',
+ ];
+ }
+ if ($isUpdating) {
+ $category->descriptions()->delete();
+ }
+ $category->descriptions()->createMany($descriptions);
+
+ if ($isUpdating) {
+ $this->updatePath($category);
+ } else {
+ $this->createPath($category);
+ }
+
+ DB::commit();
+ } catch (\Exception $e) {
+ DB::rollBack();
+
+ throw $e;
+ }
+
+ return $category;
+ }
+
+ public function createPath(Category $category)
+ {
+ // Paths
+ $paths = [];
+ // 复制上级分类的 paths
+ $level = 0;
+ $parentPaths = CategoryPath::query()->where('category_id', $category->parent_id)->orderBy('level')->get();
+ foreach ($parentPaths as $path) {
+ $paths[] = [
+ 'path_id' => $path->path_id,
+ 'level' => $level,
+ ];
+ $level++;
+ }
+ // 自身
+ $paths[] = [
+ 'path_id' => $category->id,
+ 'level' => $level,
+ ];
+ $category->paths()->createMany($paths);
+ }
+
+ public function updatePath(Category $category)
+ {
+ $categoryPaths = CategoryPath::query()
+ ->where('path_id', $category->id)
+ ->orderBy('level')
+ ->get();
+
+ // Get the nodes new parents
+ $newParentPathIds = CategoryPath::query()
+ ->where('category_id', $category->parent_id)
+ ->orderBy('level')
+ ->pluck('path_id')
+ ->toArray();
+
+ $paths = [];
+ if ($categoryPaths->count()) {
+ foreach ($categoryPaths as $category_path) {
+ $newPathIds = $newParentPathIds;
+
+ $results = CategoryPath::query()
+ ->where('category_id', (int) $category_path->category_id)
+ ->where('level', '>=', $category_path->level)
+ ->orderBy('level')
+ ->get();
+
+ foreach ($results as $result) {
+ $newPathIds[] = $result->path_id;
+ }
+
+ $level = 0;
+ foreach ($newPathIds as $path_id) {
+ $paths[] = [
+ 'category_id' => $category_path->category_id,
+ 'path_id' => $path_id,
+ 'level' => $level,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ];
+ $level++;
+ }
+ }
+ }
+
+ CategoryPath::query()
+ ->whereIn('category_id', $categoryPaths->pluck('category_id'))
+ ->delete();
+ CategoryPath::insert($paths);
+
+ // $this->repairCategories(0);
+ }
+
+ /**
+ * 重建category path
+ *
+ * @param int $parentId
+ */
+ public static function repairCategories(int $parentId = 0)
+ {
+ $categories = Category::query()->where('parent_id', $parentId)->get();
+
+ foreach ($categories as $category) {
+ // Delete the path below the current one
+ CategoryPath::query()->where('category_id', $category->id)->delete();
+
+ // Fix for records with no paths
+ $level = 0;
+ $subCategoryPaths = CategoryPath::query()->where('category_id', $parentId)->orderBy('level')->get();
+ foreach ($subCategoryPaths as $path) {
+ CategoryPath::query()->create([
+ 'category_id' => $category->id,
+ 'path_id' => $path->path_id,
+ 'level' => $level,
+ ]);
+ $level++;
+ }
+
+ $path = CategoryPath::query()
+ ->where('category_id', $category->id)
+ ->where('path_id', $category->id)
+ ->where('level', $level)
+ ->first();
+ $pathData = [
+ 'category_id' => $category->id,
+ 'path_id' => $category->id,
+ 'level' => $level,
+ ];
+ if ($path) {
+ $path->update($pathData);
+ } else {
+ CategoryPath::query()->create($pathData);
+ }
+
+ self::repairCategories($category->id);
+ }
+ }
+}
diff --git a/beike/Admin/Services/CustomerGroupService.php b/beike/Admin/Services/CustomerGroupService.php
new file mode 100644
index 00000000..ab27b0a8
--- /dev/null
+++ b/beike/Admin/Services/CustomerGroupService.php
@@ -0,0 +1,76 @@
+
+ * @created 2022-07-01 11:15:25
+ * @modified 2022-07-01 11:15:25
+ */
+
+namespace Beike\Admin\Services;
+
+use Beike\Repositories\CustomerGroupRepo;
+
+class CustomerGroupService
+{
+ /**
+ * @param $data
+ * @return int
+ */
+ public static function create($data)
+ {
+ $data = self::getParams($data);
+ $customerGroup = CustomerGroupRepo::create($data);
+
+ $descriptions = [];
+ foreach ($data['descriptions'] as $locale => $description) {
+ $description['locale'] = $locale;
+ $descriptions[] = $description;
+ }
+ $customerGroup->descriptions()->createMany($descriptions);
+
+ return $customerGroup;
+ }
+
+ public static function update($id, $data)
+ {
+ $data = self::getParams($data);
+ $customerGroup = CustomerGroupRepo::find($id);
+
+ $customerGroup->update($data);
+
+ $customerGroup->descriptions()->delete();
+ $descriptions = [];
+ foreach ($data['descriptions'] as $locale => $description) {
+ $description['locale'] = $locale;
+ $descriptions[] = $description;
+ }
+ $customerGroup->descriptions()->createMany($descriptions);
+
+ return $customerGroup;
+ }
+
+ private static function getParams($data)
+ {
+ $descriptions = [];
+ foreach ($data['name'] as $locale => $value) {
+ $descriptions[$locale] = [
+ 'name' => $value,
+ 'description' => $data['description'][$locale] ?? '',
+ ];
+ }
+
+ $params = [
+ 'total' => (int) $data['total'] ?? 0,
+ 'reward_point_factor' => (float) $data['reward_point_factor'] ?? 0,
+ 'use_point_factor' => (float) $data['use_point_factor'] ?? 0,
+ 'discount_factor' => (float) $data['discount_factor'] ?? 0,
+ 'level' => (int) $data['level'] ?? 0,
+ 'descriptions' => $descriptions,
+ ];
+
+ return $params;
+ }
+}
diff --git a/beike/Admin/Services/CustomerService.php b/beike/Admin/Services/CustomerService.php
new file mode 100644
index 00000000..19b872ab
--- /dev/null
+++ b/beike/Admin/Services/CustomerService.php
@@ -0,0 +1,26 @@
+
+ * @created 2022-07-01 11:15:25
+ * @modified 2022-07-01 11:15:25
+ */
+
+namespace Beike\Admin\Services;
+
+use Beike\Repositories\CustomerRepo;
+
+class CustomerService
+{
+ public static function create($data)
+ {
+ $data['locale'] = system_setting('base.locale');
+ $data['from'] = 'admin';
+ $customer = CustomerRepo::create($data);
+
+ return $customer;
+ }
+}
diff --git a/beike/Admin/Services/FileManagerService.php b/beike/Admin/Services/FileManagerService.php
new file mode 100644
index 00000000..60549a7c
--- /dev/null
+++ b/beike/Admin/Services/FileManagerService.php
@@ -0,0 +1,222 @@
+
+ * @created 2022-07-12 15:12:48
+ * @modified 2022-07-12 15:12:48
+ */
+
+namespace Beike\Admin\Services;
+
+class FileManagerService
+{
+ private $fileBasePath = '';
+
+ public function __construct()
+ {
+ $this->fileBasePath = public_path('catalog');
+ }
+
+ /**
+ * 获取某个目录下所有文件夹
+ */
+ public function getDirectories($baseFolder = '/'): array
+ {
+ $currentBasePath = rtrim($this->fileBasePath . $baseFolder, '/');
+ $directories = glob("{$currentBasePath}/*", GLOB_ONLYDIR);
+
+ $result = [];
+ foreach ($directories as $directory) {
+ $baseName = basename($directory);
+ $dirName = str_replace($this->fileBasePath, '', $directory);
+ if (is_dir($directory)) {
+ $item = $this->handleFolder($dirName, $baseName);
+ $subDirectories = $this->getDirectories($dirName);
+ if ($subDirectories) {
+ $item['children'] = $subDirectories;
+ }
+ $result[] = $item;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * 获取某个目录下的文件和文件夹
+ *
+ * @param $baseFolder
+ * @param int $page
+ * @param int $perPage
+ * @return array
+ * @throws \Exception
+ */
+ public function getFiles($baseFolder, int $page = 1, int $perPage = 20): array
+ {
+ $currentBasePath = rtrim($this->fileBasePath . $baseFolder, '/');
+ $files = glob($currentBasePath . '/*');
+ usort($files, function ($a, $b) {
+ return filemtime($a) - filemtime($b) < 0;
+ });
+
+ $images = [];
+ foreach ($files as $file) {
+ $baseName = basename($file);
+ if ($baseName == 'index.html') {
+ continue;
+ }
+ $fileName = str_replace($this->fileBasePath, '', $file);
+ if (is_file($file)) {
+ $images[] = $this->handleImage($fileName, $baseName);
+ }
+ }
+
+ $page = $page > 0 ? $page : 1;
+ $imageCollection = collect($images);
+
+ $currentImages = $imageCollection->forPage($page, $perPage);
+ $currentImages = $currentImages->map(function ($item) {
+ $item['url'] = image_resize("{$item['path']}");
+
+ return $item;
+ });
+
+ return [
+ 'images' => $currentImages->values(),
+ 'image_total' => $imageCollection->count(),
+ 'image_page' => $page,
+ ];
+ }
+
+ /**
+ * 创建目录
+ * @param $folderName
+ * @throws \Exception
+ */
+ public function createDirectory($folderName)
+ {
+ $catalogFolderPath = "catalog/{$folderName}";
+ $folderPath = public_path($catalogFolderPath);
+ if (is_dir($folderPath)) {
+ throw new \Exception(trans('admin/file_manager.directory_already_exist'));
+ }
+ create_directories($catalogFolderPath);
+ }
+
+ /**
+ * 删除文件或文件夹
+ *
+ * @param $filePath
+ * @throws \Exception
+ */
+ public function deleteDirectoryOrFile($filePath)
+ {
+ $filePath = public_path("catalog/{$filePath}");
+ if (is_dir($filePath)) {
+ $files = glob($filePath . '/*');
+ if ($files) {
+ throw new \Exception(trans('admin/file_manager.directory_not_empty'));
+ }
+ @rmdir($filePath);
+ } elseif (file_exists($filePath)) {
+ @unlink($filePath);
+ }
+ }
+
+ /**
+ * 批量删除文件
+ *
+ * @param $basePath
+ * @param $files
+ */
+ public function deleteFiles($basePath, $files)
+ {
+ if (empty($basePath) && empty($files)) {
+ return;
+ }
+ foreach ($files as $file) {
+ $filePath = public_path("catalog/{$basePath}/$file");
+ if (file_exists($filePath)) {
+ @unlink($filePath);
+ }
+ }
+ }
+
+ /**
+ * 修改文件夹或者文件名称
+ *
+ * @param $originPath
+ * @param $newPath
+ * @throws \Exception
+ */
+ public function updateName($originPath, $newPath)
+ {
+ $originPath = public_path("catalog/{$originPath}");
+ if (! is_dir($originPath) && ! file_exists($originPath)) {
+ throw new \Exception(trans('admin/file_manager.target_not_exist'));
+ }
+ $originBase = dirname($originPath);
+ $newPath = $originBase . '/' . $newPath;
+ if ($originPath == $newPath) {
+ return;
+ }
+ @rename($originPath, $newPath);
+ }
+
+ /**
+ * 处理文件夹
+ *
+ * @param $folderPath
+ * @param $baseName
+ * @return array
+ */
+ private function handleFolder($folderPath, $baseName): array
+ {
+ return [
+ 'path' => $folderPath,
+ 'name' => $baseName,
+ ];
+ }
+
+ /**
+ * 检测是否含有子文件夹
+ *
+ * @param $folderPath
+ * @return bool
+ */
+ private function hasSubFolders($folderPath): bool
+ {
+ $path = public_path("catalog/{$folderPath}");
+ $subFiles = glob($path . '/*');
+ foreach ($subFiles as $subFile) {
+ if (is_dir($subFile)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 处理文件
+ *
+ * @param $filePath
+ * @param $baseName
+ * @return array
+ * @throws \Exception
+ */
+ private function handleImage($filePath, $baseName): array
+ {
+ $path = "catalog{$filePath}";
+
+ return [
+ 'path' => $path,
+ 'name' => $baseName,
+ 'origin_url' => image_origin($path),
+ 'selected' => false,
+ ];
+ }
+}
diff --git a/beike/Admin/Services/LanguageService.php b/beike/Admin/Services/LanguageService.php
new file mode 100644
index 00000000..2d5699d0
--- /dev/null
+++ b/beike/Admin/Services/LanguageService.php
@@ -0,0 +1,86 @@
+toArray();
+ $languages = array_column($languages, null, 'code');
+
+ $result = [];
+ foreach (admin_languages() as $languageCode) {
+ $langFile = resource_path("lang/$languageCode/admin/base.php");
+ if (! is_file($langFile)) {
+ throw new \Exception("File ($langFile) not exist!");
+ }
+ $baseData = require $langFile;
+ $name = $baseData['name'] ?? $languageCode;
+ $result[] = [
+ 'code' => $languageCode,
+ 'name' => $name,
+ 'id' => $languages[$languageCode]['id'] ?? 0,
+ 'image' => $languages[$languageCode]['image'] ?? '',
+ 'sort_order' => $languages[$languageCode]['sort_order'] ?? '',
+ 'status' => $languages[$languageCode]['status'] ?? '',
+ ];
+ }
+
+ return $result;
+ }
+
+ public static function create($data)
+ {
+ $language = LanguageRepo::create($data);
+
+ if ($language->code == system_setting('base.locale')) {
+ return $language;
+ }
+
+ $models = self::$models;
+ foreach ($models as $className) {
+ $className = "\\Beike\\Models\\$className";
+ $items = $className::query()->where('locale', system_setting('base.locale', 'en'))->get()->toArray();
+ foreach ($items as &$item) {
+ if (isset($item['created_at'])) {
+ $item['created_at'] = now();
+ }
+ if (isset($item['updated_at'])) {
+ $item['updated_at'] = now();
+ }
+ unset($item['id']);
+ $item['locale'] = $language->code;
+ }
+ $className::query()->insert($items);
+ }
+
+ return $language;
+ }
+
+ public static function delete($id)
+ {
+ $language = LanguageRepo::find($id);
+ if (! $language) {
+ return;
+ }
+ if ($language->code == system_setting('base.locale')) {
+ throw new NotAcceptableHttpException(trans('admin/language.error_default_language_cannot_delete'));
+ }
+ LanguageRepo::delete($id);
+
+ $models = self::$models;
+ foreach ($models as $className) {
+ $className = "\\Beike\\Models\\$className";
+ $className::query()->where('locale', $language->code)->delete();
+ }
+ }
+}
diff --git a/beike/Admin/Services/MarketingService.php b/beike/Admin/Services/MarketingService.php
new file mode 100644
index 00000000..6273d48d
--- /dev/null
+++ b/beike/Admin/Services/MarketingService.php
@@ -0,0 +1,112 @@
+
+ * @created 2022-09-26 11:50:34
+ * @modified 2022-09-26 11:50:34
+ */
+
+namespace Beike\Admin\Services;
+
+use Illuminate\Http\Client\PendingRequest;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Storage;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use ZanySoft\Zip\Zip;
+
+class MarketingService
+{
+ private PendingRequest $httpClient;
+
+ public function __construct()
+ {
+ $this->httpClient = Http::withOptions([
+ 'verify' => false,
+ ])->withHeaders([
+ 'developer-token' => system_setting('base.developer_token'),
+ ]);
+ }
+
+ public static function getInstance()
+ {
+ return new self;
+ }
+
+ /**
+ * 获取可插件市场插件列表
+ *
+ * @param array $filters
+ * @return mixed
+ */
+ public function getList(array $filters = []): mixed
+ {
+ $url = config('beike.api_url') . '/api/plugins';
+ if (! empty($filters)) {
+ $url .= '?' . http_build_query($filters);
+ }
+
+ return $this->httpClient->get($url)->json();
+ }
+
+ /**
+ * 获取插件市场单个插件信息
+ *
+ * @param $pluginCode
+ * @return mixed
+ */
+ public function getPlugin($pluginCode): mixed
+ {
+ $url = config('beike.api_url') . "/api/plugins/{$pluginCode}";
+ $plugin = $this->httpClient->get($url)->json();
+ if (empty($plugin)) {
+ throw new NotFoundHttpException('该插件不存在或已下架');
+ }
+
+ return $plugin;
+ }
+
+ /**
+ * 购买插件市场单个插件
+ *
+ * @throws \Exception
+ */
+ public function buy($pluginCode, $postData)
+ {
+ $url = config('beike.api_url') . "/api/plugins/{$pluginCode}/buy";
+
+ $content = $this->httpClient->withBody($postData, 'application/json')
+ ->post($url)
+ ->json();
+
+ $status = $content['status'] ?? '';
+ if ($status == 'success') {
+ return $content['data'];
+ }
+
+ throw new \Exception($content['message'] ?? '');
+ }
+
+ /**
+ * 下载插件到网站
+ *
+ * @param $pluginCode
+ * @throws \Exception
+ */
+ public function download($pluginCode)
+ {
+ $datetime = date('Y-m-d');
+ $url = config('beike.api_url') . "/api/plugins/{$pluginCode}/download";
+
+ $content = $this->httpClient->get($url)->body();
+
+ $pluginPath = "plugins/{$pluginCode}-{$datetime}.zip";
+ Storage::disk('local')->put($pluginPath, $content);
+
+ $pluginZip = storage_path('app/' . $pluginPath);
+ $zipFile = (new Zip)->open($pluginZip);
+ $zipFile->extract(base_path('plugins'));
+ }
+}
diff --git a/beike/Admin/Services/ProductService.php b/beike/Admin/Services/ProductService.php
new file mode 100644
index 00000000..9ffcf3ac
--- /dev/null
+++ b/beike/Admin/Services/ProductService.php
@@ -0,0 +1,73 @@
+createOrUpdate($product, $data);
+ }
+
+ public function update(Product $product, array $data): Product
+ {
+ return $this->createOrUpdate($product, $data);
+ }
+
+ protected function createOrUpdate(Product $product, array $data): Product
+ {
+ $isUpdating = $product->id > 0;
+
+ try {
+ DB::beginTransaction();
+
+ $data['brand_id'] = (int) $data['brand_id'];
+ $data['variables'] = json_decode($data['variables']);
+ $product->fill($data);
+ $product->save();
+
+ if ($isUpdating) {
+ $product->skus()->delete();
+ $product->descriptions()->delete();
+ $product->attributes()->delete();
+ }
+
+ $descriptions = [];
+ foreach ($data['descriptions'] as $locale => $description) {
+ $description['locale'] = $locale;
+ $description['content'] = $description['content'] ?? '';
+
+ $descriptions[] = $description;
+ }
+ $product->descriptions()->createMany($descriptions);
+
+ $product->attributes()->createMany($data['attributes'] ?? []);
+
+ $skus = [];
+ foreach ($data['skus'] as $index => $sku) {
+ $sku['position'] = $index;
+ $sku['origin_price'] = (float) $sku['origin_price'];
+ $sku['cost_price'] = (float) $sku['cost_price'];
+ $sku['quantity'] = (int) $sku['quantity'];
+ $skus[] = $sku;
+ }
+ $product->skus()->createMany($skus);
+
+ $product->categories()->sync($data['categories'] ?? []);
+ $product->relations()->sync($data['relations'] ?? []);
+
+ DB::commit();
+
+ return $product;
+ } catch (\Exception $e) {
+ DB::rollBack();
+
+ throw $e;
+ }
+ }
+}
diff --git a/beike/Admin/Services/UserService.php b/beike/Admin/Services/UserService.php
new file mode 100644
index 00000000..1b755273
--- /dev/null
+++ b/beike/Admin/Services/UserService.php
@@ -0,0 +1,69 @@
+
+ * @created 2022-07-14 12:12:57
+ * @modified 2022-07-14 12:12:57
+ */
+
+namespace Beike\Admin\Services;
+
+use Beike\Repositories\UserRepo;
+use Beike\Repositories\VerifyCodeRepo;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Log;
+
+class UserService
+{
+ /**
+ * 发送验证码通过$type方式,type为email或telephone
+ * @param $email
+ * @return void
+ */
+ public static function sendVerifyCodeForForgotten($email)
+ {
+ $code = str_pad(mt_rand(10, 999999), 6, '0', STR_PAD_LEFT);
+
+ VerifyCodeRepo::deleteByAccount($email);
+ VerifyCodeRepo::create([
+ 'account' => $email,
+ 'code' => $code,
+ ]);
+
+ Log::info("找回密码验证码:{$code}");
+
+ UserRepo::findByEmail($email)->notifyVerifyCodeForForgotten($code);
+ }
+
+ /**
+ * 验证验证码是否正确,并修改密码为新密码
+ * @param $code
+ * @param $account
+ * @param $password
+ * @return void
+ */
+ public static function verifyAndChangePassword($code, $account, $password)
+ {
+ $verifyCode = VerifyCodeRepo::findByAccount($account);
+ if ($verifyCode->created_at->addMinutes(10) < Carbon::now()) {
+ $verifyCode->delete();
+
+ throw new \Exception(trans('admin/user.verify_code_expired'));
+ }
+
+ if ($verifyCode->code != $code) {
+ throw new \Exception(trans('admin/user.verify_code_error'));
+ }
+
+ $user = UserRepo::findByEmail($account);
+ if (! $user) {
+ throw new \Exception(trans('admin/user.account_not_exist'));
+ }
+
+ UserRepo::update($user, ['password' => $password]);
+ $verifyCode->delete();
+ }
+}
diff --git a/beike/Admin/View/Components/Alert.php b/beike/Admin/View/Components/Alert.php
new file mode 100644
index 00000000..7d60c203
--- /dev/null
+++ b/beike/Admin/View/Components/Alert.php
@@ -0,0 +1,23 @@
+type = $type ?? 'success';
+ $this->msg = $msg;
+ }
+
+ public function render()
+ {
+ return view('admin::components.alert');
+ }
+}
diff --git a/beike/Admin/View/Components/Filter.php b/beike/Admin/View/Components/Filter.php
new file mode 100644
index 00000000..a67c458d
--- /dev/null
+++ b/beike/Admin/View/Components/Filter.php
@@ -0,0 +1,33 @@
+url = $url;
+ $this->queries = request()->query() ?? [];
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return \Illuminate\Contracts\View\View|\Closure|string
+ */
+ public function render()
+ {
+ return view('Resources::components.admin.filter');
+ }
+}
diff --git a/beike/Admin/View/Components/Form/Image.php b/beike/Admin/View/Components/Form/Image.php
new file mode 100644
index 00000000..f362eb86
--- /dev/null
+++ b/beike/Admin/View/Components/Form/Image.php
@@ -0,0 +1,26 @@
+name = $name;
+ $this->title = $title ?? '';
+ $this->value = $value ?? '';
+ }
+
+ public function render()
+ {
+ return view('admin::components.form.image');
+ }
+}
diff --git a/beike/Admin/View/Components/Form/Input.php b/beike/Admin/View/Components/Form/Input.php
new file mode 100644
index 00000000..c9f4c3dd
--- /dev/null
+++ b/beike/Admin/View/Components/Form/Input.php
@@ -0,0 +1,47 @@
+name = $name;
+ $this->title = $title;
+ $this->value = html_entity_decode($value, ENT_QUOTES);
+ $this->error = $error;
+ $this->width = $width;
+ $this->placeholder = $placeholder;
+ $this->type = $type;
+ $this->step = $step;
+ $this->required = $required;
+ $this->description = $description;
+ }
+
+ public function render()
+ {
+ return view('admin::components.form.input');
+ }
+}
diff --git a/beike/Admin/View/Components/Form/InputLocale.php b/beike/Admin/View/Components/Form/InputLocale.php
new file mode 100644
index 00000000..7f4e8dc2
--- /dev/null
+++ b/beike/Admin/View/Components/Form/InputLocale.php
@@ -0,0 +1,87 @@
+name = $name;
+ $this->title = $title;
+ $this->width = $width;
+ $this->placeholder = $placeholder;
+ $this->value = $value;
+ $this->required = $required;
+ }
+
+ public function render()
+ {
+ return view('admin::components.form.input-locale');
+ }
+
+ public function formatName(string $code)
+ {
+ // descriptions.*.name => descriptions[zh_cn][name]
+
+ $segments = explode('.', $this->name);
+ $key = $segments[0];
+ for ($i = 1; $i < count($segments); $i++) {
+ $segment = $segments[$i];
+ if ($segment == '*') {
+ $key .= '[' . $code . ']';
+ } else {
+ $key .= '[' . $segment . ']';
+ }
+ }
+
+ return $key;
+ }
+
+ /**
+ * Get value from database
+ *
+ * @param $code
+ * @return mixed
+ */
+ public function formatValue($code)
+ {
+ $oldKey = str_replace('*', $code, $this->name);
+
+ if (is_string($this->value)) {
+ $value = json_decode($this->value, true);
+
+ return old($oldKey, Arr::get($value, $code, ''));
+ } elseif ($this->value instanceof Collection) {
+ // descriptions.*.name
+ $segments = explode('.', $this->name);
+ array_shift($segments);
+ $valueKey = implode('.', $segments);
+ $valueKey = str_replace('*', $code, $valueKey);
+
+ return old($oldKey, Arr::get($this->value, $valueKey, ''));
+ }
+
+ return '';
+ }
+
+ public function errorKey($code)
+ {
+ return str_replace('*', $code, $this->name);
+ }
+}
diff --git a/beike/Admin/View/Components/Form/RichText.php b/beike/Admin/View/Components/Form/RichText.php
new file mode 100644
index 00000000..c3a16e7f
--- /dev/null
+++ b/beike/Admin/View/Components/Form/RichText.php
@@ -0,0 +1,38 @@
+name = $name;
+ $this->title = $title;
+ $this->value = $value;
+ $this->required = $required;
+ $this->multiple = $multiple;
+ }
+
+ public function render()
+ {
+ return view('admin::components.form.rich-text');
+ }
+}
diff --git a/beike/Admin/View/Components/Form/Select.php b/beike/Admin/View/Components/Form/Select.php
new file mode 100644
index 00000000..3984247c
--- /dev/null
+++ b/beike/Admin/View/Components/Form/Select.php
@@ -0,0 +1,35 @@
+name = $name;
+ $this->title = $title;
+ $this->value = $value;
+ $this->options = $options;
+ $this->key = $key;
+ $this->label = $label;
+ }
+
+ public function render()
+ {
+ return view('admin::components.form.select');
+ }
+}
diff --git a/beike/Admin/View/Components/Form/SwitchRadio.php b/beike/Admin/View/Components/Form/SwitchRadio.php
new file mode 100644
index 00000000..6604ed61
--- /dev/null
+++ b/beike/Admin/View/Components/Form/SwitchRadio.php
@@ -0,0 +1,26 @@
+name = $name;
+ $this->title = $title;
+ $this->value = $value;
+ }
+
+ public function render()
+ {
+ return view('admin::components.form.switch-radio');
+ }
+}
diff --git a/beike/Admin/View/Components/Form/Textarea.php b/beike/Admin/View/Components/Form/Textarea.php
new file mode 100644
index 00000000..b0ed7ef1
--- /dev/null
+++ b/beike/Admin/View/Components/Form/Textarea.php
@@ -0,0 +1,29 @@
+name = $name;
+ $this->title = $title;
+ $this->value = html_entity_decode($value, ENT_QUOTES);
+ $this->required = $required;
+ }
+
+ public function render()
+ {
+ return view('admin::components.form.textarea');
+ }
+}
diff --git a/beike/Admin/View/Components/Header.php b/beike/Admin/View/Components/Header.php
new file mode 100644
index 00000000..b1a13a0e
--- /dev/null
+++ b/beike/Admin/View/Components/Header.php
@@ -0,0 +1,108 @@
+adminUser = current_user();
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return mixed
+ */
+ public function render()
+ {
+ $sidebar = new Sidebar();
+ $preparedMenus = $this->prepareMenus();
+
+ foreach ($preparedMenus as $menu) {
+ $menuCode = $menu['code'] ?? '';
+ if ($menuCode) {
+ $routes = [];
+ $subRoutesMethod = "get{$menu['code']}SubRoutes";
+ if (method_exists($sidebar, $subRoutesMethod)) {
+ $sideMenuRoutes = $sidebar->{"get{$menu['code']}SubRoutes"}();
+ foreach ($sideMenuRoutes as $route) {
+ $routeFirst = explode('.', $route['route'])[0] ?? '';
+ $routes[] = 'admin.' . $route['route'];
+ $routes[] = 'admin.' . $routeFirst . '.edit';
+ $routes[] = 'admin.' . $routeFirst . '.show';
+ }
+ }
+
+ $data = [
+ 'menu_code' => $menuCode,
+ 'routes' => $routes,
+ ];
+ $filterRoutes = hook_filter('admin.components.header.routes', $data);
+ $routes = $filterRoutes['routes'] ?? [];
+ if (empty($routes)) {
+ $is_route = equal_route('admin.' . $menu['route']);
+ } else {
+ $is_route = equal_route($routes);
+ }
+ } else {
+ $is_route = equal_route('admin.' . $menu['route']);
+ }
+
+ $this->addLink($menu['name'], $menu['route'], $is_route);
+ }
+
+ return view('admin::components.header');
+ }
+
+ /**
+ * 默认菜单
+ */
+ private function prepareMenus()
+ {
+ $menus = [
+ ['name' => trans('admin/common.home'), 'route' => 'home.index', 'code' => ''],
+ ['name' => trans('admin/common.order'), 'route' => 'orders.index', 'code' => 'Order'],
+ ['name' => trans('admin/common.product'), 'route' => 'products.index', 'code' => 'Product'],
+ ['name' => trans('admin/common.customer'), 'route' => 'customers.index', 'code' => 'Customer'],
+ ['name' => trans('admin/common.page'), 'route' => 'pages.index', 'code' => 'Page'],
+ ['name' => trans('admin/common.setting'), 'route' => 'settings.index', 'code' => 'Setting'],
+ ];
+
+ return hook_filter('admin.header_menus', $menus);
+ }
+
+ /**
+ * 添加后台顶部菜单链接
+ *
+ * @param $title
+ * @param $route
+ * @param false $active
+ */
+ private function addLink($title, $route, bool $active = false)
+ {
+ $permissionRoute = str_replace('.', '_', $route);
+ if ($this->adminUser->cannot($permissionRoute) && $route != 'home.index') {
+ return;
+ }
+
+ $url = admin_route($route);
+ $this->links[] = [
+ 'title' => $title,
+ 'url' => $url,
+ 'active' => $active,
+ ];
+ }
+}
diff --git a/beike/Admin/View/Components/NoData.php b/beike/Admin/View/Components/NoData.php
new file mode 100644
index 00000000..67e2e262
--- /dev/null
+++ b/beike/Admin/View/Components/NoData.php
@@ -0,0 +1,20 @@
+text = $text ?: trans('common.no_data');
+ }
+
+ public function render()
+ {
+ return view('admin::components.no-data');
+ }
+}
diff --git a/beike/Admin/View/Components/Sidebar.php b/beike/Admin/View/Components/Sidebar.php
new file mode 100644
index 00000000..5c32fd9e
--- /dev/null
+++ b/beike/Admin/View/Components/Sidebar.php
@@ -0,0 +1,285 @@
+adminName = admin_name();
+ $this->routeNameWithPrefix = request()->route()->getName();
+ $this->adminUser = current_user();
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return mixed
+ */
+ public function render()
+ {
+ $adminName = $this->adminName;
+ $routeNameWithPrefix = request()->route()->getName();
+ $routeName = str_replace($adminName . '.', '', $routeNameWithPrefix);
+
+ if (Str::startsWith($routeName, $this->getHomeSubPrefix())) {
+ $routes = $this->getHomeSubRoutes();
+ foreach ($routes as $route) {
+ $this->addLink($route, $this->equalRoute($route['route']), (bool) ($route['blank'] ?? false), $route['hide_mobile'] ?? 0);
+ }
+ } elseif (Str::startsWith($routeName, $this->getProductSubPrefix())) {
+ $routes = $this->getProductSubRoutes();
+ foreach ($routes as $route) {
+ $this->addLink($route, $this->equalRoute($route['route']), (bool) ($route['blank'] ?? false), $route['hide_mobile'] ?? 0);
+ }
+ } elseif (Str::startsWith($routeName, $this->getCustomerSubPrefix())) {
+ $routes = $this->getCustomerSubRoutes();
+ foreach ($routes as $route) {
+ $this->addLink($route, $this->equalRoute($route['route']), (bool) ($route['blank'] ?? false), $route['hide_mobile'] ?? 0);
+ }
+ } elseif (Str::startsWith($routeName, $this->getOrderSubPrefix())) {
+ $routes = $this->getOrderSubRoutes();
+ foreach ($routes as $route) {
+ $this->addLink($route, $this->equalRoute($route['route']), (bool) ($route['blank'] ?? false), $route['hide_mobile'] ?? 0);
+ }
+ } elseif (Str::startsWith($routeName, $this->getPageSubPrefix())) {
+ $routes = $this->getPageSubRoutes();
+ foreach ($routes as $route) {
+ $this->addLink($route, $this->equalRoute($route['route']), (bool) ($route['blank'] ?? false), $route['hide_mobile'] ?? 0);
+ }
+ } elseif (Str::startsWith($routeName, $this->getSettingSubPrefix())) {
+ $routes = $this->getSettingSubRoutes();
+ foreach ($routes as $route) {
+ $this->addLink($route, $this->equalRoute($route['route']), (bool) ($route['blank'] ?? false), $route['hide_mobile'] ?? 0);
+ }
+ }
+
+ return view('admin::components.sidebar');
+ }
+
+ /**
+ * 添加左侧菜单链接
+ *
+ * @param $routeData
+ * @param $active
+ * @param false $newWindow
+ * @param int $hide_mobile
+ */
+ private function addLink($routeData, $active, bool $newWindow = false, int $hide_mobile = 0)
+ {
+ $route = $routeData['route'];
+ $icon = $routeData['icon'] ?? '';
+ $title = $routeData['title'] ?? '';
+
+ $permissionRoute = str_replace('.', '_', $route);
+ if ($this->adminUser->cannot($permissionRoute)) {
+ return;
+ }
+
+ if (empty($title)) {
+ $title = trans("admin/common.{$permissionRoute}");
+ }
+ $url = admin_route($route);
+ $this->links[] = [
+ 'title' => $title,
+ 'url' => $url,
+ 'icon' => $icon,
+ 'active' => $active,
+ 'hide_mobile' => $hide_mobile,
+ 'new_window' => $newWindow,
+ ];
+ }
+
+ /**
+ * 获取后台首页子页面路由前缀列表
+ */
+ private function getHomeSubPrefix()
+ {
+ $prefix = ['home.'];
+
+ return hook_filter('admin.sidebar.home.prefix', $prefix);
+ }
+
+ /**
+ * 获取后台产品子页面路由前缀列表
+ */
+ private function getProductSubPrefix()
+ {
+ $prefix = ['products.', 'categories.', 'brands.', 'attribute_groups.', 'attributes.'];
+
+ return hook_filter('admin.sidebar.product.prefix', $prefix);
+ }
+
+ /**
+ * 获取后台客户子页面路由前缀列表
+ */
+ private function getCustomerSubPrefix()
+ {
+ $prefix = ['customers.', 'customer_groups.'];
+
+ return hook_filter('admin.sidebar.customer.prefix', $prefix);
+ }
+
+ /**
+ * 获取后台订单子页面路由前缀列表
+ */
+ private function getOrderSubPrefix()
+ {
+ $prefix = ['orders.', 'rmas.', 'rma_reasons.'];
+
+ return hook_filter('admin.sidebar.order.prefix', $prefix);
+ }
+
+ /**
+ * 获取后台内容子页面路由前缀列表
+ */
+ private function getPageSubPrefix()
+ {
+ $prefix = ['pages.', 'page_categories.'];
+
+ return hook_filter('admin.sidebar.page.prefix', $prefix);
+ }
+
+ /**
+ * 获取后台系统设置子页面路由前缀列表
+ */
+ private function getSettingSubPrefix()
+ {
+ $prefix = ['settings.', 'admin_users.', 'admin_roles.', 'plugins.', 'theme.', 'marketing.', 'tax_classes', 'tax_rates', 'regions', 'currencies', 'languages', 'design_menu', 'countries', 'zones'];
+
+ return hook_filter('admin.sidebar.setting.prefix', $prefix);
+ }
+
+ /**
+ * 获取首页子页面路由
+ */
+ public function getHomeSubRoutes()
+ {
+ $routes = [
+ ['route' => 'design.index', 'icon' => 'fa fa-tachometer-alt', 'blank' => 1, 'hide_mobile' => 1],
+ ['route' => 'design_footer.index', 'icon' => 'fa fa-tachometer-alt', 'blank' => 1, 'hide_mobile' => 1],
+ ['route' => 'design_menu.index', 'icon' => 'fa fa-tachometer-alt', 'hide_mobile' => 1],
+ ['route' => 'languages.index', 'icon' => 'fa fa-tachometer-alt', 'hide_mobile' => 1],
+ ['route' => 'currencies.index', 'icon' => 'fa fa-tachometer-alt', 'hide_mobile' => 1],
+ ['route' => 'plugins.index', 'icon' => 'fa fa-tachometer-alt', 'hide_mobile' => 1],
+ ];
+
+ return hook_filter('admin.sidebar.home_routes', $routes);
+ }
+
+ /**
+ * 获取商品子页面路由
+ */
+ public function getProductSubRoutes()
+ {
+ $routes = [
+ ['route' => 'categories.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'products.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'brands.index', 'icon' => 'fa fa-tachometer-alt', 'hide_mobile' => 1],
+ ['route' => 'attribute_groups.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'attributes.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'products.trashed', 'icon' => 'fa fa-tachometer-alt'],
+ ];
+
+ return hook_filter('admin.sidebar.product_routes', $routes);
+ }
+
+ /**
+ * 获取商品子页面路由
+ */
+ public function getCustomerSubRoutes()
+ {
+ $routes = [
+ ['route' => 'customers.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'customer_groups.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'customers.trashed', 'icon' => 'fa fa-tachometer-alt'],
+ ];
+
+ return hook_filter('admin.sidebar.customer_routes', $routes);
+ }
+
+ /**
+ * 获取订单子页面路由
+ */
+ public function getOrderSubRoutes()
+ {
+ $routes = [
+ ['route' => 'orders.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'rmas.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'rma_reasons.index', 'icon' => 'fa fa-tachometer-alt'],
+ ];
+
+ return hook_filter('admin.sidebar.order_routes', $routes);
+ }
+
+ /**
+ * 获取文章管理子页面路由
+ * @return mixed
+ */
+ public function getPageSubRoutes()
+ {
+ $routes = [
+ ['route' => 'page_categories.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'pages.index', 'icon' => 'fa fa-tachometer-alt'],
+ ];
+
+ return hook_filter('admin.sidebar.pages_routes', $routes);
+ }
+
+ /**
+ * 获取系统设置子页面路由
+ * @return mixed
+ */
+ public function getSettingSubRoutes()
+ {
+ $routes = [
+ ['route' => 'settings.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'admin_users.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'plugins.index', 'icon' => 'fa fa-tachometer-alt', 'hide_mobile' => 1],
+ ['route' => 'theme.index', 'icon' => 'fa fa-tachometer-alt', 'hide_mobile' => 1],
+ ['route' => 'marketing.index', 'icon' => 'fa fa-tachometer-alt', 'hide_mobile' => 1],
+ ['route' => 'regions.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'tax_rates.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'tax_classes.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'currencies.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'languages.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'countries.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'zones.index', 'icon' => 'fa fa-tachometer-alt'],
+ ['route' => 'design.index', 'icon' => 'fa fa-tachometer-alt', 'blank' => true, 'hide_mobile' => 1],
+ ['route' => 'design_footer.index', 'icon' => 'fa fa-tachometer-alt', 'blank' => true, 'hide_mobile' => 1],
+ ['route' => 'design_menu.index', 'icon' => 'fa fa-tachometer-alt', 'hide_mobile' => 1],
+ ];
+
+ return hook_filter('admin.sidebar.setting_routes', $routes);
+ }
+
+ /**
+ * 是否为当前访问路由
+ *
+ * @param $routeName
+ * @return bool
+ */
+ private function equalRoute($routeName): bool
+ {
+ $currentRouteName = str_replace($this->adminName . '.', '', $this->routeNameWithPrefix);
+
+ return $routeName == $currentRouteName;
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/Brand.php b/beike/Admin/View/DesignBuilders/Brand.php
new file mode 100644
index 00000000..7dafab5f
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/Brand.php
@@ -0,0 +1,44 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Brand extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'brand',
+ 'sort' => 0,
+ 'name' => trans('admin/design_builder.module_brand'),
+ 'icon' => '',
+ ];
+
+ return view('admin::pages.design.module.brand', $data);
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/Icons.php b/beike/Admin/View/DesignBuilders/Icons.php
new file mode 100644
index 00000000..80e5af1a
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/Icons.php
@@ -0,0 +1,44 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Icons extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'icons',
+ 'sort' => 0,
+ 'name' => trans('admin/design_builder.module_icons'),
+ 'icon' => '',
+ ];
+
+ return view('admin::pages.design.module.icons', $data);
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/Image100.php b/beike/Admin/View/DesignBuilders/Image100.php
new file mode 100644
index 00000000..709d3f45
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/Image100.php
@@ -0,0 +1,44 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Image100 extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'image100',
+ 'sort' => 0,
+ 'name' => trans('admin/design_builder.module_banner'),
+ 'icon' => '',
+ ];
+
+ return view('admin::pages.design.module.image100', $data);
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/Image200.php b/beike/Admin/View/DesignBuilders/Image200.php
new file mode 100644
index 00000000..804ef694
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/Image200.php
@@ -0,0 +1,44 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Image200 extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'image200',
+ 'sort' => 0,
+ 'name' => trans('admin/builder.modules_image_200'),
+ 'icon' => '',
+ ];
+
+ return view('admin::pages.design.module.image200', $data);
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/Image300.php b/beike/Admin/View/DesignBuilders/Image300.php
new file mode 100644
index 00000000..50d88fcb
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/Image300.php
@@ -0,0 +1,44 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Image300 extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'image300',
+ 'sort' => 0,
+ 'name' => trans('admin/builder.modules_image_300'),
+ 'icon' => '',
+ ];
+
+ return view('admin::pages.design.module.image300', $data);
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/Image401.php b/beike/Admin/View/DesignBuilders/Image401.php
new file mode 100644
index 00000000..ed2b07d8
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/Image401.php
@@ -0,0 +1,44 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Image401 extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'image401',
+ 'sort' => 0,
+ 'name' => trans('admin/design_builder.module_four_image_pro'),
+ 'icon' => '',
+ ];
+
+ return view('admin::pages.design.module.image401', $data);
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/Product.php b/beike/Admin/View/DesignBuilders/Product.php
new file mode 100644
index 00000000..3630af4e
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/Product.php
@@ -0,0 +1,44 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Product extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'product',
+ 'sort' => 0,
+ 'name' => trans('admin/design_builder.module_product'),
+ 'icon' => '',
+ ];
+
+ return view('admin::pages.design.module.product', $data);
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/RichText.php b/beike/Admin/View/DesignBuilders/RichText.php
new file mode 100644
index 00000000..293d5f64
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/RichText.php
@@ -0,0 +1,44 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class RichText extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'rich_text',
+ 'sort' => 0,
+ 'name' => trans('admin/design_builder.module_rich_text'),
+ 'icon' => '',
+ ];
+
+ return view('admin::pages.design.module.rich_text', $data);
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/SlideShow.php b/beike/Admin/View/DesignBuilders/SlideShow.php
new file mode 100644
index 00000000..e45211ee
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/SlideShow.php
@@ -0,0 +1,45 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class SlideShow extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'slideshow',
+ 'sort' => 0,
+ 'name' => trans('admin/design_builder.module_slideshow'),
+ 'icon' => '',
+ 'style' => 'font-size: 40px;',
+ ];
+
+ return view('admin::pages.design.module.slideshow', $data);
+ }
+}
diff --git a/beike/Admin/View/DesignBuilders/TabProduct.php b/beike/Admin/View/DesignBuilders/TabProduct.php
new file mode 100644
index 00000000..c620310b
--- /dev/null
+++ b/beike/Admin/View/DesignBuilders/TabProduct.php
@@ -0,0 +1,44 @@
+
+ * @created 2022-07-08 17:09:15
+ * @modified 2022-07-08 17:09:15
+ */
+
+namespace Beike\Admin\View\DesignBuilders;
+
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class TabProduct extends Component
+{
+ /**
+ * Create a new component instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ *
+ * @return View
+ */
+ public function render(): View
+ {
+ $data['register'] = [
+ 'code' => 'tab_product',
+ 'sort' => 0,
+ 'name' => trans('admin/design_builder.module_tab_products'),
+ 'icon' => '',
+ ];
+
+ return view('admin::pages.design.module.tab_product', $data);
+ }
+}
diff --git a/beike/Config/beike.php b/beike/Config/beike.php
new file mode 100644
index 00000000..00486c5b
--- /dev/null
+++ b/beike/Config/beike.php
@@ -0,0 +1,19 @@
+
+ * @created 2022-06-06 09:09:09
+ * @modified 2022-09-13 22:32:41
+ */
+
+return [
+ 'api_url' => env('BEIKE_API_URL', 'https://beikeshop.com'),
+ 'version' => '1.3.4',
+ 'build' => '20230318',
+
+ 'admin_name' => env('ADMIN_NAME'),
+ 'force_url_https' => env('APP_FORCE_HTTPS', false),
+];
diff --git a/beike/Console/Commands/ChangeRootPassword.php b/beike/Console/Commands/ChangeRootPassword.php
new file mode 100644
index 00000000..dbfba762
--- /dev/null
+++ b/beike/Console/Commands/ChangeRootPassword.php
@@ -0,0 +1,41 @@
+
+ * @created 2023-02-13 20:56:16
+ * @modified 2023-02-13 20:56:16
+ */
+
+namespace Beike\Console\Commands;
+
+use Beike\Models\AdminUser;
+use Illuminate\Console\Command;
+
+class ChangeRootPassword extends Command
+{
+ protected $signature = 'root:password';
+
+ protected $description = '修改后台Root账号(第一个管理员)';
+
+ /**
+ * @throws \Throwable
+ */
+ public function handle()
+ {
+ $user = AdminUser::query()->first();
+ $newPassword = $this->ask("请为管理员 {$user->email} 设置新密码");
+
+ if (! $newPassword) {
+ $this->info('请输入新密码');
+
+ return;
+ }
+
+ $user->password = bcrypt($newPassword);
+ $user->saveOrFail();
+ $this->info('管理员密码设置成功!');
+ }
+}
diff --git a/beike/Console/Commands/FetchCurrencyRate.php b/beike/Console/Commands/FetchCurrencyRate.php
new file mode 100644
index 00000000..cd7e590d
--- /dev/null
+++ b/beike/Console/Commands/FetchCurrencyRate.php
@@ -0,0 +1,35 @@
+info(sprintf('获取 %s 汇率数据开始', $today));
+
+ try {
+ $tableRows = [];
+ $data = CurrencyService::getInstance()->getRatesFromApi($today);
+
+ foreach ($data as $key => $val) {
+ $tableRows[] = [$key, $val];
+ }
+
+ $this->table(['货币', '汇率'], $tableRows);
+
+ $this->info(sprintf('获取 %s 汇率数据完成', $today));
+ }catch (\Exception) {
+ $this->error(sprintf('获取 %s 汇率数据失败', $today));
+ }
+ }
+}
diff --git a/beike/Console/Commands/GenerateDatabaseDict.php b/beike/Console/Commands/GenerateDatabaseDict.php
new file mode 100644
index 00000000..ae7e0fc2
--- /dev/null
+++ b/beike/Console/Commands/GenerateDatabaseDict.php
@@ -0,0 +1,51 @@
+
+ * @created 2022-11-11 09:00:25
+ * @modified 2022-11-11 09:00:25
+ */
+
+namespace Beike\Console\Commands;
+
+use Illuminate\Console\Command;
+use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\DB;
+use UniSharp\DocUs\Parser;
+
+class GenerateDatabaseDict extends Command
+{
+ protected $signature = 'make:dict';
+
+ protected $description = '生成数据字典 Markdown 文档';
+
+ public function handle()
+ {
+ $filePath = storage_path('database.md');
+ // $filePath = '/Users/edward/Guangda/Products/beike/beikedocs/docs/dev/database.md';
+ $tables = $this->getTables();
+ $markdown = view('vendor.unisharp.markdown', compact('tables'))->render();
+ file_put_contents($filePath, $markdown);
+ dump('done');
+ }
+
+ /**
+ * 获取所有数据表信息
+ * @return Collection
+ */
+ private function getTables(): Collection
+ {
+ $schema = Parser::getSchema();
+
+ return $schema->map(function ($item) {
+ $tableName = $item['name'];
+ $result = collect(DB::select("SHOW TABLE STATUS WHERE Name='{$tableName}'"))->first();
+ $item['comment'] = $result->Comment;
+
+ return $item;
+ });
+ }
+}
diff --git a/beike/Console/Commands/GenerateSitemap.php b/beike/Console/Commands/GenerateSitemap.php
new file mode 100644
index 00000000..3b155516
--- /dev/null
+++ b/beike/Console/Commands/GenerateSitemap.php
@@ -0,0 +1,32 @@
+ask('请输入登录邮箱地址');
+ $password = $this->ask('请输入密码');
+
+ if (! $email || ! $password) {
+ $this->info('邮箱地址/手机号码不能为空,退出');
+
+ return;
+ }
+
+ $admin = AdminUser::create([
+ 'name' => 'John Doe',
+ 'email' => $email,
+ 'password' => bcrypt($password),
+ 'active' => true,
+ ]);
+
+ $this->info('账号创建成功,退出');
+ }
+}
diff --git a/beike/Console/Commands/MigrateFromOpenCart.php b/beike/Console/Commands/MigrateFromOpenCart.php
new file mode 100644
index 00000000..da8fedf3
--- /dev/null
+++ b/beike/Console/Commands/MigrateFromOpenCart.php
@@ -0,0 +1,460 @@
+
+ * @created 2023-01-03 18:57:53
+ * @modified 2023-01-03 18:57:53
+ */
+
+namespace Beike\Console\Commands;
+
+use Beike\Admin\Services\CategoryService;
+use Beike\Admin\Services\ProductService;
+use Beike\Models\Brand;
+use Beike\Models\Category;
+use Beike\Models\CategoryDescription;
+use Beike\Models\CategoryPath;
+use Beike\Models\Product;
+use Beike\Models\ProductDescription;
+use Beike\Models\ProductSku;
+use Illuminate\Console\Command;
+use Illuminate\Database\ConnectionInterface;
+use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\DB;
+
+class MigrateFromOpenCart extends Command
+{
+ public const PER_PAGE = 1000;
+
+ public const LANG_MAPPING = [
+ 'zh_cn' => 11,
+ 'es' => 6,
+ ];
+
+ protected $signature = 'migrate:oc';
+
+ protected $description = '从 OpenCart 迁移数据';
+
+ protected ConnectionInterface $ocdb;
+
+ private $ocProductVariants;
+
+ private $ocVariantDescriptions;
+
+ private $ocVariantValues;
+
+ private $ocVariantValueDescriptions;
+
+ private $ocProductImages;
+
+ private $ocProductCategories;
+
+ private int $page = 1;
+
+ public function __construct()
+ {
+ parent::__construct();
+ $this->ocdb = DB::connection('opencart');
+ }
+
+ /**
+ * 导入OC产品数据
+ */
+ public function handle()
+ {
+ $this->importCategories();
+ $this->importBrands();
+ $this->importProducts();
+ }
+
+ /**
+ * 导入分类数据
+ */
+ private function importCategories()
+ {
+ Category::query()->truncate();
+ CategoryDescription::query()->truncate();
+ CategoryPath::query()->truncate();
+
+ $this->ocdb->table('category')
+ ->orderBy('category_id')
+ ->chunk(self::PER_PAGE, function ($ocCategories) {
+ $bkCategories = [];
+ foreach ($ocCategories as $ocCategory) {
+ $bkCategories[] = [
+ 'id' => $ocCategory->category_id,
+ 'parent_id' => $ocCategory->parent_id,
+ 'position' => $ocCategory->sort_order,
+ 'active' => $ocCategory->status,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ];
+ }
+ Category::query()->insert($bkCategories);
+ });
+
+ $descriptions = [];
+ $ocDescriptions = $this->ocdb->table('category_description')->orderBy('category_id')->get();
+ $langMapping = array_flip(self::LANG_MAPPING);
+ foreach ($ocDescriptions as $description) {
+ $descriptions[] = [
+ 'category_id' => $description->category_id,
+ 'locale' => $langMapping[$description->language_id],
+ 'name' => $description->name,
+ 'content' => html_entity_decode($description->description, ENT_QUOTES),
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ];
+ }
+ CategoryDescription::query()->insert($descriptions);
+
+ CategoryService::repairCategories();
+ }
+
+ /**
+ * 导入品牌数据
+ */
+ private function importBrands()
+ {
+ Brand::query()->truncate();
+ $this->ocdb->table('manufacturer')
+ ->orderBy('manufacturer_id')
+ ->chunk(self::PER_PAGE, function ($ocBrands) {
+ $bkBrands = [];
+ foreach ($ocBrands as $ocBrand) {
+ $bkBrands[] = [
+ 'id' => $ocBrand->manufacturer_id,
+ 'name' => $ocBrand->name,
+ 'first' => mb_strtoupper(mb_substr($ocBrand->name, 0, 1)),
+ 'logo' => $ocBrand->image,
+ 'sort_order' => $ocBrand->sort_order,
+ 'status' => $ocBrand->status,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ];
+ }
+ Brand::query()->insert($bkBrands);
+ });
+ }
+
+ /**
+ * 导入产品
+ */
+ private function importProducts()
+ {
+ $this->ocProductVariants = $this->ocdb->table('product_variant')->get()->groupBy('product_id');
+ $this->ocVariantDescriptions = $this->ocdb->table('variant_description')->get()->groupBy('variant_id');
+ $this->ocVariantValues = $this->ocdb->table('variant_value')->get()->keyBy('variant_value_id');
+ $this->ocVariantValueDescriptions = $this->ocdb->table('variant_value_description')->get()->groupBy('variant_value_id');
+ $this->ocProductImages = $this->ocdb->table('product_image')->get()->groupBy('product_id');
+ $this->ocProductCategories = $this->ocdb->table('product_to_category')->get()->groupBy('product_id');
+
+ $this->clearData();
+ $this->ocdb->table('product')
+ ->where('parent_id', 0)
+ // ->where('product_id', 1894)
+ // ->where('sku', '10012378')
+ ->orderBy('product_id')
+ ->chunk(self::PER_PAGE, function ($ocProducts) {
+ $this->importProduct($ocProducts);
+ });
+ }
+
+ /**
+ * 导入单个产品
+ * @param Collection $ocProducts
+ */
+ private function importProduct(Collection $ocProducts)
+ {
+ $total = $ocProducts->count();
+ $ocProductIds = $ocProducts->pluck('product_id');
+ $childProducts = $this->ocdb->table('product')->whereIn('parent_id', $ocProductIds)->get()->groupBy('parent_id');
+ foreach ($ocProducts as $index => $ocProduct) {
+ dump("Start handle Page: $this->page - {$index}/{$total}");
+ $ocProductId = $ocProduct->product_id;
+ $productVariants = $this->ocProductVariants[$ocProductId] ?? [];
+ $childProducts = $childProducts[$ocProductId] ?? [];
+ $bkProduct = $this->generateBeikeProduct($ocProduct, $productVariants, $childProducts);
+ (new ProductService)->create($bkProduct);
+ }
+ $this->page++;
+ }
+
+ /**
+ * 构造 beike 产品
+ */
+ private function generateBeikeProduct($ocProduct, $productVariants, $childProducts)
+ {
+ $variables = $this->generateVariables($ocProduct, $childProducts);
+ $bkProduct = [
+ 'active' => $ocProduct->status,
+ 'brand_id' => $ocProduct->manufacturer_id,
+ 'position' => $ocProduct->sort_order,
+ 'tax_class_id' => $ocProduct->tax_class_id,
+ 'variables' => json_encode($variables),
+ ];
+ $bkProduct['descriptions'] = $this->generateDescriptions($ocProduct);
+ $bkProduct['images'] = [$ocProduct->image];
+ $bkProduct['skus'] = $this->generateSkus($ocProduct, $productVariants, $childProducts, $variables);
+ $bkProduct['categories'] = $this->generateCategories($ocProduct);
+
+ return $bkProduct;
+ }
+
+ /**
+ * 生成 beike 产品规格
+ * @return array[]
+ */
+ private function generateVariables($ocProduct, $childProducts): array
+ {
+ $productIds = [$ocProduct->product_id];
+ foreach ($childProducts as $childProduct) {
+ $productIds[] = $childProduct->product_id;
+ }
+
+ $locales = locales();
+ $items = $values = [];
+ foreach ($productIds as $productId) {
+ $productVariants = $this->ocProductVariants[$productId] ?? [];
+ foreach ($productVariants as $productVariant) {
+ $productVariantId = $productVariant->variant_id;
+ $productVariantValueId = $productVariant->variant_value_id;
+
+ $variants = $this->ocVariantDescriptions[$productVariantId];
+ $variantValue = $this->ocVariantValues[$productVariantValueId];
+ $variantValueDescriptions = $this->ocVariantValueDescriptions[$productVariantValueId];
+
+ $variants = $variants->keyBy('language_id');
+ $names = [];
+ foreach ($locales as $locale) {
+ $variant = $variants[self::LANG_MAPPING[$locale['code']]];
+ $names[$locale['code']] = $variant->name;
+ }
+
+ $valueNames = [];
+ $variantValueDescriptions = $variantValueDescriptions->keyBy('language_id');
+ foreach ($locales as $locale) {
+ $variantValueDescription = $variantValueDescriptions[self::LANG_MAPPING[$locale['code']]];
+ $valueNames[$locale['code']] = $variantValueDescription->name;
+ }
+
+ $values[$productVariantValueId] = [
+ 'variant_value_id' => $productVariantValueId,
+ 'name' => $valueNames,
+ 'image' => $variantValue->image,
+ ];
+
+ $items[$productVariantId] = [
+ 'variant_id' => $productVariantId,
+ 'name' => $names,
+ 'values' => $values,
+ 'isImage' => (bool) $variantValue->image,
+ ];
+ }
+ }
+
+ $items = array_values($items);
+ foreach ($items as $index => $item) {
+ $items[$index]['values'] = array_values($item['values']);
+ }
+
+ return $items;
+ }
+
+ /**
+ * 生成 beike 产品描述
+ * @param $ocProduct
+ * @return array
+ */
+ private function generateDescriptions($ocProduct): array
+ {
+ $descriptions = [];
+ $locales = locales();
+ $ocDescriptions = $this->ocdb->table('product_description')
+ ->where('product_id', $ocProduct->product_id)
+ ->get()
+ ->keyBy('language_id')
+ ->toArray();
+
+ foreach ($locales as $locale) {
+ $ocDescription = $ocDescriptions[self::LANG_MAPPING[$locale['code']]];
+ $descriptions[$locale['code']] = [
+ 'name' => $ocDescription->name,
+ 'content' => html_entity_decode($ocDescription->description, ENT_QUOTES),
+ ];
+ }
+
+ return $descriptions;
+ }
+
+ /**
+ * 生成 beike 产品 SKU
+ *
+ * @param $ocProduct
+ * @param $productVariants
+ * @param $childProducts
+ * @param array $variables
+ * @return array
+ */
+ private function generateSkus($ocProduct, $productVariants, $childProducts, array $variables): array
+ {
+ // 简单商品
+ if (count($productVariants) == 0) {
+ return $this->generateSimpleSku($ocProduct);
+ }
+
+ $masterSku = $childSkus = [];
+ // 有主商品
+ if (count($productVariants) > 0) {
+ $masterSku = $this->generateMasterSku($ocProduct, $productVariants, $variables);
+ }
+ // 有子商品
+ if (count($childProducts) > 0) {
+ $childSkus = $this->generateChildSkus($childProducts, $variables);
+ }
+ if ($masterSku) {
+ array_push($childSkus, $masterSku);
+ }
+
+ return $childSkus;
+ }
+
+ /**
+ * 获取简单商品 SKU
+ * @param $ocProduct
+ * @return array[]
+ */
+ private function generateSimpleSku($ocProduct): array
+ {
+ $images = $this->ocProductImages[$ocProduct->product_id] ?? [];
+
+ return [
+ [
+ 'image' => $images,
+ 'model' => $ocProduct->model,
+ 'sku' => $ocProduct->sku,
+ 'price' => $ocProduct->price,
+ 'origin_price' => $ocProduct->price,
+ 'cost_price' => $ocProduct->cost_price,
+ 'quantity' => $ocProduct->quantity,
+ 'variants' => null,
+ 'position' => $ocProduct->sort_order,
+ 'is_default' => 1,
+ ],
+ ];
+ }
+
+ /**
+ * 获取主商品 SKU
+ * @param $ocProduct
+ * @param $productVariants
+ * @param $variables
+ * @return array
+ */
+ private function generateMasterSku($ocProduct, $productVariants, $variables): array
+ {
+ $variants = $this->generateVariants($productVariants, $variables);
+ $images = $this->ocProductImages[$ocProduct->product_id] ?? [];
+
+ return [
+ 'image' => $images,
+ 'model' => $ocProduct->model,
+ 'sku' => $ocProduct->sku,
+ 'price' => $ocProduct->price,
+ 'origin_price' => $ocProduct->price,
+ 'cost_price' => $ocProduct->cost_price,
+ 'quantity' => $ocProduct->quantity,
+ 'variants' => $variants,
+ 'position' => $ocProduct->sort_order,
+ 'is_default' => 1,
+ ];
+ }
+
+ /**
+ * 获取子商品SKU
+ * @param $childProducts
+ * @param $variables
+ * @return array
+ */
+ private function generateChildSkus($childProducts, $variables): array
+ {
+ $items = [];
+ foreach ($childProducts as $ocProduct) {
+ $ocProductId = $ocProduct->product_id;
+ $productVariants = $this->ocProductVariants[$ocProductId] ?? [];
+
+ $images = $this->ocProductImages[$ocProductId] ?? [];
+ $variants = $this->generateVariants($productVariants, $variables);
+ $items[] = [
+ 'image' => $images,
+ 'model' => $ocProduct->model,
+ 'sku' => $ocProduct->sku,
+ 'price' => $ocProduct->price,
+ 'origin_price' => $ocProduct->price,
+ 'cost_price' => $ocProduct->cost_price,
+ 'quantity' => $ocProduct->quantity,
+ 'variants' => $variants,
+ 'position' => $ocProduct->sort_order,
+ 'is_default' => 0,
+ ];
+ }
+
+ return $items;
+ }
+
+ /**
+ * 生成商品 SKU 多规格数据
+ *
+ * @param $productVariants
+ * @param $variables
+ * @return array
+ */
+ private function generateVariants($productVariants, $variables): array
+ {
+ $items = [];
+ foreach ($productVariants as $productVariant) {
+ $variantId = $productVariant->variant_id;
+ $variantValueId = $productVariant->variant_value_id;
+ foreach ($variables as $index1 => $variable) {
+ if ($variantId == $variable['variant_id']) {
+ foreach ($variable['values'] as $index2 => $value) {
+ if ($variantValueId == $value['variant_value_id']) {
+ $items[$index1] = (string) $index2;
+ }
+ }
+ }
+ }
+ }
+
+ return $items;
+ }
+
+ /**
+ * 生成商品分类关联
+ *
+ * @param $ocProduct
+ * @return array
+ */
+ private function generateCategories($ocProduct): array
+ {
+ $ocProductCategories = $this->ocProductCategories[$ocProduct->product_id] ?? [];
+ if ($ocProductCategories) {
+ return $ocProductCategories->pluck('category_id')->toArray();
+ }
+
+ return [];
+ }
+
+ /**
+ * 清空产品相关数据
+ */
+ private function clearData()
+ {
+ Product::query()->truncate();
+ ProductSku::query()->truncate();
+ ProductDescription::query()->truncate();
+ }
+}
diff --git a/beike/Helpers.php b/beike/Helpers.php
new file mode 100644
index 00000000..6fdb9a4d
--- /dev/null
+++ b/beike/Helpers.php
@@ -0,0 +1,720 @@
+ $code, 'path' => $filePath]);
+}
+
+/**
+ * 获取后台管理前缀名称, 默认为 admin
+ */
+function admin_name(): string
+{
+ if ($envAdminName = config('beike.admin_name')) {
+ return Str::snake($envAdminName);
+ } elseif ($settingAdminName = system_setting('base.admin_name')) {
+ return Str::snake($settingAdminName);
+ }
+
+ return 'admin';
+}
+
+/**
+ * 获取后台设置项
+ */
+function load_settings()
+{
+ if (is_installer() || ! file_exists(__DIR__ . '/../storage/installed')) {
+ return;
+ }
+ $result = \Beike\Repositories\SettingRepo::getGroupedSettings();
+ config(['bk' => $result]);
+}
+
+/**
+ * 获取后台链接
+ *
+ * @param $route
+ * @param mixed $params
+ * @return string
+ */
+function admin_route($route, $params = []): string
+{
+ $adminName = admin_name();
+
+ return route("{$adminName}.{$route}", $params);
+}
+
+/**
+ * 获取前台链接
+ *
+ * @param $route
+ * @param mixed $params
+ * @return string
+ */
+function shop_route($route, $params = []): string
+{
+ return route('shop.' . $route, $params);
+}
+
+/**
+ * 获取 category, product, brand, page, static, custom 路由链接
+ *
+ * @param $type
+ * @param $value
+ * @return string
+ * @throws Exception
+ */
+function type_route($type, $value): string
+{
+ return \Beike\Libraries\Url::getInstance()->link($type, $value);
+}
+
+/**
+ * 获取 category, product, brand, page, static, custom 链接名称
+ *
+ * @param $type
+ * @param $value
+ * @param array $texts
+ * @return string
+ */
+function type_label($type, $value, array $texts = []): string
+{
+ return \Beike\Libraries\Url::getInstance()->label($type, $value, $texts);
+}
+
+/**
+ * 处理配置链接
+ *
+ * @param $link
+ * @return array
+ * @throws Exception
+ */
+function handle_link($link): array
+{
+ $type = $link['type'] ?? '';
+ $value = $link['value'] ?? '';
+ $texts = $link['text'] ?? [];
+
+ $link['link'] = type_route($type, $value);
+ $link['text'] = type_label($type, $value, $texts);
+
+ return $link;
+}
+
+/**
+ * 是否访问的后端
+ * @return bool
+ */
+function is_admin(): bool
+{
+ $adminName = admin_name();
+ $uri = request()->getRequestUri();
+ if (Str::startsWith($uri, "/{$adminName}")) {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * 是否访问安装页面
+ * @return bool
+ */
+function is_installer(): bool
+{
+ $uri = request()->getRequestUri();
+
+ return Str::startsWith($uri, '/installer');
+}
+
+/**
+ * 是否为当前访问路由
+ *
+ * @param $routeName
+ * @return bool
+ */
+function equal_route($routeName): bool
+{
+ if (is_array($routeName)) {
+ return in_array(Route::getCurrentRoute()->getName(), $routeName);
+ }
+
+ return $routeName == Route::getCurrentRoute()->getName();
+}
+
+/**
+ * 获取后台当前登录用户
+ *
+ * @return mixed
+ */
+function current_user(): ?AdminUser
+{
+ return auth()->guard(AdminUser::AUTH_GUARD)->user();
+}
+
+/**
+ * 获取前台当前登录客户
+ *
+ * @return mixed
+ */
+function current_customer(): ?Customer
+{
+ return auth()->guard(Customer::AUTH_GUARD)->user();
+}
+
+/**
+ * 获取语言列表
+ *
+ * @return array
+ */
+function locales(): array
+{
+ $locales = LanguageRepo::enabled()->toArray();
+
+ return array_map(function ($item) {
+ return [
+ 'name' => $item['name'],
+ 'code' => $item['code'],
+ ];
+ }, $locales);
+}
+
+/**
+ * 获取当前语言
+ *
+ * @return string
+ */
+function locale(): string
+{
+ if (is_admin()) {
+ $locales = collect(locales())->pluck('code');
+ $userLocale = current_user()->locale;
+
+ return ($locales->contains($userLocale)) ? $userLocale : 'en';
+ }
+
+ return Session::get('locale') ?? system_setting('base.locale');
+}
+
+/**
+ * 获取后台当前语言
+ *
+ * @return string
+ */
+function admin_locale(): string
+{
+ if (is_admin()) {
+ return current_user()->locale;
+ }
+
+ return locale();
+}
+
+/**
+ * 货币格式化
+ *
+ * @param $price
+ * @param string $currency
+ * @param string $value
+ * @param bool $format
+ * @return string
+ */
+function currency_format($price, string $currency = '', string $value = '', bool $format = true): string
+{
+ if (! $currency) {
+ $currency = is_admin() ? system_setting('base.currency') : current_currency_code();
+ }
+
+ return CurrencyService::getInstance()->format($price, $currency, $value, $format);
+}
+
+/**
+ * 获取指定货币汇率
+ *
+ * @return string
+ */
+function current_currency_rate(): float
+{
+ $currency = current_currency_code();
+
+ return Currency::query()->where('code', $currency)->value('value') ?? 1;
+}
+
+/**
+ * 时间格式化
+ *
+ * @param null $datetime
+ * @return false|string
+ */
+function time_format($datetime = null)
+{
+ $format = 'Y-m-d H:i:s';
+ if ($datetime instanceof Illuminate\Support\Carbon) {
+ return $datetime->format($format);
+ } elseif (is_int($datetime)) {
+ return date($format, $datetime);
+ }
+
+ return date($format);
+}
+
+/**
+ * 获取插件根目录
+ *
+ * @param string $path
+ * @return string
+ */
+function plugin_path(string $path = ''): string
+{
+ return base_path('plugins') . ($path ? DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR) : $path);
+}
+
+/**
+ * @param $code
+ * @return Plugin|null
+ */
+function plugin($code): ?Plugin
+{
+ return app('plugin')->getPlugin($code);
+}
+
+/**
+ * 插件图片缩放
+ *
+ * @param $pluginCode
+ * @param $image
+ * @param int $width
+ * @param int $height
+ * @return mixed|void
+ * @throws Exception
+ */
+function plugin_resize($pluginCode, $image, int $width = 100, int $height = 100)
+{
+ if (Str::startsWith($image, 'http')) {
+ return $image;
+ }
+
+ $plugin = plugin($pluginCode);
+ $pluginDirName = $plugin->getDirname();
+
+ return (new \Beike\Services\ImageService($image))->setPluginDirName($pluginDirName)->resize($width, $height);
+}
+
+/**
+ * Get origin image from plugin
+ *
+ * @param $pluginCode
+ * @param $image
+ * @return mixed|void
+ * @throws Exception
+ */
+function plugin_origin($pluginCode, $image)
+{
+ if (Str::startsWith($image, 'http')) {
+ return $image;
+ }
+
+ $plugin = plugin($pluginCode);
+ $pluginDirName = $plugin->getDirname();
+
+ return (new \Beike\Services\ImageService($image))->setPluginDirName($pluginDirName)->originUrl();
+}
+
+/**
+ * 图片缩放
+ *
+ * @param $image
+ * @param int $width
+ * @param int $height
+ * @return mixed|void
+ * @throws Exception
+ */
+function image_resize($image, int $width = 100, int $height = 100)
+{
+ if (Str::startsWith($image, 'http')) {
+ return $image;
+ }
+
+ return (new \Beike\Services\ImageService($image))->resize($width, $height);
+}
+
+/**
+ * 获取原图地址
+ * @throws Exception
+ */
+function image_origin($image)
+{
+ if (Str::startsWith($image, 'http')) {
+ return $image;
+ }
+
+ return (new \Beike\Services\ImageService($image))->originUrl();
+}
+
+/**
+ * 获取后台开启的所有语言
+ *
+ * @return Collection
+ */
+function languages(): Collection
+{
+ return LanguageRepo::enabled()->pluck('code');
+}
+
+/**
+ * 当前语言名称
+ *
+ * @return string
+ */
+function current_language()
+{
+ $code = locale();
+
+ return Language::query()->where('code', $code)->first();
+}
+
+/**
+ * 获取后台所有语言包列表
+ *
+ * @return array
+ */
+function admin_languages(): array
+{
+ $packages = language_packages();
+ $adminLanguages = collect($packages)->filter(function ($package) {
+ return file_exists(resource_path("lang/{$package}/admin"));
+ })->toArray();
+
+ return array_values($adminLanguages);
+}
+
+/**
+ * 获取语言包列表
+ * @return array
+ */
+function language_packages(): array
+{
+ $languageDir = resource_path('lang');
+
+ return array_values(array_diff(scandir($languageDir), ['..', '.']));
+}
+
+/**
+ * @return Builder[]|\Illuminate\Database\Eloquent\Collection
+ */
+function currencies()
+{
+ return CurrencyRepo::listEnabled();
+}
+
+/**
+ * 获取当前货币
+ *
+ * @return string
+ */
+function current_currency_code(): string
+{
+ return Session::get('currency') ?? system_setting('base.currency');
+}
+
+/**
+ * 获取当前货币
+ *
+ * @return string
+ */
+function current_currency_id(): string
+{
+ $currencyCode = current_currency_code();
+ $currency = \Beike\Models\Currency::query()->where('code', $currencyCode)->first();
+
+ return $currency->id ?? 0;
+}
+
+/**
+ * 数量格式化, 用于商品、订单统计
+ *
+ * @param $quantity
+ * @return mixed|string
+ */
+function quantity_format($quantity)
+{
+ if ($quantity > 1000000000000) {
+ return round($quantity / 1000000000000, 1) . 'T';
+ } elseif ($quantity > 1000000000) {
+ return round($quantity / 1000000000, 1) . 'B';
+ } elseif ($quantity > 1000000) {
+ return round($quantity / 1000000, 1) . 'M';
+ } elseif ($quantity > 1000) {
+ return round($quantity / 1000, 1) . 'K';
+ }
+
+ return $quantity;
+
+}
+
+/**
+ * 返回json序列化结果
+ */
+function json_success($message, $data = []): array
+{
+ return [
+ 'status' => 'success',
+ 'message' => $message,
+ 'data' => $data,
+ ];
+}
+
+/**
+ * 返回json序列化结果
+ */
+function json_fail($message, $data = []): array
+{
+ return [
+ 'status' => 'fail',
+ 'message' => $message,
+ 'data' => $data,
+ ];
+}
+
+if (! function_exists('sub_string')) {
+ /**
+ * @param $string
+ * @param int $length
+ * @param string $dot
+ * @return string
+ */
+ function sub_string($string, int $length = 16, string $dot = '...'): string
+ {
+ $strLength = mb_strlen($string);
+ if ($length <= 0) {
+ return $string;
+ } elseif ($strLength <= $length) {
+ return $string;
+ }
+
+ return mb_substr($string, 0, $length) . $dot;
+ }
+}
+
+/**
+ * 根据 $builder 对象输出SQL语句
+ * @param mixed $builder
+ * @return string|string[]|null
+ */
+function to_sql($builder): array|string|null
+{
+ $sql = $builder->toSql();
+ foreach ($builder->getBindings() as $binding) {
+ $value = is_numeric($binding) ? $binding : "'" . $binding . "'";
+ $sql = preg_replace('/\?/', $value, $sql, 1);
+ }
+
+ return $sql;
+}
+
+/**
+ * 递归创建文件夹
+ * @param $directoryPath
+ */
+function create_directories($directoryPath)
+{
+ $path = '';
+ $directories = explode('/', $directoryPath);
+ foreach ($directories as $directory) {
+ $path = $path . '/' . $directory;
+ if (! is_dir(public_path($path))) {
+ @mkdir(public_path($path), 0755);
+ }
+ }
+}
+
+/**
+ * 是否安装 debugbar
+ *
+ * @return bool
+ */
+function has_debugbar(): bool
+{
+ return class_exists(\Barryvdh\Debugbar\Facades\Debugbar::class);
+}
+
+/**
+ * PHP 代码 hook filter 埋点
+ *
+ * @param $hookKey
+ * @param $hookValue
+ * @return mixed
+ */
+function hook_filter($hookKey, $hookValue): mixed
+{
+ if (config('app.debug') && has_debugbar()) {
+ Debugbar::log('HOOK === hook_filter: ' . $hookKey);
+ }
+
+ return Eventy::filter($hookKey, $hookValue);
+}
+
+/**
+ * PHP 代码 hook action 埋点
+ *
+ * @param $hookKey
+ * @param $hookValue
+ */
+function hook_action($hookKey, $hookValue)
+{
+ if (config('app.debug') && has_debugbar()) {
+ Debugbar::log('HOOK === hook_action: ' . $hookKey);
+ }
+ Eventy::action($hookKey, $hookValue);
+}
+
+/**
+ * 添加 Filter, 执行 PHP 逻辑
+ *
+ * @param $hookKey
+ * @param $callback
+ * @param int $priority
+ * @param int $arguments
+ * @return mixed
+ */
+function add_hook_filter($hookKey, $callback, int $priority = 20, int $arguments = 1): mixed
+{
+ return Eventy::addFilter($hookKey, $callback, $priority, $arguments);
+}
+
+/**
+ * 添加 Action, 执行 PHP 逻辑
+ *
+ * @param $hookKey
+ * @param $callback
+ * @param int $priority
+ * @param int $arguments
+ */
+function add_hook_action($hookKey, $callback, int $priority = 20, int $arguments = 1)
+{
+ Eventy::addAction($hookKey, $callback, $priority, $arguments);
+}
+
+/**
+ * 采用 Hook 修改 Blade 代码
+ *
+ * @param $hookKey
+ * @param $callback
+ * @param int $priority
+ */
+function add_hook_blade($hookKey, $callback, int $priority = 0)
+{
+ Hook::listen($hookKey, $callback, $priority);
+}
+
+/**
+ * 检测系统是否已安装
+ *
+ * @return bool
+ */
+function installed(): bool
+{
+ return file_exists(storage_path('installed'));
+}
+
+/**
+ * 是否为移动端访问
+ *
+ * @return bool
+ */
+function is_mobile(): bool
+{
+ return (new \Jenssegers\Agent\Agent())->isMobile();
+}
+
+/**
+ * 当前访问协议是否为 https
+ *
+ * @return bool
+ */
+function is_secure(): bool
+{
+ if (! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
+ return true;
+ } elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https') {
+ return true;
+ } elseif (! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') {
+ return true;
+ } elseif (isset($_SERVER['SERVER_PORT']) && intval($_SERVER['SERVER_PORT']) === 443) {
+ return true;
+ } elseif (isset($_SERVER['REQUEST_SCHEME']) && strtolower($_SERVER['REQUEST_SCHEME']) === 'https') {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * 每页商品显示数量
+ *
+ * @return int
+ */
+function perPage(): int
+{
+ return (int) system_setting('base.product_per_page', 20);
+}
diff --git a/beike/Hook/Callback.php b/beike/Hook/Callback.php
new file mode 100644
index 00000000..693e022b
--- /dev/null
+++ b/beike/Hook/Callback.php
@@ -0,0 +1,37 @@
+setCallback($function, $parameters);
+ }
+
+ public function setCallback($function, $parameters)
+ {
+ $this->function = $function;
+ $this->parameters = $parameters;
+ }
+
+ public function call($parameters = null)
+ {
+ if ($this->run) {
+ $this->run = false;
+
+ return call_user_func_array($this->function, ($parameters ?: $this->parameters));
+ }
+ }
+
+ public function reset()
+ {
+ $this->run = true;
+ }
+}
diff --git a/beike/Hook/Console/HookListeners.php b/beike/Hook/Console/HookListeners.php
new file mode 100644
index 00000000..3535f4e7
--- /dev/null
+++ b/beike/Hook/Console/HookListeners.php
@@ -0,0 +1,48 @@
+ $lister) {
+ foreach ($lister as $key => $element) {
+ $array[] = [
+ $key,
+ $hook,
+ $element['caller']['class'],
+ ];
+ }
+ }
+
+ $headers = ['Sort', 'Hook name', 'Listener class'];
+
+ $this->table($headers, $array);
+ }
+}
diff --git a/beike/Hook/Facades/Hook.php b/beike/Hook/Facades/Hook.php
new file mode 100644
index 00000000..1bc22cf9
--- /dev/null
+++ b/beike/Hook/Facades/Hook.php
@@ -0,0 +1,13 @@
+createCallbackObject($callback, $params);
+
+ $output = $this->returnMockIfDebugModeAndMockExists($hook);
+ if ($output) {
+ return $output;
+ }
+
+ $output = $this->run($hook, $params, $callbackObject, $htmlContent);
+
+ if (! $output) {
+ $output = $callbackObject->call();
+ }
+
+ unset($callbackObject);
+
+ return $output;
+ }
+
+ /**
+ * @param string $hook
+ * @param array $params
+ * @param callable|null $callback
+ * @param string $htmlContent
+ * @return string|void|null
+ */
+ public function getHook(string $hook, array $params = [], callable $callback = null, string $htmlContent = '')
+ {
+ if (config('app.debug') && has_debugbar()) {
+ Debugbar::log("HOOK === @hook: {$hook}");
+ }
+
+ return $this->get($hook, $params, $callback, $htmlContent);
+ }
+
+
+ /**
+ * @param string $hook
+ * @param array $params
+ * @param callable|null $callback
+ * @param string $htmlContent
+ * @return string|void|null
+ */
+ public function getWrapper(string $hook, array $params = [], callable $callback = null, string $htmlContent = '')
+ {
+ if (config('app.debug') && has_debugbar()) {
+ Debugbar::log("HOOK === @hookwrapper: {$hook}");
+ }
+
+ return $this->get($hook, $params, $callback, $htmlContent);
+ }
+
+ /**
+ * Stop all another hook running.
+ *
+ * @param string $hook Hook name
+ */
+ public function stop(string $hook)
+ {
+ $this->stop[$hook] = true;
+ }
+
+ /**
+ * Subscribe to hook.
+ *
+ * @param string $hook Hook name
+ * @param $priority
+ * @param $function
+ */
+ public function listen(string $hook, $function, $priority = null)
+ {
+ $caller = debug_backtrace(null, 3)[2];
+
+ if (in_array(Arr::get($caller, 'function'), ['include', 'require'])) {
+ $caller = debug_backtrace(null, 4)[3];
+ }
+
+ if (empty($this->watch[$hook])) {
+ $this->watch[$hook] = [];
+ }
+
+ if (! is_numeric($priority)) {
+ $priority = null;
+ }
+
+ $this->watch[$hook][$priority] = [
+ 'function' => $function,
+ 'caller' => [
+ //'file' => $caller['file'],
+ //'line' => $caller['line'],
+ 'class' => Arr::get($caller, 'class'),
+ ],
+ ];
+
+ ksort($this->watch[$hook]);
+ }
+
+ /**
+ * Return all registered hooks.
+ *
+ * @return array
+ */
+ public function getHooks(): array
+ {
+ $hookNames = (array_keys($this->watch));
+ ksort($hookNames);
+
+ return $hookNames;
+ }
+
+ /**
+ * Return all listeners for hook.
+ *
+ * @param string $hook
+ *
+ * @return array
+ */
+ public function getEvents(string $hook): array
+ {
+ $output = [];
+
+ foreach ($this->watch[$hook] as $key => $value) {
+ $output[$key] = $value['caller'];
+ }
+
+ return $output;
+ }
+
+ /**
+ * For testing.
+ *
+ * @param string $name Hook name
+ * @param mixed $return Answer
+ */
+ public function mock(string $name, mixed $return)
+ {
+ $this->testing = true;
+ $this->mock[$name] = ['return' => $return];
+ }
+
+ /**
+ * Return the mock value.
+ *
+ * @param string $hook Hook name
+ */
+ protected function returnMockIfDebugModeAndMockExists(string $hook)
+ {
+ if ($this->testing) {
+ if (array_key_exists($hook, $this->mock)) {
+ $output = $this->mock[$hook]['return'];
+ unset($this->mock[$hook]);
+
+ return $output;
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * Return a new callback object.
+ *
+ * @param callable $callback function
+ * @param array $params parameters
+ *
+ * @return Callback
+ */
+ protected function createCallbackObject(callable $callback, array $params): Callback
+ {
+ return new Callback($callback, $params);
+ }
+
+ /**
+ * Run hook events.
+ *
+ * @param string $hook Hook name
+ * @param array $params Parameters
+ * @param Callback $callback Callback object
+ * @param string|null $output html wrapped by hook
+ *
+ * @return mixed
+ */
+ protected function run(string $hook, array $params, Callback $callback, string $output = null): mixed
+ {
+ array_unshift($params, $output);
+ array_unshift($params, $callback);
+
+ if (array_key_exists($hook, $this->watch)) {
+ if (is_array($this->watch[$hook])) {
+ foreach ($this->watch[$hook] as $function) {
+ if (! empty($this->stop[$hook])) {
+ unset($this->stop[$hook]);
+
+ break;
+ }
+
+ $output = call_user_func_array($function['function'], $params);
+ $params[1] = $output;
+ }
+ }
+ }
+
+ return $output;
+ }
+
+ /**
+ * Return the listeners.
+ *
+ * @return array
+ */
+ public function getListeners(): array
+ {
+ return $this->watch;
+ }
+}
diff --git a/beike/Hook/HookServiceProvider.php b/beike/Hook/HookServiceProvider.php
new file mode 100644
index 00000000..9c7297cf
--- /dev/null
+++ b/beike/Hook/HookServiceProvider.php
@@ -0,0 +1,89 @@
+commands([
+ HookListeners::class,
+ ]);
+
+ $this->app->singleton('Hook', function () {
+ return new Hook();
+ });
+ }
+
+
+ public function boot()
+ {
+ $this->bootHookDirectives();
+ $this->bootWrapperHookDirectives();
+ }
+
+ /**
+ * 添加 blade hook 标签, 不需要 @endhook
+ * @hook('xxx'), 添加 hook 直接输出到页面
+ */
+ protected function bootHookDirectives()
+ {
+ Blade::directive('hook', function ($parameter) {
+ $parameter = trim($parameter, '()');
+ $parameters = explode(',', $parameter);
+
+ $name = trim($parameters[0], "'");
+
+ return ' $__definedVars],function($data) { return null; });
+ if ($output)
+ echo $output;
+ ?>';
+ });
+ }
+
+
+ /**
+ * 添加 blade wrapper hook 标签
+ *
+ * @hookwrapper('xxx') --- @endhookwrapper, 将某段代码打包输出再添加 hook 输出
+ */
+ protected function bootWrapperHookDirectives()
+ {
+ Blade::directive('hookwrapper', function ($parameter) {
+ $parameter = trim($parameter, '()');
+ $parameters = explode(',', $parameter);
+ $name = trim($parameters[0], "'");
+
+ return ' ';
+ });
+
+ Blade::directive('endhookwrapper', function () {
+ return ' $__definedVars],function($data) { return null; },$__hook_content);
+ unset($__hook_name);
+ unset($__hook_content);
+ if ($output)
+ echo $output;
+ ?>';
+ });
+ }
+}
diff --git a/beike/Installer/Controllers/DatabaseController.php b/beike/Installer/Controllers/DatabaseController.php
new file mode 100644
index 00000000..0b1a2422
--- /dev/null
+++ b/beike/Installer/Controllers/DatabaseController.php
@@ -0,0 +1,68 @@
+databaseManager = $databaseManager;
+ }
+
+ /**
+ * Migrate and seed the database.
+ *
+ * @return RedirectResponse
+ */
+ public function index()
+ {
+ DB::statement('SET FOREIGN_KEY_CHECKS = 0');
+ $rows = DB::select('SHOW TABLES');
+ $database = config('database.connections.mysql.database');
+ $tables = array_column($rows, 'Tables_in_' . $database);
+ foreach ($tables as $table) {
+ Schema::drop($table);
+ }
+ DB::statement('SET FOREIGN_KEY_CHECKS = 1');
+
+ $params = request()->all();
+
+ try {
+ $response = $this->databaseManager->migrateAndSeed();
+ $status = $response['status'] ?? '';
+ $message = $response['message'] ?? '';
+ if ($status == 'error' && $message) {
+ return redirect()->route('installer.environment')->withInput($params)->withErrors(['error' => $message]);
+ }
+ } catch (\Exception $e) {
+ return redirect()->route('installer.environment')->withInput($params)->withErrors(['error' => $e->getMessage()]);
+ }
+
+ $email = request('admin_email');
+ $data = [
+ 'name' => substr($email, 0, strpos($email, '@')),
+ 'email' => $email,
+ 'password' => request('admin_password'),
+ 'locale' => session('locale') ?? 'zh_cn',
+ 'active' => true,
+ ];
+ AdminUserRepo::createAdminUser($data);
+
+ return redirect()->route('installer.final', request()->only('admin_email', 'admin_password'))->with(['message' => $response]);
+ }
+}
diff --git a/beike/Installer/Controllers/EnvironmentController.php b/beike/Installer/Controllers/EnvironmentController.php
new file mode 100644
index 00000000..c96f6192
--- /dev/null
+++ b/beike/Installer/Controllers/EnvironmentController.php
@@ -0,0 +1,175 @@
+EnvironmentManager = $environmentManager;
+ }
+
+ /**
+ * Display the Environment page.
+ *
+ * @return \Illuminate\View\View
+ */
+ public function index()
+ {
+ $steps = 4;
+
+ return view('installer::environment-wizard', compact('steps'));
+ }
+
+ /**
+ * Processes the newly saved environment configuration (Form Wizard).
+ *
+ * @param Request $request
+ * @param Redirector $redirect
+ * @return RedirectResponse
+ */
+ public function saveWizard(Request $request, Redirector $redirect): RedirectResponse
+ {
+ $rules = config('installer.environment.form.rules');
+ $messages = [
+ 'environment_custom.required_if' => trans('installer::installer_messages.environment.name_required'),
+ ];
+
+ $validator = Validator::make($request->all(), $rules, $messages);
+
+ if ($validator->fails()) {
+ return $redirect->route('installer.environment')->withInput()->withErrors($validator->errors());
+ }
+
+ if ($this->checkDatabaseConnection($request) !== true) {
+ return $redirect->route('installer.environment')->withInput()->withErrors([
+ 'database_connection' => trans('installer::installer_messages.environment.db_connection_failed'),
+ ]);
+ }
+
+ $this->EnvironmentManager->saveFileWizard($request);
+
+ $params = $request->all();
+
+ return redirect(route('installer.database', $params));
+ }
+
+ /**
+ * 数据库信息检测
+ *
+ * @param Request $request
+ * @return array
+ */
+ public function validateDatabase(Request $request): array
+ {
+ $rules = config('installer.environment.form.rules');
+ $messages = [
+ 'environment_custom.required_if' => trans('installer::installer_messages.environment.name_required'),
+ ];
+
+ unset($rules['admin_email'], $rules['admin_password']);
+
+ $validator = Validator::make($request->all(), $rules, $messages);
+
+ if ($validator->fails()) {
+ return json_fail('', $validator->errors());
+ }
+
+ $dbValidateResult = $this->checkDatabaseConnection($request);
+ if ($dbValidateResult !== true) {
+ return json_fail('', $dbValidateResult);
+ }
+
+ return json_success('');
+ }
+
+ /**
+ * TODO: We can remove this code if PR will be merged: https://github.com/RachidLaasri/LaravelInstaller/pull/162
+ * Validate database connection with user credentials (Form Wizard).
+ *
+ * @param Request $request
+ * @return array|bool
+ */
+ private function checkDatabaseConnection(Request $request): bool|array
+ {
+ $connection = $request->input('database_connection');
+
+ $settings = config("database.connections.$connection");
+
+ config([
+ 'database' => [
+ 'default' => $connection,
+ 'connections' => [
+ $connection => array_merge($settings, [
+ 'driver' => $connection,
+ 'host' => $request->input('database_hostname'),
+ 'port' => $request->input('database_port'),
+ 'database' => $request->input('database_name'),
+ 'username' => $request->input('database_username'),
+ 'password' => $request->input('database_password'),
+ 'options' => [
+ \PDO::ATTR_TIMEOUT => 1,
+ ],
+ ]),
+ ],
+ ],
+ ]);
+
+ DB::purge();
+
+ $result = [];
+
+ try {
+ $pdo = DB::connection()->getPdo();
+ $serverVersion = $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION);
+ if (version_compare($serverVersion, '5.7', '<')) {
+ $result['database_version'] = trans('installer::installer_messages.environment.db_connection_failed_invalid_version');
+
+ return $result;
+ }
+
+ return true;
+ } catch (\PDOException $e) {
+ switch ($e->getCode()) {
+ case 1115:
+ $result['database_version'] = trans('installer::installer_messages.environment.db_connection_failed_invalid_version');
+
+ break;
+ case 2002:
+ $result['database_hostname'] = trans('installer::installer_messages.environment.db_connection_failed_host_port');
+ $result['database_port'] = trans('installer::installer_messages.environment.db_connection_failed_host_port');
+
+ break;
+ case 1045:
+ $result['database_username'] = trans('installer::installer_messages.environment.db_connection_failed_user_password');
+ $result['database_password'] = trans('installer::installer_messages.environment.db_connection_failed_user_password');
+
+ break;
+ case 1049:
+ $result['database_name'] = trans('installer::installer_messages.environment.db_connection_failed_database_name');
+
+ break;
+ default:
+ $result['database_other'] = $e->getMessage();
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/beike/Installer/Controllers/FinalController.php b/beike/Installer/Controllers/FinalController.php
new file mode 100644
index 00000000..4fb40035
--- /dev/null
+++ b/beike/Installer/Controllers/FinalController.php
@@ -0,0 +1,34 @@
+runFinal();
+ $finalStatusMessage = $fileManager->update();
+ $finalEnvFile = $environment->getEnvContent();
+
+ $steps = 5;
+
+ $data = compact('finalMessages', 'finalStatusMessage', 'finalEnvFile', 'steps');
+ $data['admin_email'] = request('admin_email');
+ $data['admin_password'] = request('admin_password');
+
+ return view('installer::finished', $data);
+ }
+}
diff --git a/beike/Installer/Controllers/PermissionsController.php b/beike/Installer/Controllers/PermissionsController.php
new file mode 100644
index 00000000..2e6769fc
--- /dev/null
+++ b/beike/Installer/Controllers/PermissionsController.php
@@ -0,0 +1,38 @@
+permissions = $checker;
+ }
+
+ /**
+ * Display the permissions check page.
+ *
+ * @return \Illuminate\View\View
+ */
+ public function index()
+ {
+ $permissions = $this->permissions->check(
+ config('installer.permissions')
+ );
+
+ $steps = 3;
+
+ return view('installer::permissions', compact('permissions', 'steps'));
+ }
+}
diff --git a/beike/Installer/Controllers/RequirementsController.php b/beike/Installer/Controllers/RequirementsController.php
new file mode 100644
index 00000000..36a61397
--- /dev/null
+++ b/beike/Installer/Controllers/RequirementsController.php
@@ -0,0 +1,41 @@
+requirements = $checker;
+ }
+
+ /**
+ * Display the requirements page.
+ *
+ * @return \Illuminate\View\View
+ */
+ public function index()
+ {
+ $phpSupportInfo = $this->requirements->checkPHPversion(
+ config('installer.core.minPhpVersion')
+ );
+ $requirements = $this->requirements->check(
+ config('installer.requirements')
+ );
+
+ $steps = 2;
+
+ return view('installer::requirements', compact('requirements', 'phpSupportInfo', 'steps'));
+ }
+}
diff --git a/beike/Installer/Controllers/WelcomeController.php b/beike/Installer/Controllers/WelcomeController.php
new file mode 100644
index 00000000..34fa95f3
--- /dev/null
+++ b/beike/Installer/Controllers/WelcomeController.php
@@ -0,0 +1,43 @@
+
+ * @created 2022-08-12 20:17:04
+ * @modified 2022-08-12 20:17:04
+ */
+
+namespace Beike\Installer\Controllers;
+
+use App\Http\Controllers\Controller;
+use Illuminate\Support\Facades\Redirect;
+
+class WelcomeController extends Controller
+{
+ private $languages = [
+ 'zh_cn' => '简体中文',
+ 'en' => 'English',
+ ];
+
+ public function index()
+ {
+ if (installed()) {
+ exit('Already installed');
+ }
+
+ $data['languages'] = $this->languages;
+ $data['locale'] = $_COOKIE['locale'] ?? 'zh_cn';
+ $data['steps'] = 1;
+
+ return view('installer::welcome', $data);
+ }
+
+ public function locale($lang)
+ {
+ setcookie('locale', $lang, 0, '/');
+
+ return Redirect::back();
+ }
+}
diff --git a/beike/Installer/Helpers/DatabaseManager.php b/beike/Installer/Helpers/DatabaseManager.php
new file mode 100644
index 00000000..7c20f2db
--- /dev/null
+++ b/beike/Installer/Helpers/DatabaseManager.php
@@ -0,0 +1,95 @@
+sqlite($outputLog);
+
+ return $this->migrate($outputLog);
+ }
+
+ /**
+ * Run the migration and call the seeder.
+ *
+ * @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
+ * @return array
+ */
+ private function migrate(BufferedOutput $outputLog)
+ {
+ try {
+ Artisan::call('migrate', ['--force' => true], $outputLog);
+ } catch (Exception $e) {
+ return $this->response($e->getMessage(), 'error', $outputLog);
+ }
+
+ return $this->seed($outputLog);
+ }
+
+ /**
+ * Seed the database.
+ *
+ * @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
+ * @return array
+ */
+ private function seed(BufferedOutput $outputLog)
+ {
+ try {
+ Artisan::call('db:seed', ['--force' => true], $outputLog);
+ } catch (Exception $e) {
+ return $this->response($e->getMessage(), 'error', $outputLog);
+ }
+
+ return $this->response(trans('installer::installer_messages.final.finished'), 'success', $outputLog);
+ }
+
+ /**
+ * Return a formatted error messages.
+ *
+ * @param string $message
+ * @param string $status
+ * @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
+ * @return array
+ */
+ private function response($message, $status, BufferedOutput $outputLog)
+ {
+ return [
+ 'status' => $status,
+ 'message' => $message,
+ 'dbOutputLog' => $outputLog->fetch(),
+ ];
+ }
+
+ /**
+ * Check database type. If SQLite, then create the database file.
+ *
+ * @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
+ */
+ private function sqlite(BufferedOutput $outputLog)
+ {
+ if (DB::connection() instanceof SQLiteConnection) {
+ $database = DB::connection()->getDatabaseName();
+ if (! file_exists($database)) {
+ touch($database);
+ DB::reconnect(Config::get('database.default'));
+ }
+ $outputLog->write('Using SqlLite database: ' . $database, 1);
+ }
+ }
+}
diff --git a/beike/Installer/Helpers/EnvironmentManager.php b/beike/Installer/Helpers/EnvironmentManager.php
new file mode 100644
index 00000000..d3405859
--- /dev/null
+++ b/beike/Installer/Helpers/EnvironmentManager.php
@@ -0,0 +1,133 @@
+envPath = base_path('.env');
+ $this->envExamplePath = base_path('.env.example');
+ }
+
+ /**
+ * Get the content of the .env file.
+ *
+ * @return string
+ */
+ public function getEnvContent()
+ {
+ if (! file_exists($this->envPath)) {
+ if (file_exists($this->envExamplePath)) {
+ copy($this->envExamplePath, $this->envPath);
+ } else {
+ touch($this->envPath);
+ }
+ }
+
+ return file_get_contents($this->envPath);
+ }
+
+ /**
+ * Get the the .env file path.
+ *
+ * @return string
+ */
+ public function getEnvPath()
+ {
+ return $this->envPath;
+ }
+
+ /**
+ * Get the the .env.example file path.
+ *
+ * @return string
+ */
+ public function getEnvExamplePath()
+ {
+ return $this->envExamplePath;
+ }
+
+ /**
+ * Save the edited content to the .env file.
+ *
+ * @param Request $input
+ * @return string
+ */
+ public function saveFileClassic(Request $input)
+ {
+ $message = trans('installer::installer_messages.environment.success');
+
+ try {
+ file_put_contents($this->envPath, $input->get('envConfig'));
+ } catch (Exception $e) {
+ $message = trans('installer::installer_messages.environment.errors');
+ }
+
+ return $message;
+ }
+
+ /**
+ * Save the form content to the .env file.
+ *
+ * @param Request $request
+ * @return string
+ */
+ public function saveFileWizard(Request $request)
+ {
+ $results = trans('installer::installer_messages.environment.success');
+
+ $scheme = is_secure() ? 'https' : 'http';
+ $appUrl = $scheme . '://' . $_SERVER['HTTP_HOST'];
+
+ $envFileData =
+ 'APP_NAME=\'' . ($request->app_name ?: 'BeikeShop') . "'\n" .
+ 'APP_ENV=' . $request->environment . "\n" .
+ 'APP_KEY=' . 'base64:' . base64_encode(Str::random(32)) . "\n" .
+ 'APP_DEBUG=false' . "\n" .
+ 'APP_LOG_LEVEL=' . $request->app_log_level . "\n" .
+ 'APP_URL=' . $appUrl . "\n\n" .
+ 'BEIKE_API_URL=https://beikeshop.com' . "\n\n" .
+ 'DB_CONNECTION=' . $request->database_connection . "\n" .
+ 'DB_HOST=' . $request->database_hostname . "\n" .
+ 'DB_PORT=' . $request->database_port . "\n" .
+ 'DB_DATABASE=' . $request->database_name . "\n" .
+ 'DB_USERNAME=' . $request->database_username . "\n" .
+ 'DB_PASSWORD=\'' . $request->database_password . "'\n\n" .
+ 'BROADCAST_DRIVER=log' . "\n" .
+ 'CACHE_DRIVER=file' . "\n" .
+ 'SESSION_DRIVER=file' . "\n" .
+ 'QUEUE_CONNECTION=sync' . "\n\n" .
+ 'MAIL_DRIVER=' . $request->mail_driver . "\n" .
+ 'MAIL_HOST=' . $request->mail_host . "\n" .
+ 'MAIL_PORT=' . $request->mail_port . "\n" .
+ 'MAIL_USERNAME=' . $request->mail_username . "\n" .
+ 'MAIL_PASSWORD=' . $request->mail_password . "\n" .
+ 'MAIL_ENCRYPTION=' . $request->mail_encryption . "\n\n";
+
+ try {
+ file_put_contents($this->envPath, $envFileData);
+ } catch (Exception $e) {
+ $results = trans('installer::installer_messages.environment.errors');
+ }
+
+ return $results;
+ }
+}
diff --git a/beike/Installer/Helpers/FinalInstallManager.php b/beike/Installer/Helpers/FinalInstallManager.php
new file mode 100644
index 00000000..ffcf4716
--- /dev/null
+++ b/beike/Installer/Helpers/FinalInstallManager.php
@@ -0,0 +1,79 @@
+generateKey($outputLog);
+ $this->publishVendorAssets($outputLog);
+
+ return $outputLog->fetch();
+ }
+
+ /**
+ * Generate New Application Key.
+ *
+ * @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
+ * @return \Symfony\Component\Console\Output\BufferedOutput|array
+ */
+ private static function generateKey(BufferedOutput $outputLog)
+ {
+ try {
+ if (config('installer.final.key')) {
+ Artisan::call('key:generate', ['--force' => true], $outputLog);
+ }
+ } catch (Exception $e) {
+ return static::response($e->getMessage(), $outputLog);
+ }
+
+ return $outputLog;
+ }
+
+ /**
+ * Publish vendor assets.
+ *
+ * @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
+ * @return \Symfony\Component\Console\Output\BufferedOutput|array
+ */
+ private static function publishVendorAssets(BufferedOutput $outputLog)
+ {
+ try {
+ if (config('installer.final.publish')) {
+ Artisan::call('vendor:publish', ['--all' => true], $outputLog);
+ }
+ } catch (Exception $e) {
+ return static::response($e->getMessage(), $outputLog);
+ }
+
+ return $outputLog;
+ }
+
+ /**
+ * Return a formatted error messages.
+ *
+ * @param $message
+ * @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
+ * @return array
+ */
+ private static function response($message, BufferedOutput $outputLog)
+ {
+ return [
+ 'status' => 'error',
+ 'message' => $message,
+ 'dbOutputLog' => $outputLog->fetch(),
+ ];
+ }
+}
diff --git a/beike/Installer/Helpers/InstalledFileManager.php b/beike/Installer/Helpers/InstalledFileManager.php
new file mode 100644
index 00000000..68795d8c
--- /dev/null
+++ b/beike/Installer/Helpers/InstalledFileManager.php
@@ -0,0 +1,40 @@
+create();
+ }
+}
diff --git a/beike/Installer/Helpers/MigrationsHelper.php b/beike/Installer/Helpers/MigrationsHelper.php
new file mode 100644
index 00000000..4ed717b5
--- /dev/null
+++ b/beike/Installer/Helpers/MigrationsHelper.php
@@ -0,0 +1,31 @@
+get()->pluck('migration');
+ }
+}
diff --git a/beike/Installer/Helpers/PermissionsChecker.php b/beike/Installer/Helpers/PermissionsChecker.php
new file mode 100644
index 00000000..dd064d6b
--- /dev/null
+++ b/beike/Installer/Helpers/PermissionsChecker.php
@@ -0,0 +1,83 @@
+results['permissions'] = [];
+
+ $this->results['errors'] = null;
+ }
+
+ /**
+ * Check for the folders permissions.
+ *
+ * @param array $folders
+ * @return array
+ */
+ public function check(array $folders)
+ {
+ foreach ($folders as $folder => $permission) {
+ if (! ($this->getPermission($folder) >= $permission) && php_uname('s') != 'Windows NT') {
+ $this->addFileAndSetErrors($folder, $permission, false);
+ } else {
+ $this->addFile($folder, $permission, true);
+ }
+ }
+
+ return $this->results;
+ }
+
+ /**
+ * Get a folder permission.
+ *
+ * @param $folder
+ * @return string
+ */
+ private function getPermission($folder)
+ {
+ return substr(sprintf('%o', fileperms(base_path($folder))), -4);
+ }
+
+ /**
+ * Add the file to the list of results.
+ *
+ * @param $folder
+ * @param $permission
+ * @param $isSet
+ */
+ private function addFile($folder, $permission, $isSet)
+ {
+ array_push($this->results['permissions'], [
+ 'folder' => $folder,
+ 'permission' => $permission,
+ 'isSet' => $isSet,
+ ]);
+ }
+
+ /**
+ * Add the file and set the errors.
+ *
+ * @param $folder
+ * @param $permission
+ * @param $isSet
+ */
+ private function addFileAndSetErrors($folder, $permission, $isSet)
+ {
+ $this->addFile($folder, $permission, $isSet);
+
+ $this->results['errors'] = true;
+ }
+}
diff --git a/beike/Installer/Helpers/RequirementsChecker.php b/beike/Installer/Helpers/RequirementsChecker.php
new file mode 100644
index 00000000..0a15ebfc
--- /dev/null
+++ b/beike/Installer/Helpers/RequirementsChecker.php
@@ -0,0 +1,116 @@
+ $requirement) {
+ switch ($type) {
+ // check php requirements
+ case 'php':
+ foreach ($requirements[$type] as $requirement) {
+ $results['requirements'][$type][$requirement] = true;
+
+ if (! extension_loaded($requirement)) {
+ $results['requirements'][$type][$requirement] = false;
+
+ $results['errors'] = true;
+ }
+ }
+
+ break;
+ // check apache requirements
+ case 'apache':
+ foreach ($requirements[$type] as $requirement) {
+ // if function doesn't exist we can't check apache modules
+ if (function_exists('apache_get_modules')) {
+ $results['requirements'][$type][$requirement] = true;
+
+ if (! in_array($requirement, apache_get_modules())) {
+ $results['requirements'][$type][$requirement] = false;
+
+ $results['errors'] = true;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ return $results;
+ }
+
+ /**
+ * Check PHP version requirement.
+ *
+ * @return array
+ */
+ public function checkPHPversion(string $minPhpVersion = null)
+ {
+ $minVersionPhp = $minPhpVersion;
+ $currentPhpVersion = $this->getPhpVersionInfo();
+ $supported = false;
+
+ if ($minPhpVersion == null) {
+ $minVersionPhp = $this->getMinPhpVersion();
+ }
+
+ if (version_compare($currentPhpVersion['version'], $minVersionPhp) >= 0) {
+ $supported = true;
+ }
+
+ $phpStatus = [
+ 'full' => $currentPhpVersion['full'],
+ 'current' => $currentPhpVersion['version'],
+ 'minimum' => $minVersionPhp,
+ 'supported' => $supported,
+ ];
+
+ return $phpStatus;
+ }
+
+ /**
+ * Get current Php version information.
+ *
+ * @return array
+ */
+ private static function getPhpVersionInfo()
+ {
+ $currentVersionFull = PHP_VERSION;
+ preg_match("#^\d+(\.\d+)*#", $currentVersionFull, $filtered);
+ $currentVersion = $filtered[0];
+
+ return [
+ 'full' => $currentVersionFull,
+ 'version' => $currentVersion,
+ ];
+ }
+
+ /**
+ * Get minimum PHP version ID.
+ *
+ * @return string _minPhpVersion
+ */
+ protected function getMinPhpVersion()
+ {
+ return $this->_minPhpVersion;
+ }
+}
diff --git a/beike/Installer/Helpers/functions.php b/beike/Installer/Helpers/functions.php
new file mode 100644
index 00000000..1f337b6a
--- /dev/null
+++ b/beike/Installer/Helpers/functions.php
@@ -0,0 +1,28 @@
+ 'Laravel Installer',
+ 'next' => 'Next Step',
+ 'back' => 'Previous',
+ 'finish' => 'Install',
+ 'status' => 'Status',
+ 'forms' => [
+ 'errorTitle' => 'The Following errors occurred:',
+ ],
+
+ /*
+ *
+ * Home page translations.
+ *
+ */
+ 'welcome' => [
+ 'template_title' => 'Welcome',
+ 'title' => 'Welcome',
+ 'describe' => 'Welcome to install BeikeShop. Easy Installation and Setup Wizard.',
+ 'message' => 'Easy Installation and Setup Wizard.',
+ 'next' => 'Check Requirements',
+ 'copyright_btn' => 'I have read the agreement and agree',
+ 'copyright_title' => 'Copyright Description',
+ 'copyright_list_1' => '1. The copyright of this system belongs to Chengdu GuangDa Network Technology Co., Ltd.',
+ 'copyright_list_2' => '2. Any individual or organization can not be allowed to sell or lease this system and its derivatives without our explicit written authorization.',
+ 'copyright_list_3' => '3. Please keep the copyright information, and please contact us if you wanna remove it.',
+ ],
+
+ /*
+ *
+ * Requirements page translations.
+ *
+ */
+ 'requirements' => [
+ 'template_title' => 'Step 1 | Server Requirements',
+ 'environment' => 'Environmen',
+ 'title' => 'Server Requirements',
+ 'next' => 'Check Permissions',
+ ],
+
+ /*
+ *
+ * Permissions page translations.
+ *
+ */
+ 'permissions' => [
+ 'template_title' => 'Step 2 | Directory Permission',
+ 'title' => 'Directory permission detection',
+ 'next' => 'Configure Environment',
+ 'table' => 'Table of contents',
+ ],
+
+ /*
+ *
+ * Environment page translations.
+ *
+ */
+ 'environment' => [
+ 'template_title' => 'Step 3 | System Parameters',
+ 'title' => 'System parameter configuration',
+ 'name_required' => 'An environment name is required.',
+ 'database_link' => 'Database link',
+ 'admin_info' => 'Set admin account password',
+ 'app_name_label' => 'App Name',
+ 'app_name_placeholder' => 'App Name',
+ 'app_environment_label' => 'App Environment',
+ 'db_connection_failed_host_port' => 'Database host or port error!',
+ 'db_connection_failed_user_password' => 'Database username or password error!',
+ 'db_connection_failed_database_name' => 'Database name not exist!',
+ 'db_connection_failed_invalid_version' => 'MySQL version must grater than 5.7!',
+ 'app_environment_label_local' => 'Local',
+ 'app_environment_label_developement' => 'Development',
+ 'app_environment_label_qa' => 'Qa',
+ 'app_environment_label_production' => 'Production',
+ 'app_environment_label_other' => 'Other',
+ 'app_environment_placeholder_other' => 'Enter your environment...',
+ 'app_url_label' => 'App Url',
+ 'app_url_placeholder' => 'App Url',
+ 'db_connection_failed' => 'Could not connect to the database.',
+ 'db_connection_label' => 'Database Connection',
+ 'db_connection_label_mysql' => 'mysql',
+ 'db_connection_label_sqlite' => 'sqlite',
+ 'db_connection_label_pgsql' => 'pgsql',
+ 'db_connection_label_sqlsrv' => 'sqlsrv',
+ 'db_host_label' => 'Database Host',
+ 'db_host_placeholder' => 'Database Host',
+ 'db_port_label' => 'Database Port',
+ 'db_port_placeholder' => 'Database Port',
+ 'db_name_label' => 'Database Name',
+ 'db_name_placeholder' => 'Database Name',
+ 'db_username_label' => 'Database User Name',
+ 'db_username_placeholder' => 'Database User Name',
+ 'db_password_label' => 'Database Password',
+ 'db_password_placeholder' => 'Database Password',
+ 'admin_email' => 'Admin User Account',
+ 'admin_password' => 'Admin Password',
+ 'install' => 'Install',
+ 'ajax_database_parameters' => 'Check database parameters...',
+ 'ajax_database_success' => 'Database connection succeeded',
+ 'error_email' => 'Please fill in the correct email address',
+ ],
+
+ /*
+ *
+ * Installed Log translations.
+ *
+ */
+ 'installed' => [
+ 'success_log_message' => 'Laravel Installer successfully INSTALLED on ',
+ ],
+
+ /*
+ *
+ * Final page translations.
+ *
+ */
+ 'final' => [
+ 'title' => 'Installation Finished',
+ 'template_title' => 'Installation Finished',
+ 'migration' => 'Migration & Seed Console Output:',
+ 'console' => 'Application Console Output:',
+ 'log' => 'Installation Log Entry:',
+ 'env' => 'Final .env File:',
+ 'exit' => 'Click here to exit',
+ 'finished' => 'Congratulations, the system is successfully installed, let\'s experience it now',
+ 'to_front' => 'Shop',
+ 'to_admin' => 'Admin Panel',
+ ],
+
+ /*
+ *
+ * Update specific translations
+ *
+ */
+ 'updater' => [
+ /*
+ *
+ * Shared translations.
+ *
+ */
+ 'title' => 'Laravel Updater',
+
+ /*
+ *
+ * Welcome page translations for update feature.
+ *
+ */
+ 'welcome' => [
+ 'title' => 'Welcome To The Updater',
+ 'message' => 'Welcome to the update wizard.',
+ ],
+
+ /*
+ *
+ * Welcome page translations for update feature.
+ *
+ */
+ 'overview' => [
+ 'title' => 'Overview',
+ 'message' => 'There is 1 update.|There are :number updates.',
+ 'install_updates' => 'Install Updates',
+ ],
+
+ /*
+ *
+ * Final page translations.
+ *
+ */
+ 'final' => [
+ 'title' => 'Finished',
+ 'finished' => 'Application\'s database has been successfully updated.',
+ 'exit' => 'Click here to exit',
+ ],
+
+ 'log' => [
+ 'success_message' => 'Laravel Installer successfully UPDATED on ',
+ ],
+ ],
+];
diff --git a/beike/Installer/Lang/zh_cn/installer_messages.php b/beike/Installer/Lang/zh_cn/installer_messages.php
new file mode 100644
index 00000000..848659c0
--- /dev/null
+++ b/beike/Installer/Lang/zh_cn/installer_messages.php
@@ -0,0 +1,109 @@
+ 'Laravel安装程序',
+ 'next' => '下一步',
+ 'finish' => '安装',
+ 'status' => '状态',
+
+ /*
+ *
+ * Home page translations.
+ *
+ */
+ 'welcome' => [
+ 'template_title' => '欢迎',
+ 'title' => '欢迎来到安装引导程序',
+ 'describe' => '欢迎使用安装引导,在后面的步骤中我们将检测您的系统环境和安装条件是否达标,请根据每一步中的提示信息操作,谢谢。',
+ 'message' => '欢迎来到安装向导.',
+ 'next' => '检测系统环境',
+ 'copyright_title' => '版权说明',
+ 'copyright_btn' => '已阅读协议并同意',
+ 'copyright_list_1' => '1、本系统版权归属成都光大网络科技有限公司所有。',
+ 'copyright_list_2' => '2、除本公司书面许可外,任何个人、单位、组织不得将本系统及其衍生品作为商品贩卖租赁销售获利。',
+ 'copyright_list_3' => '3、请保留我公司版权信息,如要移除,需要我公司授权。',
+ ],
+
+ /*
+ *
+ * Requirements page translations.
+ *
+ */
+ 'requirements' => [
+ 'template_title' => '第一步 | 服务器环境',
+ 'title' => '系统环境要求检测',
+ 'environment' => '环境',
+ 'next' => '检测权限',
+ ],
+
+ /*
+ *
+ * Permissions page translations.
+ *
+ */
+ 'permissions' => [
+ 'template_title' => '第二步 | 目录权限',
+ 'title' => '目录权限检测',
+ 'table' => '目录',
+ 'next' => '配置环境参数',
+ ],
+
+ /*
+ *
+ * Environment page translations.
+ *
+ */
+ 'environment' => [
+ 'template_title' => '第三步 | 系统参数',
+ 'title' => '系统参数配置',
+ 'app_url_label' => '您的应用URL',
+ 'database_link' => '数据库链接',
+ 'admin_info' => '设置后台账号密码',
+ 'app_url_placeholder' => '输入您的应用URL',
+ 'db_connection_failed' => '无法连接到数据库!',
+ 'db_connection_label' => '数据库类型',
+ 'db_connection_failed_host_port' => '数据库主机或端口错误!',
+ 'db_connection_failed_user_password' => '数据库账号或密码错误!',
+ 'db_connection_failed_database_name' => '数据库名不存在!',
+ 'db_connection_failed_invalid_version' => '数据库版本必须大于5.7!',
+ 'db_connection_label_mysql' => 'MySQL',
+ 'db_connection_label_sqlite' => 'SQLite',
+ 'db_connection_label_pgsql' => 'PostgreSQL',
+ 'db_connection_label_sqlsrv' => 'SQL Server',
+ 'db_host_label' => '数据库主机',
+ 'db_host_placeholder' => '输入数据库主机ip或url',
+ 'db_port_label' => '数据库端口',
+ 'db_port_placeholder' => '输入数据库端口',
+ 'db_name_label' => '数据库名',
+ 'db_name_placeholder' => '输入数据库名',
+ 'db_username_label' => '数据库账号',
+ 'db_username_placeholder' => '输入数据库账号',
+ 'db_password_label' => '数据库账号密码',
+ 'db_password_placeholder' => '输入数据库账号密码',
+ 'admin_email' => '后台账号',
+ 'admin_password' => '后台密码',
+ 'install' => '安装',
+ 'ajax_database_parameters' => '检测数据库参数...',
+ 'ajax_database_success' => '数据库连接成功',
+ 'error_email' => '请填写正确的邮箱地址',
+ ],
+
+ /*
+ *
+ * Final page translations.
+ *
+ */
+ 'final' => [
+ 'template_title' => '安装完成',
+ 'title' => '获取安装结果',
+ 'finished' => '恭喜您,系统安装成功,赶快体验吧',
+ 'to_front' => '访问前台',
+ 'to_admin' => '访问后台',
+ ],
+];
diff --git a/beike/Installer/Providers/InstallerServiceProvider.php b/beike/Installer/Providers/InstallerServiceProvider.php
new file mode 100644
index 00000000..c141812a
--- /dev/null
+++ b/beike/Installer/Providers/InstallerServiceProvider.php
@@ -0,0 +1,30 @@
+loadRoutesFrom(__DIR__ . '/../Routes/installer.php');
+
+ if (! is_installer()) {
+ return;
+ }
+
+ Schema::defaultStringLength(191);
+
+ $this->mergeConfigFrom(__DIR__ . '/../config.php', 'installer');
+ $this->mergeConfigFrom(__DIR__ . '/../../Config/beike.php', 'beike');
+ $this->loadViewsFrom(__DIR__ . '/../Views', 'installer');
+
+ $pathInstaller = base_path('beike/Installer');
+ $this->loadTranslationsFrom("{$pathInstaller}/Lang", 'installer');
+ }
+}
diff --git a/beike/Installer/Routes/installer.php b/beike/Installer/Routes/installer.php
new file mode 100644
index 00000000..59f31cdd
--- /dev/null
+++ b/beike/Installer/Routes/installer.php
@@ -0,0 +1,28 @@
+name('installer.')
+ ->middleware(\App\Http\Middleware\SetLocaleInstaller::class)
+ ->group(function () {
+ Route::get('/', [WelcomeController::class, 'index'])->name('welcome');
+ Route::get('requirements', [RequirementsController::class, 'index'])->name('requirements');
+ Route::get('permissions', [PermissionsController::class, 'index'])->name('permissions');
+ Route::middleware(['installer'])
+ ->group(function () {
+ Route::get('lang/{lang}', [WelcomeController::class, 'locale'])->name('lang.switch');
+ Route::get('environment', [EnvironmentController::class, 'index'])->name('environment');
+ Route::post('environment/save', [EnvironmentController::class, 'saveWizard'])->name('environment.save');
+ Route::post('environment/validate_db', [EnvironmentController::class, 'validateDatabase'])->name('environment.validate_db');
+ Route::get('database', [DatabaseController::class, 'index'])->name('database');
+ Route::get('final', [FinalController::class, 'index'])->name('final');
+ });
+
+ });
diff --git a/beike/Installer/Views/environment-wizard.blade.php b/beike/Installer/Views/environment-wizard.blade.php
new file mode 100644
index 00000000..12f77629
--- /dev/null
+++ b/beike/Installer/Views/environment-wizard.blade.php
@@ -0,0 +1,260 @@
+@extends('installer::layouts.master')
+
+@section('template_title')
+ {{ trans('installer::installer_messages.environment.template_title') }}
+@endsection
+
+@section('title')
+
+ {!! trans('installer::installer_messages.environment.title') !!}
+@endsection
+
+@section('content')
+ @php
+ $entry_key = 'installer::installer_messages.environment.';
+ @endphp
+  }}&build_date={{ config('beike.build') }})
| {{ __('installer::installer_messages.permissions.table') }} | +{{ __('installer::installer_messages.permissions.next') }} | +{{ __('installer::installer_messages.status') }} | +
|---|---|---|
| {{ $permission['folder'] }} | +{{ $permission['permission'] }} | ++ + | +
| {{ trans('installer::installer_messages.requirements.environment') }} | +{{ trans('installer::installer_messages.status') }} | + + + @foreach ($requirements['requirements'] as $type => $requirement) +|
|---|---|---|
| + {{ ucfirst($type) }} + @if ($type == 'php') + (version {{ $phpSupportInfo['minimum'] }} required) + + {{ $phpSupportInfo['current'] }} + + + @endif + | +||
| {{ $extention }} | ++ | |
 }}&build_date={{ config('beike.build') }})
+ + {{ trans('installer::installer_messages.welcome.next') }} + + +
+