智慧教务系统
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.
 
 
 
 
 
 

244 lines
7.7 KiB

<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\job\contract;
use core\base\BaseJob;
use app\model\document\DocumentGenerateLog;
use app\model\contract\Contract;
use app\model\document\DocumentDataSourceConfig;
use app\service\admin\document\DocumentTemplateService;
use think\facade\Log;
/**
* 文档生成队列任务
* Class DocumentGenerateJob
* @package app\job\contract
*/
class DocumentGenerateJob extends BaseJob
{
/**
* 执行文档生成任务
* @param array $data 任务数据
* @return bool
*/
public function doJob(array $data): bool
{
$logId = $data['log_id'] ?? 0;
if (!$logId) {
Log::error('DocumentGenerateJob: log_id is required');
return false;
}
try {
// 获取生成记录
$log = (new DocumentGenerateLog())->find($logId);
if (!$log) {
Log::error('DocumentGenerateJob: Generate log not found', ['log_id' => $logId]);
return false;
}
// 更新状态为处理中
$log->save(['status' => 'processing']);
// 执行文档生成
$result = $this->generateDocument($log);
if ($result['success']) {
// 生成成功
$log->save([
'status' => 'completed',
'generated_file' => $result['file_path'],
'completed_at' => time(),
'error_msg' => null
]);
Log::info('DocumentGenerateJob: Document generated successfully', [
'log_id' => $logId,
'file_path' => $result['file_path']
]);
} else {
// 生成失败
$log->save([
'status' => 'failed',
'error_msg' => $result['error'],
'completed_at' => time()
]);
Log::error('DocumentGenerateJob: Document generation failed', [
'log_id' => $logId,
'error' => $result['error']
]);
}
return $result['success'];
} catch (\Exception $e) {
// 异常处理
if (isset($log)) {
$log->save([
'status' => 'failed',
'error_msg' => $e->getMessage(),
'completed_at' => time()
]);
}
Log::error('DocumentGenerateJob: Exception occurred', [
'log_id' => $logId,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return false;
}
}
/**
* 生成文档
* @param DocumentGenerateLog $log 生成记录
* @return array
*/
private function generateDocument(DocumentGenerateLog $log): array
{
try {
// 获取合同模板信息
$contract = (new Contract())->find($log['template_id']);
if (!$contract) {
return ['success' => false, 'error' => '合同模板不存在'];
}
if (empty($contract['file_path'])) {
return ['success' => false, 'error' => '合同模板文件不存在'];
}
// 解析填充数据
$fillData = json_decode($log['fill_data'], true);
if (!$fillData) {
return ['success' => false, 'error' => '填充数据格式错误'];
}
// 获取数据源配置
$dataSourceConfigs = (new DocumentDataSourceConfig())
->where('contract_id', $log['template_id'])
->select()
->toArray();
// 构建占位符替换数据
$replacements = $this->buildReplacements($dataSourceConfigs, $fillData);
// 使用DocumentTemplateService生成文档
$service = new DocumentTemplateService();
$result = $service->generateDocument([
'template_path' => $contract['file_path'],
'replacements' => $replacements,
'output_name' => $this->generateFileName($contract, $log)
]);
if ($result['success']) {
return [
'success' => true,
'file_path' => $result['file_path']
];
} else {
return [
'success' => false,
'error' => $result['error'] ?? '文档生成失败'
];
}
} catch (\Exception $e) {
return [
'success' => false,
'error' => '文档生成异常:' . $e->getMessage()
];
}
}
/**
* 构建占位符替换数据
* @param array $dataSourceConfigs 数据源配置
* @param array $fillData 填充数据
* @return array
*/
private function buildReplacements(array $dataSourceConfigs, array $fillData): array
{
$replacements = [];
foreach ($dataSourceConfigs as $config) {
$placeholder = $config['field_alias'] ?? $config['placeholder'] ?? '';
$fieldName = $config['field_name'] ?? '';
if (empty($placeholder)) {
continue;
}
// 从填充数据中获取值
$value = $fillData[$fieldName] ?? $config['default_value'] ?? '';
// 格式化值
$value = $this->formatValue($value, $config['field_type'] ?? 'string');
// 添加到替换数组
$replacements['{{' . $placeholder . '}}'] = $value;
}
return $replacements;
}
/**
* 格式化值
* @param mixed $value 原始值
* @param string $type 字段类型
* @return string
*/
private function formatValue($value, string $type): string
{
switch ($type) {
case 'datetime':
if (is_numeric($value)) {
return date('Y-m-d H:i:s', $value);
} elseif (strtotime($value)) {
return date('Y-m-d H:i:s', strtotime($value));
}
break;
case 'date':
if (is_numeric($value)) {
return date('Y-m-d', $value);
} elseif (strtotime($value)) {
return date('Y-m-d', strtotime($value));
}
break;
case 'decimal':
return number_format((float)$value, 2);
case 'integer':
return (string)(int)$value;
default:
return (string)$value;
}
return (string)$value;
}
/**
* 生成文件名
* @param Contract $contract 合同模板
* @param DocumentGenerateLog $log 生成记录
* @return string
*/
private function generateFileName(Contract $contract, DocumentGenerateLog $log): string
{
$timestamp = date('YmdHis');
$contractName = preg_replace('/[^\w\-_\.]/', '_', $contract['name']);
$userId = $log['user_id'];
return "{$contractName}_{$userId}_{$timestamp}.docx";
}
}