['name' => '产品代发协议', 'code' => 'TPL-SUPPLIER-DROPSHIPPING-V1', 'version' => '1', 'file' => '产品代发协议-2022年确定版.docx', 'attachments' => 2], 'consignment' => ['name' => '产品代销协议', 'code' => 'TPL-SUPPLIER-CONSIGNMENT-V1', 'version' => '1', 'file' => '产品代销协议-2022确定版.docx', 'attachments' => 4], 'production' => ['name' => '生产合作协议', 'code' => 'TPL-SUPPLIER-PRODUCTION-V1', 'version' => '1', 'file' => '生产合作协议-2022确定版.docx', 'attachments' => 5], ]; public const FIELDS = [ 'number' => ['label' => '合同编号', 'required' => true], 'location' => ['label' => '合同签订地', 'required' => true, 'default' => '常州市武进区'], 'party_a_address' => ['label' => '甲方地址'], 'party_a_legal' => ['label' => '甲方法定代表人'], 'party_a_contact' => ['label' => '甲方联系人'], 'party_a_email' => ['label' => '甲方邮箱', 'type' => 'email'], 'party_a_fax' => ['label' => '甲方传真'], 'party_b_address' => ['label' => '乙方地址'], 'party_b_legal' => ['label' => '乙方法定代表人'], 'party_b_contact' => ['label' => '乙方联系人'], 'party_b_email' => ['label' => '乙方邮箱', 'type' => 'email'], 'party_b_fax' => ['label' => '乙方传真'], 'account_name' => ['label' => '合同账户名称(原文为甲方付款账户)'], 'account_number' => ['label' => '合同银行账号'], 'bank_name' => ['label' => '合同开户行'], 'brands' => ['label' => '生产协议使用的品牌', 'default' => '亿家达、欧意朗', 'templates' => ['production']], 'product_model' => ['label' => '采购订单产品型号/SKU', 'templates' => ['consignment', 'production']], 'supply_price' => ['label' => '采购订单供货价格/明细说明', 'templates' => ['consignment', 'production']], 'purchase_contact' => ['label' => '采购对接人(订单附件)', 'templates' => ['consignment', 'production']], 'purchase_qq' => ['label' => '采购对接人 QQ', 'templates' => ['consignment', 'production']], 'purchase_wechat' => ['label' => '采购对接人微信', 'templates' => ['consignment', 'production']], 'purchase_phone' => ['label' => '采购对接人电话', 'templates' => ['consignment', 'production']], ]; public function metadata(string $key): array { return self::TEMPLATES[$key] ?? throw ValidationException::withMessages([ 'supplier_contract_template' => '请选择有效的供应商合作合同模板。', ]); } public function blocks(string $key): array { $this->metadata($key); return json_decode(file_get_contents(resource_path("contracts/supplier/{$key}-v1.json")), true, 512, JSON_THROW_ON_ERROR)['blocks']; } public function values(array $payload): array { $values = []; foreach (self::FIELDS as $key => $field) { $values[$key] = trim((string) ($payload['supplier_contract_fields'][$key] ?? '')); } $values += [ 'party_a' => $payload['cooperation_party_a_name'] ?? $payload['company_full_name'] ?? '', 'party_b' => $payload['cooperation_party_b_name'] ?? '', 'party_a_phone' => $payload['cooperation_party_a_phone'] ?? '', 'party_b_phone' => $payload['cooperation_party_b_phone'] ?? '', 'start_date' => $this->date($payload['cooperation_start_date'] ?? ''), 'end_date' => $this->date($payload['cooperation_end_date'] ?? ''), 'signature_date' => $this->date($payload['signature_date'] ?? ''), 'party_a_signer' => $payload['secondary_operator_name'] ?? '', 'party_b_signer' => $payload['supplier_contract_signer_name'] ?? '', ]; return $values; } public function text(string $text, array $values, bool $preview = false): string { $parts = preg_split('/(\[\[[a-z_]+\]\])/', $text, -1, PREG_SPLIT_DELIM_CAPTURE); return implode('', array_map(static function (string $part) use ($values, $preview): string { if (preg_match('/^\[\[([a-z_]+)\]\]$/', $part, $match)) { $value = trim((string) ($values[$match[1]] ?? '')); return $preview ? '' . e($value ?: '待填写') . '' : e($value ?: '________'); } return e($part); }, $parts)); } public function isSupplierContract(CourierAgreementSignature $signature): bool { return $signature->document_type === 'cooperation-contract' && ($signature->payload['partner_type'] ?? 'courier') === 'supplier'; } private function date(string $value): string { return $value === '' ? '' : Carbon::parse($value)->format('Y年n月j日'); } }