This commit is contained in:
liqianjin 2023-05-27 11:47:26 +08:00
parent d620e28567
commit 5e552c572e
1464 changed files with 224942 additions and 0 deletions

21
.editorconfig Normal file
View File

@ -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

28
.env Normal file
View File

@ -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=

21
.htaccess Normal file
View File

@ -0,0 +1,21 @@
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

14
.styleci.yml Normal file
View File

@ -0,0 +1,14 @@
php:
preset: laravel
version: 8
disabled:
- no_unused_imports
finder:
not-name:
- index.php
- server.php
js:
finder:
not-name:
- webpack.mix.js
css: true

7
404.html Normal file
View File

@ -0,0 +1,7 @@
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

172
LICENSE Normal file
View File

@ -0,0 +1,172 @@
Open Software License ("OSL") v 3.0
This Open Software License (the "License") applies to any original work of
authorship (the "Original Work") whose owner (the "Licensor") has placed the
following licensing notice adjacent to the copyright notice for the Original
Work:
Licensed under the Open Software License version 3.0
1) Grant of Copyright License. Licensor grants You a worldwide, royalty-free,
non-exclusive, sublicensable license, for the duration of the copyright, to do
the following:
a) to reproduce the Original Work in copies, either alone or as part of a
collective work;
b) to translate, adapt, alter, transform, modify, or arrange the Original
Work, thereby creating derivative works ("Derivative Works") based upon the
Original Work;
c) to distribute or communicate copies of the Original Work and Derivative
Works to the public, with the proviso that copies of Original Work or
Derivative Works that You distribute or communicate shall be licensed under
this Open Software License;
d) to perform the Original Work publicly; and
e) to display the Original Work publicly.
2) Grant of Patent License. Licensor grants You a worldwide, royalty-free,
non-exclusive, sublicensable license, under patent claims owned or controlled
by the Licensor that are embodied in the Original Work as furnished by the
Licensor, for the duration of the patents, to make, use, sell, offer for sale,
have made, and import the Original Work and Derivative Works.
3) Grant of Source Code License. The term "Source Code" means the preferred
form of the Original Work for making modifications to it and all available
documentation describing how to modify the Original Work. Licensor agrees to
provide a machine-readable copy of the Source Code of the Original Work along
with each copy of the Original Work that Licensor distributes. Licensor
reserves the right to satisfy this obligation by placing a machine-readable
copy of the Source Code in an information repository reasonably calculated to
permit inexpensive and convenient access by You for as long as Licensor
continues to distribute the Original Work.
4) Exclusions From License Grant. Neither the names of Licensor, nor the names
of any contributors to the Original Work, nor any of their trademarks or
service marks, may be used to endorse or promote products derived from this
Original Work without express prior permission of the Licensor. Except as
expressly stated herein, nothing in this License grants any license to
Licensor's trademarks, copyrights, patents, trade secrets or any other
intellectual property. No patent license is granted to make, use, sell, offer
for sale, have made, or import embodiments of any patent claims other than the
licensed claims defined in Section 2. No license is granted to the trademarks
of Licensor even if such marks are included in the Original Work. Nothing in
this License shall be interpreted to prohibit Licensor from licensing under
terms different from this License any Original Work that Licensor otherwise
would have a right to license.
5) External Deployment. The term "External Deployment" means the use,
distribution, or communication of the Original Work or Derivative Works in any
way such that the Original Work or Derivative Works may be used by anyone
other than You, whether those works are distributed or communicated to those
persons or made available as an application intended for use over a network.
As an express condition for the grants of license hereunder, You must treat
any External Deployment by You of the Original Work or a Derivative Work as a
distribution under section 1(c).
6) Attribution Rights. You must retain, in the Source Code of any Derivative
Works that You create, all copyright, patent, or trademark notices from the
Source Code of the Original Work, as well as any notices of licensing and any
descriptive text identified therein as an "Attribution Notice." You must cause
the Source Code for any Derivative Works that You create to carry a prominent
Attribution Notice reasonably calculated to inform recipients that You have
modified the Original Work.
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
the copyright in and to the Original Work and the patent rights granted herein
by Licensor are owned by the Licensor or are sublicensed to You under the
terms of this License with the permission of the contributor(s) of those
copyrights and patent rights. Except as expressly stated in the immediately
preceding sentence, the Original Work is provided under this License on an "AS
IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without
limitation, the warranties of non-infringement, merchantability or fitness for
a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK
IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this
License. No license to the Original Work is granted by this License except
under this disclaimer.
8) Limitation of Liability. Under no circumstances and under no legal theory,
whether in tort (including negligence), contract, or otherwise, shall the
Licensor be liable to anyone for any indirect, special, incidental, or
consequential damages of any character arising as a result of this License or
the use of the Original Work including, without limitation, damages for loss
of goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses. This limitation of liability shall not
apply to the extent applicable law prohibits such limitation.
9) Acceptance and Termination. If, at any time, You expressly assented to this
License, that assent indicates your clear and irrevocable acceptance of this
License and all of its terms and conditions. If You distribute or communicate
copies of the Original Work or a Derivative Work, You must make a reasonable
effort under the circumstances to obtain the express assent of recipients to
the terms of this License. This License conditions your rights to undertake
the activities listed in Section 1, including your right to create Derivative
Works based upon the Original Work, and doing so without honoring these terms
and conditions is prohibited by copyright law and international treaty.
Nothing in this License is intended to affect copyright exceptions and
limitations (including "fair use" or "fair dealing"). This License shall
terminate immediately and You may no longer exercise any of the rights granted
to You by this License upon your failure to honor the conditions in Section
1(c).
10) Termination for Patent Action. This License shall terminate automatically
and You may no longer exercise any of the rights granted to You by this
License as of the date You commence an action, including a cross-claim or
counterclaim, against Licensor or any licensee alleging that the Original Work
infringes a patent. This termination provision shall not apply for an action
alleging patent infringement by combinations of the Original Work with other
software or hardware.
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
License may be brought only in the courts of a jurisdiction wherein the
Licensor resides or in which Licensor conducts its primary business, and under
the laws of that jurisdiction excluding its conflict-of-law provisions. The
application of the United Nations Convention on Contracts for the
International Sale of Goods is expressly excluded. Any use of the Original
Work outside the scope of this License or after its termination shall be
subject to the requirements and penalties of copyright or patent law in the
appropriate jurisdiction. This section shall survive the termination of this
License.
12) Attorneys' Fees. In any action to enforce the terms of this License or
seeking damages relating thereto, the prevailing party shall be entitled to
recover its costs and expenses, including, without limitation, reasonable
attorneys' fees and costs incurred in connection with such action, including
any appeal of such action. This section shall survive the termination of this
License.
13) Miscellaneous. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent necessary
to make it enforceable.
14) Definition of "You" in This License. "You" throughout this License,
whether in upper or lower case, means an individual or a legal entity
exercising rights under, and complying with all of the terms of, this License.
For legal entities, "You" includes any entity that controls, is controlled by,
or is under common control with you. For purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or (ii) ownership
of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
ownership of such entity.
15) Right to Use. You may use the Original Work in all ways not otherwise
restricted or conditioned by this License or by law, and Licensor promises not
to interfere with or be responsible for such uses by You.
16) Modification of This License. This License is Copyright © 2005 Lawrence
Rosen. Permission is granted to copy, distribute, or communicate this License
without modification. Nothing in this License permits You to modify this
License as applied to the Original Work or to Derivative Works. However, You
may modify the text of this License and copy, distribute or communicate your
modified version (the "Modified License") and apply it to other original works
of authorship subject to the following conditions: (i) You may not indicate in
any way that your Modified License is the "Open Software License" or "OSL" and
you may not use those names in the name of your Modified License; (ii) You
must replace the notice specified in the first paragraph above with the notice
"Licensed under <insert your license name here>" or with a notice of your own
that is not confusingly similar to the notice in this License; and (iii) You
may not claim that your original works are open source software unless your
Modified License has been approved by Open Source Initiative (OSI) and You
comply with its license review and certification process.

