|
|
3 giorni fa | |
|---|---|---|
| .. | ||
| src | 3 giorni fa | |
| README.md | 3 giorni fa | |
一个用于 Bagisto 的批发询盘(Wholesale)模块,对应 asteriahair.com/wholesale 的询盘功能。前端用户通过 API 提交批发询盘,后台管理员在 Sales 菜单下查看和管理这些询盘记录。
php artisan wholesale:import-message)Longyi/Wholesale/
├── src/
│ ├── Config/
│ │ ├── admin-menu.php # 后台菜单(sales.wholesale)
│ │ └── acl.php # 权限配置
│ ├── Console/
│ │ └── Commands/
│ │ └── ImportMessageData.php # 历史数据导入命令
│ ├── Database/
│ │ ├── Migrations/ # message 表迁移
│ │ └── message.sql # 历史数据 SQL(Navicat 导出)
│ ├── 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 路由
bootstrap/providers.php 中已添加:
Longyi\Wholesale\Providers\WholesaleServiceProvider::class,
composer.json 的 autoload.psr-4 中已添加命名空间映射:
"Longyi\\Wholesale\\": "packages/Longyi/Wholesale/src/"
composer dump-autoload
php artisan migrate
这将创建 message 表,用于存储批发询盘记录。
php artisan config:clear
php artisan route:clear
php artisan view:clear
首次使用需要到后台 设置 → 角色 中,为管理员角色勾选以下权限,否则侧边栏不显示「批发询盘」菜单:
sales.wholesale —— 查看批发询盘列表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 = true,CREATED_AT = 'created_at',UPDATED_AT = null)。
模块内置了一条 artisan 命令,用于将历史询盘数据(src/Database/message.sql,Navicat 导出的 MySQL 文件)批量导入到现有的 message 表。
php artisan wholesale:import-message
| 参数 | 说明 | 默认值 |
|---|---|---|
--file |
SQL 文件路径 | 包内 src/Database/message.sql |
--batch |
每次批量插入的行数 | 500 |
# 使用默认文件、默认批大小导入
php artisan wholesale:import-message
# 指定 SQL 文件路径
php artisan wholesale:import-message --file=/path/to/message.sql
# 调整批量插入大小
php artisan wholesale:import-message --batch=1000
TRUNCATE 现有 message 表,再导入 SQL 文件中的数据(全量替换)。DROP TABLE、CREATE TABLE、注释等语句,不会重建表结构。Email(大写)字段会正确映射到现有表的 email(小写)列。message_id 转为整数,保留原始主键值;NULL 和空字符串转为 null;\'、\r\n、\t 等 SQL 转义字符。请求:
POST /api/wholesale
Content-Type: application/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 |
✅ | 50 | |
number |
❌ | string | 300 |
message |
❌ | string | 600 |
country |
❌ | string | 50 |
business_name |
❌ | string | 300 |
business_role |
❌ | string | 50 |
成功响应:
{
"success": true,
"message": "Your enquiry has been submitted successfully.",
"data": {
"id": 1
}
}
失败响应:
{
"success": false,
"message": "Error message",
"data": []
}
前台 API 的所有提示信息统一使用英文,不随当前语言(locale)变化。
接口内置了双重防护,防止恶意重复提交:
{
"success": false,
"message": "Too many requests. Please try again later.",
"data": []
}
{
"success": false,
"message": "You have already submitted an enquiry. Please try again later.",
"data": []
}
阈值与窗口期通过
WholesaleController中的常量MAX_ATTEMPTS、DECAY_SECONDS、DAILY_MAX_ATTEMPTS、DAILY_DECAY_SECONDS、DUPLICATE_SECONDS配置。
本模块的 API 统一使用 Longyi\Wholesale\Helpers\ApiResponse 返回,格式与 RewardPoints 模块一致:
{
"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 # 询盘列表
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);
}
}
MIT License
Longyi Team dev@longyi.com