|
|
|
@ -0,0 +1,181 @@
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Services\TestData;
|
|
|
|
|
|
|
|
|
|
use App\Models\Dialogue;
|
|
|
|
|
use App\Models\Message;
|
|
|
|
|
use App\Models\SupplyDemand;
|
|
|
|
|
use App\Models\SupplyDemandKeep;
|
|
|
|
|
use App\Models\Upload;
|
|
|
|
|
use App\Models\User;
|
|
|
|
|
use Faker\Factory as FakerFactory;
|
|
|
|
|
use Illuminate\Support\Arr;
|
|
|
|
|
use Illuminate\Support\Carbon;
|
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
|
|
|
|
|
|
class SupplyDemandTestDataGenerator
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* 生成供需相关的全量测试数据
|
|
|
|
|
*
|
|
|
|
|
* @param int $supplyDemandCount 生成供需数量
|
|
|
|
|
* @param int $minUsers 最少用户数量,不足会自动补充
|
|
|
|
|
* @param callable|null $logger 可选日志输出函数 function(string $message): void
|
|
|
|
|
*/
|
|
|
|
|
public function generate(int $supplyDemandCount = 50, int $minUsers = 20, ?callable $logger = null): void
|
|
|
|
|
{
|
|
|
|
|
$log = $logger ?? static function (string $message): void {
|
|
|
|
|
// no-op
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$faker = FakerFactory::create('zh_CN');
|
|
|
|
|
|
|
|
|
|
DB::transaction(function () use ($supplyDemandCount, $minUsers, $faker, $log) {
|
|
|
|
|
// 1) 确保用户数量
|
|
|
|
|
$currentUserCount = User::count();
|
|
|
|
|
if ($currentUserCount < $minUsers) {
|
|
|
|
|
$need = $minUsers - $currentUserCount;
|
|
|
|
|
$log("创建用户: {$need}");
|
|
|
|
|
// 使用 factory 填充用户
|
|
|
|
|
\App\Models\User::factory($need)->create();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$allUsers = User::query()->get(['id', 'name', 'nickname', 'username']);
|
|
|
|
|
if ($allUsers->count() < 2) {
|
|
|
|
|
throw new \RuntimeException('生成对话与消息至少需要2个用户');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2) 生成供需主数据
|
|
|
|
|
for ($i = 0; $i < $supplyDemandCount; $i++) {
|
|
|
|
|
$publisher = $allUsers->random();
|
|
|
|
|
|
|
|
|
|
$supplyDemand = new SupplyDemand();
|
|
|
|
|
$supplyDemand->user_id = $publisher->id;
|
|
|
|
|
$supplyDemand->title = $faker->sentence(4);
|
|
|
|
|
$supplyDemand->type = $faker->randomElement([1, 2]);
|
|
|
|
|
$supplyDemand->content = $faker->paragraphs($faker->numberBetween(1, 3), true);
|
|
|
|
|
$supplyDemand->tag = implode(',', $faker->randomElements(['采购', '合作', '招聘', '渠道', '推广', '技术', '投资'], $faker->numberBetween(1, 3)));
|
|
|
|
|
$supplyDemand->wechat = 'wx_' . $faker->bothify('??####');
|
|
|
|
|
$supplyDemand->mobile = $faker->phoneNumber();
|
|
|
|
|
$supplyDemand->email = $faker->safeEmail();
|
|
|
|
|
$supplyDemand->status = $faker->randomElement([0, 1, 2, 3, 4]);
|
|
|
|
|
$supplyDemand->view_count = 0; // 稍后回填
|
|
|
|
|
$supplyDemand->contact_count = 0; // 稍后回填
|
|
|
|
|
$supplyDemand->expire_time = $faker->optional(0.6)->dateTimeBetween('now', '+90 days')?->format('Y-m-d H:i:s');
|
|
|
|
|
// public_way 实际业务需要三态(1/2/3),但列类型为 boolean,这里按 0/1 赋值
|
|
|
|
|
$supplyDemand->public_way = $faker->boolean ? 1 : 0;
|
|
|
|
|
$supplyDemand->contact_name = $faker->name();
|
|
|
|
|
$supplyDemand->save();
|
|
|
|
|
|
|
|
|
|
// 3) 附件:0~3 个,并同步回填 file_ids
|
|
|
|
|
$uploadIds = [];
|
|
|
|
|
$attachmentsCount = $faker->numberBetween(0, 3);
|
|
|
|
|
for ($k = 0; $k < $attachmentsCount; $k++) {
|
|
|
|
|
$originalName = $faker->lexify('file_????') . '.' . $faker->randomElement(['pdf', 'png', 'jpg', 'docx']);
|
|
|
|
|
$extension = pathinfo($originalName, PATHINFO_EXTENSION);
|
|
|
|
|
$upload = new Upload();
|
|
|
|
|
$upload->belongs_type = SupplyDemand::class;
|
|
|
|
|
$upload->belongs_id = $supplyDemand->id;
|
|
|
|
|
$upload->original_name = $originalName;
|
|
|
|
|
$upload->folder = 'test/' . date('Ymd');
|
|
|
|
|
$upload->name = $faker->uuid . '.' . $extension;
|
|
|
|
|
$upload->extension = $extension;
|
|
|
|
|
$upload->size = $faker->numberBetween(5 * 1024, 2 * 1024 * 1024);
|
|
|
|
|
$upload->creator_type = 'seeder';
|
|
|
|
|
$upload->creator_id = $publisher->id;
|
|
|
|
|
$upload->save();
|
|
|
|
|
$uploadIds[] = $upload->id;
|
|
|
|
|
}
|
|
|
|
|
if (!empty($uploadIds)) {
|
|
|
|
|
$supplyDemand->file_ids = $uploadIds;
|
|
|
|
|
$supplyDemand->save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4) 会话与消息:0~2 个会话,每个会话 1~5 条消息,严格交替
|
|
|
|
|
$dialogueCount = $faker->numberBetween(0, 2);
|
|
|
|
|
$totalMessages = 0;
|
|
|
|
|
$totalContacts = 0; // 统计对发布者的有效联系次数
|
|
|
|
|
|
|
|
|
|
for ($d = 0; $d < $dialogueCount; $d++) {
|
|
|
|
|
// 选择一个不同于发布者的用户作为对话方
|
|
|
|
|
$other = $allUsers->where('id', '!=', $publisher->id)->random();
|
|
|
|
|
|
|
|
|
|
$dialogue = new Dialogue();
|
|
|
|
|
$dialogue->user_id = $faker->randomElement([$publisher->id, $other->id]); // 对话发起方随机
|
|
|
|
|
$dialogue->to_user_id = ($dialogue->user_id === $publisher->id) ? $other->id : $publisher->id;
|
|
|
|
|
$dialogue->supply_demand_id = $supplyDemand->id;
|
|
|
|
|
$dialogue->last_content = null;
|
|
|
|
|
$dialogue->last_datetime = null;
|
|
|
|
|
$dialogue->save();
|
|
|
|
|
|
|
|
|
|
$messageCount = $faker->numberBetween(1, 5);
|
|
|
|
|
$sender = $faker->randomElement([$publisher->id, $other->id]);
|
|
|
|
|
$receiver = ($sender === $publisher->id) ? $other->id : $publisher->id;
|
|
|
|
|
|
|
|
|
|
$lastContent = null;
|
|
|
|
|
$lastDatetime = null;
|
|
|
|
|
for ($m = 0; $m < $messageCount; $m++) {
|
|
|
|
|
$content = $faker->realText($faker->numberBetween(20, 80));
|
|
|
|
|
$createdAt = Carbon::now()->subDays($faker->numberBetween(0, 10))->addMinutes($faker->numberBetween(0, 1440));
|
|
|
|
|
|
|
|
|
|
$msg = new Message();
|
|
|
|
|
$msg->dialogue_id = $dialogue->id;
|
|
|
|
|
$msg->user_id = $sender;
|
|
|
|
|
$msg->to_user_id = $receiver;
|
|
|
|
|
$msg->supply_demand_id = $supplyDemand->id;
|
|
|
|
|
$msg->content = $content;
|
|
|
|
|
$msg->is_read = $faker->boolean ? 1 : 0;
|
|
|
|
|
$msg->created_at = $createdAt;
|
|
|
|
|
$msg->updated_at = $createdAt;
|
|
|
|
|
$msg->save();
|
|
|
|
|
|
|
|
|
|
// 统计“对发布者的联系”
|
|
|
|
|
if ($receiver === $publisher->id) {
|
|
|
|
|
$totalContacts++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$lastContent = $content;
|
|
|
|
|
$lastDatetime = $createdAt->format('Y-m-d H:i:s');
|
|
|
|
|
|
|
|
|
|
// 严格交替:交换 sender/receiver
|
|
|
|
|
[$sender, $receiver] = [$receiver, $sender];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$dialogue->last_content = $lastContent;
|
|
|
|
|
$dialogue->last_datetime = $lastDatetime;
|
|
|
|
|
$dialogue->save();
|
|
|
|
|
|
|
|
|
|
$totalMessages += $messageCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5) 收藏:0~5 个
|
|
|
|
|
$keepCount = $faker->numberBetween(0, 5);
|
|
|
|
|
if ($keepCount > 0) {
|
|
|
|
|
$keeperPool = $allUsers->where('id', '!=', $publisher->id)->pluck('id')->all();
|
|
|
|
|
$keepers = Arr::random($keeperPool, min($keepCount, count($keeperPool)));
|
|
|
|
|
foreach ((array)$keepers as $keeperId) {
|
|
|
|
|
SupplyDemandKeep::firstOrCreate([
|
|
|
|
|
'user_id' => $keeperId,
|
|
|
|
|
'supply_demand_id' => $supplyDemand->id,
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 6) 回填统计:浏览量 >= 消息数,联系次数 = 对发布者的消息次数
|
|
|
|
|
$supplyDemand->contact_count = $totalContacts;
|
|
|
|
|
$supplyDemand->view_count = $totalMessages + $faker->numberBetween(0, 20);
|
|
|
|
|
$supplyDemand->save();
|
|
|
|
|
|
|
|
|
|
$log(sprintf('供需#%d 已生成:附件%s个,会话%s个,消息%s条,收藏%s个',
|
|
|
|
|
$supplyDemand->id,
|
|
|
|
|
count($uploadIds),
|
|
|
|
|
$dialogueCount,
|
|
|
|
|
$totalMessages,
|
|
|
|
|
$keepCount
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|