|
|
@ -64,25 +64,25 @@ class ContractService extends BaseService |
|
|
foreach ($list as &$contract) { |
|
|
foreach ($list as &$contract) { |
|
|
// 状态文本映射 |
|
|
// 状态文本映射 |
|
|
$contract['status_text'] = $this->getStatusText($contract['status']); |
|
|
$contract['status_text'] = $this->getStatusText($contract['status']); |
|
|
|
|
|
|
|
|
// 获取合同相关的课程信息 |
|
|
// 获取合同相关的课程信息 |
|
|
$courseInfo = $this->getContractCourseInfo($contract['contract_id'], $studentId); |
|
|
$courseInfo = $this->getContractCourseInfo($contract['contract_id'], $studentId); |
|
|
$contract = array_merge($contract, $courseInfo); |
|
|
$contract = array_merge($contract, $courseInfo); |
|
|
|
|
|
|
|
|
// 格式化日期 |
|
|
// 格式化日期 |
|
|
$contract['sign_date'] = $contract['sign_time'] ? date('Y-m-d', strtotime($contract['sign_time'])) : null; |
|
|
$contract['sign_date'] = $contract['sign_time'] ? date('Y-m-d', strtotime($contract['sign_time'])) : null; |
|
|
$contract['create_date'] = date('Y-m-d', strtotime($contract['created_at'])); |
|
|
$contract['create_date'] = date('Y-m-d', strtotime($contract['created_at'])); |
|
|
|
|
|
|
|
|
// 文件路径处理 |
|
|
// 文件路径处理 |
|
|
$contract['contract_file_url'] = $contract['contract_template'] ? get_image_url($contract['contract_template']) : ''; |
|
|
$contract['contract_file_url'] = $contract['contract_template'] ? get_image_url($contract['contract_template']) : ''; |
|
|
|
|
|
|
|
|
// 计算课时使用进度 |
|
|
// 计算课时使用进度 |
|
|
if ($contract['total_hours'] > 0) { |
|
|
if ($contract['total_hours'] > 0) { |
|
|
$contract['progress_percent'] = round(($contract['used_hours'] / $contract['total_hours']) * 100, 1); |
|
|
$contract['progress_percent'] = round(($contract['used_hours'] / $contract['total_hours']) * 100, 1); |
|
|
} else { |
|
|
} else { |
|
|
$contract['progress_percent'] = 0; |
|
|
$contract['progress_percent'] = 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 判断是否可以续约(生效状态且课时即将用完) |
|
|
// 判断是否可以续约(生效状态且课时即将用完) |
|
|
$contract['can_renew'] = $contract['status'] == 3 && $contract['remaining_hours'] <= 5; |
|
|
$contract['can_renew'] = $contract['status'] == 3 && $contract['remaining_hours'] <= 5; |
|
|
} |
|
|
} |
|
|
@ -158,7 +158,7 @@ class ContractService extends BaseService |
|
|
|
|
|
|
|
|
// 合同条款(如果有内容的话) |
|
|
// 合同条款(如果有内容的话) |
|
|
$contractSign['terms'] = $contractSign['contract_content'] ?: $contractSign['remarks']; |
|
|
$contractSign['terms'] = $contractSign['contract_content'] ?: $contractSign['remarks']; |
|
|
|
|
|
|
|
|
// 对于已签署成功的合同(status=3),进行占位符替换 |
|
|
// 对于已签署成功的合同(status=3),进行占位符替换 |
|
|
if ($contractSign['status'] == 3 && !empty($contractSign['terms'])) { |
|
|
if ($contractSign['status'] == 3 && !empty($contractSign['terms'])) { |
|
|
$contractSign['terms'] = $this->replacePlaceholdersInTerms( |
|
|
$contractSign['terms'] = $this->replacePlaceholdersInTerms( |
|
|
@ -207,7 +207,9 @@ class ContractService extends BaseService |
|
|
if (!$contract) { |
|
|
if (!$contract) { |
|
|
throw new CommonException('合同模板不存在'); |
|
|
throw new CommonException('合同模板不存在'); |
|
|
} |
|
|
} |
|
|
|
|
|
if(!empty($contract['contract_content'])){ |
|
|
|
|
|
$contract['contract_content'] = replace_placeholders_with_underlines($contract['contract_content']); |
|
|
|
|
|
} |
|
|
// 获取所有字段配置 |
|
|
// 获取所有字段配置 |
|
|
$formFields = Db::table('school_document_data_source_config') |
|
|
$formFields = Db::table('school_document_data_source_config') |
|
|
->where('contract_id', $contractId) |
|
|
->where('contract_id', $contractId) |
|
|
@ -287,10 +289,10 @@ class ContractService extends BaseService |
|
|
|
|
|
|
|
|
// 从form_data中提取签名图片路径 |
|
|
// 从form_data中提取签名图片路径 |
|
|
$extractedSignatures = $this->extractSignatureImages($formData); |
|
|
$extractedSignatures = $this->extractSignatureImages($formData); |
|
|
|
|
|
|
|
|
// 上传并处理签名图片 |
|
|
// 上传并处理签名图片 |
|
|
$processedSignatures = $this->uploadSignatureImages($extractedSignatures); |
|
|
$processedSignatures = $this->uploadSignatureImages($extractedSignatures); |
|
|
|
|
|
|
|
|
// 更新form_data中的签名路径为服务器路径 |
|
|
// 更新form_data中的签名路径为服务器路径 |
|
|
$formData = $this->updateFormDataWithUploadedPaths($formData, $processedSignatures); |
|
|
$formData = $this->updateFormDataWithUploadedPaths($formData, $processedSignatures); |
|
|
|
|
|
|
|
|
@ -332,7 +334,7 @@ class ContractService extends BaseService |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Db::commit(); |
|
|
Db::commit(); |
|
|
|
|
|
|
|
|
return [ |
|
|
return [ |
|
|
'sign_id' => $contractSign['id'], |
|
|
'sign_id' => $contractSign['id'], |
|
|
'generated_file' => $generatedFile, |
|
|
'generated_file' => $generatedFile, |
|
|
@ -561,7 +563,7 @@ class ContractService extends BaseService |
|
|
$contract = Db::table('school_contract') |
|
|
$contract = Db::table('school_contract') |
|
|
->where('id', $contractId) |
|
|
->where('id', $contractId) |
|
|
->find(); |
|
|
->find(); |
|
|
|
|
|
|
|
|
if (!$contract || !$contract['contract_template']) { |
|
|
if (!$contract || !$contract['contract_template']) { |
|
|
throw new CommonException('合同模板不存在'); |
|
|
throw new CommonException('合同模板不存在'); |
|
|
} |
|
|
} |
|
|
@ -598,11 +600,11 @@ class ContractService extends BaseService |
|
|
if ($signatureImage && $this->hasSignaturePlaceholder($templateProcessor)) { |
|
|
if ($signatureImage && $this->hasSignaturePlaceholder($templateProcessor)) { |
|
|
// 处理签名图片 - 支持base64和URL |
|
|
// 处理签名图片 - 支持base64和URL |
|
|
$signImagePath = $this->processSignatureImage($signatureImage); |
|
|
$signImagePath = $this->processSignatureImage($signatureImage); |
|
|
|
|
|
|
|
|
// 使用ContractSign服务插入签名 |
|
|
// 使用ContractSign服务插入签名 |
|
|
$contractSignService = new ContractSign(); |
|
|
$contractSignService = new ContractSign(); |
|
|
$contractSignService->setSign($templatePath, $outputFullPath, $signImagePath, '学员签名'); |
|
|
$contractSignService->setSign($templatePath, $outputFullPath, $signImagePath, '学员签名'); |
|
|
|
|
|
|
|
|
// 清理临时文件 |
|
|
// 清理临时文件 |
|
|
if (file_exists($signImagePath)) { |
|
|
if (file_exists($signImagePath)) { |
|
|
unlink($signImagePath); |
|
|
unlink($signImagePath); |
|
|
@ -792,14 +794,14 @@ class ContractService extends BaseService |
|
|
private function extractSignatureImages($formData) |
|
|
private function extractSignatureImages($formData) |
|
|
{ |
|
|
{ |
|
|
$signatures = []; |
|
|
$signatures = []; |
|
|
|
|
|
|
|
|
// 常见的签名字段模式 |
|
|
// 常见的签名字段模式 |
|
|
$signaturePatterns = ['签名', '乙方', '甲方', '学员签名']; |
|
|
$signaturePatterns = ['签名', '乙方', '甲方', '学员签名']; |
|
|
|
|
|
|
|
|
foreach ($formData as $key => $value) { |
|
|
foreach ($formData as $key => $value) { |
|
|
// 检查是否为图片URL(临时路径或正式路径) |
|
|
// 检查是否为图片URL(临时路径或正式路径) |
|
|
if (is_string($value) && ( |
|
|
if (is_string($value) && ( |
|
|
strpos($value, 'http://tmp/') === 0 || |
|
|
strpos($value, 'http://tmp/') === 0 || |
|
|
strpos($value, 'https://tmp/') === 0 || |
|
|
strpos($value, 'https://tmp/') === 0 || |
|
|
preg_match('/\.(png|jpg|jpeg|gif)$/i', $value) |
|
|
preg_match('/\.(png|jpg|jpeg|gif)$/i', $value) |
|
|
)) { |
|
|
)) { |
|
|
@ -812,7 +814,7 @@ class ContractService extends BaseService |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return $signatures; |
|
|
return $signatures; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -824,7 +826,7 @@ class ContractService extends BaseService |
|
|
private function uploadSignatureImages($signatures) |
|
|
private function uploadSignatureImages($signatures) |
|
|
{ |
|
|
{ |
|
|
$processed = []; |
|
|
$processed = []; |
|
|
|
|
|
|
|
|
foreach ($signatures as $key => $imagePath) { |
|
|
foreach ($signatures as $key => $imagePath) { |
|
|
try { |
|
|
try { |
|
|
// 如果是临时路径,需要下载并保存 |
|
|
// 如果是临时路径,需要下载并保存 |
|
|
@ -834,18 +836,18 @@ class ContractService extends BaseService |
|
|
$filename = 'signature_' . date('YmdHis') . '_' . mt_rand(1000, 9999) . '.png'; |
|
|
$filename = 'signature_' . date('YmdHis') . '_' . mt_rand(1000, 9999) . '.png'; |
|
|
$relativePath = 'signatures/' . date('Y/m/') . $filename; |
|
|
$relativePath = 'signatures/' . date('Y/m/') . $filename; |
|
|
$fullPath = public_path() . '/upload/' . $relativePath; |
|
|
$fullPath = public_path() . '/upload/' . $relativePath; |
|
|
|
|
|
|
|
|
// 确保目录存在 |
|
|
// 确保目录存在 |
|
|
$dir = dirname($fullPath); |
|
|
$dir = dirname($fullPath); |
|
|
if (!is_dir($dir)) { |
|
|
if (!is_dir($dir)) { |
|
|
mkdir($dir, 0755, true); |
|
|
mkdir($dir, 0755, true); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 尝试下载临时文件(实际环境中需要通过微信API) |
|
|
// 尝试下载临时文件(实际环境中需要通过微信API) |
|
|
// 这里模拟处理,生成一个占位文件 |
|
|
// 这里模拟处理,生成一个占位文件 |
|
|
$placeholderContent = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); |
|
|
$placeholderContent = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); |
|
|
file_put_contents($fullPath, $placeholderContent); |
|
|
file_put_contents($fullPath, $placeholderContent); |
|
|
|
|
|
|
|
|
$processed[$key] = $relativePath; |
|
|
$processed[$key] = $relativePath; |
|
|
} else { |
|
|
} else { |
|
|
// 已经是正式路径,直接使用 |
|
|
// 已经是正式路径,直接使用 |
|
|
@ -857,7 +859,7 @@ class ContractService extends BaseService |
|
|
$processed[$key] = $imagePath; // 保持原路径 |
|
|
$processed[$key] = $imagePath; // 保持原路径 |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return $processed; |
|
|
return $processed; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -874,14 +876,14 @@ class ContractService extends BaseService |
|
|
$formData[$key] = $newPath; |
|
|
$formData[$key] = $newPath; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return $formData; |
|
|
return $formData; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 在合同条款中替换占位符 |
|
|
* 在合同条款中替换占位符 |
|
|
* 使用 school_document_data_source_config 表中的 default_value 数据进行替换 |
|
|
* 使用 school_document_data_source_config 表中的 default_value 数据进行替换 |
|
|
* |
|
|
* |
|
|
* @param string $terms 合同条款内容 |
|
|
* @param string $terms 合同条款内容 |
|
|
* @param int $contractId 合同模板ID |
|
|
* @param int $contractId 合同模板ID |
|
|
* @param int $contractSignId 合同签署记录ID |
|
|
* @param int $contractSignId 合同签署记录ID |
|
|
@ -1134,4 +1136,4 @@ class ContractService extends BaseService |
|
|
return (string)$value; |
|
|
return (string)$value; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|