bianjunhui 3 天之前
父節點
當前提交
f02bcbca20

+ 1 - 0
bootstrap/providers.php

@@ -18,6 +18,7 @@ return [
     Longyi\ImageUpload\Providers\ImageUploadServiceProvider::class,
     Longyi\RewardPoints\Providers\RewardPointsServiceProvider::class,
     Longyi\Member\Providers\MemberServiceProvider::class,
+    Longyi\Wholesale\Providers\WholesaleServiceProvider::class,
     Longyi\Gift\Providers\GiftServiceProvider::class,
     Longyi\ShippingInsurance\Providers\ShippingInsuranceServiceProvider::class,
     Longyi\Pay\AwxAfterpay\Providers\AwxAfterpayServiceProvider::class,

+ 1 - 0
composer.json

@@ -87,6 +87,7 @@
             "Longyi\\ImageUpload\\": "packages/Longyi/ImageUpload/src/",
             "Longyi\\RewardPoints\\": "packages/Longyi/RewardPoints/src/",
             "Longyi\\Member\\": "packages/Longyi/Member/src/",
+            "Longyi\\Wholesale\\": "packages/Longyi/Wholesale/src/",
             "Longyi\\Gift\\": "packages/Longyi/Gift/src/",
             "Longyi\\FreeGift\\": "packages/Longyi/FreeGift/src/",
             "Longyi\\ShippingInsurance\\": "packages/Longyi/ShippingInsurance/src/",

+ 252 - 0
packages/Longyi/Wholesale/README.md

@@ -0,0 +1,252 @@
+# Longyi Wholesale Module
+
+一个用于 Bagisto 的批发询盘(Wholesale)模块,对应 `asteriahair.com/wholesale` 的询盘功能。前端用户通过 API 提交批发询盘,后台管理员在 Sales 菜单下查看和管理这些询盘记录。
+
+## 功能特性
+
+- ✅ 前台公开 API 提交询盘(无需登录)
+- ✅ 询盘字段校验(姓名、邮箱必填)
+- ✅ 中英文提示文案
+- ✅ 后台 Sales 菜单新增「批发询盘」目录
+- ✅ 后台询盘列表(DataGrid:搜索 / 排序 / 分页)
+- ✅ 后台删除询盘记录
+- ✅ 基于角色的权限控制(ACL)
+
+## 目录结构
+
+```
+Longyi/Wholesale/
+├── src/
+│   ├── Config/
+│   │   ├── admin-menu.php          # 后台菜单(sales.wholesale)
+│   │   └── acl.php                 # 权限配置
+│   ├── Database/
+│   │   └── Migrations/             # message 表迁移
+│   ├── DataGrids/
+│   │   └── MessageDataGrid.php     # 后台列表
+│   ├── Helpers/
+│   │   └── ApiResponse.php         # 统一 API 返回格式
+│   ├── Http/Controllers/
+│   │   ├── Admin/WholesaleController.php   # 后台控制器
+│   │   └── WholesaleController.php         # 前台 API 控制器
+│   ├── Models/
+│   │   └── Message.php             # 询盘模型
+│   ├── Providers/
+│   │   └── WholesaleServiceProvider.php
+│   ├── Resources/
+│   │   ├── lang/{en,zh_CN}/app.php # 中英文文案
+│   │   └── views/admin/index.blade.php
+│   └── Routes/
+│       ├── admin-routes.php        # 后台路由
+│       └── shop-routes.php         # 前台 API 路由
+```
+
+## 安装步骤
+
+### 1. 确认插件已注册
+
+`bootstrap/providers.php` 中已添加:
+
+```php
+Longyi\Wholesale\Providers\WholesaleServiceProvider::class,
+```
+
+`composer.json` 的 `autoload.psr-4` 中已添加命名空间映射:
+
+```json
+"Longyi\\Wholesale\\": "packages/Longyi/Wholesale/src/"
+```
+
+### 2. 生成自动加载
+
+```bash
+composer dump-autoload
+```
+
+### 3. 运行数据库迁移
+
+```bash
+php artisan migrate
+```
+
+这将创建 `message` 表,用于存储批发询盘记录。
+
+### 4. 清理缓存
+
+```bash
+php artisan config:clear
+php artisan route:clear
+php artisan view:clear
+```
+
+### 5. 配置后台角色权限
+
+首次使用需要到后台 **设置 → 角色** 中,为管理员角色勾选以下权限,否则侧边栏不显示「批发询盘」菜单:
+
+- `sales.wholesale` —— 查看批发询盘列表
+- `sales.wholesale.delete` —— 删除询盘记录
+
+## 数据表结构
+
+`message` 表:
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `message_id` | int unsigned PK, auto increment | 主键 |
+| `name` | varchar(200) | 姓名 |
+| `Email` | varchar(50) | 邮箱 |
+| `number` | varchar(300) | 联系方式 |
+| `message` | varchar(600) | 留言内容 |
+| `country` | varchar(50) | 国家 |
+| `created_at` | timestamp | 提交时间 |
+| `business_name` | varchar(300) | 公司名称 |
+| `business_role` | varchar(50) | 公司角色 |
+
+> 注意:表的主键为 `message_id`(非 `id`),且只有 `created_at` 字段(无 `updated_at`),模型已做相应适配(`$timestamps = false`)。
+
+## 前端 API
+
+### 提交批发询盘
+
+**请求:**
+
+```http
+POST /api/wholesale
+Content-Type: application/json
+```
+
+```json
+{
+    "name": "John Doe",
+    "email": "john@example.com",
+    "number": "+1 234 567 8900",
+    "message": "I'm interested in your wholesale products.",
+    "country": "United States",
+    "business_name": "ABC Trading Co.",
+    "business_role": "Distributor"
+}
+```
+
+**字段说明:**
+
+| 字段 | 必填 | 类型 | 长度限制 |
+|------|:---:|------|:---:|
+| `name` | ✅ | string | 200 |
+| `email` | ✅ | email | 50 |
+| `number` | ❌ | string | 300 |
+| `message` | ❌ | string | 600 |
+| `country` | ❌ | string | 50 |
+| `business_name` | ❌ | string | 300 |
+| `business_role` | ❌ | string | 50 |
+
+**成功响应:**
+
+```json
+{
+    "success": true,
+    "message": "您的询盘已提交成功。",
+    "data": {
+        "id": 1
+    }
+}
+```
+
+**失败响应:**
+
+```json
+{
+    "success": false,
+    "message": "错误信息",
+    "data": []
+}
+```
+
+### 统一返回格式
+
+本模块的 API 统一使用 `Longyi\Wholesale\Helpers\ApiResponse` 返回,格式与 `RewardPoints` 模块一致:
+
+```json
+{
+    "success": true,
+    "message": "Success",
+    "data": {}
+}
+```
+
+支持的静态方法:
+
+| 方法 | 说明 |
+|------|------|
+| `ApiResponse::success($data, $message, $code)` | 成功响应(默认 200) |
+| `ApiResponse::paginated($data, $paginator, $message, $code)` | 带分页的成功响应 |
+| `ApiResponse::error($message, $data, $code)` | 错误响应(默认 400) |
+| `ApiResponse::unauthorized($message)` | 未授权响应(401) |
+| `ApiResponse::validationError($message, $errors)` | 验证错误响应(422) |
+
+## 后台管理
+
+### 访问入口
+
+后台侧边栏 **Sales → 批发询盘(Wholesale)**,路由:
+
+```
+GET  /admin/sales/wholesale       # 询盘列表
+DELETE /admin/sales/wholesale/{id} # 删除询盘
+```
+
+### 列表功能
+
+- 列表展示:ID、姓名、邮箱、联系方式、公司名称、公司角色、国家、留言内容、提交时间
+- 支持按姓名 / 邮箱 / 联系方式 / 公司名称 / 留言内容搜索
+- 支持按 ID、时间等排序、分页
+- 支持删除单条询盘记录(需 `sales.wholesale.delete` 权限)
+
+## JavaScript / Fetch 使用示例
+
+```javascript
+async function submitWholesaleEnquiry(formData) {
+    try {
+        const response = await fetch('/api/wholesale', {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/json',
+                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content,
+            },
+            body: JSON.stringify({
+                name: formData.name,
+                email: formData.email,
+                number: formData.number,
+                message: formData.message,
+                country: formData.country,
+                business_name: formData.business_name,
+                business_role: formData.business_role,
+            }),
+        });
+
+        const data = await response.json();
+
+        if (data.success) {
+            console.log('提交成功:', data.data);
+            return data.data;
+        } else {
+            console.error('提交失败:', data.message);
+        }
+    } catch (error) {
+        console.error('错误:', error);
+    }
+}
+```
+
+## 依赖要求
+
+- PHP >= 8.2
+- Laravel >= 11.0
+- Bagisto 2.x
+
+## 许可证
+
+MIT License
+
+## 作者
+
+Longyi Team <dev@longyi.com>

+ 15 - 0
packages/Longyi/Wholesale/src/Config/acl.php

@@ -0,0 +1,15 @@
+<?php
+
+return [
+    [
+        'key'   => 'sales.wholesale',
+        'name'  => 'wholesale::app.admin.menu-title',
+        'route' => 'admin.sales.wholesale.index',
+        'sort'  => 7,
+    ], [
+        'key'   => 'sales.wholesale.delete',
+        'name'  => 'wholesale::app.admin.acl.delete',
+        'route' => 'admin.sales.wholesale.delete',
+        'sort'  => 1,
+    ],
+];

+ 11 - 0
packages/Longyi/Wholesale/src/Config/admin-menu.php

@@ -0,0 +1,11 @@
+<?php
+
+return [
+    [
+        'key'   => 'sales.wholesale',
+        'name'  => 'wholesale::app.admin.menu-title',
+        'route' => 'admin.sales.wholesale.index',
+        'sort'  => 7,
+        'icon'  => '',
+    ],
+];

+ 154 - 0
packages/Longyi/Wholesale/src/DataGrids/MessageDataGrid.php

@@ -0,0 +1,154 @@
+<?php
+
+namespace Longyi\Wholesale\DataGrids;
+
+use Illuminate\Support\Facades\DB;
+use Webkul\DataGrid\DataGrid;
+
+class MessageDataGrid extends DataGrid
+{
+    /**
+     * Primary column.
+     *
+     * The `message` table uses `message_id` as its primary key instead of `id`.
+     *
+     * @var string
+     */
+    protected $primaryColumn = 'message_id';
+
+    /**
+     * Default sort column of datagrid.
+     *
+     * @var string
+     */
+    protected $sortColumn = 'message_id';
+
+    /**
+     * Prepare query builder.
+     *
+     * @return \Illuminate\Database\Query\Builder
+     */
+    public function prepareQueryBuilder()
+    {
+        return DB::table('message')
+            ->select(
+                'message_id',
+                'name',
+                'Email',
+                'number',
+                'message',
+                'country',
+                'created_at',
+                'business_name',
+                'business_role'
+            );
+    }
+
+    /**
+     * Add columns.
+     *
+     * @return void
+     */
+    public function prepareColumns()
+    {
+        $this->addColumn([
+            'index'      => 'message_id',
+            'label'      => trans('wholesale::app.admin.datagrid.id'),
+            'type'       => 'integer',
+            'filterable' => true,
+            'sortable'   => true,
+        ]);
+
+        $this->addColumn([
+            'index'      => 'name',
+            'label'      => trans('wholesale::app.admin.datagrid.name'),
+            'type'       => 'string',
+            'filterable' => true,
+            'sortable'   => true,
+            'searchable' => true,
+        ]);
+
+        $this->addColumn([
+            'index'      => 'Email',
+            'label'      => trans('wholesale::app.admin.datagrid.email'),
+            'type'       => 'string',
+            'filterable' => true,
+            'sortable'   => true,
+            'searchable' => true,
+        ]);
+
+        $this->addColumn([
+            'index'      => 'number',
+            'label'      => trans('wholesale::app.admin.datagrid.number'),
+            'type'       => 'string',
+            'filterable' => true,
+            'sortable'   => true,
+            'searchable' => true,
+        ]);
+
+        $this->addColumn([
+            'index'      => 'business_name',
+            'label'      => trans('wholesale::app.admin.datagrid.business-name'),
+            'type'       => 'string',
+            'filterable' => true,
+            'sortable'   => true,
+            'searchable' => true,
+        ]);
+
+        $this->addColumn([
+            'index'      => 'business_role',
+            'label'      => trans('wholesale::app.admin.datagrid.business-role'),
+            'type'       => 'string',
+            'filterable' => true,
+            'sortable'   => true,
+        ]);
+
+        $this->addColumn([
+            'index'      => 'country',
+            'label'      => trans('wholesale::app.admin.datagrid.country'),
+            'type'       => 'string',
+            'filterable' => true,
+            'sortable'   => true,
+        ]);
+
+        $this->addColumn([
+            'index'      => 'message',
+            'label'      => trans('wholesale::app.admin.datagrid.message'),
+            'type'       => 'string',
+            'filterable' => false,
+            'sortable'   => false,
+            'searchable' => true,
+            'closure'    => function ($row) {
+                return $row->message;
+            },
+        ]);
+
+        $this->addColumn([
+            'index'      => 'created_at',
+            'label'      => trans('wholesale::app.admin.datagrid.created-at'),
+            'type'       => 'datetime',
+            'filterable' => true,
+            'sortable'   => true,
+        ]);
+    }
+
+    /**
+     * Prepare actions.
+     *
+     * @return void
+     */
+    public function prepareActions()
+    {
+        if (bouncer()->hasPermission('sales.wholesale.delete')) {
+            $this->addAction([
+                'index'  => 'delete',
+                'icon'   => 'icon-delete',
+                'title'  => trans('wholesale::app.admin.datagrid.delete'),
+                'method' => 'DELETE',
+                'url'    => function ($row) {
+                    return route('admin.sales.wholesale.delete', $row->message_id);
+                },
+            ]);
+        }
+    }
+}

+ 34 - 0
packages/Longyi/Wholesale/src/Database/Migrations/2026_10_20_000000_create_message_table.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::create('message', function (Blueprint $table) {
+            $table->increments('message_id');
+            $table->string('name', 200)->nullable();
+            $table->string('Email', 50)->nullable();
+            $table->string('number', 300)->nullable();
+            $table->string('message', 600)->nullable();
+            $table->string('country', 50)->nullable();
+            $table->timestamp('created_at')->nullable();
+            $table->string('business_name', 300)->default('');
+            $table->string('business_role', 50)->default('');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('message');
+    }
+};

+ 67 - 0
packages/Longyi/Wholesale/src/Helpers/ApiResponse.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace Longyi\Wholesale\Helpers;
+
+use Illuminate\Pagination\LengthAwarePaginator;
+
+class ApiResponse
+{
+    /**
+     * 成功响应
+     */
+    public static function success($data = [], string $message = 'Success', int $code = 200)
+    {
+        return response()->json([
+            'success' => true,
+            'message' => $message,
+            'data'    => $data,
+        ], $code);
+    }
+
+    /**
+     * 带分页的成功响应
+     */
+    public static function paginated($data, LengthAwarePaginator $paginator, string $message = 'Success', int $code = 200)
+    {
+        return response()->json([
+            'success'    => true,
+            'message'    => $message,
+            'data'       => $data,
+            'pagination' => [
+                'current_page' => $paginator->currentPage(),
+                'per_page'     => $paginator->perPage(),
+                'total'        => $paginator->total(),
+                'last_page'    => $paginator->lastPage(),
+                'has_more'     => $paginator->hasMorePages(),
+            ],
+        ], $code);
+    }
+
+    /**
+     * 错误响应
+     */
+    public static function error(string $message, $data = [], int $code = 400)
+    {
+        return response()->json([
+            'success' => false,
+            'message' => $message,
+            'data'    => $data,
+        ], $code);
+    }
+
+    /**
+     * 未授权响应
+     */
+    public static function unauthorized(string $message = 'Please login first')
+    {
+        return self::error($message, [], 401);
+    }
+
+    /**
+     * 验证错误响应
+     */
+    public static function validationError(string $message, $errors = [])
+    {
+        return self::error($message, $errors, 422);
+    }
+}

+ 55 - 0
packages/Longyi/Wholesale/src/Http/Controllers/Admin/WholesaleController.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace Longyi\Wholesale\Http\Controllers\Admin;
+
+use Illuminate\Http\JsonResponse;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\View\View;
+use Longyi\Wholesale\DataGrids\MessageDataGrid;
+use Longyi\Wholesale\Models\Message;
+use Webkul\Admin\Http\Controllers\Controller;
+
+class WholesaleController extends Controller
+{
+    /**
+     * Display a listing of the wholesale enquiries.
+     */
+    public function index(): View|JsonResponse
+    {
+        if (request()->ajax()) {
+            return datagrid(MessageDataGrid::class)->process();
+        }
+
+        return view('wholesale::admin.index');
+    }
+
+    /**
+     * Remove the specified wholesale enquiry.
+     */
+    public function destroy(int $id): JsonResponse|RedirectResponse
+    {
+        $message = Message::query()->find($id);
+
+        if (! $message) {
+            if (request()->ajax()) {
+                return new JsonResponse([
+                    'message' => trans('wholesale::app.admin.not-found'),
+                ], 404);
+            }
+
+            return redirect()->route('admin.sales.wholesale.index')
+                ->with('error', trans('wholesale::app.admin.not-found'));
+        }
+
+        $message->delete();
+
+        if (request()->ajax()) {
+            return new JsonResponse([
+                'message' => trans('wholesale::app.admin.delete-success'),
+            ]);
+        }
+
+        return redirect()->route('admin.sales.wholesale.index')
+            ->with('success', trans('wholesale::app.admin.delete-success'));
+    }
+}

+ 47 - 0
packages/Longyi/Wholesale/src/Http/Controllers/WholesaleController.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace Longyi\Wholesale\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Routing\Controller;
+use Longyi\Wholesale\Helpers\ApiResponse;
+use Longyi\Wholesale\Models\Message;
+
+class WholesaleController extends Controller
+{
+    /**
+     * Store a new wholesale enquiry.
+     *
+     * POST /api/wholesale
+     */
+    public function store(Request $request)
+    {
+        try {
+            $validated = $request->validate([
+                'name'          => 'required|string|max:200',
+                'email'         => 'required|email|max:50',
+                'number'        => 'nullable|string|max:300',
+                'message'       => 'nullable|string|max:600',
+                'country'       => 'nullable|string|max:50',
+                'business_name' => 'nullable|string|max:300',
+                'business_role' => 'nullable|string|max:50',
+            ]);
+
+            $message = Message::create([
+                'name'          => $validated['name'],
+                'Email'         => $validated['email'],
+                'number'        => $validated['number'] ?? null,
+                'message'       => $validated['message'] ?? null,
+                'country'       => $validated['country'] ?? null,
+                'business_name' => $validated['business_name'] ?? '',
+                'business_role' => $validated['business_role'] ?? '',
+            ]);
+
+            return ApiResponse::success([
+                'id' => $message->message_id,
+            ], trans('wholesale::app.shop.success'));
+        } catch (\Exception $e) {
+            return ApiResponse::error($e->getMessage());
+        }
+    }
+}

+ 71 - 0
packages/Longyi/Wholesale/src/Models/Message.php

@@ -0,0 +1,71 @@
+<?php
+
+namespace Longyi\Wholesale\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Message extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'message';
+
+    /**
+     * The primary key for the model.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'message_id';
+
+    /**
+     * The "type" of the primary key ID.
+     *
+     * @var string
+     */
+    protected $keyType = 'int';
+
+    /**
+     * Indicates if the IDs are auto-incrementing.
+     *
+     * @var bool
+     */
+    public $incrementing = true;
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * The `message` table only has a `created_at` column (no `updated_at`),
+     * and it is maintained by the database, so we disable Eloquent's
+     * automatic timestamps.
+     *
+     * @var bool
+     */
+    public $timestamps = false;
+
+    /**
+     * The attributes that are mass assignable.
+     *
+     * @var array
+     */
+    protected $fillable = [
+        'name',
+        'Email',
+        'number',
+        'message',
+        'country',
+        'business_name',
+        'business_role',
+    ];
+
+    /**
+     * The attributes that should be cast.
+     *
+     * @var array
+     */
+    protected $casts = [
+        'created_at' => 'datetime',
+    ];
+}