110
README.md Normal file
View File

@ -0,0 +1,110 @@
<img height=70 src="https://beikeshop.com/image/beike.svg" >
# &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;一款开源好用的跨境电商系统
## BeikeShop介绍
BeikeShop 是基于 Laravel 开发的一款开源商城系统,主要面向外贸,跨境行业提供的商品管理、订单管理、会员管理、支付、物流、系统管理等功能。
<br>
<br>
<a href="https://beikeshop.com/">
<img src="https://beikeshop.com/readme/README-1.png">
</a>
请保留我公司版权信息,如要移除,需要我公司授权。
## BeikeShop系统亮点
- **全新支持ChatGPTBeikeShop1.3.2 集成ChatGPT打造高效智能化跨境电商系统**
- 开源免费BeikeShop以开源方式发布OSL-3.0协议允许用户自由使用、修改。
- 轻量级框架BeikeShop基于Laravel框架开发具有高效、灵活、易用等特点。
- 灵活的插件机制BeikeShop提供灵活的Hook插件机制可以方便地扩展和定制系统功能。
- 多语言多货币支持:支持多种语言/货币切换,可灵活扩展其他语言/货币。
- 多种支付方式:支持 PayPal、Stripe、Alipay、WeChat Pay 等多种支付方式,覆盖全球主要外贸国家
- 快速搭建向VIP提供一键安装脚本帮助用户快速搭建起一个稳定、高效、易用的跨境电商独立站。
![ ](https://beikeshop.com/readme/README-2.png)
<br>
## BeikeShop 商城预览视频
<p>
<a href="https://demo.beikeshop.com/" target="_blank" style="border: 1px solid #eee; display: inline-block;">
<img src="https://beikeshop.com/image/gif/demo.gif" style="width: 100%;">
</a>
</p>
<a href="https://demo.beikeshop.com/" target="_blank">点击立刻体验BeikeShop演示站</a>
<br>
<br>
## 页面展示
![ ](https://beikeshop.com/readme/README-7.png)
![ ](https://beikeshop.com/readme/README-5.png)
![ ](https://beikeshop.com/readme/README-6.png)
![ ](https://beikeshop.com/readme/README-8.png)
## 软件架构
PHP语言开发基于 Laravel 框架,前端 Blade 模板 + Vue
## 环境要求
- PHP 8.0.2+
- MySQL 5.7+
- Apache httpd 2.4+ 或者 Nginx 1.10+
## PHP组件
- BCMath PHP Extension
- Ctype PHP Extension
- cURL PHP Extension
- DOM PHP Extension
- Fileinfo PHP Extension
- JSON PHP Extension
- Mbstring PHP Extension
- OpenSSL PHP Extension
- PCRE PHP Extension
- PDO PHP Extension
- Tokenizer PHP Extension
- XML PHP Extension
<a href="https://beikeshop.com/download">
<img src="https://beikeshop.com/readme/README-3.png">
</a>
## 安装教程(面向非开发者)
1. <a href="https://beikeshop.com/download" target="_blank">下载BeikeShop</a>
1. 上传到你的服务器并解压
1. 将解压文件夹下的 public 设置为网站根目录
1. 通过浏览器访问网站根据提示完成安装
1. <a href="https://docs.beikeshop.com/install/bt.html" target="_blank">BeikeShop详细安装指引</a>
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

32
app/Console/Kernel.php Normal file
View File

@ -0,0 +1,32 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Foundation\Exceptions\RegisterErrorViewPaths;
use Illuminate\Support\Arr;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var string[]
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var string[]
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->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())();
}
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Exceptions;
use Illuminate\Support\Facades\View;
class RegisterAdminErrorViewPaths
{
/**
* Register the error view paths.
*
* @return void
*/
public function __invoke()
{
if (is_admin()) {
$viewPaths[] = base_path('resources/beike/admin/views');
View::replaceNamespace('errors', collect($viewPaths)->map(function ($path) {
return "{$path}/errors";
})->all());
}
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

94
app/Http/Kernel.php Normal file
View File

@ -0,0 +1,94 @@
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
];
/**
* The application's route middleware groups.
* session => 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,
];
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
// 后台
return admin_route('login.show');
}
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace App\Http\Middleware;
use Beike\Models\Customer;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class CheckoutAuthenticate extends Middleware
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param \Closure $next
* @param string[] ...$guards
* @return mixed
*
* @throws AuthenticationException
*/
public function handle($request, \Closure $next, ...$guards)
{
if (system_setting('base.guest_checkout', 1)) {
return $next($request);
}
$this->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)
);
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
//
];
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
//
];
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null ...$guards
* @return mixed
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
class SetLocaleAdmin
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$currentLocale = current_user()->locale ?? 'zh_cn';
if (in_array($currentLocale, admin_languages())) {
App::setLocale($currentLocale);
} else {
App::setLocale('en');
}
return $next($request);
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
class SetLocaleFromSession
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$sessionLocale = session('locale');
if ($sessionLocale && in_array($sessionLocale, languages()->toArray())) {
App::setLocale($sessionLocale);
} else {
$configLocale = system_setting('base.locale');
App::setLocale($configLocale);
session(['locale' => $configLocale]);
}
return $next($request);
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace App\Http\Middleware;
use Beike\Installer\Helpers\EnvironmentManager;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
class SetLocaleInstaller
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$locale = $_COOKIE['locale'] ?? 'zh_cn';
$languageDir = base_path('beike/Installer/Lang');
$languages = array_values(array_diff(scandir($languageDir), ['..', '.']));
(new EnvironmentManager)->getEnvContent();
if ($locale && in_array($locale, $languages)) {
App::setLocale($locale);
} else {
App::setLocale('zh_cn');
}
return $next($request);
}
}

