You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

303 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace Database\Seeders;
use App\Models\Competition;
use App\Models\FormSchemaDefinition;
use App\Support\SignupFieldI18n;
use App\Support\SignupOptionCatalog;
use Illuminate\Database\Seeder;
/**
* 与选手端 ApplyFormView 字段 key / 校验口径对齐的报名表 schema(purpose=signup)。
*
* 运行:php artisan db:seed --class=CompetitionSignupFormSchemaSeeder
* 可选:SIGNUP_SCHEMA_COMPETITION_ID=1(默认 1)
*/
class CompetitionSignupFormSchemaSeeder extends Seeder
{
public function run(): void
{
$competitionId = (int) env('SIGNUP_SCHEMA_COMPETITION_ID', 1);
$competition = Competition::query()->find($competitionId);
if (! $competition) {
$this->command?->warn("Competition {$competitionId} not found, skip.");
return;
}
$purpose = FormSchemaDefinition::PURPOSE_SIGNUP;
$nextVersion = (int) FormSchemaDefinition::query()
->where('competition_id', $competition->id)
->where('purpose', $purpose)
->max('version') + 1;
$schema = FormSchemaDefinition::query()->create([
'competition_id' => $competition->id,
'purpose' => $purpose,
'name' => '选手端报名表(与 /c/{slug}/apply 一致)',
'version' => $nextVersion,
'schema_json' => $this->schemaJson(),
'is_published' => true,
]);
$competition->update(['form_schema_id' => $schema->id]);
$this->command?->info("Form schema #{$schema->id} (v{$nextVersion}) created and bound to competition #{$competitionId}.");
$audiencePurpose = FormSchemaDefinition::PURPOSE_AUDIENCE;
$audienceVersion = (int) FormSchemaDefinition::query()
->where('competition_id', $competition->id)
->where('purpose', $audiencePurpose)
->max('version') + 1;
$audienceSchema = FormSchemaDefinition::query()->create([
'competition_id' => $competition->id,
'purpose' => $audiencePurpose,
'name' => '观众报名表(默认五项)',
'version' => $audienceVersion,
'schema_json' => $this->audienceSchemaJson(),
'is_published' => true,
]);
$competition->update(['audience_form_schema_id' => $audienceSchema->id]);
$this->command?->info("Audience form schema #{$audienceSchema->id} (v{$audienceVersion}) bound to competition #{$competitionId}.");
}
/**
* @return list<array<string, mixed>>
*/
private function schemaJson(): array
{
$degreeOptions = SignupOptionCatalog::schemaOptions(SignupOptionCatalog::degrees());
$countryOptions = SignupOptionCatalog::schemaOptions(SignupOptionCatalog::locationCountries());
$eventLocationOptions = SignupOptionCatalog::schemaOptions(SignupOptionCatalog::eventLocations());
$provinceOptions = array_map(
fn (string $p) => ['label' => $p, 'value' => $p],
$this->provinceOrder(),
);
return $this->withFieldI18n([
[
'key' => 'project_name',
'type' => 'text',
'label' => '项目名称',
'required' => true,
],
[
'key' => 'player_name',
'type' => 'text',
'label' => '申请人姓名',
'required' => true,
],
[
'key' => 'contact_email',
'type' => 'email',
'label' => '注册邮箱',
'required' => true,
],
[
'key' => 'contact_mobile',
'type' => 'tel',
'label' => '申请人电话',
'required' => true,
],
[
'key' => 'school',
'type' => 'text',
'label' => '毕业院校',
'required' => true,
],
[
'key' => 'degree',
'type' => 'select',
'label' => '最高学历',
'required' => true,
'list' => true,
'filter' => true,
'options' => $degreeOptions,
],
[
'key' => 'track',
'type' => 'select',
'label' => '细分赛道',
'required' => true,
'list' => true,
'filter' => true,
],
[
'key' => 'company_name',
'type' => 'text',
'label' => '企业名称',
'required' => true,
'prefill_from' => 'user.company',
],
[
'key' => 'location_country',
'type' => 'select',
'label' => '项目所在地',
'required' => true,
'list' => true,
'filter' => true,
'options' => $countryOptions,
],
[
'key' => 'location_province',
'type' => 'select',
'label' => '省份',
'required' => false,
'options' => $provinceOptions,
'help' => '选择「中国」时必填',
],
[
'key' => 'location_city',
'type' => 'text',
'label' => '城市',
'required' => false,
'help' => '选择「中国」时填写所在城市',
],
[
'key' => 'oversea_country',
'type' => 'text',
'label' => '所在国',
'required' => false,
'placeholder' => '如:新加坡、日本、美国',
'help' => '选择「海外」时必填',
],
[
'key' => 'event_location',
'type' => 'select',
'label' => '意向参赛地点',
'required' => true,
'list' => true,
'filter' => true,
'options' => $eventLocationOptions,
],
[
'key' => 'team_members',
'type' => 'text',
'label' => '团队成员',
'required' => true,
'placeholder' => '多人请用顿号分隔',
],
[
'key' => 'recommend',
'type' => 'text',
'label' => '推荐方',
'required' => false,
'placeholder' => '单位或推荐人名称',
],
[
'key' => 'intro',
'type' => 'textarea',
'label' => '项目简介',
'required' => true,
'placeholder' => '约200字左右',
],
[
'key' => 'commitment_accepted',
'type' => 'checkbox',
'label' => '参赛承诺书',
'required' => true,
'help' => '请点击按钮打开承诺书全文,阅读后在文末手写签名并点击「确认签署」。',
],
[
'key' => 'plan',
'type' => 'file',
'label' => '上传商业计划书',
'required' => true,
'help' => '包括企业概况与定位、核心产品/服务、市场规模和竞争情况、创新壁垒与差异化优势、核心团队介绍与优势、未来发展战略规划等,PDF格式,建议不超过20页。',
'file_extensions' => ['pdf'],
'file_max_count' => 1,
],
[
'key' => 'supporting',
'type' => 'file',
'label' => '其他佐证材料',
'required' => false,
'help' => '可上传多个文件:企业营业执照扫描件;知识产权相关证明材料(专利证书、商标注册证、软件著作权等),其他佐证材料(产品或服务介绍、获奖证书、投融资证明等)、创始人或主要负责人学历学位等资质证明。单文件 20M 以内,支持:PDF、PPT、PPTX、DOC、DOCX、WPS、RAR、ZIP',
],
]);
}
/**
* @return list<array<string, mixed>>
*/
private function audienceSchemaJson(): array
{
$purposeOptions = SignupOptionCatalog::schemaOptions(SignupOptionCatalog::audiencePurposes());
return $this->withFieldI18n([
[
'key' => 'name',
'type' => 'text',
'label' => '个人姓名',
'required' => true,
'list' => true,
'placeholder' => '请输入姓名',
],
[
'key' => 'phone',
'type' => 'tel',
'label' => '联系电话',
'required' => true,
'list' => true,
'placeholder' => '请输入11位手机号',
],
[
'key' => 'company',
'type' => 'text',
'label' => '所属单位',
'required' => true,
'list' => true,
'placeholder' => '请输入单位名称',
],
[
'key' => 'job',
'type' => 'text',
'label' => '个人职务',
'required' => false,
'list' => true,
'placeholder' => '请输入职务',
],
[
'key' => 'purpose',
'type' => 'select',
'label' => '观赛目的',
'required' => true,
'list' => true,
'filter' => true,
'placeholder' => '请选择观赛目的',
'options' => $purposeOptions,
],
]);
}
/**
* 与前端 src/data/chinaRegion.ts provinceOrder 一致。
*
* @return list<string>
*/
private function provinceOrder(): array
{
return [
'北京市', '天津市', '上海市', '重庆市',
'河北省', '山西省', '内蒙古自治区',
'辽宁省', '吉林省', '黑龙江省',
'江苏省', '浙江省', '安徽省', '福建省', '江西省', '山东省',
'河南省', '湖北省', '湖南省', '广东省', '广西壮族自治区', '海南省',
'四川省', '贵州省', '云南省', '西藏自治区',
'陕西省', '甘肃省', '青海省', '宁夏回族自治区', '新疆维吾尔自治区',
'香港特别行政区', '澳门特别行政区', '台湾省',
];
}
/**
* @param list<array<string, mixed>> $rows
* @return list<array<string, mixed>>
*/
private function withFieldI18n(array $rows): array
{
return SignupFieldI18n::enrichSchemaRows($rows);
}
}