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}."); } /** * @return list> */ private function schemaJson(): array { $tracks = config('contest.tracks', []); $degrees = config('contest.degrees', []); $countries = config('contest.location_countries', ['中国', '海外']); $trackOptions = array_map(fn (string $t) => ['label' => $t, 'value' => $t], $tracks); $degreeOptions = array_map(fn (string $d) => ['label' => $d, 'value' => $d], $degrees); $countryOptions = array_map(fn (string $c) => ['label' => $c, 'value' => $c], $countries); $provinceOptions = array_map( fn (string $p) => ['label' => $p, 'value' => $p], $this->provinceOrder(), ); return [ [ 'key' => 'player_name', 'type' => 'text', 'label' => '参赛人姓名', 'required' => true, ], [ 'key' => 'school', 'type' => 'text', 'label' => '毕业院校', 'required' => true, ], [ 'key' => 'degree', 'type' => 'select', 'label' => '最高学历', 'required' => true, 'options' => $degreeOptions, ], [ 'key' => 'contact_email', 'type' => 'email', 'label' => '注册邮箱', 'required' => true, ], [ 'key' => 'contact_mobile', 'type' => 'tel', 'label' => '联系电话', 'required' => true, 'placeholder' => '11 位中国大陆手机号', ], [ 'key' => 'entry_group', 'type' => 'select', 'label' => '参赛组别', 'required' => true, 'options' => [ ['label' => '创新组', 'value' => '创新组'], ['label' => '创业组', 'value' => '创业组'], ], 'help' => '选择「创业组」时须填写企业名称', ], [ 'key' => 'company_name', 'type' => 'text', 'label' => '企业名称', 'required' => false, 'placeholder' => '创业组为必填;创新组选填', 'required_when' => [ 'field' => 'entry_group', 'values' => [(string) config('contest.entry_group_company_required_value', '创业组')], ], ], [ 'key' => 'project_name', 'type' => 'text', 'label' => '项目名称', 'required' => true, ], [ 'key' => 'track', 'type' => 'select', 'label' => '主题赛道', 'required' => true, 'options' => $trackOptions, 'help' => '请从本场赛事公布的赛道中选择', ], [ 'key' => 'location_country', 'type' => 'select', 'label' => '项目所在地(国家或地区)', 'required' => 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' => 'intro', 'type' => 'textarea', 'label' => '项目简介', 'required' => false, 'placeholder' => '约200字左右', ], [ 'key' => 'commitment_accepted', 'type' => 'checkbox', 'label' => '本人已阅读并同意《参赛承诺书》的全部内容', 'required' => true, 'help' => '提交报名即表示承诺所填信息真实有效,并遵守赛事规则。', ], [ 'key' => 'plan', 'type' => 'file', 'label' => '上传商业计划书', 'required' => true, 'help' => '可传多份,单文件 20M 内;支持 PDF、PPT、Office 文档及压缩包', ], [ 'key' => 'supporting', 'type' => 'file', 'label' => '其他佐证材料', 'required' => false, 'help' => '可选;格式要求同上', ], ]; } /** * 与前端 src/data/chinaRegion.ts provinceOrder 一致。 * * @return list */ private function provinceOrder(): array { return [ '北京市', '天津市', '上海市', '重庆市', '河北省', '山西省', '内蒙古自治区', '辽宁省', '吉林省', '黑龙江省', '江苏省', '浙江省', '安徽省', '福建省', '江西省', '山东省', '河南省', '湖北省', '湖南省', '广东省', '广西壮族自治区', '海南省', '四川省', '贵州省', '云南省', '西藏自治区', '陕西省', '甘肃省', '青海省', '宁夏回族自治区', '新疆维吾尔自治区', '香港特别行政区', '澳门特别行政区', '台湾省', ]; } }