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.
444 lines
15 KiB
444 lines
15 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Niucloud-admin 企业快速开发的多应用管理平台
|
|
// +----------------------------------------------------------------------
|
|
// | 官方网址:https://www.niucloud.com
|
|
// +----------------------------------------------------------------------
|
|
// | niucloud团队 版权所有 开源版本可自由商用
|
|
// +----------------------------------------------------------------------
|
|
// | Author: Niucloud Team
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\service\admin\contract_sign;
|
|
|
|
use app\model\contract_sign\ContractSign;
|
|
use app\model\contract\Contract;
|
|
use app\model\personnel\Personnel;
|
|
|
|
use core\base\BaseAdminService;
|
|
|
|
|
|
/**
|
|
* 合同关系服务层
|
|
* Class ContractSignService
|
|
* @package app\service\admin\contract_sign
|
|
*/
|
|
class ContractSignService extends BaseAdminService
|
|
{
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
$this->model = new ContractSign();
|
|
}
|
|
|
|
/**
|
|
* 获取合同关系列表
|
|
* @param array $where
|
|
* @return array
|
|
*/
|
|
public function getPage(array $where = [])
|
|
{
|
|
$field = 'id,contract_id,personnel_id,sign_file,status,created_at,sign_time,updated_at,deleted_at';
|
|
$order = 'id desc';
|
|
|
|
$search_model = $this->model->withSearch(["status","created_at","sign_time","contract_id","personnel_id"], $where)
|
|
->with(['contract','personnel'])
|
|
->field($field)
|
|
->order($order);
|
|
|
|
$result = $this->pageQuery($search_model);
|
|
|
|
// 处理合同内容占位符
|
|
if (isset($result['data']) && is_array($result['data'])) {
|
|
foreach ($result['data'] as &$item) {
|
|
// 检查直接的 contract_content 字段
|
|
if (isset($item['contract_content']) && !empty($item['contract_content'])) {
|
|
$item['contract_content'] = replace_placeholders_with_underlines($item['contract_content']);
|
|
}
|
|
// 检查关联对象中的 contract_content 字段
|
|
elseif (isset($item['contract']['contract_content']) && !empty($item['contract']['contract_content'])) {
|
|
$item['contract']['contract_content'] = replace_placeholders_with_underlines($item['contract']['contract_content']);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* 获取合同关系信息(包含完整字段配置和填充数据)
|
|
* @param int $id
|
|
* @return array
|
|
*/
|
|
public function getInfo(int $id)
|
|
{
|
|
$field = 'id,contract_id,personnel_id,sign_file,status,created_at,sign_time,signature_image,source_type,fill_data,type,student_id,updated_at,deleted_at';
|
|
|
|
// 获取基础合同签署信息
|
|
$info = $this->model->field($field)->where([['id', "=", $id]])->with(['contract','personnel'])->findOrEmpty()->toArray();
|
|
|
|
if (empty($info)) {
|
|
return $info;
|
|
}
|
|
|
|
// 解析填充数据
|
|
$fillData = [];
|
|
if (!empty($info['fill_data'])) {
|
|
$fillData = json_decode($info['fill_data'], true) ?: [];
|
|
}
|
|
|
|
// 获取合同占位符配置
|
|
$placeholderConfig = [];
|
|
if (!empty($info['contract']['placeholder_config'])) {
|
|
$placeholderConfig = json_decode($info['contract']['placeholder_config'], true) ?: [];
|
|
}
|
|
|
|
// 获取文档数据源配置
|
|
$fieldConfigs = \think\facade\Db::table('school_document_data_source_config')
|
|
->where('contract_id', $info['contract_id'])
|
|
->where('contract_sign_id', $info['id'])
|
|
->select()
|
|
->toArray();
|
|
|
|
// 如果没有找到特定配置,则使用通用配置(contract_sign_id IS NULL)
|
|
if (empty($fieldConfigs)) {
|
|
$fieldConfigs = \think\facade\Db::table('school_document_data_source_config')
|
|
->where('contract_id', $info['contract_id'])
|
|
->where('contract_sign_id', null)
|
|
->select()
|
|
->toArray();
|
|
}
|
|
|
|
// 如果数据源配置为空,从占位符配置生成
|
|
if (empty($fieldConfigs) && !empty($placeholderConfig)) {
|
|
$fieldConfigs = $this->generateFieldConfigsFromPlaceholder($placeholderConfig, $info['contract_id']);
|
|
}
|
|
|
|
// 处理字段配置和数据获取
|
|
$processedFields = $this->processFieldConfigs($fieldConfigs, $info['personnel_id'], $fillData, $info['contract']['contract_type'] ?? '');
|
|
|
|
// 组装完整数据
|
|
$info['field_configs'] = $processedFields;
|
|
$info['fill_data'] = $fillData;
|
|
$info['placeholder_config'] = $placeholderConfig;
|
|
|
|
return $info;
|
|
}
|
|
|
|
/**
|
|
* 添加合同关系
|
|
* @param array $data
|
|
* @return mixed
|
|
*/
|
|
public function add(array $data)
|
|
{
|
|
$res = $this->model->create($data);
|
|
return $res->id;
|
|
|
|
}
|
|
|
|
/**
|
|
* 合同关系编辑
|
|
* @param int $id
|
|
* @param array $data
|
|
* @return bool
|
|
*/
|
|
public function edit(int $id, array $data)
|
|
{
|
|
|
|
$this->model->where([['id', '=', $id]])->update($data);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 删除合同关系
|
|
* @param int $id
|
|
* @return bool
|
|
*/
|
|
public function del(int $id)
|
|
{
|
|
$model = $this->model->where([['id', '=', $id]])->find();
|
|
$res = $model->delete();
|
|
return $res;
|
|
}
|
|
|
|
|
|
public function getContractAll(){
|
|
$contractModel = new Contract();
|
|
return $contractModel->select()->toArray();
|
|
}
|
|
|
|
public function getPersonnelAll(){
|
|
$personnelModel = new Personnel();
|
|
return $personnelModel->select()->toArray();
|
|
}
|
|
|
|
/**
|
|
* 获取员工所有合同(包括未签署的)
|
|
* @param array $where
|
|
* @return array
|
|
*/
|
|
public function getPersonnelContracts(array $where)
|
|
{
|
|
$personnel_id = $where['personnel_id'] ?? 0;
|
|
|
|
if (!$personnel_id) {
|
|
return [];
|
|
}
|
|
|
|
// 获取所有可用的合同
|
|
$contractModel = new Contract();
|
|
$contracts = $contractModel->where([['deleted_at', '=', 0]])->select();
|
|
$contracts = $contracts ? $contracts->toArray() : [];
|
|
|
|
// 获取该员工已有的签署记录
|
|
$signRecords = $this->model->where([
|
|
['personnel_id', '=', $personnel_id],
|
|
['deleted_at', '=', 0]
|
|
])->select();
|
|
|
|
$signRecords = $signRecords ? $signRecords->toArray() : [];
|
|
$signMap = [];
|
|
foreach ($signRecords as $record) {
|
|
$signMap[$record['contract_id']] = $record;
|
|
}
|
|
|
|
// 合并数据
|
|
$result = [];
|
|
foreach ($contracts as $contract) {
|
|
$contractId = $contract['id'];
|
|
$signRecord = $signMap[$contractId] ?? null;
|
|
|
|
$result[] = [
|
|
'contract_id' => $contractId,
|
|
'personnel_id' => $personnel_id,
|
|
'contract_name' => $contract['contract_name'],
|
|
'contract_type' => $contract['contract_type'],
|
|
'contract_status' => $contract['contract_status'],
|
|
'created_at' => $signRecord['created_at'] ?? $contract['created_at'],
|
|
'contract_content' => $contract['contract_content'] ?? '',
|
|
'sign_status' => $signRecord ? $signRecord['status'] : 1, // 默认未签署
|
|
'sign_time' => $signRecord['sign_time'] ?? null,
|
|
'signature_image' => $signRecord['signature_image'] ?? null,
|
|
'source_type' => $signRecord['source_type'] ?? null
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* 从占位符配置生成字段配置
|
|
* @param array $placeholderConfig
|
|
* @param int $contractId
|
|
* @return array
|
|
*/
|
|
private function generateFieldConfigsFromPlaceholder(array $placeholderConfig, int $contractId): array
|
|
{
|
|
$fieldConfigs = [];
|
|
foreach ($placeholderConfig as $placeholder => $config) {
|
|
$fieldConfigs[] = [
|
|
'placeholder' => $placeholder,
|
|
'data_type' => $config['data_type'] ?? 'user_input',
|
|
'field_name' => $config['field_name'] ?? '',
|
|
'field_type' => $config['field_type'] ?? 'text',
|
|
'sign_party' => $config['sign_party'] ?? '',
|
|
'table_name' => $config['table_name'] ?? '',
|
|
'is_required' => $config['is_required'] ?? 0,
|
|
'default_value' => $config['default_value'] ?? '',
|
|
'system_function' => $config['system_function'] ?? '',
|
|
'contract_id' => $contractId
|
|
];
|
|
}
|
|
return $fieldConfigs;
|
|
}
|
|
|
|
/**
|
|
* 处理字段配置和数据获取
|
|
* @param array $fieldConfigs
|
|
* @param int $personnelId
|
|
* @param array $fillData
|
|
* @param string $contractType
|
|
* @return array
|
|
*/
|
|
private function processFieldConfigs(array $fieldConfigs, int $personnelId, array $fillData, string $contractType = ''): array
|
|
{
|
|
$processedFields = [];
|
|
|
|
foreach ($fieldConfigs as $config) {
|
|
$placeholder = $config['placeholder'];
|
|
$dataType = $config['data_type'];
|
|
$signParty = $config['sign_party'] ?? '';
|
|
$value = $fillData[$placeholder] ?? '';
|
|
|
|
// 根据数据类型获取值
|
|
switch ($dataType) {
|
|
case 'database':
|
|
$value = $this->getDatabaseValue($config, $personnelId, $contractType);
|
|
break;
|
|
case 'system':
|
|
$value = $this->getSystemValue($config['system_function'] ?? '', $personnelId);
|
|
break;
|
|
case 'signature':
|
|
if (!empty($value)) {
|
|
// 处理签名图片显示
|
|
$value = $this->getSignatureImagePath($value);
|
|
}
|
|
break;
|
|
case 'sign_img':
|
|
if (!empty($value)) {
|
|
// 处理上传的签名图片
|
|
$value = $this->getSignatureImagePath($value);
|
|
}
|
|
break;
|
|
case 'user_input':
|
|
// 用户输入的值直接使用
|
|
break;
|
|
}
|
|
|
|
// 判断是否可编辑(只有甲方可以编辑)
|
|
$isEditable = ($signParty === 'party_a');
|
|
|
|
$processedFields[] = [
|
|
'placeholder' => $placeholder,
|
|
'data_type' => $dataType,
|
|
'field_name' => $config['field_name'] ?? '',
|
|
'field_type' => $config['field_type'] ?? 'text',
|
|
'sign_party' => $signParty,
|
|
'table_name' => $config['table_name'] ?? '',
|
|
'is_required' => $config['is_required'] ?? 0,
|
|
'default_value' => $config['default_value'] ?? '',
|
|
'system_function' => $config['system_function'] ?? '',
|
|
'value' => $value,
|
|
'is_editable' => $isEditable,
|
|
'display_value' => $this->formatDisplayValue($value, $dataType)
|
|
];
|
|
}
|
|
|
|
return $processedFields;
|
|
}
|
|
|
|
/**
|
|
* 获取数据库字段值
|
|
* @param array $config
|
|
* @param int $personnelId
|
|
* @param string $contractType
|
|
* @return mixed
|
|
*/
|
|
private function getDatabaseValue(array $config, int $personnelId, string $contractType = '')
|
|
{
|
|
$tableName = $config['table_name'] ?? '';
|
|
$fieldName = $config['field_name'] ?? '';
|
|
|
|
if (empty($tableName) || empty($fieldName)) {
|
|
return $config['default_value'] ?? '';
|
|
}
|
|
|
|
try {
|
|
// 根据表名和人员ID获取数据
|
|
$value = '';
|
|
|
|
// 如果表名是动态的(如students),根据合同类型选择实际表名
|
|
$actualTableName = $tableName;
|
|
if ($tableName === 'students') {
|
|
$actualTableName = ($contractType === '外部') ? 'school_student' : 'school_personnel';
|
|
}
|
|
|
|
switch ($actualTableName) {
|
|
case 'school_personnel':
|
|
$personnel = \app\model\personnel\Personnel::where('id', $personnelId)
|
|
->value($fieldName);
|
|
$value = $personnel ?: $config['default_value'] ?? '';
|
|
break;
|
|
case 'school_student':
|
|
// 从学员表获取数据,需要根据personnel_id找到对应的sys_user_id,再查找学生记录
|
|
$sysUserId = \app\model\personnel\Personnel::where('id', $personnelId)->value('sys_user_id');
|
|
if ($sysUserId) {
|
|
$student = \think\facade\Db::table('school_student')
|
|
->where('user_id', $sysUserId)
|
|
->value($fieldName);
|
|
$value = $student ?: $config['default_value'] ?? '';
|
|
} else {
|
|
$value = $config['default_value'] ?? '';
|
|
}
|
|
break;
|
|
default:
|
|
$value = \think\facade\Db::table($actualTableName)
|
|
->where('personnel_id', $personnelId)
|
|
->value($fieldName) ?: $config['default_value'] ?? '';
|
|
break;
|
|
}
|
|
return $value;
|
|
} catch (\Exception $e) {
|
|
return $config['default_value'] ?? '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取系统函数值
|
|
* @param string $functionName
|
|
* @param int $personnelId
|
|
* @return mixed
|
|
*/
|
|
private function getSystemValue(string $functionName, int $personnelId)
|
|
{
|
|
if (empty($functionName)) {
|
|
return '';
|
|
}
|
|
|
|
try {
|
|
// 检查函数是否存在
|
|
if (function_exists($functionName)) {
|
|
return $functionName($personnelId);
|
|
}
|
|
} catch (\Exception $e) {
|
|
// 函数调用失败,返回空值
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* 获取签名图片路径
|
|
* @param string $signatureData
|
|
* @return string
|
|
*/
|
|
private function getSignatureImagePath(string $signatureData): string
|
|
{
|
|
// 如果是base64图片数据,直接返回
|
|
if (strpos($signatureData, 'data:image') === 0) {
|
|
return $signatureData;
|
|
}
|
|
|
|
// 如果是文件路径,转换为完整URL
|
|
if (!empty($signatureData) && strpos($signatureData, 'http') !== 0) {
|
|
return request()->domain() . '/' . ltrim($signatureData, '/');
|
|
}
|
|
|
|
return $signatureData;
|
|
}
|
|
|
|
/**
|
|
* 格式化显示值
|
|
* @param mixed $value
|
|
* @param string $dataType
|
|
* @return string
|
|
*/
|
|
private function formatDisplayValue($value, string $dataType): string
|
|
{
|
|
if (empty($value)) {
|
|
return '';
|
|
}
|
|
|
|
switch ($dataType) {
|
|
case 'signature':
|
|
case 'sign_img':
|
|
// 返回图片URL或base64数据
|
|
return $value;
|
|
default:
|
|
return (string)$value;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|