View File

@ -0,0 +1,75 @@
<?php
/**
* ShareViewData.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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;
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace App\Http\Middleware;
use Beike\Models\Customer;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ShopAuthenticate extends Middleware
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param \Closure $next
* @param string[] ...$guards
* @return mixed
*
* @throws AuthenticationException
*/
public function handle($request, \Closure $next, ...$guards)
{
$this->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)
);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array
*/
protected $except = [
'current_password',
'password',
'password_confirmation',
];
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array
*/
public function hosts()
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array|string|null
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
'callback/*',
];
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ContactRequest 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|string|max:100|min:10',
];
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
if (env('APP_FORCE_HTTPS', false)) {
URL::forceScheme('https');
}
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Gate::before(function ($user, $ability) {
return $user->id == 1;
});
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Broadcast::routes();
require base_path('routes/channels.php');
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
// Registered::class => [
// SendEmailVerificationNotification::class,
// ],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
//
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Laravel\Horizon\Horizon;
use Laravel\Horizon\HorizonApplicationServiceProvider;
class HorizonServiceProvider extends HorizonApplicationServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
parent::boot();
// Horizon::routeSmsNotificationsTo('15556667777');
// Horizon::routeMailNotificationsTo('example@example.com');
// Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
// Horizon::night();
}
/**
* Register the Horizon gate.
*
* This gate determines who can access Horizon in non-local environments.
*
* @return void
*/
protected function gate()
{
Gate::define('viewHorizon', function ($user) {
return in_array($user->email, [
]);
});
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to the "home" route for your application.
*
* This is used by Laravel authentication to redirect users after login.
*
* @var string
*/
public const HOME = '/home';
/**
* The controller namespace for the application.
*
* When present, controller route declarations will automatically be prefixed with this namespace.
*
* @var string|null
*/
// protected $namespace = 'App\\Http\\Controllers';
/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
$this->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());
});
}
}