+ 50 - 0
packages/Longyi/Wholesale/src/Providers/WholesaleServiceProvider.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace Longyi\Wholesale\Providers;
+
+use Illuminate\Support\ServiceProvider;
+
+class WholesaleServiceProvider extends ServiceProvider
+{
+    /**
+     * Register services.
+     */
+    public function register(): void
+    {
+        $this->registerConfig();
+    }
+
+    /**
+     * Bootstrap services.
+     */
+    public function boot(): void
+    {
+        $this->loadMigrationsFrom(__DIR__.'/../Database/Migrations');
+
+        $this->loadRoutesFrom(__DIR__.'/../Routes/admin-routes.php');
+
+        $this->loadRoutesFrom(__DIR__.'/../Routes/shop-routes.php');
+
+        $this->loadTranslationsFrom(__DIR__.'/../Resources/lang', 'wholesale');
+
+        $this->loadViewsFrom(__DIR__.'/../Resources/views', 'wholesale');
+    }
+
+    /**
+     * Register package config.
+     */
+    protected function registerConfig(): void
+    {
+        // Register the admin menu item under the existing "Sales" menu.
+        $this->mergeConfigFrom(
+            dirname(__DIR__).'/Config/admin-menu.php',
+            'menu.admin'
+        );
+
+        // Register ACL permissions so the menu item is visible to admin users.
+        $this->mergeConfigFrom(
+            dirname(__DIR__).'/Config/acl.php',
+            'acl'
+        );
+    }
+}

