first
This commit is contained in:
4
modules/Mall/.gitignore
vendored
Normal file
4
modules/Mall/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.idea
|
||||
vendor
|
||||
.DS_Store
|
||||
composer.lock
|
||||
168
modules/Mall/Config/config.php
Normal file
168
modules/Mall/Config/config.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 模块名称
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'name' => 'Mall',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 订单编号计数器位数,取值范围 6 - 16
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'order_no_counter_length' => 8,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 退款单编号前缀
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'refund_no_counter_prefix' => 'RF',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 退款单编号计数器位数,取值范围 6 - 16 - 退款编号前缀位数
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'refund_no_counter_length' => 6,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 商品规格的扩展属性
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'sku_extends_attributes' => [
|
||||
'market_fee' => '平台手续费',
|
||||
],
|
||||
|
||||
'administrator_max_id' => 10000,
|
||||
|
||||
'workflow' => [
|
||||
'orders' => [
|
||||
'type' => 'state_machine',
|
||||
'marking_store' => [
|
||||
'type' => 'single_state',
|
||||
'property' => 'currentState',
|
||||
],
|
||||
'supports' => [Modules\Mall\Models\Order::class],
|
||||
'places' => [
|
||||
'INIT',
|
||||
'CANCEL',
|
||||
'PAID',
|
||||
'DELIVERED',
|
||||
'SIGNED',
|
||||
'COMPLETED',
|
||||
'REFUND_APPLY',
|
||||
'REFUND_AGREE',
|
||||
'REFUND_REFUSE',
|
||||
'REFUND_DELIVER',
|
||||
'REFUND_DELIVERD',
|
||||
'REFUND_PROCESS',
|
||||
'REFUND_COMPLETED',
|
||||
],
|
||||
'transitions' => [
|
||||
'cancel' => [
|
||||
'from' => ['INIT', 'PAID'],
|
||||
'to' => 'CANCEL',
|
||||
],
|
||||
'pay' => [
|
||||
'from' => 'INIT',
|
||||
'to' => 'PAID',
|
||||
],
|
||||
'deliver' => [
|
||||
'from' => 'PAID',
|
||||
'to' => 'DELIVERED',
|
||||
],
|
||||
'sign' => [
|
||||
'from' => 'DELIVERED',
|
||||
'to' => 'SIGNED',
|
||||
],
|
||||
'complete' => [
|
||||
'from' => 'SIGNED',
|
||||
'to' => 'COMPLETED',
|
||||
],
|
||||
'refund' => [
|
||||
'from' => ['PAID', 'SIGNED'],
|
||||
'to' => 'REFUND_APPLY',
|
||||
],
|
||||
'agree' => [
|
||||
'from' => ['PAID', 'SIGNED', 'REFUND_APPLY'],
|
||||
'to' => 'REFUND_AGREE',
|
||||
],
|
||||
'refuse' => [
|
||||
'from' => 'REFUND_APPLY',
|
||||
'to' => 'REFUND_REFUSE',
|
||||
],
|
||||
'user_deliver' => [
|
||||
'from' => 'REFUND_AGREE',
|
||||
'to' => 'REFUND_DELIVER',
|
||||
],
|
||||
'user_deliverd' => [
|
||||
'from' => 'REFUND_DELIVER',
|
||||
'to' => 'REFUND_DELIVERD',
|
||||
],
|
||||
'process' => [
|
||||
'from' => ['REFUND_AGREE', 'REFUND_DELIVERD'],
|
||||
'to' => 'REFUND_PROCESS',
|
||||
],
|
||||
'completed' => [
|
||||
'from' => ['PAID', 'DELIVERED', 'SIGNED', 'REFUND_PROCESS', 'REFUND_DELIVERD'],
|
||||
'to' => 'REFUND_COMPLETED',
|
||||
],
|
||||
],
|
||||
],
|
||||
'refunds' => [
|
||||
'type' => 'state_machine',
|
||||
'marking_store' => [
|
||||
'type' => 'single_state',
|
||||
'property' => 'currentState',
|
||||
],
|
||||
'supports' => [Modules\Mall\Models\Refund::class],
|
||||
'places' => [
|
||||
'REFUND_APPLY',
|
||||
'REFUND_AGREE',
|
||||
'REFUND_REFUSE',
|
||||
'REFUND_PROCESS',
|
||||
'REFUND_DELIVER',
|
||||
'REFUND_DELIVERED',
|
||||
'REFUND_SIGNED',
|
||||
'REFUND_COMPLETED',
|
||||
],
|
||||
'transitions' => [
|
||||
'agree' => [
|
||||
'from' => 'REFUND_APPLY',
|
||||
'to' => 'REFUND_AGREE',
|
||||
],
|
||||
'refuse' => [
|
||||
'from' => 'REFUND_APPLY',
|
||||
'to' => 'REFUND_REFUSE',
|
||||
],
|
||||
'deliver' => [
|
||||
'from' => 'REFUND_AGREE',
|
||||
'to' => 'REFUND_DELIVER',
|
||||
],
|
||||
'delivered' => [
|
||||
'from' => 'REFUND_DELIVER',
|
||||
'to' => 'REFUND_DELIVERED',
|
||||
],
|
||||
'sign' => [
|
||||
'from' => 'REFUND_DELIVERED',
|
||||
'to' => 'REFUND_SIGNED',
|
||||
],
|
||||
'process' => [
|
||||
'from' => ['REFUND_AGREE', 'REFUND_SIGNED'],
|
||||
'to' => 'REFUND_PROCESS',
|
||||
],
|
||||
'completed' => [
|
||||
'from' => 'REFUND_PROCESS',
|
||||
'to' => 'REFUND_COMPLETED',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallAddressesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_addresses', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedInteger('user_id')->index();
|
||||
$table->string('name', 32);
|
||||
$table->string('mobile', 32);
|
||||
$table->unsignedInteger('province_id');
|
||||
$table->unsignedInteger('city_id');
|
||||
$table->unsignedInteger('district_id');
|
||||
$table->string('address');
|
||||
$table->boolean('is_default')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_addresses');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallBannersTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_banners', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->default(0)->index()->comment('所属店铺');
|
||||
$table->string('title');
|
||||
$table->string('cover');
|
||||
$table->integer('position')->unsigned();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_banners');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallBrandsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_brands', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->string('name');
|
||||
$table->string('cover')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_brands');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallCartsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_carts', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->unsignedBigInteger('sku_id')->comment('加入购物车的商品条目');
|
||||
$table->unsignedInteger('qty')->default(1)->comment('数量');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_carts');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallCategoriesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('parent_id')->default(0)->index()->comment('父级id');
|
||||
$table->string('name');
|
||||
$table->string('slug')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->string('cover')->nullable();
|
||||
$table->integer('order')->default(0);
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_categories');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallDeliveriesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_deliveries', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->string('name')->comment('模板名称');
|
||||
$table->unsignedTinyInteger('type')->comment('计费方式:1按件数 2按重量');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_deliveries');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMallDeliveryRulesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_delivery_rules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->integer('delivery_id')->comment('配送模板id');
|
||||
$table->json('regions')->nullable()->comment('可配送区域(城市id集)');
|
||||
$table->decimal('first', 8, 2)->default(0)->comment('首件(个)/首重(Kg)');
|
||||
$table->decimal('first_fee', 8, 2)->default(0)->comment('运费(元)');
|
||||
|
||||
$table->decimal('additional', 8, 2)->default(0)->comment('续件/续重');
|
||||
$table->decimal('additional_fee', 8, 2)->default(0)->comment('续费(元)');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_delivery_rules');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Modules\Mall\Database\Seeders\ExpressSeeder;
|
||||
|
||||
class CreateMallExpressesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_expresses', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('slug')->nullable()->comment('简称');
|
||||
$table->string('cover')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Artisan::call('db:seed', [
|
||||
'--class' => ExpressSeeder::class,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_expresses');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsSkusTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods_skus', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('goods_id')->index();
|
||||
$table->string('unit')->nullable()->comment('商品单元编号');
|
||||
$table->string('cover')->nullable();
|
||||
$table->decimal('price');
|
||||
$table->decimal('score')->comment('积分/原石');
|
||||
$table->decimal('assets', 8, 2)->comment('资产');
|
||||
$table->integer('stock')->default(0);
|
||||
$table->decimal('weight')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods_skus');
|
||||
Schema::dropIfExists('mall_goods_sku_spec');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsSpecValuesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods_spec_values', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('spec_id')->index();
|
||||
$table->string('value');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods_spec_values');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsSpecsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods_specs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('goods_id')->index();
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods_specs');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('category_id')->index()->comment('分类');
|
||||
$table->unsignedBigInteger('brand_id')->nullable()->index()->comment('品牌ID');
|
||||
$table->unsignedBigInteger('delivery_id')->nullable()->comment('物流模板');
|
||||
$table->unsignedTinyInteger('type')->default(1)->comment('规格类型');
|
||||
$table->unsignedTinyInteger('pay_type')->default(1)->comment('支付方式');
|
||||
$table->unsignedTinyInteger('deduct_stock_type')->default(1)->comment('库存扣减方式');
|
||||
$table->unsignedTinyInteger('channel')->default(1)->comment('商品类型');
|
||||
$table->boolean('status')->default(0);
|
||||
$table->boolean('is_post_sale')->default(1)->comment('是否可以申请售后');
|
||||
$table->unsignedInteger('clicks')->default(0)->comment('浏览量');
|
||||
$table->unsignedInteger('sales')->default(0)->comment('总销量');
|
||||
$table->decimal('original_price', 10, 2)->default(0)->comment('商品显示的原价');
|
||||
$table->string('name');
|
||||
$table->string('cover')->nullable();
|
||||
$table->json('pictures')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->text('content')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsTagTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods_tag', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('goods_id')->index();
|
||||
$table->unsignedBigInteger('tag_id')->index();
|
||||
$table->timestamps();
|
||||
|
||||
$table->primary(['goods_id', 'tag_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods_tag');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallJobsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_jobs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->unsignedBigInteger('shop_id')->index();
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_jobs');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallOrderExpressesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_order_expresses', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('order_id')->index();
|
||||
|
||||
$table->string('name', 32)->nullable();
|
||||
$table->string('mobile', 32)->nullable();
|
||||
$table->unsignedInteger('province_id')->index()->nullable();
|
||||
$table->unsignedInteger('city_id')->index()->nullable();
|
||||
$table->unsignedInteger('district_id')->index()->nullable();
|
||||
$table->string('address')->nullable();
|
||||
|
||||
$table->unsignedBigInteger('express_id')->nullable()->comment('物流公司');
|
||||
$table->string('express_no', 32)->nullable()->comment('物流单号');
|
||||
$table->dateTime('deliver_at')->nullable()->comment('发货时间');
|
||||
$table->dateTime('receive_at')->nullable()->comment('签收时间');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_order_expresses');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallOrderItemsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_order_items', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('order_id')->index('order_id');
|
||||
$table->morphs('item');
|
||||
$table->unsignedInteger('qty')->comment('数量');
|
||||
$table->unsignedDecimal('price', 20, 2)->comment('单价');
|
||||
$table->json('source')->nullable();
|
||||
$table->timestamp('created_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_order_items');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallOrdersTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_orders', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->string('order_no', 32)->unique()->comment('订单编号');
|
||||
$table->unsignedInteger('user_id')->index()->comment('下单用户');
|
||||
|
||||
$table->unsignedDecimal('amount', 20, 2)->comment('订单金额');
|
||||
$table->unsignedDecimal('freight', 10, 2)->default(0)->comment('运费');
|
||||
|
||||
$table->timestamp('expired_at')->nullable()->comment('订单过期时间');
|
||||
$table->timestamp('paid_at')->nullable()->comment('支付时间');
|
||||
|
||||
$table->string('state', 16)->comment('状态')->nullable();
|
||||
$table->boolean('type')->comment('订单类型:1 正常 2试用');
|
||||
$table->string('remark')->nullable()->comment('用户留言');
|
||||
$table->string('description')->nullable()->comment('备注');
|
||||
|
||||
$table->json('source')->comment('附加数据')->nullable();
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_orders');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallReasonsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_reasons', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('reasons');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallRefundExpressesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_refund_expresses', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('refund_id')->index()->comment('所属退款单');
|
||||
$table->string('company')->nullable()->comment('退款物流');
|
||||
$table->string('number')->nullable()->comment('退款单号');
|
||||
$table->timestamp('deliver_at')->nullable()->comment('寄回时间');
|
||||
$table->timestamp('receive_at')->nullable()->comment('收到时间');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_refund_expresses');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallRefundItemsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_refund_items', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('refund_id')->index()->comment('所属退款单');
|
||||
$table->unsignedBigInteger('order_id')->comment('所属订单');
|
||||
$table->unsignedBigInteger('order_item_id')->comment('详情ID');
|
||||
$table->unsignedInteger('qty')->comment('数量');
|
||||
$table->unsignedDecimal('price', 20, 2)->comment('单价');
|
||||
$table->json('source')->nullable();
|
||||
$table->timestamp('created_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_refund_items');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallRefundLogsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_refund_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('refund_id');
|
||||
$table->morphs('userable');
|
||||
$table->string('pictures')->nullable()->comment('图片');
|
||||
$table->string('title')->nullable()->comment('原因');
|
||||
$table->string('remark')->nullable()->comment('备注');
|
||||
$table->string('state', 16)->comment('状态')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_tags');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallRefundsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_refunds', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('order_id')->index()->comment('所属订单');
|
||||
$table->string('refund_no', 32)->comment('退款单号');
|
||||
$table->unsignedBigInteger('user_id')->comment('下单用户');
|
||||
$table->unsignedDecimal('refund_total', 20, 2)->comment('申请退款金额');
|
||||
$table->unsignedDecimal('actual_total', 20, 2)->comment('实退金额');
|
||||
$table->string('state', 16)->comment('状态')->nullable();
|
||||
$table->string('remark')->nullable()->comment('备注');
|
||||
$table->timestamp('refunded_at')->nullable()->comment('退款时间');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_refunds');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Modules\Mall\Database\Seeders\RegionSeeder;
|
||||
|
||||
class CreateMallRegionsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_regions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('parent_id')->index();
|
||||
$table->string('name');
|
||||
$table->boolean('depth');
|
||||
});
|
||||
|
||||
Artisan::call('db:seed', [
|
||||
'--class' => RegionSeeder::class,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_regions');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallShopExpressTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_shop_express', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('shop_id')->index();
|
||||
$table->unsignedBigInteger('express_id')->index();
|
||||
$table->timestamps();
|
||||
|
||||
$table->primary(['shop_id', 'express_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_shop_express');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMallShopReasonsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_shop_reasons', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('shop_id')->index();
|
||||
$table->unsignedBigInteger('reason_id')->index();
|
||||
$table->timestamps();
|
||||
$table->primary(['shop_id', 'reason_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_shop_reasons');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallShopStaffersTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_shop_staffers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->unsignedBigInteger('shop_id')->index();
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->unsignedBigInteger('job_id')->index();
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_shop_staffers');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallShopsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_shops', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedInteger('user_id')->index()->default(0);
|
||||
$table->string('name');
|
||||
$table->boolean('is_self')->unsigned()->default(0)->comment('是否自营');
|
||||
$table->string('description')->nullable();
|
||||
$table->string('mobile')->nullable();
|
||||
$table->string('cover')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->unsignedInteger('province_id')->index()->default(0);
|
||||
$table->unsignedInteger('city_id')->index()->default(0);
|
||||
$table->unsignedInteger('district_id')->index()->default(0);
|
||||
$table->string('address')->nullable();
|
||||
$table->json('configs')->nullable();
|
||||
$table->integer('order')->default(9999)->comment('排序用的,后台控制');
|
||||
$table->string('reject_reason')->comment('驳回原因')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_shops');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallTagsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_tags', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_tags');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMallActivitiesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_activities', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->string('description')->nullable();
|
||||
$table->string('cover')->nullable();
|
||||
$table->text('content')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_activities');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddChannelToMallOrdersTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('mall_orders', function (Blueprint $table) {
|
||||
$table->boolean('channel')->default(1)->comment('渠道')->after('type');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('mall_orders', function (Blueprint $table) {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddTypeAndPersonToMallOrdersExpressesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('mall_order_expresses', function (Blueprint $table) {
|
||||
$table->boolean('type')->default(1)->comment('方式')->after('receive_at');
|
||||
$table->boolean('person')->nullable()->comment('经办人')->after('type');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('mall_orders_expresses', function (Blueprint $table) {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMallVideosTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_videos', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('cover')->nullable();
|
||||
$table->string('path');
|
||||
$table->boolean('status')->default(1);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_videos');
|
||||
}
|
||||
}
|
||||
45
modules/Mall/Database/Seeders/ExpressSeeder.php
Normal file
45
modules/Mall/Database/Seeders/ExpressSeeder.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ExpressSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* 基础物流公司数据
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
DB::insert("INSERT INTO `mall_expresses` (`name`, `slug`, `status`, `created_at`, `updated_at`) VALUES
|
||||
('圆通速递', 'yuantong', 1, now(), now()),
|
||||
('韵达快递', 'yunda', 1, now(), now()),
|
||||
('中通快递', 'zhongtong', 1, now(), now()),
|
||||
('百世快递', 'huitongkuaidi', 1, now(), now()),
|
||||
('申通快递', 'shentong', 1, now(), now()),
|
||||
('顺丰速运', 'shunfeng', 1, now(), now()),
|
||||
('邮政快递包裹', 'youzhengguonei', 1, now(), now()),
|
||||
('京东物流', 'jd', 1, now(), now()),
|
||||
('EMS', 'ems', 1, now(), now()),
|
||||
('极兔速递', 'jtexpress', 1, now(), now()),
|
||||
('邮政标准快递', 'youzhengbk', 1, now(), now()),
|
||||
('德邦', 'debangwuliu', 1, now(), now()),
|
||||
('德邦快递', 'debangkuaidi', 1, now(), now()),
|
||||
('宅急送', 'zhaijisong', 1, now(), now()),
|
||||
('优速快递', 'youshuwuliu', 1, now(), now()),
|
||||
('圆通快运', 'yuantongkuaiyun', 1, now(), now()),
|
||||
('百世快运', 'baishiwuliu', 1, now(), now()),
|
||||
('顺丰快运', 'shunfengkuaiyun', 1, now(), now()),
|
||||
('众邮快递', 'zhongyouex', 1, now(), now()),
|
||||
('中通快运', 'zhongtongkuaiyun', 1, now(), now()),
|
||||
('UPS', 'ups', 1, now(), now()),
|
||||
('安能快运', 'annengwuliu', 1, now(), now()),
|
||||
('韵达快运', 'yundakuaiyun', 1, now(), now()),
|
||||
('中通国际', 'zhongtongguoji', 1, now(), now()),
|
||||
('D速快递', 'dsukuaidi', 1, now(), now()),
|
||||
('特急送', 'lntjs', 1, now(), now()),
|
||||
('九曳供应链', 'jiuyescm', 1, now(), now()),
|
||||
('丹鸟', 'danniao', 1, now(), now())");
|
||||
}
|
||||
}
|
||||
3314
modules/Mall/Database/Seeders/RegionSeeder.php
Normal file
3314
modules/Mall/Database/Seeders/RegionSeeder.php
Normal file
File diff suppressed because it is too large
Load Diff
11
modules/Mall/Events/OrderCanceled.php
Normal file
11
modules/Mall/Events/OrderCanceled.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
/**
|
||||
* 订单取消事件
|
||||
*/
|
||||
class OrderCanceled extends OrderEvent
|
||||
{
|
||||
|
||||
}
|
||||
11
modules/Mall/Events/OrderClosed.php
Normal file
11
modules/Mall/Events/OrderClosed.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
/**
|
||||
* 订单关闭事件
|
||||
*/
|
||||
class OrderClosed extends OrderEvent
|
||||
{
|
||||
|
||||
}
|
||||
11
modules/Mall/Events/OrderCompleted.php
Normal file
11
modules/Mall/Events/OrderCompleted.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
/**
|
||||
* 订单完结事件
|
||||
*/
|
||||
class OrderCompleted extends OrderEvent
|
||||
{
|
||||
|
||||
}
|
||||
11
modules/Mall/Events/OrderCreated.php
Normal file
11
modules/Mall/Events/OrderCreated.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
/**
|
||||
* 订单创建完成事件
|
||||
*/
|
||||
class OrderCreated extends OrderEvent
|
||||
{
|
||||
|
||||
}
|
||||
11
modules/Mall/Events/OrderDelivered.php
Normal file
11
modules/Mall/Events/OrderDelivered.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
/**
|
||||
* 订单已发货完成
|
||||
*/
|
||||
class OrderDelivered extends OrderEvent
|
||||
{
|
||||
|
||||
}
|
||||
27
modules/Mall/Events/OrderEvent.php
Normal file
27
modules/Mall/Events/OrderEvent.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Modules\Mall\Models\Order;
|
||||
|
||||
class OrderEvent
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var \Modules\Mall\Models\Order
|
||||
*/
|
||||
public Order $order;
|
||||
|
||||
/**
|
||||
* 创建事件实例,传播订单模型
|
||||
* @param \Modules\Mall\Models\Order $order
|
||||
*/
|
||||
public function __construct(Order $order)
|
||||
{
|
||||
$this->order = $order;
|
||||
}
|
||||
|
||||
}
|
||||
11
modules/Mall/Events/OrderPaid.php
Normal file
11
modules/Mall/Events/OrderPaid.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
/**
|
||||
* 订单支付完成事件
|
||||
*/
|
||||
class OrderPaid extends OrderEvent
|
||||
{
|
||||
|
||||
}
|
||||
11
modules/Mall/Events/OrderSigned.php
Normal file
11
modules/Mall/Events/OrderSigned.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
/**
|
||||
* 订单签收完成
|
||||
*/
|
||||
class OrderSigned extends OrderEvent
|
||||
{
|
||||
|
||||
}
|
||||
23
modules/Mall/Events/RefundAgreed.php
Normal file
23
modules/Mall/Events/RefundAgreed.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Modules\Mall\Models\Refund;
|
||||
|
||||
/**
|
||||
* 同意退款
|
||||
*/
|
||||
class RefundAgreed
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public Refund $refund;
|
||||
|
||||
public function __construct(Refund $refund)
|
||||
{
|
||||
$this->refund = $refund;
|
||||
}
|
||||
|
||||
}
|
||||
27
modules/Mall/Events/RefundApplied.php
Normal file
27
modules/Mall/Events/RefundApplied.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Modules\Mall\Models\Order;
|
||||
use Modules\Mall\Models\Refund;
|
||||
|
||||
/**
|
||||
* 订单申请退款
|
||||
*/
|
||||
class RefundApplied
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public Order $order;
|
||||
|
||||
public Refund $refund;
|
||||
|
||||
public function __construct(Order $order, Refund $refund)
|
||||
{
|
||||
$this->order = $order;
|
||||
$this->refund = $refund;
|
||||
}
|
||||
|
||||
}
|
||||
23
modules/Mall/Events/RefundCompleted.php
Normal file
23
modules/Mall/Events/RefundCompleted.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Modules\Mall\Models\Refund;
|
||||
|
||||
/**
|
||||
* 退款完成事件
|
||||
*/
|
||||
class RefundCompleted
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public Refund $refund;
|
||||
|
||||
public function __construct(Refund $refund)
|
||||
{
|
||||
$this->refund = $refund;
|
||||
}
|
||||
|
||||
}
|
||||
23
modules/Mall/Events/RefundProcessed.php
Normal file
23
modules/Mall/Events/RefundProcessed.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Modules\Mall\Models\Refund;
|
||||
|
||||
/**
|
||||
* 退款中事件,可选择在此处切入退款功能
|
||||
*/
|
||||
class RefundProcessed
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public Refund $refund;
|
||||
|
||||
public function __construct(Refund $refund)
|
||||
{
|
||||
$this->refund = $refund;
|
||||
}
|
||||
|
||||
}
|
||||
23
modules/Mall/Events/RefundRefused.php
Normal file
23
modules/Mall/Events/RefundRefused.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Modules\Mall\Models\Refund;
|
||||
|
||||
/**
|
||||
* 拒绝退款
|
||||
*/
|
||||
class RefundRefused
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public Refund $refund;
|
||||
|
||||
public function __construct(Refund $refund)
|
||||
{
|
||||
$this->refund = $refund;
|
||||
}
|
||||
|
||||
}
|
||||
127
modules/Mall/Facades/Item.php
Normal file
127
modules/Mall/Facades/Item.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Facades;
|
||||
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Modules\Mall\Models\Address;
|
||||
use Modules\Mall\Models\GoodsSku;
|
||||
|
||||
class Item implements Arrayable
|
||||
{
|
||||
|
||||
public GoodsSku $model;
|
||||
|
||||
public int $sku_id;
|
||||
|
||||
public int $qty;
|
||||
|
||||
public float $price;
|
||||
|
||||
public int $shop_id;
|
||||
|
||||
public array $source;
|
||||
|
||||
public string $orderby;
|
||||
|
||||
public $address;
|
||||
|
||||
/**
|
||||
* Item constructor.
|
||||
*
|
||||
* @param \Modules\Mall\Models\GoodsSku $item
|
||||
* @param Address|null $address
|
||||
* @param int $qty
|
||||
*/
|
||||
public function __construct(GoodsSku $item, $address = null, int $qty = 1)
|
||||
{
|
||||
$this->model = $item;
|
||||
$this->sku_id = $item->id;
|
||||
$this->shop_id = $item->getShopIdAttribute();
|
||||
$this->orderby = $item->getShopTypeAttribute().'_'.$item->getShopIdAttribute();
|
||||
$this->qty = $qty;
|
||||
$this->price = $item->getItemPrice();
|
||||
$this->address = $address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取条目总价
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2019/11/21 11:03 上午
|
||||
* @return float
|
||||
*/
|
||||
public function total(): float
|
||||
{
|
||||
return bcmul($this->price, $this->qty, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取总总量
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/14 13:20
|
||||
* @return float
|
||||
*/
|
||||
public function weight(): float
|
||||
{
|
||||
return bcmul($this->model->getGoodsWeight(), $this->qty, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取运费
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/14 13:34
|
||||
*/
|
||||
public function freight(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取shop
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/14 14:15
|
||||
*/
|
||||
public function shop(): array
|
||||
{
|
||||
return [
|
||||
'shop_id' => $this->model->getShopIdAttribute(),
|
||||
'name' => $this->model->getShopNameAttribute(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 下单存入order_item表
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/18 8:37
|
||||
*/
|
||||
public function getSource(): array
|
||||
{
|
||||
return $this->model->getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 转换成数组
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2020/9/23 4:00 下午
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'goods_id' => $this->model->goods_id,
|
||||
'goods_sku_id' => $this->sku_id,
|
||||
'title' => $this->model->getGoodsName(),
|
||||
'value' => $this->model->getItemValue(),
|
||||
'cover' => $this->model->cover_url,
|
||||
'price' => $this->price,
|
||||
'qty' => $this->qty,
|
||||
'score' => $this->model->score,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
386
modules/Mall/Facades/Order.php
Normal file
386
modules/Mall/Facades/Order.php
Normal file
@@ -0,0 +1,386 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Facades;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Mall\Events\OrderCreated;
|
||||
use Modules\Mall\Models\Address;
|
||||
use Modules\Mall\Models\Goods;
|
||||
use Modules\Mall\Models\Order as OrderModel;
|
||||
use Modules\User\Models\User;
|
||||
|
||||
class Order
|
||||
{
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected int $user_id;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected float $total;
|
||||
|
||||
/**
|
||||
* @var Address
|
||||
*/
|
||||
protected Address $address;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected Collection $items;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected string $remark;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected int $type;
|
||||
protected int $channel = 1;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $source;
|
||||
|
||||
/**
|
||||
* Notes: 设置当前用户
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/19 10:40
|
||||
* @param User $user
|
||||
* @return $this
|
||||
*/
|
||||
public function user(User $user): Order
|
||||
{
|
||||
$this->user_id = $user->getAuthIdentifier();;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 设置类型
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/10/18 10:03
|
||||
* @param $type
|
||||
* @return $this
|
||||
*/
|
||||
public function type($type): Order
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 订单渠道
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/9/8 15:51
|
||||
*/
|
||||
public function channel($channel): self
|
||||
{
|
||||
$this->channel = $channel;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 设置订单备注信息
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/19 10:40
|
||||
* @param string|null $remark
|
||||
* @return $this
|
||||
*/
|
||||
public function remark(?string $remark = ''): Order
|
||||
{
|
||||
$this->remark = $remark;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 附加数据
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/19 10:40
|
||||
* @param array $source
|
||||
* @return $this
|
||||
*/
|
||||
public function source(array $source): Order
|
||||
{
|
||||
$this->source = $source;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 设置商品数据
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/14 13:58
|
||||
* @param $items
|
||||
* @return $this
|
||||
*/
|
||||
public function items($items): Order
|
||||
{
|
||||
$this->items = new Collection($items);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 设置订单收货地址
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/19 10:41
|
||||
* @param Address $address
|
||||
* @return $this
|
||||
*/
|
||||
public function address(Address $address): Order
|
||||
{
|
||||
$this->address = $address;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 创建订单
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/19 10:42
|
||||
* @return Collection
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create(): Collection
|
||||
{
|
||||
if ($this->items->isEmpty()) {
|
||||
throw new Exception('无法创建无内容的订单');
|
||||
}
|
||||
|
||||
if (! is_numeric($this->user_id)) {
|
||||
throw new Exception('必须先设置订单用户');
|
||||
}
|
||||
$splits = $this->splitOrderByShop();
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$orders = [];
|
||||
foreach ($splits as $split) {
|
||||
$orders[] = $this->createOne($split['items']);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
$result = new Collection($orders);
|
||||
|
||||
$result->total = $this->total();
|
||||
|
||||
return $result;
|
||||
} catch (Exception $exception) {
|
||||
DB::rollBack();
|
||||
throw new Exception($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 按照商户,对订单进行分组
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/19 10:43
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function splitOrderByShop()
|
||||
{
|
||||
if (empty($this->items)) {
|
||||
throw new Exception('无法创建无内容的订单');
|
||||
}
|
||||
|
||||
return $this->items->groupBy('orderby')->map(function ($items, $key) {
|
||||
/**
|
||||
* 计算分订单总价格
|
||||
*/
|
||||
$items->amount = $items->reduce(function ($total, $item) {
|
||||
return $total + $item->total();
|
||||
});
|
||||
|
||||
/**
|
||||
* 计算分订单总数量
|
||||
*/
|
||||
$items->qty = $items->reduce(function ($qty, $item) {
|
||||
return $qty + $item->qty;
|
||||
});
|
||||
|
||||
/**
|
||||
* 计算分订单运费
|
||||
*/
|
||||
$items->freight = $items->reduce(function ($total, $item) {
|
||||
return $total + $item->freight();
|
||||
});
|
||||
|
||||
/**
|
||||
* 回传店铺ID
|
||||
*/
|
||||
$items->shop_id = $items->first()->shop_id;
|
||||
|
||||
return [
|
||||
'shop' => $items->first()->shop(),
|
||||
'items' => $items,
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 创建一条订单记录
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/21 10:24
|
||||
* @param Collection $split
|
||||
* @return Builder|Model
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function createOne(Collection $split)
|
||||
{
|
||||
/**
|
||||
* 创建主订单
|
||||
*/
|
||||
$order = OrderModel::query()
|
||||
->create([
|
||||
'shop_id' => $split->shop_id,
|
||||
'user_id' => $this->user_id,
|
||||
'amount' => $split->amount,
|
||||
'type' => $this->type,
|
||||
'channel' => $this->channel,
|
||||
'freight' => $split->freight,
|
||||
'remark' => $this->remark,
|
||||
'source' => $this->source ?? null,
|
||||
]);
|
||||
|
||||
/**
|
||||
* 创建订单子条目
|
||||
*/
|
||||
foreach ($split as $item) {
|
||||
// 库存校验
|
||||
if ($item->qty > $item->model->getGoodsStock()) {
|
||||
throw new Exception(sprintf('[%s]库存不足', $item->model->getGoodsName()));
|
||||
}
|
||||
|
||||
$order->items()
|
||||
->create([
|
||||
'item_type' => get_class($item->model),
|
||||
'item_id' => $item->sku_id,
|
||||
'qty' => $item->qty,
|
||||
'price' => $item->price,
|
||||
'source' => $item->getSource(),
|
||||
]);
|
||||
|
||||
if ($item->model->goods->deduct_stock_type == Goods::DEDUCT_STOCK_ORDER) {
|
||||
// 扣减库存
|
||||
$item->model->deductStock($item->qty, $order->user_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动更新地址
|
||||
*/
|
||||
if ($this->address instanceof Address) {
|
||||
$this->setOrderAddress($order, $this->address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单自动审核
|
||||
*/
|
||||
if (config('order.auto_audit')) {
|
||||
$order->audit();
|
||||
}
|
||||
|
||||
event(new OrderCreated($order));
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 计算订单总价格
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/21 10:26
|
||||
* @return float|int|string
|
||||
*/
|
||||
public function total()
|
||||
{
|
||||
$this->total = 0;
|
||||
foreach ($this->items as $item) {
|
||||
$this->total = bcadd($this->total, $item->total(), 2);
|
||||
}
|
||||
|
||||
return $this->total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 设置订单收货地址
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/21 10:26
|
||||
* @param $order
|
||||
* @param $address
|
||||
*/
|
||||
protected function setOrderAddress($order, $address)
|
||||
{
|
||||
$order->express()
|
||||
->create([
|
||||
'name' => $address->name,
|
||||
'mobile' => $address->mobile,
|
||||
'province_id' => $address->province_id,
|
||||
'city_id' => $address->city_id,
|
||||
'district_id' => $address->district_id,
|
||||
'address' => $address->address,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 魔术方法,获取一些参数
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/21 10:27
|
||||
* @param $attr
|
||||
* @return float|int|string|null
|
||||
*/
|
||||
public function __get($attr)
|
||||
{
|
||||
switch ($attr) {
|
||||
case 'total':
|
||||
return $this->total();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取订单详情
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2019/11/22 1:51 下午
|
||||
* @param string $order_no
|
||||
* @return mixed
|
||||
*/
|
||||
public function get(string $order_no)
|
||||
{
|
||||
return OrderModel::where('user_id', $this->user_id)
|
||||
->with(['user', 'items', 'express', 'seller', 'logs'])
|
||||
->where('order_no', $order_no)
|
||||
->first();
|
||||
}
|
||||
|
||||
}
|
||||
250
modules/Mall/Facades/Refund.php
Normal file
250
modules/Mall/Facades/Refund.php
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Facades;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Mall\Events\RefundApplied;
|
||||
use Modules\Mall\Models\Order as OrderModel;
|
||||
use Modules\Mall\Models\Refund as RefundModel;
|
||||
|
||||
class Refund
|
||||
{
|
||||
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected string $remark;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $logs;
|
||||
|
||||
protected $refund;
|
||||
|
||||
protected $order;
|
||||
|
||||
protected $items;
|
||||
|
||||
protected $total;
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function user($user): Refund
|
||||
{
|
||||
if ($user instanceof Authenticatable) {
|
||||
$this->user = $user;
|
||||
} else {
|
||||
throw new Exception('非法用户');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 订单
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/17 8:46
|
||||
* @param OrderModel $order
|
||||
* @return $this
|
||||
*/
|
||||
public function order(OrderModel $order): Refund
|
||||
{
|
||||
$this->order = $order;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes:商品
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/17 8:46
|
||||
* @param array $items
|
||||
* @return Refund
|
||||
*/
|
||||
public function items(array $items): Refund
|
||||
{
|
||||
$this->items = $items;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 退款金额
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/17 8:48
|
||||
* @param float $total
|
||||
* @return Refund
|
||||
*/
|
||||
public function total(float $total): Refund
|
||||
{
|
||||
$this->total = $total;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 设置订单备注信息
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/21 10:31
|
||||
* @param string $remark
|
||||
* @return $this
|
||||
*/
|
||||
public function remark(string $remark): Refund
|
||||
{
|
||||
$this->remark = $remark;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 退款日志
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/17 11:37
|
||||
* @param $logs
|
||||
* @return $this
|
||||
*/
|
||||
public function logs($logs): Refund
|
||||
{
|
||||
if (! isset($logs['remark']) && ! empty($this->remark)) {
|
||||
$logs['remark'] = $this->remark;
|
||||
}
|
||||
|
||||
$this->logs = $logs;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 设置退款商品
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/17 8:51
|
||||
*/
|
||||
public function setItems(): Refund
|
||||
{
|
||||
$this->items = $this->order->items->map(function ($item) {
|
||||
return [
|
||||
'order_item_id' => $item->id,
|
||||
'qty' => $item->qty,
|
||||
];
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 创建退款单
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/17 8:49
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
|
||||
if (! $this->order) {
|
||||
throw new Exception('未设置订单');
|
||||
}
|
||||
|
||||
if (empty($this->items)) {
|
||||
$this->setItems();
|
||||
}
|
||||
|
||||
if (! $this->order->can('refund')) {
|
||||
throw new Exception('订单状态不可退款');
|
||||
}
|
||||
|
||||
$maxAmount = 0;
|
||||
$refundItems = [];
|
||||
|
||||
//判断最大可退数量
|
||||
foreach ($this->items as $item) {
|
||||
|
||||
$orderItem = $this->order->items()->find($item['order_item_id']);
|
||||
if (! $orderItem) {
|
||||
throw new Exception('未找到可退商品');
|
||||
}
|
||||
|
||||
if (! $orderItem->canRefund()) {
|
||||
throw new \Exception('退款/货失败,此商品不可退款/货');
|
||||
}
|
||||
|
||||
if ($item['qty'] <= 0) {
|
||||
throw new Exception('【'.$orderItem->source['goods_name'].'】退货数量必须大于0');
|
||||
}
|
||||
|
||||
if ($item['qty'] > $orderItem->qty) {
|
||||
throw new Exception('【'.$orderItem->source['goods_name'].'】超过最大可退数量');
|
||||
}
|
||||
|
||||
$maxAmount += $orderItem->price * $item['qty'];
|
||||
|
||||
$refundItems[] = new RefundItem($orderItem, $item['qty']);
|
||||
}
|
||||
|
||||
// 自动计算退款金额
|
||||
if (is_null($this->total)) {
|
||||
$this->total = $maxAmount;
|
||||
} elseif ($this->total > $maxAmount) {
|
||||
throw new Exception('超过最大可退金额');
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($refundItems) {
|
||||
$this->refund = $this->order->refunds()
|
||||
->create([
|
||||
'refund_total' => $this->total,
|
||||
'actual_total' => 0,
|
||||
'user_id' => $this->user->id,
|
||||
'shop_id' => $this->order->shop_id,
|
||||
'state' => RefundModel::REFUND_APPLY,
|
||||
'remark' => $this->remark,
|
||||
]);
|
||||
|
||||
foreach ($refundItems as $item) {
|
||||
$this->refund->items()->create($item->toArray());
|
||||
}
|
||||
|
||||
if ($this->logs) {
|
||||
$this->createLog();
|
||||
}
|
||||
|
||||
event(new RefundApplied($this->order, $this->refund));
|
||||
|
||||
});
|
||||
|
||||
return $this->refund;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 添加日志
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date : 2020/12/11 11:43
|
||||
*/
|
||||
public function createLog()
|
||||
{
|
||||
$logs = $this->logs;
|
||||
|
||||
if ($this->user) {
|
||||
$logs['userable_type'] = get_class($this->user);
|
||||
$logs['userable_id'] = $this->user->id;
|
||||
$logs['state'] = $this->refund->state;
|
||||
}
|
||||
|
||||
$this->refund->logs()->create($logs);
|
||||
}
|
||||
|
||||
}
|
||||
68
modules/Mall/Facades/RefundItem.php
Normal file
68
modules/Mall/Facades/RefundItem.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Facades;
|
||||
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Support\Jsonable;
|
||||
|
||||
class RefundItem implements Arrayable, Jsonable
|
||||
{
|
||||
|
||||
public int $qty;
|
||||
|
||||
public float $price;
|
||||
|
||||
public $order_item_id;
|
||||
|
||||
public $order_id;
|
||||
|
||||
public $source;
|
||||
|
||||
/**
|
||||
* RefundItem constructor.
|
||||
* @param $item
|
||||
* @param int $qty
|
||||
*/
|
||||
public function __construct($item, int $qty = 1)
|
||||
{
|
||||
$this->qty = $qty;
|
||||
$this->price = $item->price;
|
||||
$this->order_id = $item->order_id;
|
||||
$this->order_item_id = $item->id;
|
||||
$this->source = $item->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取条目总价
|
||||
* @Author: 玄尘
|
||||
* @Date : 2020/12/10 9:43
|
||||
* @return float
|
||||
*/
|
||||
public function total(): float
|
||||
{
|
||||
return bcmul($this->price, $this->qty, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 返回数组
|
||||
* @Author: 玄尘
|
||||
* @Date : 2021/5/21 10:40
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'qty' => $this->qty,
|
||||
'price' => $this->price,
|
||||
'order_id' => $this->order_id,
|
||||
'order_item_id' => $this->order_item_id,
|
||||
'source' => $this->source,
|
||||
];
|
||||
}
|
||||
|
||||
public function toJson($options = 0)
|
||||
{
|
||||
return json_encode($this->toArray(), $options);
|
||||
}
|
||||
|
||||
}
|
||||
15
modules/Mall/Facades/Workflow.php
Normal file
15
modules/Mall/Facades/Workflow.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class Workflow extends Facade
|
||||
{
|
||||
|
||||
protected static function getFacadeAccessor(): string
|
||||
{
|
||||
return 'workflow';
|
||||
}
|
||||
|
||||
}
|
||||
25
modules/Mall/Http/Controllers/Admin/Action/Order/Audit.php
Normal file
25
modules/Mall/Http/Controllers/Admin/Action/Order/Audit.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Modules\Mall\Models\Order;
|
||||
|
||||
class Audit extends RowAction
|
||||
{
|
||||
|
||||
public $name = '通过审核';
|
||||
|
||||
public function handle(Order $order): Response
|
||||
{
|
||||
try {
|
||||
$order->pay();
|
||||
|
||||
return $this->response()->success('审核通过')->refresh();
|
||||
} catch (\Exception $exception) {
|
||||
return $this->response()->error($exception->getMessage())->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Models\Express;
|
||||
use Modules\Mall\Models\Order;
|
||||
use Modules\Mall\Models\OrderExpress;
|
||||
|
||||
class Delivered extends RowAction
|
||||
{
|
||||
|
||||
public $name = '商品发货';
|
||||
|
||||
public function handle(Order $order, Request $request): Response
|
||||
{
|
||||
if ($request->type == OrderExpress::TYPE_EXPRESS && (empty($request->express_id) || empty($request->express_no))) {
|
||||
return $this->response()->error('缺少快递公司或快递单号');
|
||||
}
|
||||
|
||||
$result = $order->deliver($request->express_id, $request->express_no, $request->type, $request->person);
|
||||
if ($result === true) {
|
||||
return $this->response()->success('发货成功')->refresh();
|
||||
} else {
|
||||
return $this->response()->error('失败');
|
||||
}
|
||||
}
|
||||
|
||||
public function form()
|
||||
{
|
||||
$order = Order::find($this->getKey());
|
||||
$expresses = $order->shop->expresses()->pluck('name', 'id');
|
||||
|
||||
$this->select('type', '方式')
|
||||
->options(OrderExpress::TYPE_MAP)
|
||||
->required();
|
||||
|
||||
$this->select('express_id', '物流')
|
||||
->options($expresses);
|
||||
$this->text('express_no', '物流单号');
|
||||
$this->text('person', '经办人');
|
||||
}
|
||||
|
||||
}
|
||||
25
modules/Mall/Http/Controllers/Admin/Action/Order/Pay.php
Normal file
25
modules/Mall/Http/Controllers/Admin/Action/Order/Pay.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Modules\Mall\Models\Order;
|
||||
|
||||
class Pay extends RowAction
|
||||
{
|
||||
|
||||
public $name = '支付测试-正式版本移除';
|
||||
|
||||
public function handle(Order $order): Response
|
||||
{
|
||||
try {
|
||||
$order->pay();
|
||||
|
||||
return $this->response()->success('支付状态调整成功')->refresh();
|
||||
} catch (\Exception $exception) {
|
||||
return $this->response()->error($exception->getMessage())->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Encore\Admin\Facades\Admin;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class RefundAudit extends RowAction
|
||||
{
|
||||
|
||||
public $name = '审核';
|
||||
|
||||
public function handle(Model $model, Request $request): Response
|
||||
{
|
||||
$admin = Admin::user();
|
||||
|
||||
$state = $request->state;
|
||||
$remark = $request->remark;
|
||||
$res = false;
|
||||
|
||||
if (!$model->can('agree')) {
|
||||
return $this->response()->error('不可操作')->refresh();
|
||||
}
|
||||
|
||||
if ($state == 'agree') {
|
||||
$res = $model->setOperator($admin)->agree($remark);
|
||||
}
|
||||
|
||||
if ($state == 'refuse') {
|
||||
$res = $model->setOperator($admin)->refuse($remark);
|
||||
}
|
||||
|
||||
if ($res === true) {
|
||||
return $this->response()->success('操作成功')->refresh();
|
||||
}
|
||||
|
||||
return $this->response()->error('操作失败')->refresh();
|
||||
}
|
||||
|
||||
public function form(Model $model)
|
||||
{
|
||||
$this->select('state', '状态')
|
||||
->options([
|
||||
'agree' => '通过',
|
||||
'refuse' => '驳回',
|
||||
])
|
||||
->required();
|
||||
|
||||
$this->text('remark', '说明')
|
||||
->default($express->number ?? '')
|
||||
->required();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Encore\Admin\Facades\Admin;
|
||||
use Modules\Mall\Models\Refund;
|
||||
|
||||
class RefundReturns extends RowAction
|
||||
{
|
||||
|
||||
public $name = '退款';
|
||||
|
||||
public function handle(Refund $refund): Response
|
||||
{
|
||||
try {
|
||||
$admin = Admin::user();
|
||||
|
||||
if (!$refund->can('completed')) {
|
||||
return $this->response()->error('不可操作')->refresh();
|
||||
}
|
||||
|
||||
$res = $refund->setOperator($admin)->returns();
|
||||
|
||||
if ($res === true) {
|
||||
$refund->setOperator($admin)->complete();//设置完成
|
||||
|
||||
return $this->response()->success('操作成功')->refresh();
|
||||
}
|
||||
|
||||
return $this->response()->error('操作失败')->refresh();
|
||||
} catch (\Exception $exception) {
|
||||
return $this->response()->error($exception->getMessage())->refresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function dialog()
|
||||
{
|
||||
$this->confirm('您确定要打款吗');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Order;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Encore\Admin\Facades\Admin;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class RefundSign extends RowAction
|
||||
{
|
||||
|
||||
public $name = '签收';
|
||||
|
||||
public function handle(Model $model): Response
|
||||
{
|
||||
try {
|
||||
$admin = Admin::user();
|
||||
|
||||
if (!$model->can('sign')) {
|
||||
return $this->response()->error('不可操作')->refresh();
|
||||
}
|
||||
|
||||
$res = $model->setOperator($admin)->receive();
|
||||
|
||||
if ($res === true) {
|
||||
return $this->response()->success('操作成功')->refresh();
|
||||
}
|
||||
|
||||
return $this->response()->error('操作失败')->refresh();
|
||||
} catch (\Exception $exception) {
|
||||
return $this->response()->error($exception->getMessage())->refresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function dialog()
|
||||
{
|
||||
$this->confirm('您确定已经收到货了吗');
|
||||
}
|
||||
|
||||
}
|
||||
32
modules/Mall/Http/Controllers/Admin/Action/Shop/Close.php
Normal file
32
modules/Mall/Http/Controllers/Admin/Action/Shop/Close.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Shop;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Modules\Mall\Models\Shop;
|
||||
|
||||
class Close extends RowAction
|
||||
{
|
||||
|
||||
public $name = '关闭店铺';
|
||||
|
||||
public function handle(Shop $shop): Response
|
||||
{
|
||||
try {
|
||||
if ($shop->close()) {
|
||||
return $this->response()->success('店铺关闭成功')->refresh();
|
||||
} else {
|
||||
return $this->response()->error('店铺关闭失败')->refresh();
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
return $this->response()->error($exception->getMessage())->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public function dialog()
|
||||
{
|
||||
$this->confirm('确定关闭店铺吗?');
|
||||
}
|
||||
|
||||
}
|
||||
32
modules/Mall/Http/Controllers/Admin/Action/Shop/Open.php
Normal file
32
modules/Mall/Http/Controllers/Admin/Action/Shop/Open.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Shop;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Modules\Mall\Models\Shop;
|
||||
|
||||
class Open extends RowAction
|
||||
{
|
||||
|
||||
public $name = '开启店铺';
|
||||
|
||||
public function handle(Shop $shop): Response
|
||||
{
|
||||
try {
|
||||
if ($shop->open()) {
|
||||
return $this->response()->success('店铺开启成功')->refresh();
|
||||
} else {
|
||||
return $this->response()->error('店铺开启失败')->refresh();
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
return $this->response()->error($exception->getMessage())->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public function dialog()
|
||||
{
|
||||
$this->confirm('确定开启店铺吗?');
|
||||
}
|
||||
|
||||
}
|
||||
32
modules/Mall/Http/Controllers/Admin/Action/Shop/Pass.php
Normal file
32
modules/Mall/Http/Controllers/Admin/Action/Shop/Pass.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Shop;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Modules\Mall\Models\Shop;
|
||||
|
||||
class Pass extends RowAction
|
||||
{
|
||||
|
||||
public $name = '审核通过';
|
||||
|
||||
public function handle(Shop $shop): Response
|
||||
{
|
||||
try {
|
||||
if ($shop->pass()) {
|
||||
return $this->response()->success('审核通过成功')->refresh();
|
||||
} else {
|
||||
return $this->response()->error('审核通过失败')->refresh();
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
return $this->response()->error($exception->getMessage())->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public function dialog()
|
||||
{
|
||||
$this->confirm('确定审核通过?');
|
||||
}
|
||||
|
||||
}
|
||||
33
modules/Mall/Http/Controllers/Admin/Action/Shop/Reject.php
Normal file
33
modules/Mall/Http/Controllers/Admin/Action/Shop/Reject.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Action\Shop;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Models\Shop;
|
||||
|
||||
class Reject extends RowAction
|
||||
{
|
||||
|
||||
public $name = '驳回申请';
|
||||
|
||||
public function handle(Shop $shop, Request $request): Response
|
||||
{
|
||||
try {
|
||||
if ($shop->reject($request->reject_reason)) {
|
||||
return $this->response()->success('驳回申请成功')->refresh();
|
||||
} else {
|
||||
return $this->response()->error('驳回申请失败')->refresh();
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
return $this->response()->error($exception->getMessage())->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public function form()
|
||||
{
|
||||
$this->textarea('reject_reason', '驳回原因')->rules('required');
|
||||
}
|
||||
|
||||
}
|
||||
48
modules/Mall/Http/Controllers/Admin/ActivityController.php
Normal file
48
modules/Mall/Http/Controllers/Admin/ActivityController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Mall\Models\Activity;
|
||||
|
||||
class ActivityController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads;
|
||||
|
||||
public $title = "活动列表";
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Activity());
|
||||
|
||||
$grid->disableFilter();
|
||||
|
||||
|
||||
$grid->column('id', '#ID#');
|
||||
$grid->column('title', '活动名称');
|
||||
$grid->column('description', '简介');
|
||||
$grid->column('status', '状态')->switch();
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
protected function form(): Form
|
||||
{
|
||||
$form = new Form(new Activity());
|
||||
|
||||
$form->text('title', '活动名称');
|
||||
$this->cover($form);
|
||||
$form->textarea('description', '简介');
|
||||
$form->ueditor('content', '详情')->required();
|
||||
|
||||
$form->switch('status', '状态')->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
93
modules/Mall/Http/Controllers/Admin/AddressController.php
Normal file
93
modules/Mall/Http/Controllers/Admin/AddressController.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Linker\Traits\WithLinker;
|
||||
use Modules\Mall\Models\Address;
|
||||
use Modules\Mall\Models\Banner;
|
||||
use Modules\Mall\Models\Region;
|
||||
use Modules\User\Models\User;
|
||||
|
||||
class AddressController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads,
|
||||
WithLinker;
|
||||
|
||||
public $title = "收货地址";
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Address());
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('user_id', '所属用户')->select()->ajax(route('admin.user.users.ajax'));
|
||||
});
|
||||
});
|
||||
|
||||
$grid->model()->with(['user']);
|
||||
|
||||
$grid->column('id', '#ID#');
|
||||
$grid->column('user.username', '所属用户');
|
||||
$grid->column('name', '姓名');
|
||||
$grid->column('mobile', '手机号');
|
||||
$grid->column('province.name', '省');
|
||||
$grid->column('city.name', '市');
|
||||
$grid->column('district.name', '区');
|
||||
$grid->column('address', '详细地址');
|
||||
$grid->column('is_default', '默认?')->bool();
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
protected function form(): Form
|
||||
{
|
||||
$form = new Form(new Address);
|
||||
|
||||
$form->select('user_id', '所属用户')
|
||||
->options(function ($userId) {
|
||||
$user = User::find($userId);
|
||||
if ($user) {
|
||||
return [$user->id => $user->username.' ['.$user->info->nickname.']'];
|
||||
}
|
||||
})
|
||||
->value(request()->user_id ?? '')
|
||||
->ajax(route('admin.user.users.ajax'))
|
||||
->required();
|
||||
$form->text('name', '姓名');
|
||||
$form->text('mobile', '手机号');
|
||||
$form->select('province_id', '省份')
|
||||
->options(Region::where('parent_id', 1)->pluck('name', 'id'))
|
||||
->load('city_id', route('admin.mall.regions.region'))
|
||||
->required();
|
||||
$form->select('city_id', '城市')
|
||||
->options(function ($option) {
|
||||
$parent = Region::where('id', $option)->value('parent_id');
|
||||
|
||||
return Region::where(['parent_id' => $parent])->pluck('name', 'id');
|
||||
})
|
||||
->load('district_id', route('admin.mall.regions.region'))
|
||||
->required();
|
||||
$form->select('district_id', '区/县')
|
||||
->options(function ($option) {
|
||||
$parent = Region::where('id', $option)->value('parent_id');
|
||||
|
||||
return Region::where(['parent_id' => $parent])->pluck('name', 'id');
|
||||
})
|
||||
->required();
|
||||
$form->text('address', '详细地址')
|
||||
->required();
|
||||
|
||||
$form->switch('is_default', '默认?')->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
70
modules/Mall/Http/Controllers/Admin/AjaxController.php
Normal file
70
modules/Mall/Http/Controllers/Admin/AjaxController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Models\Activity;
|
||||
use Modules\Mall\Models\Address;
|
||||
use Modules\Mall\Models\Goods;
|
||||
use Modules\Mall\Models\GoodsSku;
|
||||
|
||||
class AjaxController
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes: 获取用户收货地址
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/7/29 13:33
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function address(Request $request)
|
||||
{
|
||||
$user_id = $request->get('q');
|
||||
|
||||
return Address::ByUserId($user_id)
|
||||
->oldest('is_default')
|
||||
->get()
|
||||
->map(function ($address) {
|
||||
return [
|
||||
'id' => $address->id,
|
||||
'text' => $address->getFullAddress(),
|
||||
];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取商品
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/7/29 13:46
|
||||
* @param Request $request
|
||||
*/
|
||||
public function goods(Request $request)
|
||||
{
|
||||
$address_id = $request->q;
|
||||
if (!$address_id){
|
||||
return [];
|
||||
}
|
||||
$address = Address::find($address_id);
|
||||
|
||||
return GoodsSku::query()
|
||||
->whereHas('goods', function ($q) {
|
||||
$q->where('channel', Goods::CHANNEL_FREE)->where('status', Goods::STATUS_UP);
|
||||
})
|
||||
->get()
|
||||
->map(function ($sku) use ($address) {
|
||||
$stockData = $address->user->getStockData();
|
||||
return [
|
||||
'id' => $sku->id,
|
||||
'text' => $sku->goods->name."(库存:{$stockData['residue']})",
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
74
modules/Mall/Http/Controllers/Admin/BannerController.php
Normal file
74
modules/Mall/Http/Controllers/Admin/BannerController.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Linker\Traits\WithLinker;
|
||||
use Modules\Mall\Models\Banner;
|
||||
|
||||
class BannerController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads,
|
||||
WithShop,
|
||||
WithLinker;
|
||||
|
||||
public $title = "轮播图管理";
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Banner);
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('title', '轮播标题');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('status', '状态')->radio([
|
||||
0 => '禁用',
|
||||
1 => '正常',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
$grid->model()->with(['shop']);
|
||||
|
||||
$grid->column('id', '#ID#');
|
||||
$grid->column('shop.name', '所属店铺');
|
||||
$grid->column('cover', '封面图片')->image('', 100, 100);
|
||||
$grid->column('展示位置')->display(function () {
|
||||
$data = [];
|
||||
foreach ($this->position as $position) {
|
||||
$data[] = $this->position_map[$position];
|
||||
}
|
||||
|
||||
return $data;
|
||||
})->label();
|
||||
$grid->column('title', '轮播标题');
|
||||
$grid->column('status', '状态')->bool();
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
protected function form(): Form
|
||||
{
|
||||
$form = new Form((new Banner)->disableModelCaching());
|
||||
|
||||
$this->shop($form)->help('不选择,默认为平台轮播');
|
||||
$form->text('title', '标题')
|
||||
->required();
|
||||
$form->multipleSelect('position', '展示位置')
|
||||
->options($form->model()->position_map)
|
||||
->required();
|
||||
$this->cover($form);
|
||||
$this->withUrl($form);
|
||||
$form->switch('status', '显示')->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
56
modules/Mall/Http/Controllers/Admin/BrandController.php
Normal file
56
modules/Mall/Http/Controllers/Admin/BrandController.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Models\Brand;
|
||||
|
||||
class BrandController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads,
|
||||
WithShop;
|
||||
|
||||
protected $title = '品牌管理';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Brand());
|
||||
|
||||
$grid->model()->with(['shop']);
|
||||
|
||||
$grid->column('cover', 'LOGO')->image('', 80);
|
||||
$grid->column('shop.name', '所属店铺');
|
||||
$grid->column('name', '品牌名称');
|
||||
$grid->column('status', '状态')->bool();
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Brand());
|
||||
|
||||
$this->shop($form)->required();
|
||||
$form->text('name', '品牌名称')
|
||||
->required();
|
||||
$this->cover($form);
|
||||
$form->textarea('description', '品牌简介');
|
||||
$form->switch('status', '状态')->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function ajax(Request $request)
|
||||
{
|
||||
$key = $request->q;
|
||||
|
||||
return Brand::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
|
||||
}
|
||||
|
||||
}
|
||||
101
modules/Mall/Http/Controllers/Admin/CategoryController.php
Normal file
101
modules/Mall/Http/Controllers/Admin/CategoryController.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Models\Category;
|
||||
|
||||
class CategoryController extends AdminController
|
||||
{
|
||||
|
||||
use WithShop,
|
||||
WithUploads;
|
||||
|
||||
protected $title = "分类管理";
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Category());
|
||||
|
||||
$parentId = request()->get('parent_id');
|
||||
$grid->model()
|
||||
->with(['shop'])
|
||||
->withCount('goods')
|
||||
->when($parentId, function ($query) use ($parentId) {
|
||||
$query->where('parent_id', $parentId);
|
||||
});
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('trashed', '回收站')->onlyTrashed();
|
||||
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('name', '分类名称');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('slug', '分类简称');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('status', '状态')->select([
|
||||
0 => '禁用',
|
||||
1 => '正常',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
$grid->column('shop.name', '所属店铺');
|
||||
$grid->column('parent.name', '上级分类')
|
||||
->link(function () {
|
||||
return route('admin.mall.categories.index', ['parent_id' => $this->parent_id]);
|
||||
}, '_self');;
|
||||
$grid->column('name', '分类名称')
|
||||
->link(function () {
|
||||
return route('admin.mall.categories.index', ['parent_id' => $this->id]);
|
||||
}, '_self');
|
||||
$grid->column('slug', '分类简称');
|
||||
$grid->column('goods_count', '分类商品');
|
||||
$grid->column('order', '排序');
|
||||
$grid->column('status', '状态')->bool();
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 编辑表单
|
||||
* @Date : 2021/4/25 1:41 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Encore\Admin\Form
|
||||
*/
|
||||
protected function form(): Form
|
||||
{
|
||||
$form = new Form(new Category);
|
||||
|
||||
$this->shop($form)->required();
|
||||
$form->select('parent_id', '上级分类')
|
||||
->options(Category::selectOptions(function ($model) {
|
||||
return $model->where('status', 1);
|
||||
}, '一级分类'))
|
||||
->required();
|
||||
$form->text('name', '分类名称')
|
||||
->required()
|
||||
->rules('required');
|
||||
$form->text('slug', '分类简称');
|
||||
$form->textarea('description', '分类简介');
|
||||
$this->cover($form, 'cover', '分类图片');
|
||||
$form->number('order', '排序')->default(0);
|
||||
$form->switch('status', '显示')->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function ajax(Request $request)
|
||||
{
|
||||
$key = $request->q;
|
||||
|
||||
return Category::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
|
||||
}
|
||||
|
||||
}
|
||||
67
modules/Mall/Http/Controllers/Admin/DashboardController.php
Normal file
67
modules/Mall/Http/Controllers/Admin/DashboardController.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Layout\Column;
|
||||
use Encore\Admin\Layout\Content;
|
||||
use Encore\Admin\Layout\Row;
|
||||
use Encore\Admin\Widgets\InfoBox;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Mall\Models\Goods;
|
||||
use Modules\Mall\Models\Order;
|
||||
use Modules\Mall\Models\Refund;
|
||||
use Modules\Mall\Models\Shop;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
|
||||
public function index(Content $content): Content
|
||||
{
|
||||
return $content
|
||||
->header('商城看板')
|
||||
->description('商城数据概览')
|
||||
->row(function (Row $row) {
|
||||
$row->column(3, function (Column $column) {
|
||||
$column->append(new InfoBox('店铺数量',
|
||||
'anchor',
|
||||
'blue',
|
||||
route('admin.mall.shops.index'),
|
||||
Shop::count()
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
$row->column(3, function (Column $column) {
|
||||
$column->append(new InfoBox('商品数量',
|
||||
'anchor',
|
||||
'blue',
|
||||
route('admin.mall.goods.index'),
|
||||
Goods::count()
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
$row->column(3, function (Column $column) {
|
||||
$column->append(new InfoBox('订单总数',
|
||||
'anchor',
|
||||
'blue',
|
||||
route('admin.mall.orders.index'),
|
||||
Order::count()
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
$row->column(3, function (Column $column) {
|
||||
$column->append(new InfoBox('退款订单',
|
||||
'anchor',
|
||||
'blue',
|
||||
route('admin.mall.refunds.index'),
|
||||
Refund::count()
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
82
modules/Mall/Http/Controllers/Admin/DeliveryController.php
Normal file
82
modules/Mall/Http/Controllers/Admin/DeliveryController.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Models\Delivery;
|
||||
|
||||
class DeliveryController extends AdminController
|
||||
{
|
||||
|
||||
use WithShop;
|
||||
|
||||
protected $title = '运费模板';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Delivery());
|
||||
|
||||
$grid->model()
|
||||
->with(['shop'])
|
||||
->withCount('rules');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('trashed', '回收站')->onlyTrashed();
|
||||
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('shop.name', '所属店铺');
|
||||
});
|
||||
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('name', '模板名称');
|
||||
});
|
||||
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('name', '计费方式')->select(Delivery::TYPE_MAP);
|
||||
});
|
||||
});
|
||||
|
||||
$grid->column('shop.name', '所属店铺');
|
||||
$grid->column('name', '模板名称');
|
||||
$grid->column('type', '计费方式')->using(Delivery::TYPE_MAP);
|
||||
|
||||
$grid->column('rules_count', '模板规则')->link(function () {
|
||||
return route('admin.mall.deliveries.rules.index', $this);
|
||||
}, '_self');
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Delivery());
|
||||
|
||||
$this->shop($form)->required();
|
||||
$form->text('name', '模板名称')->required();
|
||||
$form->radioButton('type', '计费方式')
|
||||
->options(Delivery::TYPE_MAP)
|
||||
->default(Delivery::TYPE_BY_COUNT)
|
||||
->required();
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 选择运费模板
|
||||
* @Date : 2021/5/11 11:36 上午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function ajax(Request $request)
|
||||
{
|
||||
$key = $request->get('q');
|
||||
|
||||
return Delivery::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
|
||||
}
|
||||
|
||||
}
|
||||
106
modules/Mall/Http/Controllers/Admin/DeliveryRuleController.php
Normal file
106
modules/Mall/Http/Controllers/Admin/DeliveryRuleController.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Encore\Admin\Layout\Content;
|
||||
use Modules\Mall\Models\Delivery;
|
||||
use Modules\Mall\Models\DeliveryRule;
|
||||
use Modules\Mall\Models\Region;
|
||||
|
||||
class DeliveryRuleController extends AdminController
|
||||
{
|
||||
|
||||
protected $title = '模板规则';
|
||||
|
||||
public function index(Content $content): Content
|
||||
{
|
||||
$delivery = Delivery::find(request()->delivery);
|
||||
|
||||
return $content
|
||||
->header($delivery->name)
|
||||
->description('模板规则')
|
||||
->body($this->grid($delivery));
|
||||
}
|
||||
|
||||
public function grid($delivery): Grid
|
||||
{
|
||||
$grid = new Grid(new DeliveryRule());
|
||||
|
||||
$grid->model()->where('delivery_id', $delivery->id);
|
||||
|
||||
if ($delivery->type === Delivery::TYPE_BY_COUNT) {
|
||||
$firstTitle = '首件(个)';
|
||||
$additionalTitle = '续件';
|
||||
} else {
|
||||
$firstTitle = '首重(Kg)';
|
||||
$additionalTitle = '续重';
|
||||
}
|
||||
|
||||
$grid->column('regions', '配送区域')
|
||||
->display(function () {
|
||||
return Region::find($this->regions);
|
||||
})
|
||||
->pluck('name')
|
||||
->label();
|
||||
$grid->column('first', $firstTitle);
|
||||
$grid->column('first_fee', '运费(元)');
|
||||
$grid->column('additional', $additionalTitle);
|
||||
$grid->column('additional_fee', '续费(元)');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function edit($id, Content $content): Content
|
||||
{
|
||||
return $content
|
||||
->title($this->title())
|
||||
->description($this->description['edit'] ?? trans('admin.edit'))
|
||||
->body($this->form()->edit(request()->rule));
|
||||
}
|
||||
|
||||
public function update($id)
|
||||
{
|
||||
return $this->form()->update(request()->rule);
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$delivery = Delivery::find(request()->delivery);
|
||||
|
||||
if ($delivery->type === Delivery::TYPE_BY_COUNT) {
|
||||
$firstTitle = '首件(个)';
|
||||
$additionalTitle = '续件';
|
||||
} else {
|
||||
$firstTitle = '首重(Kg)';
|
||||
$additionalTitle = '续重';
|
||||
}
|
||||
|
||||
$form = new Form(new DeliveryRule());
|
||||
|
||||
$form->multipleSelect('regions', '配送区域')
|
||||
->options(function ($regions) {
|
||||
if ($regions) {
|
||||
return Region::find($regions)->pluck('name', 'id');
|
||||
}
|
||||
})
|
||||
->ajax(route('admin.mall.regions.ajax'));
|
||||
$form->text('first', $firstTitle)
|
||||
->required();
|
||||
$form->currency('first_fee')
|
||||
->symbol('¥')
|
||||
->required();
|
||||
$form->text('additional', $additionalTitle)
|
||||
->required();
|
||||
$form->currency('additional_fee')
|
||||
->required()
|
||||
->symbol('¥');
|
||||
|
||||
$form->hidden('delivery_id')->value($delivery->id);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
70
modules/Mall/Http/Controllers/Admin/ExpressController.php
Normal file
70
modules/Mall/Http/Controllers/Admin/ExpressController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Mall\Models\Express;
|
||||
|
||||
class ExpressController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads;
|
||||
|
||||
protected $title = '物流管理';
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Express());
|
||||
|
||||
$grid->model()->withCount('shops');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('trashed', '回收站')->onlyTrashed();
|
||||
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('name', '物流名称');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('slug', '物流简称');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('status', '状态')->select([
|
||||
0 => '禁用',
|
||||
1 => '正常',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
$grid->column('id');
|
||||
$grid->column('cover', 'LOGO')->image('', 60);
|
||||
$grid->column('name', '物流名称');
|
||||
$grid->column('slug', '物流简称');
|
||||
$grid->column('description', '物流简介');
|
||||
$grid->column('status', '状态')->bool();
|
||||
$grid->column('shops_count', '使用商户');
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Express());
|
||||
|
||||
$form->text('name', '物流名称')
|
||||
->required();
|
||||
$form->text('slug', '物流简称')
|
||||
->required();
|
||||
$form->textarea('description', '物流简介');
|
||||
|
||||
$this->cover($form);
|
||||
|
||||
$form->switch('status', '状态')->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
228
modules/Mall/Http/Controllers/Admin/GoodsController.php
Normal file
228
modules/Mall/Http/Controllers/Admin/GoodsController.php
Normal file
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Illuminate\Support\Str;
|
||||
use Modules\Mall\Models\Brand;
|
||||
use Modules\Mall\Models\Category;
|
||||
use Modules\Mall\Models\Delivery;
|
||||
use Modules\Mall\Models\Goods;
|
||||
use Modules\Mall\Models\Shop;
|
||||
use Modules\Mall\Models\Tag;
|
||||
|
||||
class GoodsController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads,
|
||||
WithShop;
|
||||
|
||||
protected $title = '商品管理';
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Goods);
|
||||
|
||||
$grid->quickSearch('id')->placeholder('商品编号快速搜索');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('trashed', '回收站')->onlyTrashed();
|
||||
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('name', '商品名称');
|
||||
$filter->equal('channel', '类型')->select(Goods::Channels);
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('shop_id', '所属店铺')->select(function ($shopId) {
|
||||
if ($shopId) {
|
||||
return Shop::where('id', $shopId)->pluck('name', 'id');
|
||||
}
|
||||
})->ajax(route('admin.mall.shops.ajax'));
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('category_id', '分类')->select(Category::shown()->pluck('name', 'id'));
|
||||
});
|
||||
});
|
||||
|
||||
$grid->model()
|
||||
->with(['category', 'shop', 'delivery'])
|
||||
->withCount(['specs', 'skus'])
|
||||
->orderByDesc('updated_at');
|
||||
|
||||
$grid->column('id', '#ID#');
|
||||
$grid->column('brand.name', '品牌名称');
|
||||
$grid->column('category.name', '商品分类');
|
||||
// $grid->column('tags', '标签')
|
||||
// ->pluck('name')
|
||||
// ->label();
|
||||
$grid->column('shop.name', '所属店铺');
|
||||
$grid->column('name', '商品名称');
|
||||
$grid->column('type', '规格类型')->using(Goods::TYPE_MAP);
|
||||
$grid->column('sales', '销量');
|
||||
$grid->column('original_price', '原价');
|
||||
$grid->column('channel', '类型')->using(Goods::Channels)->label();
|
||||
|
||||
$grid->column('规格属性')
|
||||
->display(function () {
|
||||
if ($this->type === Goods::TYPE_MULTIPLE) {
|
||||
return $this->specs_count;
|
||||
}
|
||||
})
|
||||
->link(function () {
|
||||
return route('admin.mall.goods.specs.index', $this);
|
||||
}, '_self');
|
||||
$grid->column('价格条目')
|
||||
->display(function () {
|
||||
return $this->skus_count;
|
||||
})
|
||||
->link(function () {
|
||||
return route('admin.mall.goods.skus.index', $this);
|
||||
}, '_self');
|
||||
$grid->column('delivery.name', '运费模板');
|
||||
$grid->column('status', '状态')->switch([
|
||||
'on' => ['value' => 1, 'text' => '上架', 'color' => 'primary'],
|
||||
'off' => ['value' => 3, 'text' => '下架', 'color' => 'default'],
|
||||
]);
|
||||
// $grid->column('status', '状态')->display(function () {
|
||||
// return $this->status_text;
|
||||
// });
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Goods());
|
||||
|
||||
$form->text('name', '商品名称')->required();
|
||||
$form->textarea('description', '商品简介')->required();
|
||||
|
||||
$this->shop($form)->required();
|
||||
|
||||
$form->select('category_id', '商品分类')
|
||||
->options(function ($categoryId) {
|
||||
$category = Category::find($categoryId);
|
||||
if ($category) {
|
||||
return [$category->id => $category->name];
|
||||
}
|
||||
})
|
||||
->ajax(route('admin.mall.categories.ajax'))
|
||||
->required();
|
||||
$form->select('brand_id', '所属品牌')
|
||||
->options(function ($brandId) {
|
||||
$brand = Brand::find($brandId);
|
||||
if ($brand) {
|
||||
return [$brand->id => $brand->name];
|
||||
}
|
||||
})
|
||||
->ajax(route('admin.mall.brands.ajax'))
|
||||
->required();
|
||||
// $form->multipleSelect('tags', '商品标签')
|
||||
// ->options(function ($tagIds) {
|
||||
// if ($tagIds) {
|
||||
// return Tag::find($tagIds)->pluck('name', 'id');
|
||||
// }
|
||||
// })
|
||||
// ->ajax(route('admin.mall.tags.ajax'));
|
||||
$this->cover($form);
|
||||
$this->pictures($form);
|
||||
$states = [
|
||||
'on' => ['value' => 1, 'text' => '是', 'color' => 'success'],
|
||||
'off' => ['value' => 0, 'text' => '否', 'color' => 'danger'],
|
||||
];
|
||||
$form->switch('is_post_sale', '是否允许售后')->states($states)->default(1);
|
||||
$form->radioButton('deduct_stock_type', '库存扣减')
|
||||
->default(1)
|
||||
->options(Goods::DEDUCT_STOCK_MAP)
|
||||
->required();
|
||||
$form->radioButton('pay_type', '支付方式')
|
||||
->default(1)
|
||||
->options(Goods::PAY_TYPE_MAP)
|
||||
->required();
|
||||
$form->select('delivery_id', '运费模板')
|
||||
->options(function ($deliveryId) {
|
||||
$delivery = Delivery::find($deliveryId);
|
||||
if ($delivery) {
|
||||
return [$delivery->id => $delivery->name];
|
||||
}
|
||||
})
|
||||
->ajax(route('admin.mall.deliveries.ajax'))
|
||||
->required();
|
||||
$form->currency('original_price', '展示原价')
|
||||
->default(0)
|
||||
->help('仅作展示使用');
|
||||
$form->radioButton('channel', '商品类型')
|
||||
->options(Goods::Channels)
|
||||
->required();
|
||||
$form->radioButton('type', '规格类型')
|
||||
->options(Goods::TYPE_MAP)
|
||||
->default(Goods::CHANNEL_NORMAL)
|
||||
->required()
|
||||
->when(Goods::TYPE_SINGLE, function (Form $form) {
|
||||
$form->hasMany('skus', '单规格', function (Form\NestedForm $form) {
|
||||
$form->currency('price', '销售价格')
|
||||
->default(0)
|
||||
->required();
|
||||
$form->hidden('score', '积分')
|
||||
->default(0)
|
||||
->required();
|
||||
$form->hidden('assets', '资产')
|
||||
->default(0)
|
||||
->required();
|
||||
$form->number('stock', '商品库存')
|
||||
->default(0)
|
||||
->required();
|
||||
$form->text('weight', '商品重量')
|
||||
->default(0)
|
||||
->setWidth(2)
|
||||
->required();
|
||||
});
|
||||
})
|
||||
->when(Goods::TYPE_MULTIPLE, function ($form) {
|
||||
|
||||
})
|
||||
->default(function () use ($form) {
|
||||
return $form->isCreating() ? Goods::TYPE_SINGLE : '';
|
||||
});
|
||||
$form->ueditor('content', '商品详情')->required();
|
||||
|
||||
$form->switch('status', '状态')
|
||||
->states([
|
||||
'on' => ['value' => 1, 'text' => '上架', 'color' => 'success'],
|
||||
'off' => ['value' => 3, 'text' => '下架', 'color' => 'danger'],
|
||||
])
|
||||
->default(1);
|
||||
|
||||
$form->ignore(['single']);
|
||||
|
||||
$form->saving(function (Form $form) {
|
||||
if ($form->type === Goods::TYPE_SINGLE) {
|
||||
$form->skus = [Arr::first($form->skus)];
|
||||
}
|
||||
|
||||
if ($form->channel == Goods::CHANNEL_FREE && $form->isCreating()) {
|
||||
$hasOne = Goods::where('channel', Goods::CHANNEL_FREE)->exists();
|
||||
if ($hasOne) {
|
||||
$error = new MessageBag([
|
||||
'title' => '错误',
|
||||
'message' => '免费产品只有一个',
|
||||
]);
|
||||
|
||||
return back()->withInput()->with(compact('error'));
|
||||
}
|
||||
}
|
||||
|
||||
$form->content = Str::of(request()->get('content'))->replace('style=""', '');
|
||||
});
|
||||
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
47
modules/Mall/Http/Controllers/Admin/JobController.php
Normal file
47
modules/Mall/Http/Controllers/Admin/JobController.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Mall\Models\Job;
|
||||
|
||||
class JobController extends AdminController
|
||||
{
|
||||
|
||||
use WithShop;
|
||||
|
||||
protected $title = '职位管理';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Job());
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->like('shop.name', '所属店铺');
|
||||
});
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->like('name', '职位名称');
|
||||
});
|
||||
});
|
||||
|
||||
$grid->column('shop.name', '所属店铺');
|
||||
$grid->column('name', '职位名称');
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Job());
|
||||
|
||||
$this->shop($form)->required();
|
||||
$form->text('name', '职位名称')->required();
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
222
modules/Mall/Http/Controllers/Admin/OrderController.php
Normal file
222
modules/Mall/Http/Controllers/Admin/OrderController.php
Normal file
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Modules\Mall\Facades\Item;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\Audit;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\Delivered;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\Pay;
|
||||
use Modules\Mall\Http\Exporter\OrderExporter;
|
||||
use Modules\Mall\Models\Address;
|
||||
use Modules\Mall\Models\Express;
|
||||
use Modules\Mall\Models\GoodsSku;
|
||||
use Modules\Mall\Models\Order;
|
||||
use Modules\Mall\Models\Shop;
|
||||
use Modules\User\Models\User;
|
||||
use Modules\Mall\Facades\Order as OrderFacade;
|
||||
|
||||
class OrderController extends AdminController
|
||||
{
|
||||
|
||||
protected $title = '订单管理';
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Order());
|
||||
|
||||
$grid->model()->whereIn('type', [Order::TYPE_NORMAL, Order::TYPE_SCORE])->with('shop')->withCount('versions');
|
||||
|
||||
$grid->disableExport(false);
|
||||
$grid->exporter(new OrderExporter);
|
||||
$grid->disableCreateButton();
|
||||
$grid->quickSearch('order_no')->placeholder('搜索订单编号');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('unPay', '未付款')->unPay();
|
||||
$filter->scope('paid', '待发货')->paid();
|
||||
$filter->scope('delivered', '已发货')->delivered();
|
||||
$filter->scope('signed', '已签收')->signed();
|
||||
$filter->scope('completed', '已完成')->completed();
|
||||
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->like('order_no', '订单编号');
|
||||
$filter->equal('shop_id', '所属店铺')->select(Shop::pluck('name', 'id'));
|
||||
$filter->equal('user_id', '下单用户')->select()->ajax(route('admin.user.users.ajax'));
|
||||
$filter->equal('type', '订单类型')->select(Order::TYPE_MAP);
|
||||
});
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->between('created_at', '下单时间')->datetime();
|
||||
$filter->between('paid_at', '付款时间')->datetime();
|
||||
$filter->between('expired_at', '过期时间')->datetime();
|
||||
});
|
||||
});
|
||||
|
||||
$grid->actions(function (Grid\Displayers\Actions $actions) {
|
||||
$actions->disableEdit();
|
||||
$actions->disableDelete();
|
||||
$actions->disableView();
|
||||
if ($actions->row->can('pay') && $this->row->type == Order::TYPE_NORMAL) {
|
||||
$actions->add(new Pay());
|
||||
}
|
||||
if ($actions->row->can('deliver')) {
|
||||
$actions->add(new Delivered);
|
||||
}
|
||||
});
|
||||
|
||||
$grid->model()->with(['shop', 'user.info']);
|
||||
|
||||
$grid->column('order_no', '订单编号')->display(function () {
|
||||
return sprintf('<a href="%s">%s</a>', route('admin.mall.orders.show', $this), $this->order_no);
|
||||
});
|
||||
$grid->column('shop.name', '所属店铺');
|
||||
$grid->column('user.username', '下单用户');
|
||||
$grid->column('amount', '商品金额');
|
||||
$grid->column('freight', '运费');
|
||||
$grid->column('qty', '发货数量')
|
||||
->display(function () {
|
||||
return $this->items()->sum('qty');
|
||||
});
|
||||
$grid->column('订单金额')->display(function () {
|
||||
return $this->total;
|
||||
});
|
||||
$grid->column('state', '订单状态')
|
||||
->display(function () {
|
||||
return $this->state_text;
|
||||
})
|
||||
->label();
|
||||
$grid->column('type', '订单类型')->using(Order::TYPE_MAP)->label();
|
||||
$grid->column('paid_at', '支付时间')->sortable();
|
||||
$grid->column('expired_at', '过期时间')->sortable();
|
||||
$grid->column('versions_count', '操作日志')->link(function () {
|
||||
return route('admin.mall.versions', [
|
||||
'model' => get_class($this),
|
||||
'key' => $this->id,
|
||||
]);
|
||||
}, '_self');
|
||||
$grid->column('created_at', '下单时间')->sortable();
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 添加订单
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/7/29 13:21
|
||||
* @return Form
|
||||
*/
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Order());
|
||||
|
||||
$form->select('user_id', '用户')
|
||||
->options(function ($userId) {
|
||||
$user = User::find($userId);
|
||||
|
||||
if ($user) {
|
||||
return [$user->id => $user->username.' ['.$user->info->nickname.']'];
|
||||
}
|
||||
})
|
||||
->ajax(route('admin.user.users.ajax'))
|
||||
->load('address_id', route('admin.mall.ajax.address'))
|
||||
->required();
|
||||
|
||||
$form->select('address_id', '收货地址')
|
||||
->load('goods_sku_id', route('admin.mall.ajax.goods'))
|
||||
->required();
|
||||
$form->select('goods_sku_id', '商品')
|
||||
->required();
|
||||
$form->number('qty', '数量')->default(1);
|
||||
|
||||
$form->select('express_id', '物流')
|
||||
->options(function () {
|
||||
return Express::pluck('name', 'id');
|
||||
})
|
||||
->rules('required', ['required' => '物流公司必须选择']);
|
||||
$form->text('express_no', '物流单号')->rules('required');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取提交数据
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/7/29 14:16
|
||||
* @return mixed|void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
$user_id = request('user_id', 0);
|
||||
$remark = request('remark', '后台录入');
|
||||
$address_id = request('address_id', 0);
|
||||
$goods_sku_id = request('goods_sku_id', 0);
|
||||
$qty = request('qty', 0);
|
||||
$express_id = request('express_id');
|
||||
$express_no = request('express_no');
|
||||
|
||||
$user = User::find($user_id);
|
||||
$address = Address::find($address_id);
|
||||
$goods_sku = GoodsSku::find($goods_sku_id);
|
||||
|
||||
if (! $goods_sku) {
|
||||
$error = new MessageBag([
|
||||
'title' => '错误',
|
||||
'message' => '未找到商品',
|
||||
]);
|
||||
|
||||
return back()->withInput()->with(compact('error'));
|
||||
}
|
||||
|
||||
$stockData = $user->getStockData();
|
||||
|
||||
if ($qty > $stockData['residue']) {
|
||||
$error = new MessageBag([
|
||||
'title' => '错误',
|
||||
'message' => '用户库存不足',
|
||||
]);
|
||||
|
||||
return back()->withInput()->with(compact('error'));
|
||||
} else {
|
||||
$detail = collect();
|
||||
$item = new Item($goods_sku, $address, $qty);
|
||||
$detail->push($item);
|
||||
|
||||
$orders = (new OrderFacade)->user($user)
|
||||
->remark($remark)
|
||||
->type(Order::TYPE_SAMPLE)
|
||||
->items($detail)
|
||||
->address($address)
|
||||
->create();
|
||||
|
||||
foreach ($orders as $order) {
|
||||
$order->pay();//设置已支付
|
||||
$order->deliver($express_id, $express_no);//发货
|
||||
}
|
||||
|
||||
admin_toastr('操作完成');
|
||||
return redirect()->to('/admin/mall/orders?user_id='.$user->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Notes : 订单详情
|
||||
*
|
||||
* @Date : 2021/3/16 1:46 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param string $orderNo 订单的 order_no
|
||||
*/
|
||||
protected function detail(string $orderNo)
|
||||
{
|
||||
$order = Order::query()->firstWhere(['order_no' => $orderNo]);
|
||||
|
||||
return view('mall::admin.order.detail', compact('order'));
|
||||
}
|
||||
|
||||
}
|
||||
48
modules/Mall/Http/Controllers/Admin/ReasonController.php
Normal file
48
modules/Mall/Http/Controllers/Admin/ReasonController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Modules\Mall\Models\Express;
|
||||
use Modules\Mall\Models\Reason;
|
||||
|
||||
class ReasonController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads;
|
||||
|
||||
protected $title = '退款/货原因';
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Reason());
|
||||
|
||||
$grid->model()->withCount('shops');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('trashed', '回收站')->onlyTrashed();
|
||||
});
|
||||
|
||||
$grid->column('id');
|
||||
$grid->column('title', '名称');
|
||||
$grid->column('status', '状态')->bool();
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Reason());
|
||||
|
||||
$form->text('title', '名称')->required();
|
||||
$form->switch('status', '状态')->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
106
modules/Mall/Http/Controllers/Admin/RefundController.php
Normal file
106
modules/Mall/Http/Controllers/Admin/RefundController.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Mall\Events\RefundCompleted;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\RefundAudit;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\RefundReturns;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\RefundSign;
|
||||
use Modules\Mall\Models\Refund;
|
||||
|
||||
class RefundController extends AdminController
|
||||
{
|
||||
|
||||
protected $title = '退款订单';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Refund());
|
||||
|
||||
$grid->disableCreateButton();
|
||||
|
||||
$grid->actions(function ($actions) {
|
||||
$actions->disableDelete();
|
||||
$actions->disableEdit();
|
||||
$actions->disableView();
|
||||
|
||||
if ($actions->row->can('agree')) {
|
||||
$actions->add(new RefundAudit());
|
||||
}
|
||||
|
||||
if ($actions->row->can('sign')) {
|
||||
$actions->add(new RefundSign());
|
||||
}
|
||||
|
||||
if ($actions->row->can('completed')) {
|
||||
$actions->add(new RefundReturns());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->disableIdFilter();
|
||||
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->where(function ($query) {
|
||||
$query->whereHas('order', function ($query) {
|
||||
$query->where('order_no', 'like', "%{$this->input}%");
|
||||
});
|
||||
}, '订单编号');
|
||||
|
||||
$filter->equal('state', '状态')->select(Refund::STATUS_MAP);
|
||||
|
||||
});
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->where(function ($query) {
|
||||
$query->whereHas('user', function ($query) {
|
||||
$query->whereHas('info', function ($query) {
|
||||
$query->where('nickname', 'like', "%{$this->input}%");
|
||||
});
|
||||
});
|
||||
}, '下单用户');
|
||||
$filter->where(function ($query) {
|
||||
$query->whereHas('user', function ($query) {
|
||||
$query->where('username', $this->input);
|
||||
});
|
||||
}, '手机号');
|
||||
});
|
||||
});
|
||||
|
||||
$grid->model()
|
||||
->with(['shop', 'order', 'user.info'])
|
||||
->withCount('versions');
|
||||
|
||||
$grid->column('id');
|
||||
$grid->column('shop.name', '所属店铺');
|
||||
$grid->column('order.order_no', '订单编号')->display(function () {
|
||||
return sprintf('<a href="%s">%s</a>', route('admin.mall.orders.show', $this->order),
|
||||
$this->order->order_no);
|
||||
});
|
||||
|
||||
$grid->column('user.username', '下单用户');
|
||||
$grid->column('refund_total', '退款金额');
|
||||
$grid->column('actual_total', '实退金额');
|
||||
|
||||
$grid->column('状态')
|
||||
->display(function () {
|
||||
return $this->status_text;
|
||||
})
|
||||
->label();
|
||||
$grid->column('remark', '备注');
|
||||
|
||||
$grid->column('versions_count', '操作日志')->link(function () {
|
||||
return route('admin.mall.versions', [
|
||||
'model' => get_class($this),
|
||||
'key' => $this->id,
|
||||
]);
|
||||
}, '_self');
|
||||
|
||||
$grid->column('created_at', '申请时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
}
|
||||
27
modules/Mall/Http/Controllers/Admin/RegionController.php
Normal file
27
modules/Mall/Http/Controllers/Admin/RegionController.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Mall\Models\Region;
|
||||
|
||||
class RegionController extends AdminController
|
||||
{
|
||||
|
||||
public function ajax(Request $request)
|
||||
{
|
||||
$q = $request->q;
|
||||
|
||||
return Region::where('name', 'like', "%$q%")->paginate(null, ['id', 'name as text']);
|
||||
}
|
||||
|
||||
public function region(Request $request)
|
||||
{
|
||||
$regionId = $request->get('q');
|
||||
|
||||
return Region::where('parent_id', $regionId)->get(['id', DB::raw('name as text')]);
|
||||
}
|
||||
|
||||
}
|
||||
34
modules/Mall/Http/Controllers/Admin/Selectable/Expresses.php
Normal file
34
modules/Mall/Http/Controllers/Admin/Selectable/Expresses.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Selectable;
|
||||
|
||||
use Encore\Admin\Grid\Filter;
|
||||
use Encore\Admin\Grid\Selectable;
|
||||
use Modules\Mall\Models\Express;
|
||||
|
||||
class Expresses extends Selectable
|
||||
{
|
||||
public $model = Express::class;
|
||||
|
||||
public function make()
|
||||
{
|
||||
$this->column('id', '#ID#');
|
||||
$this->column('name', '物流名称');
|
||||
$this->column('status', '状态')->bool();
|
||||
$this->column('created_at', '时间');
|
||||
|
||||
$this->filter(function (Filter $filter) {
|
||||
$filter->like('name', '物流名称');
|
||||
});
|
||||
}
|
||||
|
||||
public static function display()
|
||||
{
|
||||
return function ($value) {
|
||||
if (is_array($value)) {
|
||||
return implode(';', array_column($value, 'name'));
|
||||
}
|
||||
return optional($this->expresses)->name;
|
||||
};
|
||||
}
|
||||
}
|
||||
32
modules/Mall/Http/Controllers/Admin/Selectable/Reasons.php
Normal file
32
modules/Mall/Http/Controllers/Admin/Selectable/Reasons.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin\Selectable;
|
||||
|
||||
use Encore\Admin\Grid\Selectable;
|
||||
use Modules\Mall\Models\Reason;
|
||||
|
||||
class Reasons extends Selectable
|
||||
{
|
||||
|
||||
public $model = Reason::class;
|
||||
|
||||
public function make()
|
||||
{
|
||||
$this->column('id', '#ID#');
|
||||
$this->column('title', '名称');
|
||||
$this->column('status', '状态')->bool();
|
||||
$this->column('created_at', '时间');
|
||||
}
|
||||
|
||||
public static function display()
|
||||
{
|
||||
return function ($value) {
|
||||
if (is_array($value)) {
|
||||
return implode(';', array_column($value, 'title'));
|
||||
}
|
||||
|
||||
return optional($this->reaons)->name;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
180
modules/Mall/Http/Controllers/Admin/ShopController.php
Normal file
180
modules/Mall/Http/Controllers/Admin/ShopController.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Shop\Close;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Shop\Open;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Shop\Pass;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Shop\Reject;
|
||||
use Modules\Mall\Http\Controllers\Admin\Selectable\Expresses;
|
||||
use Modules\Mall\Http\Controllers\Admin\Selectable\Reasons;
|
||||
use Modules\Mall\Models\Region;
|
||||
use Modules\Mall\Models\Shop;
|
||||
use Modules\User\Models\User;
|
||||
|
||||
class ShopController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads;
|
||||
|
||||
protected $title = '店铺管理';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Shop());
|
||||
|
||||
$grid->actions(function (Grid\Displayers\Actions $actions) {
|
||||
$actions->disableView();
|
||||
// $actions->disableEdit();
|
||||
$actions->disableDelete();
|
||||
if ($actions->row->status == Shop::STATUS_APPLYING) {
|
||||
$actions->add(new Pass);
|
||||
$actions->add(new Reject);
|
||||
}
|
||||
if ($actions->row->status == Shop::STATUS_NORMAL) {
|
||||
$actions->add(new Close);
|
||||
}
|
||||
|
||||
if ($actions->row->status == Shop::STATUS_CLOSE) {
|
||||
$actions->add(new Open);
|
||||
}
|
||||
});
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('name', '店铺名称');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('user.info.nickname', '用户昵称');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('mobile', '联系电话');
|
||||
});
|
||||
});
|
||||
|
||||
$grid->model()->withCount(['versions', 'staffers'])->with(['user.info']);
|
||||
|
||||
$grid->column('name', '店铺名称');
|
||||
$grid->column('所属用户')->display(fn() => $this->user->username . '[' . $this->user->info->nickname . ']');
|
||||
$grid->column('is_self', '类型')
|
||||
->using([
|
||||
0 => '合作',
|
||||
1 => '自营',
|
||||
])->label([
|
||||
0 => 'info',
|
||||
1 => 'danger',
|
||||
]);
|
||||
$grid->column('mobile', '联系电话');
|
||||
$grid->column('address', '地址')->display(fn() => $this->getFullAddress());
|
||||
$grid->column('status', '状态')
|
||||
->using(Shop::STATUS_MAP)
|
||||
->label(Shop::LABEL_MAP);
|
||||
$grid->column('order', '排序')->sortable()->editable();
|
||||
$grid->column('versions_count', '操作记录')->link(fn() => route('admin.mall.versions', [
|
||||
'model' => get_class($this),
|
||||
'key' => $this->id,
|
||||
]), '_self');
|
||||
$grid->column('staffers_count', '员工数量')->link(fn() => route('admin.mall.shops.staffers.index', $this), '_self');
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Shop());
|
||||
$form->select('user_id', '所属用户')
|
||||
->options(function ($userId) {
|
||||
$user = User::find($userId);
|
||||
|
||||
if ($user) {
|
||||
return [$user->id => $user->username . ' [' . $user->info->nickname . ']'];
|
||||
}
|
||||
})
|
||||
->ajax(route('admin.user.users.ajax'))
|
||||
->creationRules([
|
||||
'required',
|
||||
"unique:mall_shops",
|
||||
], [
|
||||
'unique' => '用户已存在店铺',
|
||||
])
|
||||
->updateRules([
|
||||
'required',
|
||||
"unique:mall_shops,user_id,{{id}}",
|
||||
], [
|
||||
'unique' => '用户已存在店铺',
|
||||
])
|
||||
->required();
|
||||
$form->text('name', '店铺名称')
|
||||
->creationRules(['required', "unique:mall_shops"], ['unique' => '店铺名称已存在'])
|
||||
->updateRules(['required', "unique:mall_shops,name,{{id}}"], ['unique' => '店铺名称已存在'])
|
||||
->required();
|
||||
$form->switch('is_self', '自营店铺');
|
||||
$form->textarea('description', '店铺简介')
|
||||
->required();
|
||||
$form->text('mobile', '联系电话')
|
||||
->rules([
|
||||
'size:11',
|
||||
'phone:CN',
|
||||
], [
|
||||
'size' => '手机号格式不正确',
|
||||
'phone' => '手机号格式不正确',
|
||||
])
|
||||
->creationRules(['required', "unique:mall_shops"], ['unique' => '店铺联系电话已存在'])
|
||||
->updateRules(['required', "unique:mall_shops,name,{{id}}"], ['unique' => '店铺联系电话已存在'])
|
||||
->required();
|
||||
$form->divider('地址信息');
|
||||
$form->select('province_id', '省份')
|
||||
->options(Region::where('parent_id', 1)->pluck('name', 'id'))
|
||||
->load('city_id', route('admin.mall.regions.region'))
|
||||
->required();
|
||||
$form->select('city_id', '城市')
|
||||
->options(function ($option) {
|
||||
$parent = Region::where('id', $option)->value('parent_id');
|
||||
|
||||
return Region::where(['parent_id' => $parent])->pluck('name', 'id');
|
||||
})
|
||||
->load('district_id', route('admin.mall.regions.region'))
|
||||
->required();
|
||||
$form->select('district_id', '区/县')
|
||||
->options(function ($option) {
|
||||
$parent = Region::where('id', $option)->value('parent_id');
|
||||
|
||||
return Region::where(['parent_id' => $parent])->pluck('name', 'id');
|
||||
})
|
||||
->required();
|
||||
$form->text('address', '详细地址')
|
||||
->required();
|
||||
$form->divider('其他信息');
|
||||
$this->cover($form, 'cover', '店铺LOGO');
|
||||
$form->radio('status', '店铺状态')
|
||||
->options(Shop::STATUS_MAP);
|
||||
$form->number('order', '排序')
|
||||
->default('9999')
|
||||
->help('仅后台可见,用于店铺推荐序列');
|
||||
$form->belongsToMany('expresses', Expresses::class, '发货物流');
|
||||
$form->belongsToMany('reasons', Reasons::class, '退款原因');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 获取店铺AJAX
|
||||
* @Date : 2021/5/7 4:39 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function ajax(Request $request)
|
||||
{
|
||||
$key = $request->get('q');
|
||||
|
||||
return Shop::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
|
||||
}
|
||||
|
||||
}
|
||||
77
modules/Mall/Http/Controllers/Admin/SkuController.php
Normal file
77
modules/Mall/Http/Controllers/Admin/SkuController.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Encore\Admin\Layout\Content;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Mall\Models\Goods;
|
||||
use Modules\Mall\Models\GoodsSku;
|
||||
|
||||
class SkuController extends Controller
|
||||
{
|
||||
|
||||
use WithUploads;
|
||||
|
||||
public function index(Content $content, Goods $good): Content
|
||||
{
|
||||
return $content
|
||||
->header($good->name)
|
||||
->description('价格表')
|
||||
->body($this->grid($good));
|
||||
}
|
||||
|
||||
public function grid($goods): Grid
|
||||
{
|
||||
$grid = new Grid(new GoodsSku());
|
||||
|
||||
$grid->model()->where('goods_id', $goods->id);
|
||||
|
||||
$grid->actions(function (Grid\Displayers\Actions $actions) {
|
||||
$actions->disableView();
|
||||
$actions->disableDelete();
|
||||
});
|
||||
$grid->disableCreateButton();
|
||||
|
||||
$grid->column('cover', '封面图')->image('', 80);
|
||||
$grid->column('unit', '产品单元');
|
||||
$grid->column('price', '售价');
|
||||
$grid->column('score', '积分/原石');
|
||||
$grid->column('assets', '资产');
|
||||
$grid->column('stock', '库存');
|
||||
$grid->column('weight', '重量');
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function edit(Content $content, Goods $good, GoodsSku $sku)
|
||||
{
|
||||
return $content
|
||||
->header($good->name)
|
||||
->description('编辑价格')
|
||||
->body($this->form($good)->edit($sku->id));
|
||||
}
|
||||
|
||||
public function form($good): Form
|
||||
{
|
||||
$form = new Form(new GoodsSku());
|
||||
|
||||
$this->cover($form);
|
||||
$form->currency('price', '销售价格');
|
||||
$form->currency('score', '积分/原石');
|
||||
$form->currency('assets', '资产');
|
||||
$form->number('stock', '库存');
|
||||
$form->text('weight', '重量')->setWidth(2);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function update(Goods $good, GoodsSku $sku)
|
||||
{
|
||||
return $this->form($good)->update($sku->id);
|
||||
}
|
||||
|
||||
}
|
||||
81
modules/Mall/Http/Controllers/Admin/SpecController.php
Normal file
81
modules/Mall/Http/Controllers/Admin/SpecController.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Form\NestedForm;
|
||||
use Encore\Admin\Grid;
|
||||
use Encore\Admin\Layout\Content;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Mall\Models\Goods;
|
||||
use Modules\Mall\Models\GoodsSpec;
|
||||
|
||||
class SpecController extends Controller
|
||||
{
|
||||
|
||||
public function index(Content $content, Goods $good): Content
|
||||
{
|
||||
return $content
|
||||
->header($good->name)
|
||||
->description('属性列表')
|
||||
->body($this->grid($good));
|
||||
}
|
||||
|
||||
public function grid($good): Grid
|
||||
{
|
||||
$grid = new Grid(new GoodsSpec());
|
||||
|
||||
$grid->model()
|
||||
->where('goods_id', $good->id)
|
||||
->withCount('values');
|
||||
|
||||
$grid->column('name', '属性名称');
|
||||
$grid->column('values_count', '属性值数量')
|
||||
->link(function () use ($good) {
|
||||
return route('admin.mall.goods.specs.values.index', [$good, $this]);
|
||||
}, '_self');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function create(Content $content, Goods $good): Content
|
||||
{
|
||||
return $content
|
||||
->header($good->name)
|
||||
->description('属性列表')
|
||||
->body($this->form($good));
|
||||
}
|
||||
|
||||
public function form($good): Form
|
||||
{
|
||||
$form = new Form(new GoodsSpec());
|
||||
|
||||
$form->text('name', '属性名称');
|
||||
$form->hidden('goods_id')->value($good->id);
|
||||
|
||||
$form->hasMany('values', '属性值列表', function (NestedForm $form) {
|
||||
$form->text('value', '属性值');
|
||||
});
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function store(Goods $good)
|
||||
{
|
||||
return $this->form($good)->store();
|
||||
}
|
||||
|
||||
public function edit(Content $content, Goods $good, GoodsSpec $spec): Content
|
||||
{
|
||||
return $content
|
||||
->header($good->name)
|
||||
->description('属性列表')
|
||||
->body($this->form($good)->edit($spec->id));
|
||||
}
|
||||
|
||||
public function update(Goods $good, GoodsSpec $spec)
|
||||
{
|
||||
return $this->form($good)->update($spec->id);
|
||||
}
|
||||
|
||||
}
|
||||
70
modules/Mall/Http/Controllers/Admin/SpecValueController.php
Normal file
70
modules/Mall/Http/Controllers/Admin/SpecValueController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Encore\Admin\Layout\Content;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Mall\Models\Goods;
|
||||
use Modules\Mall\Models\GoodsSpec;
|
||||
use Modules\Mall\Models\GoodsSpecValue;
|
||||
|
||||
class SpecValueController extends Controller
|
||||
{
|
||||
|
||||
public function index(Content $content, Goods $good, GoodsSpec $spec): Content
|
||||
{
|
||||
return $content
|
||||
->header($spec->name)
|
||||
->description('属性值列表')
|
||||
->body($this->grid($spec));
|
||||
}
|
||||
|
||||
public function grid($spec): Grid
|
||||
{
|
||||
$grid = new Grid(new GoodsSpecValue());
|
||||
|
||||
$grid->model()->where('spec_id', $spec->id);
|
||||
$grid->column('value', '属性值');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function create(Content $content, Goods $good, GoodsSpec $spec): Content
|
||||
{
|
||||
return $content
|
||||
->header($spec->name)
|
||||
->description('属性列表')
|
||||
->body($this->form($spec));
|
||||
}
|
||||
|
||||
public function form($spec): Form
|
||||
{
|
||||
$form = new Form(new GoodsSpecValue());
|
||||
|
||||
$form->text('value', '属性值');
|
||||
$form->hidden('spec_id')->value($spec->id);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function store(Goods $good, GoodsSpec $spec)
|
||||
{
|
||||
return $this->form($spec)->store();
|
||||
}
|
||||
|
||||
public function edit(Content $content, Goods $good, GoodsSpec $spec, GoodsSpecValue $value): Content
|
||||
{
|
||||
return $content
|
||||
->header($spec->name)
|
||||
->description('属性列表')
|
||||
->body($this->form($spec)->edit($value->id));
|
||||
}
|
||||
|
||||
public function update(Goods $good, GoodsSpec $spec, GoodsSpecValue $value)
|
||||
{
|
||||
return $this->form($spec)->update($value->id);
|
||||
}
|
||||
|
||||
}
|
||||
98
modules/Mall/Http/Controllers/Admin/StafferController.php
Normal file
98
modules/Mall/Http/Controllers/Admin/StafferController.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Encore\Admin\Layout\Content;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Mall\Models\Job;
|
||||
use Modules\Mall\Models\Shop;
|
||||
use Modules\Mall\Models\ShopStaffer;
|
||||
use Modules\User\Models\User;
|
||||
|
||||
class StafferController extends Controller
|
||||
{
|
||||
|
||||
public function index(Content $content, Shop $shop): Content
|
||||
{
|
||||
return $content
|
||||
->header($shop->name)
|
||||
->description('员工管理')
|
||||
->body($this->grid($shop));
|
||||
}
|
||||
|
||||
public function grid($shop): Grid
|
||||
{
|
||||
$grid = new Grid(new ShopStaffer());
|
||||
|
||||
$grid->model()->byShop($shop);
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('user.username', '用户名');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('user.info.nickname', '用户昵称');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('job.name', '职位名称');
|
||||
});
|
||||
});
|
||||
|
||||
$grid->column('所属用户')->display(fn() => $this->user->username . '[' . $this->user->info->nickname . ']');
|
||||
$grid->column('job.name', '职位名称');
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function create(Content $content, Shop $shop): Content
|
||||
{
|
||||
return $content
|
||||
->header($shop->name)
|
||||
->description('新增员工')
|
||||
->body($this->form($shop));
|
||||
}
|
||||
|
||||
public function store(Shop $shop)
|
||||
{
|
||||
return $this->form($shop)->store();
|
||||
}
|
||||
|
||||
public function form(Shop $shop): Form
|
||||
{
|
||||
$form = new Form(new ShopStaffer());
|
||||
|
||||
$form->hidden('shop_id')->value($shop->getKey());
|
||||
|
||||
$form->select('user_id', '所属用户')
|
||||
->options(function ($userId) {
|
||||
$user = User::find($userId);
|
||||
|
||||
if ($user) {
|
||||
return [$user->id => $user->username . ' [' . $user->info->nickname . ']'];
|
||||
}
|
||||
})
|
||||
->ajax(route('admin.user.users.ajax'))
|
||||
->required();
|
||||
|
||||
$form->select('job_id', '职位')->options(fn() => Job::byShop($shop)->pluck('name', 'id'));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function edit(Content $content, Shop $shop, ShopStaffer $staffer): Content
|
||||
{
|
||||
return $content
|
||||
->header($shop->name)
|
||||
->description('编辑员工')
|
||||
->body($this->form($shop)->edit($staffer->getKey()));
|
||||
}
|
||||
|
||||
public function update(Shop $shop, ShopStaffer $staffer)
|
||||
{
|
||||
return $this->form($shop)->update($staffer->getKey());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Modules\Mall\Facades\Item;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\Delivered;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\Pay;
|
||||
use Modules\Mall\Http\Exporter\OrderExporter;
|
||||
use Modules\Mall\Models\Address;
|
||||
use Modules\Mall\Models\Express;
|
||||
use Modules\Mall\Models\Goods;
|
||||
use Modules\Mall\Models\GoodsSku;
|
||||
use Modules\Mall\Models\Order;
|
||||
use Modules\Mall\Models\OrderExpress;
|
||||
use Modules\Mall\Models\Shop;
|
||||
use Modules\User\Models\User;
|
||||
use Modules\Mall\Facades\Order as OrderFacade;
|
||||
|
||||
class StockOrderBySystemController extends AdminController
|
||||
{
|
||||
|
||||
protected $title = '公司线下发货';
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Order());
|
||||
|
||||
$grid->model()
|
||||
->where('type', Order::TYPE_SAMPLE)
|
||||
->where('channel', Order::CHANNEL_SYSTEM)
|
||||
->with(['shop', 'user', 'items'])
|
||||
->withCount('versions');
|
||||
|
||||
|
||||
$grid->quickSearch('order_no')->placeholder('搜索订单编号');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('unPay', '未付款')->unPay();
|
||||
$filter->scope('paid', '待发货')->paid();
|
||||
$filter->scope('delivered', '已发货')->delivered();
|
||||
$filter->scope('signed', '已签收')->signed();
|
||||
$filter->scope('completed', '已完成')->completed();
|
||||
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->like('order_no', '订单编号');
|
||||
// $filter->equal('shop_id', '所属店铺')->select(Shop::pluck('name', 'id'));
|
||||
$filter->equal('user_id', '提货用户')->select()->ajax(route('admin.user.users.ajax'));
|
||||
// $filter->equal('type', '订单类型')->select(Order::TYPE_MAP);
|
||||
});
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
// $filter->between('created_at', '下单时间')->datetime();
|
||||
// $filter->between('paid_at', '付款时间')->datetime();
|
||||
// $filter->between('expired_at', '过期时间')->datetime();
|
||||
});
|
||||
});
|
||||
|
||||
$grid->actions(function (Grid\Displayers\Actions $actions) {
|
||||
$actions->disableEdit();
|
||||
$actions->disableDelete();
|
||||
$actions->disableView();
|
||||
if ($actions->row->can('pay') && $this->row->type == Order::TYPE_NORMAL) {
|
||||
$actions->add(new Pay());
|
||||
}
|
||||
if ($actions->row->can('deliver')) {
|
||||
$actions->add(new Delivered);
|
||||
}
|
||||
});
|
||||
|
||||
$grid->model()->with(['shop', 'user.info']);
|
||||
|
||||
$grid->column('order_no', '订单编号')->display(function () {
|
||||
return sprintf('<a href="%s">%s</a>', route('admin.mall.stock_orders.show', $this), $this->order_no);
|
||||
});
|
||||
// $grid->column('shop.name', '所属店铺');
|
||||
$grid->column('user.username', '提货用户');
|
||||
// $grid->column('amount', '商品金额');
|
||||
// $grid->column('freight', '运费');
|
||||
$grid->column('qty', '提货数量')
|
||||
->display(function () {
|
||||
return $this->items()->sum('qty');
|
||||
});
|
||||
// $grid->column('订单金额')->display(function () {
|
||||
// return $this->total;
|
||||
// });
|
||||
$grid->column('state', '订单状态')
|
||||
->display(function () {
|
||||
return $this->state_text;
|
||||
})
|
||||
->label();
|
||||
$grid->column('type', '订单类型')->using(Order::TYPE_MAP)->label();
|
||||
// $grid->column('paid_at', '支付时间')->sortable();
|
||||
// $grid->column('expired_at', '过期时间')->sortable();
|
||||
$grid->column('versions_count', '操作日志')->link(function () {
|
||||
return route('admin.mall.versions', [
|
||||
'model' => get_class($this),
|
||||
'key' => $this->id,
|
||||
]);
|
||||
}, '_self');
|
||||
$grid->column('created_at', '下单时间')->sortable();
|
||||
|
||||
$grid->disableExport(false);
|
||||
$grid->export(function ($export) {
|
||||
$export->column('order_no', function ($value, $original) {
|
||||
return strip_tags($value)."\n";
|
||||
});
|
||||
$export->column('type', function ($value, $original) {
|
||||
return strip_tags($value);
|
||||
});
|
||||
$export->column('state', function ($value, $original) {
|
||||
return strip_tags($value);
|
||||
});
|
||||
|
||||
$export->except(['versions_count', 'paid_at', 'expired_at']);
|
||||
|
||||
$export->filename($this->title.date("YmdHis"));
|
||||
});
|
||||
return $grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 添加订单
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/7/29 13:21
|
||||
* @return Form
|
||||
*/
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Order());
|
||||
|
||||
$form->select('user_id', '会员')
|
||||
->options(function ($userId) {
|
||||
$user = User::find($userId);
|
||||
|
||||
if ($user) {
|
||||
return [$user->id => $user->username.' ['.$user->info->nickname.']'];
|
||||
}
|
||||
})
|
||||
->ajax(route('admin.user.users.ajax'))
|
||||
->load('address_id', route('admin.mall.ajax.address'))
|
||||
->required();
|
||||
|
||||
$form->select('address_id', '收货地址')
|
||||
->load('goods_sku_id', route('admin.mall.ajax.goods'))
|
||||
->required();
|
||||
$form->html("<div id='showImage' style='margin-top:10px'><a href='/admin/mall/addresses/create'>添加收货地址</a></div>",
|
||||
'');
|
||||
$form->select('goods_sku_id', '剩余箱数')->required();
|
||||
|
||||
$form->number('qty', '发货箱数')->default(1);
|
||||
$form->radioButton('type', '方式')
|
||||
->options(OrderExpress::TYPE_MAP)
|
||||
->required()
|
||||
->when(OrderExpress::TYPE_EXPRESS, function ($form) {
|
||||
$form->select('express_id', '物流')
|
||||
->options(function () {
|
||||
return Express::pluck('name', 'id');
|
||||
})
|
||||
->rules('required', ['required' => '物流公司必须选择']);
|
||||
$form->text('express_no', '物流单号')->rules('required');
|
||||
|
||||
})
|
||||
->when(OrderExpress::TYPE_LOGISTICS, function ($form) {
|
||||
$form->text('person', '经办人');
|
||||
});
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 获取提交数据
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/7/29 14:16
|
||||
* @return mixed|void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
$user_id = request('user_id', 0);
|
||||
$remark = request('remark', '后台录入');
|
||||
$address_id = request('address_id', 0);
|
||||
$goods_sku_id = request('goods_sku_id', 0);
|
||||
$qty = request('qty', 0);
|
||||
$express_id = request('express_id');
|
||||
$express_no = request('express_no');
|
||||
$type = request('type');
|
||||
$person = request('person');
|
||||
|
||||
$user = User::find($user_id);
|
||||
$address = Address::find($address_id);
|
||||
$goods_sku = GoodsSku::find($goods_sku_id);
|
||||
|
||||
if (! $goods_sku) {
|
||||
$error = new MessageBag([
|
||||
'title' => '错误',
|
||||
'message' => '未找到商品',
|
||||
]);
|
||||
|
||||
return back()->withInput()->with(compact('error'));
|
||||
}
|
||||
|
||||
$stockData = $user->getStockData();
|
||||
|
||||
if ($qty > $stockData['residue']) {
|
||||
$error = new MessageBag([
|
||||
'title' => '错误',
|
||||
'message' => '用户库存不足',
|
||||
]);
|
||||
|
||||
return back()->withInput()->with(compact('error'));
|
||||
} else {
|
||||
$detail = collect();
|
||||
$item = new Item($goods_sku, $address, $qty);
|
||||
$detail->push($item);
|
||||
|
||||
$orders = (new OrderFacade)->user($user)
|
||||
->remark($remark)
|
||||
->channel(Order::CHANNEL_SYSTEM)
|
||||
->type(Order::TYPE_SAMPLE)
|
||||
->items($detail)
|
||||
->address($address)
|
||||
->create();
|
||||
|
||||
foreach ($orders as $order) {
|
||||
$order->pay();//设置已支付
|
||||
$order->deliver($express_id, $express_no, $type, $person);//发货
|
||||
}
|
||||
|
||||
admin_toastr('操作完成');
|
||||
return redirect()->to('/admin/mall/stock_orders_by_system?user_id='.$user->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Notes : 订单详情
|
||||
*
|
||||
* @Date : 2021/3/16 1:46 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param string $orderNo 订单的 order_no
|
||||
*/
|
||||
protected function detail(string $orderNo)
|
||||
{
|
||||
$order = Order::query()->firstWhere(['order_no' => $orderNo]);
|
||||
|
||||
return view('mall::admin.stock_order.detail', compact('order'));
|
||||
}
|
||||
|
||||
}
|
||||
142
modules/Mall/Http/Controllers/Admin/StockOrderController.php
Normal file
142
modules/Mall/Http/Controllers/Admin/StockOrderController.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Modules\Mall\Facades\Item;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\Delivered;
|
||||
use Modules\Mall\Http\Controllers\Admin\Action\Order\Pay;
|
||||
use Modules\Mall\Http\Exporter\OrderExporter;
|
||||
use Modules\Mall\Models\Address;
|
||||
use Modules\Mall\Models\Express;
|
||||
use Modules\Mall\Models\GoodsSku;
|
||||
use Modules\Mall\Models\Order;
|
||||
use Modules\Mall\Models\Shop;
|
||||
use Modules\User\Models\User;
|
||||
use Modules\Mall\Facades\Order as OrderFacade;
|
||||
|
||||
class StockOrderController extends AdminController
|
||||
{
|
||||
|
||||
protected $title = '会员线上提货';
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Order());
|
||||
|
||||
$grid->model()
|
||||
->where('type', Order::TYPE_SAMPLE)
|
||||
->where('channel', Order::CHANNEL_USER)
|
||||
->with(['shop', 'user', 'items'])
|
||||
->withCount('versions');
|
||||
|
||||
$grid->disableCreateButton();
|
||||
$grid->quickSearch('order_no')->placeholder('搜索订单编号');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('unPay', '未付款')->unPay();
|
||||
$filter->scope('paid', '待发货')->paid();
|
||||
$filter->scope('delivered', '已发货')->delivered();
|
||||
$filter->scope('signed', '已签收')->signed();
|
||||
$filter->scope('completed', '已完成')->completed();
|
||||
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->like('order_no', '订单编号');
|
||||
// $filter->equal('shop_id', '所属店铺')->select(Shop::pluck('name', 'id'));
|
||||
$filter->equal('user_id', '提货用户')->select()->ajax(route('admin.user.users.ajax'));
|
||||
});
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->between('created_at', '下单时间')->datetime();
|
||||
$filter->equal('state', '订单状态')->select([
|
||||
Order::STATUS_CANCEL => '已取消',
|
||||
Order::STATUS_PAID => '待发货',
|
||||
Order::STATUS_DELIVERED => '已发货',
|
||||
Order::STATUS_SIGNED => '已签收',
|
||||
]);
|
||||
|
||||
// $filter->between('paid_at', '付款时间')->datetime();
|
||||
// $filter->between('expired_at', '过期时间')->datetime();
|
||||
});
|
||||
});
|
||||
|
||||
$grid->actions(function (Grid\Displayers\Actions $actions) {
|
||||
$actions->disableEdit();
|
||||
$actions->disableDelete();
|
||||
$actions->disableView();
|
||||
if ($actions->row->can('pay') && $this->row->type == Order::TYPE_NORMAL) {
|
||||
$actions->add(new Pay());
|
||||
}
|
||||
if ($actions->row->can('deliver')) {
|
||||
$actions->add(new Delivered);
|
||||
}
|
||||
});
|
||||
|
||||
$grid->model()->with(['shop', 'user.info']);
|
||||
|
||||
$grid->column('order_no', '订单编号')->display(function () {
|
||||
return sprintf('<a href="%s">%s</a>', route('admin.mall.stock_orders.show', $this), $this->order_no);
|
||||
});
|
||||
// $grid->column('shop.name', '所属店铺');
|
||||
$grid->column('user.username', '提货用户');
|
||||
// $grid->column('amount', '商品金额');
|
||||
// $grid->column('freight', '运费');
|
||||
$grid->column('qty', '提货数量')
|
||||
->display(function () {
|
||||
return $this->items()->sum('qty');
|
||||
});
|
||||
// $grid->column('订单金额')->display(function () {
|
||||
// return $this->total;
|
||||
// });
|
||||
$grid->column('state', '订单状态')
|
||||
->display(function () {
|
||||
return $this->state_text;
|
||||
})
|
||||
->label();
|
||||
// $grid->column('type', '订单类型')->using(Order::TYPE_MAP)->label();
|
||||
// $grid->column('paid_at', '支付时间')->sortable();
|
||||
// $grid->column('expired_at', '过期时间')->sortable();
|
||||
$grid->column('versions_count', '操作日志')->link(function () {
|
||||
return route('admin.mall.versions', [
|
||||
'model' => get_class($this),
|
||||
'key' => $this->id,
|
||||
]);
|
||||
}, '_self');
|
||||
$grid->column('created_at', '下单时间')->sortable();
|
||||
|
||||
$grid->disableExport(false);
|
||||
$grid->export(function ($export) {
|
||||
$export->column('order_no', function ($value, $original) {
|
||||
return strip_tags($value)."\n";
|
||||
});
|
||||
$export->column('type', function ($value, $original) {
|
||||
return strip_tags($value);
|
||||
});
|
||||
$export->column('state', function ($value, $original) {
|
||||
return strip_tags($value);
|
||||
});
|
||||
|
||||
$export->except(['versions_count', 'paid_at', 'expired_at']);
|
||||
|
||||
$export->filename($this->title.date("YmdHis"));
|
||||
});
|
||||
return $grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 订单详情
|
||||
*
|
||||
* @Date : 2021/3/16 1:46 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param string $orderNo 订单的 order_no
|
||||
*/
|
||||
protected function detail(string $orderNo)
|
||||
{
|
||||
$order = Order::query()->firstWhere(['order_no' => $orderNo]);
|
||||
|
||||
return view('mall::admin.stock_order.detail', compact('order'));
|
||||
}
|
||||
|
||||
}
|
||||
48
modules/Mall/Http/Controllers/Admin/TagController.php
Normal file
48
modules/Mall/Http/Controllers/Admin/TagController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Models\Tag;
|
||||
|
||||
class TagController extends AdminController
|
||||
{
|
||||
|
||||
use WithShop;
|
||||
|
||||
protected $title = '商品标签';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Tag());
|
||||
|
||||
$grid->model()->with(['shop']);
|
||||
|
||||
$grid->column('shop.name', '所属店铺');
|
||||
$grid->column('name', '标签名称');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Tag());
|
||||
|
||||
$this->shop($form)->required();
|
||||
$form->text('name', '标签名称')
|
||||
->required();
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function ajax(Request $request)
|
||||
{
|
||||
$key = $request->q;
|
||||
|
||||
return Tag::where('name', 'like', "%$key%")->paginate(null, ['id', 'name as text']);
|
||||
}
|
||||
|
||||
}
|
||||
68
modules/Mall/Http/Controllers/Admin/VersionController.php
Normal file
68
modules/Mall/Http/Controllers/Admin/VersionController.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Auth\Database\Administrator;
|
||||
use Encore\Admin\Grid;
|
||||
use Encore\Admin\Layout\Content;
|
||||
use Encore\Admin\Widgets\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Overtrue\LaravelVersionable\Version;
|
||||
|
||||
class VersionController extends Controller
|
||||
{
|
||||
|
||||
public function index(Content $content, $model, $key): Content
|
||||
{
|
||||
return $content
|
||||
->header($model . ' => ' . $key)
|
||||
->description('数据操作日志')
|
||||
->body($this->grid($model, $key));
|
||||
}
|
||||
|
||||
public function grid($model, $key): Grid
|
||||
{
|
||||
$grid = new Grid(new Version());
|
||||
|
||||
$grid->disableCreateButton();
|
||||
$grid->disableActions();
|
||||
$grid->disableTools();
|
||||
|
||||
$grid->model()->whereHasMorph(
|
||||
'versionable',
|
||||
$model,
|
||||
function (Builder $query) use ($key) {
|
||||
$query->where('id', $key);
|
||||
}
|
||||
)->orderByDesc('id');
|
||||
|
||||
$grid->column('操作用户')->display(function () {
|
||||
if ($this->user_id < config('mall.administrator_max_id')) {
|
||||
config(['versionable.user_model' => Administrator::class]);
|
||||
|
||||
return '[Admin] ' . ($this->user->name ?? '--SYSTEM--');
|
||||
} else {
|
||||
return '[USER] ' . ($this->user->username ?? '--USER--');
|
||||
}
|
||||
});
|
||||
$grid->column('versionable_type', '数据变动')->expand(function () {
|
||||
$data = [];
|
||||
foreach ($this->contents as $key => $item) {
|
||||
$data[] = [
|
||||
$key,
|
||||
is_array($item) ? json_encode($item, JSON_UNESCAPED_UNICODE) : $item,
|
||||
];
|
||||
}
|
||||
|
||||
return new Table(['字段名称', '变更值'], $data);
|
||||
});
|
||||
|
||||
$grid->column('操作时间')->display(function () {
|
||||
return $this->created_at->toDateTimeString();
|
||||
});
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
}
|
||||
64
modules/Mall/Http/Controllers/Admin/VideoController.php
Normal file
64
modules/Mall/Http/Controllers/Admin/VideoController.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Linker\Traits\WithLinker;
|
||||
use Modules\Mall\Models\Banner;
|
||||
use Modules\Mall\Models\Video;
|
||||
|
||||
class VideoController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads,
|
||||
WithShop,
|
||||
WithLinker;
|
||||
|
||||
public $title = "视频管理";
|
||||
|
||||
protected function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Video());
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('name', '视频名称');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('status', '状态')->radio([
|
||||
0 => '禁用',
|
||||
1 => '正常',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$grid->column('id', '#ID#');
|
||||
$grid->column('name', '视频名称');
|
||||
$grid->column('cover', '封面地址')->image('', 60, 60);
|
||||
$grid->column('path', '视频地址')
|
||||
->display(function () {
|
||||
return $this->path_url;
|
||||
});
|
||||
$grid->column('status', '状态')->switch();
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
protected function form(): Form
|
||||
{
|
||||
$form = new Form((new Video())->disableModelCaching());
|
||||
|
||||
$form->text('name', '视频标题')->required();
|
||||
$this->cover($form);
|
||||
$this->video($form);
|
||||
$form->switch('status', '显示')->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
22
modules/Mall/Http/Controllers/Admin/WithShop.php
Normal file
22
modules/Mall/Http/Controllers/Admin/WithShop.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Admin;
|
||||
|
||||
use Modules\Mall\Models\Shop;
|
||||
|
||||
trait WithShop
|
||||
{
|
||||
|
||||
public function shop($form)
|
||||
{
|
||||
return $form->select('shop_id', '所属店铺')
|
||||
->options(function ($shopId) {
|
||||
$shop = Shop::find($shopId);
|
||||
if ($shop) {
|
||||
return [$shop->id => $shop->name];
|
||||
}
|
||||
})
|
||||
->ajax(route('admin.mall.shops.ajax'));
|
||||
}
|
||||
|
||||
}
|
||||
16
modules/Mall/Http/Controllers/Agent/IndexController.php
Normal file
16
modules/Mall/Http/Controllers/Agent/IndexController.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Agent;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class IndexController extends Controller
|
||||
{
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
return $this->success($request->shop);
|
||||
}
|
||||
|
||||
}
|
||||
19
modules/Mall/Http/Controllers/Agent/ShopController.php
Normal file
19
modules/Mall/Http/Controllers/Agent/ShopController.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Agent;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Jason\Api\Api;
|
||||
|
||||
class ShopController extends Controller
|
||||
{
|
||||
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$user = Api::user();
|
||||
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
}
|
||||
34
modules/Mall/Http/Controllers/Api/ActivityController.php
Normal file
34
modules/Mall/Http/Controllers/Api/ActivityController.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Api;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Modules\Mall\Http\Resources\Api\Activity\ActivityBaseResource;
|
||||
use Modules\Mall\Http\Resources\Api\Activity\ActivityResource;
|
||||
use Modules\Mall\Models\Activity;
|
||||
|
||||
class ActivityController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes: 活动列表
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/7/27 11:26
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$activities = Activity::shown()->get();
|
||||
|
||||
return $this->success(ActivityBaseResource::collection($activities));
|
||||
}
|
||||
|
||||
public function show(Activity $activity)
|
||||
{
|
||||
return $this->success(new ActivityResource($activity));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
160
modules/Mall/Http/Controllers/Api/AddressController.php
Normal file
160
modules/Mall/Http/Controllers/Api/AddressController.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Api;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Jason\Api\Api;
|
||||
use Modules\Mall\Http\Requests\Address\AddressRequest;
|
||||
use Modules\Mall\Http\Resources\Api\Address\AddressResource;
|
||||
use Modules\Mall\Models\Address;
|
||||
use Modules\Mall\Models\Region;
|
||||
|
||||
class AddressController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes: 地址列表
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2020/11/5 5:09 下午
|
||||
* @return mixed
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$addresses = Address::byUser(Api::user())->orderBy('is_default', 'desc')->get();
|
||||
|
||||
return $this->success(AddressResource::collection($addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 创建地址,展示地区联动数据
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2020/11/5 5:10 下午
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$parentId = $request->parent_id ?? 1;
|
||||
|
||||
$list = Region::where('parent_id', $parentId)->get();
|
||||
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 保存地址
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2020/11/5 5:13 下午
|
||||
* @param \Modules\Mall\Http\Requests\Address\AddressRequest $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function store(AddressRequest $request)
|
||||
{
|
||||
$result = Address::create([
|
||||
'user_id' => Api::userId(),
|
||||
'name' => $request->name,
|
||||
'mobile' => $request->mobile,
|
||||
'province_id' => $request->province_id,
|
||||
'city_id' => $request->city_id,
|
||||
'district_id' => $request->district_id,
|
||||
'address' => $request->address,
|
||||
'is_default' => $request->is_default,
|
||||
]);
|
||||
if ($result) {
|
||||
return $this->success('操作成功');
|
||||
} else {
|
||||
return $this->failed('失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 地址详情,如果不是自己的地址,不显示
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2020/11/5 5:31 下午
|
||||
* @param Address $address
|
||||
* @return mixed
|
||||
*/
|
||||
public function show(Address $address)
|
||||
{
|
||||
if ($address->user()->isNot(Api::user())) {
|
||||
return $this->failed('', 404);
|
||||
}
|
||||
|
||||
return $this->success(new AddressResource($address));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 设置默认地址
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2020/11/5 5:34 下午
|
||||
* @param Address $address
|
||||
* @return mixed
|
||||
*/
|
||||
public function setDefault(Address $address)
|
||||
{
|
||||
if ($address->user()->isNot(Api::user())) {
|
||||
return $this->failed('', 404);
|
||||
}
|
||||
try {
|
||||
$address->setDefault();
|
||||
|
||||
return $this->success('操作成功');
|
||||
} catch (Exception $exception) {
|
||||
return $this->failed('失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 更新地址
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2020/11/5 5:40 下午
|
||||
*/
|
||||
public function update(AddressRequest $request, Address $address)
|
||||
{
|
||||
if ($address->user()->isNot(Api::user())) {
|
||||
return $this->failed('', 404);
|
||||
}
|
||||
|
||||
$address->update([
|
||||
'name' => $request->name,
|
||||
'mobile' => $request->mobile,
|
||||
'province_id' => $request->province_id,
|
||||
'city_id' => $request->city_id,
|
||||
'district_id' => $request->district_id,
|
||||
'address' => $request->address,
|
||||
'is_default' => $request->is_default,
|
||||
]);
|
||||
|
||||
return $this->success('操作成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 删除地址
|
||||
*
|
||||
* @Author: <C.Jason>
|
||||
* @Date : 2020/11/5 5:52 下午
|
||||
* @param Address $address
|
||||
* @return mixed
|
||||
*/
|
||||
public function destroy(Address $address)
|
||||
{
|
||||
if ($address->user()->isNot(Api::user())) {
|
||||
return $this->failed('', 404);
|
||||
}
|
||||
|
||||
try {
|
||||
$address->delete();
|
||||
|
||||
return $this->success('操作成功');
|
||||
} catch (Exception$exception) {
|
||||
return $this->failed('失败');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
37
modules/Mall/Http/Controllers/Api/BannerController.php
Normal file
37
modules/Mall/Http/Controllers/Api/BannerController.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Api;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Http\Resources\Api\Banner\BannerResource;
|
||||
use Modules\Mall\Models\Banner;
|
||||
|
||||
class BannerController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 获取banner的接口
|
||||
* @Date : 2021/6/3 11:28 上午
|
||||
* @Author : <Jason.C>
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$position = $request->position;
|
||||
$shopId = $request->shop_id;
|
||||
|
||||
// 店铺ID为null的是平台轮播
|
||||
$banners = Banner::when($shopId, function (Builder $query) use ($shopId) {
|
||||
$query->where('shop_id', $shopId);
|
||||
})->when(is_numeric($position), function (Builder $query) use ($position) {
|
||||
$query->ofPosition($position);
|
||||
})->get();
|
||||
|
||||
return $this->success(BannerResource::collection($banners));
|
||||
}
|
||||
|
||||
}
|
||||
159
modules/Mall/Http/Controllers/Api/CartController.php
Normal file
159
modules/Mall/Http/Controllers/Api/CartController.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Api;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Jason\Api\Api;
|
||||
use Modules\Mall\Http\Requests\Cart\CartRequest;
|
||||
use Modules\Mall\Http\Resources\Api\Goods\CartResource;
|
||||
use Modules\Mall\Http\Resources\Api\Shop\ShopBaseInfoResource;
|
||||
use Modules\Mall\Models\Cart;
|
||||
use Modules\Mall\Models\GoodsSku;
|
||||
use Modules\Mall\Models\Shop;
|
||||
|
||||
class CartController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 购物车内商品列表
|
||||
* @Date : 2021/8/26 3:42 下午
|
||||
* @Author : <Jason.C>
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$list = Cart::byUser(Api::user())->with('sku')->orderByDesc('updated_at')->get();
|
||||
|
||||
$collection = $list->groupBy('shop_id');
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($collection as $shopId => $item) {
|
||||
$items[] = [
|
||||
'shop' => new ShopBaseInfoResource(Shop::find($shopId)),
|
||||
'items' => CartResource::collection($item),
|
||||
];
|
||||
}
|
||||
|
||||
return $this->success($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 加入购物车
|
||||
* @Date : 2021/5/14 2:17 下午
|
||||
* @Author : <Jason.C>
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$skuId = $request->sku_id;
|
||||
$qty = $request->qty ?? 1;
|
||||
|
||||
$sku = GoodsSku::findOrFail($skuId);
|
||||
|
||||
if (!$sku->canBuy($qty)) {
|
||||
return $this->failed('超过最大可购买数量');
|
||||
}
|
||||
|
||||
$cart = Cart::where('user_id', Api::userId())->where('sku_id', $skuId)->first();
|
||||
|
||||
if ($cart) {
|
||||
$cart->qty = $cart->qty + $qty;
|
||||
$cart->save();
|
||||
} else {
|
||||
$cart = Cart::create([
|
||||
'user_id' => Api::userId(),
|
||||
'shop_id' => $sku->goods->shop_id,
|
||||
'sku_id' => $skuId,
|
||||
'qty' => $qty,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->success($cart->qty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 获取购物车商品数量
|
||||
* @Date : 2021/5/14 1:47 下午
|
||||
* @Author : <Jason.C>
|
||||
*/
|
||||
public function count(): JsonResponse
|
||||
{
|
||||
if (Api::userId()) {
|
||||
$count = Cart::where('user_id', Api::userId())->count();
|
||||
} else {
|
||||
$count = 0;
|
||||
}
|
||||
|
||||
return $this->success($count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 更新购物车商品数量
|
||||
* @Date : 2021/5/13 2:52 下午
|
||||
* @Author : <Jason.C>
|
||||
* @param \Modules\Mall\Http\Requests\Cart\CartRequest $request
|
||||
* @param \Modules\Mall\Models\Cart $cart
|
||||
* @return mixed
|
||||
*/
|
||||
public function update(CartRequest $request, Cart $cart)
|
||||
{
|
||||
$skuId = $request->sku_id;
|
||||
$qty = $request->qty;
|
||||
|
||||
if ($cart->user()->isNot(Api::user())) {
|
||||
return $this->failed('', 404);
|
||||
}
|
||||
|
||||
if ($skuId && ($skuId != $cart->sku_id)) {
|
||||
$sku = GoodsSku::find($skuId);
|
||||
|
||||
if (!$cart->sku->goods->is($sku->goods)) {
|
||||
return $this->failed('错误的商品');
|
||||
}
|
||||
|
||||
$cart->sku_id = $skuId;
|
||||
} else {
|
||||
$sku = $cart->sku;
|
||||
}
|
||||
|
||||
if ($qty < 1 || $qty > $sku->stock) {
|
||||
return $this->failed('库存不足');
|
||||
}
|
||||
|
||||
$cart->qty = $qty;
|
||||
$cart->save();
|
||||
|
||||
return $this->success($qty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 删除购物车商品
|
||||
* @Date : 2021/5/17 4:00 下午
|
||||
* @Author : <Jason.C>
|
||||
* @param string $cart
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function destroy(string $cart)
|
||||
{
|
||||
if (Str::contains($cart, ',')) {
|
||||
$count = Cart::query()->where('user_id', Api::userId())->whereIn('id', explode(',', $cart))->delete();
|
||||
if (!$count) {
|
||||
return $this->failed('empty');
|
||||
}
|
||||
} else {
|
||||
$cart = Cart::find($cart);
|
||||
if ($cart->user()->isNot(Api::user())) {
|
||||
return $this->failed('', 404);
|
||||
}
|
||||
$cart->delete();
|
||||
}
|
||||
|
||||
return $this->success('删除成功');
|
||||
}
|
||||
|
||||
}
|
||||
37
modules/Mall/Http/Controllers/Api/CategoryController.php
Normal file
37
modules/Mall/Http/Controllers/Api/CategoryController.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Mall\Http\Controllers\Api;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Mall\Http\Resources\Api\Category\CategoryResource;
|
||||
use Modules\Mall\Models\Category;
|
||||
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 商品分类列表
|
||||
*
|
||||
* @Date : 2021/6/3 12:08 下午
|
||||
* @Author : <Jason.C>
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$shopId = $request->shop_id;
|
||||
|
||||
$list = Category::query()
|
||||
->where('id', '<>', 2)
|
||||
->when($shopId, function (Builder $query) use ($shopId) {
|
||||
$query->where('shop_id', $shopId);
|
||||
})->where('parent_id', 0)->get();
|
||||
|
||||
return $this->success(CategoryResource::collection($list));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user