53
artisan Normal file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env php
<?php
define('LARAVEL_START', microtime(true));
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader
| for our application. We just need to utilize it! We'll require it
| into the script here so that we do not have to worry about the
| loading of any of our classes manually. It's great to relax.
|
*/
require __DIR__.'/vendor/autoload.php';
$app = require_once __DIR__.'/bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Run The Artisan Application
|--------------------------------------------------------------------------
|
| When we run the console application, the current CLI command will be
| executed in this console and the response sent back to a terminal
| or another output device for the developers. Here goes nothing!
|
*/
$kernel = $app->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);

View File

@ -0,0 +1,62 @@
<?php
namespace Database\Seeders;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class ProductSeeder extends Seeder
{
public function run()
{
$faker = \Faker\Factory::create();
$date = Carbon::create(2021);
for ($i = 0; $i < 1000; $i++) {
$time = $date->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,
]);
}
}
}

View File

@ -0,0 +1,68 @@
<?php
/**
* AddressController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,88 @@
<?php
/**
* AdminUserController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,70 @@
<?php
/**
* AdminUserController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,151 @@
<?php
/**
* AttributeController.php
*
* @copyright 2023 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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));
}
}

View File

@ -0,0 +1,68 @@
<?php
/**
* AttributeGroupController.php
*
* @copyright 2023 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,129 @@
<?php
/**
* BrandController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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);
}
}

View File

@ -0,0 +1,108 @@
<?php
namespace Beike\Admin\Http\Controllers;
use Beike\Admin\Http\Requests\CategoryRequest;
use Beike\Admin\Http\Resources\CategoryResource;
use Beike\Admin\Services\CategoryService;
use Beike\Models\Category;
use Beike\Repositories\CategoryRepo;
use Beike\Repositories\LanguageRepo;
use Illuminate\Http\Request;
class CategoryController extends Controller
{
protected string $defaultRoute = 'categories.index';
public function index()
{
$categories = CategoryRepo::getAdminList();
$data = [
'categories' => 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);
}
}

View File

@ -0,0 +1,89 @@
<?php
namespace Beike\Admin\Http\Controllers;
use App\Http\Controllers\Controller as BaseController;
use Illuminate\Support\Facades\Route;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
abstract class Controller extends BaseController
{
protected string $defaultRoute;
/**
* 表单页面获跳转页面链接
* @return mixed
*/
public function getRedirect()
{
if (empty($this->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);
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* CountryController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* CurrencyController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,141 @@
<?php
/**
* CustomerController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
* CustomerGroupController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace Beike\Admin\Http\Controllers;
use Beike\Repositories\SettingRepo;
use Beike\Services\DesignService;
use Illuminate\Http\Request;
use Illuminate\View\View;
class DesignController extends Controller
{
/**
* 展示所有模块编辑器
*
* @param Request $request
* @return View
*/
public function index(Request $request): View
{
$data = [
'editors' => [
'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'));
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace Beike\Admin\Http\Controllers;
use Beike\Repositories\FooterRepo;
use Beike\Repositories\SettingRepo;
use Illuminate\Http\Request;
use Illuminate\View\View;
class DesignFooterController extends Controller
{
/**
* 展示所有模块编辑器
*
* @param Request $request
* @return View
*/
public function index(Request $request): View
{
$data = [
'design_settings' => 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'));
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace Beike\Admin\Http\Controllers;
use Beike\Repositories\SettingRepo;
use Illuminate\Http\Request;
use Illuminate\View\View;
class DesignMenuController extends Controller
{
/**
* 展示所有模块编辑器
*
* @param Request $request
* @return View
*/
public function index(Request $request): View
{
$data = [
'design_settings' => 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'));
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace Beike\Admin\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class EditController extends Controller
{
public function update(Request $request)
{
$user = current_user();
$user->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();
}
}

View File

@ -0,0 +1,134 @@
<?php
namespace Beike\Admin\Http\Controllers;
use Beike\Admin\Http\Requests\UploadRequest;
use Beike\Admin\Services\FileManagerService;
use Illuminate\Http\Request;
class FileManagerController extends Controller
{
/**
* 获取文件夹和文件列表
* @return mixed
* @throws \Exception
*/
public function index()
{
$data = (new FileManagerService)->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),
];
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* ForgottenController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Beike\Admin\Http\Controllers;
use App\Http\Controllers\Controller;
use Beike\Admin\Repositories\DashboardRepo;
use Beike\Admin\Repositories\Report\OrderReportRepo;
class HomeController extends Controller
{
public function index()
{
$data = [
'views' => 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);
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* LanguageController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,37 @@
<?php
/**
* LoginController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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();
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Beike\Admin\Http\Controllers;
use App\Http\Controllers\Controller;
use Beike\Models\AdminUser;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LogoutController extends Controller
{
public function index(Request $request)
{
Auth::guard(AdminUser::AUTH_GUARD)->logout();
return redirect(admin_route('login.show'));
}
}

View File

@ -0,0 +1,100 @@
<?php
/**
* MarketingController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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());
}
}
}

View File

@ -0,0 +1,123 @@
<?php
/**
* OrderController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,153 @@
<?php
/**
* PageCategoryController.php
*
* @copyright 2023 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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);
}
}

View File

@ -0,0 +1,145 @@
<?php
/**
* PagesController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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);
}
}

View File

@ -0,0 +1,137 @@
<?php
/**
* SettingController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,215 @@
<?php
namespace Beike\Admin\Http\Controllers;
use Beike\Admin\Http\Requests\ProductRequest;
use Beike\Admin\Http\Resources\ProductAttributeResource;
use Beike\Admin\Http\Resources\ProductResource;
use Beike\Admin\Repositories\TaxClassRepo;
use Beike\Admin\Services\ProductService;
use Beike\Models\Product;
use Beike\Repositories\CategoryRepo;
use Beike\Repositories\LanguageRepo;
use Beike\Repositories\ProductRepo;
use Illuminate\Http\Request;
class ProductController extends Controller
{
protected string $defaultRoute = 'products.index';
public function index(Request $request)
{
$requestData = $request->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();
}
}

View File

@ -0,0 +1,55 @@
<?php
/**
* RegionZoneController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* RmaController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* RmaController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,76 @@
<?php
/**
* SettingController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,56 @@
<?php
/**
* TaxClassController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* TaxRateController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,83 @@
<?php
/**
* ThemeController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'));
}
}

View File

@ -0,0 +1,69 @@
<?php
/**
* ZoneController.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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);
}
}

View File

@ -0,0 +1,46 @@
<?php
/**
* AdminRoleRequest.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'),
];
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* AdminUserRequest.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'),
];
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Beike\Admin\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CategoryRequest 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 [
'descriptions.*.name' => 'required|max:255',
];
}
public function attributes()
{
return [
'descriptions.*.name' => trans('category.name'),
];
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace Beike\Admin\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CurrencyRequest 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',
'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'),
];
}
}

View File

@ -0,0 +1,48 @@
<?php
/**
* CustomerGroupRequest.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'),
];
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* CustomerRequest.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'),
];
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Beike\Admin\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ForgottenRequest 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 [
'password' => 'required|confirmed',
];
}
public function attributes()
{
return [
'password' => trans('customer.password'),
];
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Beike\Admin\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class LoginRequest 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<string, mixed>
*/
public function rules(): array
{
return [
'email' => ['required', 'email'],
'password' => 'required',
];
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* PageCategoryRequest.php
*
* @copyright 2023 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'),
];
}
}

View File

@ -0,0 +1,51 @@
<?php
/**
* AdminUserRequest.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'),
];
}
}

View File

@ -0,0 +1,56 @@
<?php
/**
* PageRequest.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'),
];
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* RmaRequest.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author TL <mengwb@guangda.work>
* @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'),
];
}
}

View File

@ -0,0 +1,57 @@
<?php
/**
* AdminRoleRequest.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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'),
];
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* UploadRequest.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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',
];
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Beike\Admin\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class VerifyCodeRequest 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 [
'email' => 'required|email:rfc|exists:admin_users,email',
];
}
public function attributes()
{
return [
'email' => trans('shop/login.email_address'),
];
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class AddressResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$data = [
'name' => $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;
}
}

View File

@ -0,0 +1,31 @@
<?php
/**
* AdminUserDetail.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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),
];
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class AttributeDetailResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$data = [
'id' => $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;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class AttributeResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$data = [
'id' => $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;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class AttributeValueResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$data = [
'id' => $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;
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class AutocompleteResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$data = [
'id' => $this->id,
'name' => $this->description->name ?? '',
];
return $data;
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class CategoryResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$data = [
'id' => $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;
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class CustomerGroupDetail extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param Request $request
* @return array
*/
public function toArray($request): array
{
$data = [
'id' => $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;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class CustomerResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param Request $request
* @return mixed
* @throws \Exception
*/
public function toArray($request)
{
$data = [
'id' => $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'];
}
}

View File

@ -0,0 +1,33 @@
<?php
/**
* OrderSimple.php
*
* @copyright 2022 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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;
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
* PageCategoryResource.php
*
* @copyright 2023 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @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),
];
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class PluginResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param Request $request
* @return array
* @throws \Exception
*/
public function toArray($request): array
{
return [
'code' => $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(),
];
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ProductAttributeResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param Request $request
* @return array
* @throws \Exception
*/
public function toArray($request): array
{
$this->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;
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace Beike\Admin\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ProductResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param Request $request
* @return array
* @throws \Exception
*/
public function toArray($request): array
{
$masterSku = $this->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);
}
}

Some files were not shown because too many files have changed in this diff Show More