+ 31 - 0
packages/Longyi/Wholesale/src/Resources/lang/en/app.php

@@ -0,0 +1,31 @@
+<?php
+
+return [
+    'shop' => [
+        'success' => 'Your enquiry has been submitted successfully.',
+    ],
+
+    'admin' => [
+        'menu-title'     => 'Wholesale',
+        'page-title'     => 'Wholesale Enquiries',
+        'not-found'      => 'Enquiry not found.',
+        'delete-success' => 'Enquiry deleted successfully.',
+
+        'acl' => [
+            'delete' => 'Delete Wholesale Enquiry',
+        ],
+
+        'datagrid' => [
+            'id'            => 'ID',
+            'name'          => 'Name',
+            'email'         => 'Email',
+            'number'        => 'Number',
+            'business-name' => 'Business Name',
+            'business-role' => 'Business Role',
+            'country'       => 'Country',
+            'message'       => 'Message',
+            'created-at'    => 'Created At',
+            'delete'        => 'Delete',
+        ],
+    ],
+];

+ 31 - 0
packages/Longyi/Wholesale/src/Resources/lang/zh_CN/app.php

@@ -0,0 +1,31 @@
+<?php
+
+return [
+    'shop' => [
+        'success' => '您的询盘已提交成功。',
+    ],
+
+    'admin' => [
+        'menu-title'     => '批发询盘',
+        'page-title'     => '批发询盘列表',
+        'not-found'      => '未找到该询盘记录。',
+        'delete-success' => '询盘记录删除成功。',
+
+        'acl' => [
+            'delete' => '删除批发询盘',
+        ],
+
+        'datagrid' => [
+            'id'            => 'ID',
+            'name'          => '姓名',
+            'email'         => '邮箱',
+            'number'        => '联系方式',
+            'business-name' => '公司名称',
+            'business-role' => '公司角色',
+            'country'       => '国家',
+            'message'       => '留言内容',
+            'created-at'    => '提交时间',
+            'delete'        => '删除',
+        ],
+    ],
+];

