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

<?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;
}
}
}