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.
287 lines
8.2 KiB
287 lines
8.2 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Niucloud-admin 企业快速开发的多应用管理平台
|
|
// +----------------------------------------------------------------------
|
|
// | 官方网址:https://www.niucloud.com
|
|
// +----------------------------------------------------------------------
|
|
// | niucloud团队 版权所有 开源版本可自由商用
|
|
// +----------------------------------------------------------------------
|
|
// | Author: Niucloud Team
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\service\admin\document;
|
|
|
|
use app\model\document\DocumentGenerateLog;
|
|
use app\model\contract\Contract;
|
|
use app\job\contract\DocumentGenerateJob;
|
|
use core\base\BaseAdminService;
|
|
use think\facade\Queue;
|
|
use think\facade\Db;
|
|
|
|
/**
|
|
* 文档生成服务类
|
|
* Class DocumentGenerateService
|
|
* @package app\service\admin\document
|
|
*/
|
|
class DocumentGenerateService extends BaseAdminService
|
|
{
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
$this->model = new DocumentGenerateLog();
|
|
}
|
|
|
|
/**
|
|
* 获取生成记录分页列表
|
|
* @param array $where
|
|
* @return array
|
|
*/
|
|
public function getPage(array $where = []): array
|
|
{
|
|
$field = 'id, user_type, template_id, user_id, generated_file, status, error_msg, created_at, completed_at';
|
|
$order = 'created_at desc';
|
|
|
|
$search_model = $this->model
|
|
->withSearch(['template_id', 'user_id', 'user_type', 'status'], $where)
|
|
->field($field)
|
|
->order($order);
|
|
|
|
$list = $this->pageQuery($search_model, $where);
|
|
|
|
// 关联合同信息
|
|
if (!empty($list['data'])) {
|
|
$template_ids = array_unique(array_column($list['data'], 'template_id'));
|
|
$contracts = (new Contract())->whereIn('id', $template_ids)->column('name', 'id');
|
|
|
|
foreach ($list['data'] as &$item) {
|
|
$item['template_name'] = $contracts[$item['template_id']] ?? '';
|
|
$item['user_type_text'] = $item['user_type'] == 1 ? '内部员工' : '外部会员';
|
|
$item['status_text'] = $this->getStatusText($item['status']);
|
|
}
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* 获取生成记录信息
|
|
* @param int $id
|
|
* @return array
|
|
*/
|
|
public function getInfo(int $id): array
|
|
{
|
|
$field = 'id, user_type, template_id, user_id, fill_data, generated_file, status, error_msg, created_at, completed_at';
|
|
|
|
$info = $this->model->field($field)->where([['id', '=', $id]])->findOrEmpty()->toArray();
|
|
if (empty($info)) {
|
|
throw new \Exception('DATA_NOT_EXIST');
|
|
}
|
|
|
|
// 获取合同信息
|
|
if (!empty($info['template_id'])) {
|
|
$contract = (new Contract())->where('id', $info['template_id'])->field('id, name')->findOrEmpty();
|
|
$info['template_name'] = $contract['name'] ?? '';
|
|
}
|
|
|
|
// 解析填充数据
|
|
$info['fill_data'] = json_decode($info['fill_data'], true) ?: [];
|
|
$info['user_type_text'] = $info['user_type'] == 1 ? '内部员工' : '外部会员';
|
|
$info['status_text'] = $this->getStatusText($info['status']);
|
|
|
|
return $info;
|
|
}
|
|
|
|
/**
|
|
* 生成文档
|
|
* @param array $data
|
|
* @return array
|
|
*/
|
|
public function generate(array $data): array
|
|
{
|
|
// 验证模板是否存在
|
|
$contract = (new Contract())->find($data['template_id']);
|
|
if (!$contract) {
|
|
throw new \Exception('合同模板不存在');
|
|
}
|
|
|
|
// 创建生成记录
|
|
$logData = [
|
|
'user_type' => $data['user_type'],
|
|
'template_id' => $data['template_id'],
|
|
'user_id' => $data['user_id'],
|
|
'fill_data' => json_encode($data['fill_data']),
|
|
'status' => 'pending',
|
|
'created_at' => time()
|
|
];
|
|
|
|
$log = $this->model->create($logData);
|
|
if (!$log) {
|
|
throw new \Exception('创建生成记录失败');
|
|
}
|
|
|
|
// 推送到队列
|
|
Queue::push(DocumentGenerateJob::class, ['log_id' => $log->id]);
|
|
|
|
return [
|
|
'log_id' => $log->id,
|
|
'status' => 'pending'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 重新生成文档
|
|
* @param int $id
|
|
* @return array
|
|
*/
|
|
public function regenerate(int $id): array
|
|
{
|
|
$log = $this->model->find($id);
|
|
if (!$log) {
|
|
throw new \Exception('生成记录不存在');
|
|
}
|
|
|
|
// 重置状态
|
|
$log->save([
|
|
'status' => 'pending',
|
|
'error_msg' => null,
|
|
'completed_at' => 0
|
|
]);
|
|
|
|
// 重新推送到队列
|
|
Queue::push(DocumentGenerateJob::class, ['log_id' => $id]);
|
|
|
|
return [
|
|
'log_id' => $id,
|
|
'status' => 'pending'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 下载生成的文档
|
|
* @param int $id
|
|
* @return array
|
|
*/
|
|
public function download(int $id): array
|
|
{
|
|
$log = $this->model->find($id);
|
|
if (!$log) {
|
|
return ['success' => false, 'error' => '生成记录不存在'];
|
|
}
|
|
|
|
if ($log['status'] !== 'completed') {
|
|
return ['success' => false, 'error' => '文档尚未生成完成'];
|
|
}
|
|
|
|
if (empty($log['generated_file']) || !file_exists($log['generated_file'])) {
|
|
return ['success' => false, 'error' => '文件不存在'];
|
|
}
|
|
|
|
return [
|
|
'success' => true,
|
|
'file_path' => $log['generated_file'],
|
|
'file_name' => basename($log['generated_file'])
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 删除生成记录
|
|
* @param int $id
|
|
* @return bool
|
|
*/
|
|
public function del(int $id): bool
|
|
{
|
|
$info = $this->model->findOrEmpty($id);
|
|
if ($info->isEmpty()) {
|
|
throw new \Exception('DATA_NOT_EXIST');
|
|
}
|
|
|
|
// 删除生成的文件
|
|
if (!empty($info['generated_file']) && file_exists($info['generated_file'])) {
|
|
unlink($info['generated_file']);
|
|
}
|
|
|
|
$res = $info->delete();
|
|
if (!$res) {
|
|
throw new \Exception('DELETE_FAIL');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 批量删除生成记录
|
|
* @param array $ids
|
|
* @return bool
|
|
*/
|
|
public function batchDel(array $ids): bool
|
|
{
|
|
if (empty($ids)) {
|
|
throw new \Exception('请选择要删除的记录');
|
|
}
|
|
|
|
Db::startTrans();
|
|
try {
|
|
foreach ($ids as $id) {
|
|
$this->del($id);
|
|
}
|
|
Db::commit();
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
Db::rollback();
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取生成统计信息
|
|
* @param int $templateId
|
|
* @return array
|
|
*/
|
|
public function getStats(int $templateId = 0): array
|
|
{
|
|
$where = [];
|
|
if ($templateId) {
|
|
$where[] = ['template_id', '=', $templateId];
|
|
}
|
|
|
|
$stats = [
|
|
'total' => $this->model->where($where)->count(),
|
|
'pending' => $this->model->where($where)->where('status', 'pending')->count(),
|
|
'processing' => $this->model->where($where)->where('status', 'processing')->count(),
|
|
'completed' => $this->model->where($where)->where('status', 'completed')->count(),
|
|
'failed' => $this->model->where($where)->where('status', 'failed')->count(),
|
|
];
|
|
|
|
return $stats;
|
|
}
|
|
|
|
/**
|
|
* 预览文档数据
|
|
* @param int $templateId
|
|
* @param array $fillData
|
|
* @return array
|
|
*/
|
|
public function preview(int $templateId, array $fillData): array
|
|
{
|
|
// 获取数据源配置
|
|
$dataSourceService = new DocumentDataSourceService();
|
|
return $dataSourceService->preview($templateId, $fillData);
|
|
}
|
|
|
|
/**
|
|
* 获取状态文本
|
|
* @param string $status
|
|
* @return string
|
|
*/
|
|
private function getStatusText(string $status): string
|
|
{
|
|
$statusMap = [
|
|
'pending' => '等待处理',
|
|
'processing' => '处理中',
|
|
'completed' => '已完成',
|
|
'failed' => '失败'
|
|
];
|
|
|
|
return $statusMap[$status] ?? '未知状态';
|
|
}
|
|
}
|
|
|