+ 13 - 0
packages/Longyi/Wholesale/src/Resources/views/admin/index.blade.php

@@ -0,0 +1,13 @@
+<x-admin::layouts>
+    <x-slot:title>
+        @lang('wholesale::app.admin.page-title')
+    </x-slot>
+
+    <div class="flex items-center justify-between gap-4">
+        <p class="text-xl font-bold text-gray-800 dark:text-white">
+            @lang('wholesale::app.admin.page-title')
+        </p>
+    </div>
+
+    <x-admin::datagrid :src="route('admin.sales.wholesale.index')" />
+</x-admin::layouts>

+ 12 - 0
packages/Longyi/Wholesale/src/Routes/admin-routes.php

@@ -0,0 +1,12 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+use Longyi\Wholesale\Http\Controllers\Admin\WholesaleController;
+
+Route::group(['middleware' => ['web', 'admin'], 'prefix' => 'admin/sales/wholesale'], function () {
+    Route::controller(WholesaleController::class)->group(function () {
+        Route::get('', 'index')->name('admin.sales.wholesale.index');
+
+        Route::delete('{id}', 'destroy')->name('admin.sales.wholesale.delete');
+    });
+});

+ 11 - 0
packages/Longyi/Wholesale/src/Routes/shop-routes.php

@@ -0,0 +1,11 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+use Longyi\Wholesale\Http\Controllers\WholesaleController;
+
+// 前台公开 API:提交批发询盘
+Route::group(['middleware' => ['web'], 'prefix' => 'api'], function () {
+    Route::controller(WholesaleController::class)->prefix('wholesale')->group(function () {
+        Route::post('', 'store')->name('shop.api.wholesale.store');
+    });
+});