<?php

namespace Application\Form\item\patient;


use Application\Common\BehaviorsEnum;
use Application\Common\DictionaryVarNameEnum;
use Application\Common\EventEnum;
use Application\Common\EventEnumV2;
use Application\Common\RedisEnum;
use Application\Service\DB\AbstractDb;
use Application\Service\DB\Db;
use Application\Service\DB\Dictionary\Form;
use Application\Service\DB\Dictionary\FormField;
use Application\Service\DB\Dictionary\FormGroup;
use Application\Service\DB\Dictionary\ItemForm;
use Application\Service\DB\Dictionary\ItemFormFieldRadio;
use Application\Service\DB\Item\PatientFormContentImg;
use Application\Service\DB\Item\PatientFormUnlock;
use Application\Service\DB\Project\Patientworkannex;
use Application\Service\Exceptions\InvalidArgumentException;
use Application\Service\Extension\CheckLogic\CheckLogicApplication;
use Application\Service\Extension\Event;
use Application\Service\Extension\Events\FormEventHandler;
use Application\Service\Extension\Form\BaseForm;
use Application\Service\Extension\Formatter\Formatter;
use Application\Service\Extension\Helper\ArrayHelper;
use Application\Service\Extension\Helper\CurlHelper;
use Application\Service\Extension\Helper\DataHelper;
use Application\Service\Extension\Helper\EdcHelper;
use Application\Service\Extension\Helper\FormContentHelper;
use Application\Service\Extension\Helper\SDMHelper;
use Application\Service\Extension\Helper\StringHelper;
use Application\Service\Extension\Helper\ValidatorHelper;
use Application\Service\Extension\Laminas;
use Application\Service\Extension\Middleware\components\HandleAutoReplyQuestion;
use Application\Service\Extension\Middleware\components\HandleFormImages;
use Application\Service\Extension\Middleware\components\HandleLogic;
use Application\Service\Extension\Middleware\components\HandlePatientWorkBatch;
use Application\Service\Extension\Middleware\components\HandleNormalFormOverField;
use Application\Service\Extension\Middleware\components\HandleCmFormPatientDrug;
use Application\Service\Extension\Middleware\components\HandleStorageLogic;
use Application\Service\Extension\Middleware\components\Preprocessing;
use Application\Service\Extension\Middleware\components\PreProcessResponse;
use Application\Service\Extension\Middleware\components\RateLimit;
use Application\Service\Extension\Middleware\components\ValidIsAnnexLock;
use Application\Service\Extension\Middleware\components\ValidIsOcr;
use Application\Service\Extension\Middleware\components\ValidIsRepeatCreate;
use Application\Service\Extension\Middleware\components\ValidPermission;
use Application\Service\Extension\Middleware\components\ValidPostData;
use Application\Service\Extension\Middleware\components\ValidResubmitData;
use Application\Service\Extension\Middleware\Middleware;
use Application\Service\Extension\Params\Params;
use Application\Service\Extension\Uploader\adapter\Oss;
use Application\Service\Extension\Validator\ValidatorApplication;
use EasyWeChat\Kernel\Exceptions\Exception;
use Laminas\Db\Sql\Predicate\Like;
use Laminas\Db\Sql\Predicate\NotIn;
use Laminas\Db\Sql\Predicate\Operator;
use Laminas\Db\Sql\Where;
use Laminas\Json\Json;
use Laminas\Stdlib\ArrayUtils;
use Symfony\Component\VarDumper\Cloner\Data;

/**
 * @property-read string $scenario 场景
 */
class PatientFormModel extends BaseForm
{
    /** @var string excel excel导入 */
    public const SCENARIO_EXCEL_IMPORT = 'EXCEL_IMPORT';

    /** @var string 预览未锁定的共享表单 */
    public const SCENARIO_VIEW_SHARE_FORM_UNLOCK = 'viewShareFormUnlock';

    /** @var string 评分功能场景 */
    const SCENARIO_USING_SCORE = 'USING_SCORE';

    /** @var string 受试者脱落功能场景 */
    const SCENARIO_OUT_FORM = 'OUT_FORM';

    const SCENARIO_CM_LIST = 'CM_LIST';

    const SCENARIO_CM_LIST_VIEW = 'CM_LIST_VIEW';

    /** @var int 手动填写 */
    const ANNEX_TYPE_SDTX = 3;

    /** @var int 补单类型 */
    const ANNEX_TYPE_REPLACEMENT_ORDER = 4;

    /** @var int 医嘱类型 */
    const ANNEX_TYPE_DO = 5;

    /** @var int 计划外检查 */
    public const ANNEX_TYPE_OUTPLANCHECK = 2;
    /**
     * @var mixed|string|null
     */
    public $systemRandomFieldKey;

    private array $contentId = [];

    private bool $isCheckLogic = false;

    /**
     * 版本数据
     * @var array|null
     */
    private ?array $beforeCommit = [];

    /**
     * 检查点数据
     * @var array|null
     */
    private ?array $checkTimeData = [];

    /**
     * 表单数据
     * @var array|null
     */
    private ?array $formData = [];

    /**
     * 前端提交处理过的的数据
     * @var array|null
     */
    public ?array $postData = [];

    /**
     * 前端提交未被处理过的数据
     * @var array|null
     */
    public ?array $postOriginData = [];

    /**
     * 化验单图片
     * @var array|null
     */
    private ?array $checkImgArray = [];

    /**
     * 不处理的图片
     * @var array|null
     */
    private ?array $keepAnnex = [];

    /**
     * 新增的图片
     * @var array|null
     */
    private ?array $insertAnnexArray = [];

    /**
     * 一对多表单总数
     * @var int|null
     */
    public ?int $totalCount = null;

    /**
     * 表单修改是否来自于质疑沟通
     * @var bool
     */
    public bool $isEditFormByQuestion = false;

    /**
     * 手动填写附件主键
     * 编辑手动填写内容用到
     * @var int|null
     */
    private ?int $sdtxAnnexID = null;

    /**
     * 是否已经识别过
     * @var int|null
     */
    private ?int $isScreen = 0;

    /**
     * 项目检查项名称设置表数据
     * @var array|null
     */
    private ?array $checkNameData = [];

    /**
     * 行为
     * @var BehaviorsEnum|null
     */
    public ?BehaviorsEnum $behavior = null;

    public bool $skipEDCValid = false;

//    public ?string $scenario = null;

    /**
     * 是否是补单类型
     * @var bool
     */
    public bool $isReplacementOrder = false;

    /**
     * 表单内容主键
     * @var int|null
     */
    public ?int $contentPrimaryKey = null;

    /**
     * 【新系统】化验单解锁之后的状态或解锁原因提醒 --蒙
     * https://e.gitee.com/yikeen_project/dashboard?issue=I7YJ6M
     * 是否是化验单解锁之后的状态
     * @var bool|null
     */
    private ?bool $isLockOperate = null;

    private ?bool $isComplete = null;

    /**
     * 哪些字段编辑后被修改了
     * @var array
     */
    private array $updatedFields = [];

    public ?ValidatorApplication $validator;

    public array $images = [];

    public ?string $CMINDCVal = null;

    public ?string $originCMINDCVal = null;

    public ?FormContentHelper $logger = null;

    public $importErrors = [];

    /**
     * 需要排除, 不验证是否填写的字段
     * @var array|string[]
     */
    private array $_exceptCode = [
        'OPCH', // 计划外检查
        'CHRE', // 备注说明
        'OUTPLANCHECK', // 计划外检查
        'CHECKREMARK', // 备注说明
    ];
    /**
     * @var true
     */
    private bool $dataHaveDel = false;

    public function __construct(ValidatorApplication $validator = null)
    {
        parent::__construct($validator);
        $this->logger = $this->h()->log->formContentLog;

        Event::on(EventEnum::AFTER_EVENT_SUBMIT_PATIENT_FORM, [FormEventHandler::class, 'eventAfterSubmitPatientForm']);

        Event::on(EventEnum::EVENT_LOCK_SHARE_FORM_CONTENT, function () {
            if (SDMHelper::app()->form->getGroupId($this->formId) != FormGroup::NORMAL_OCR) {
                return;
            }

            $forms = $this->h()->form->getGcoGroupForm($this->formId);
            foreach ($forms as $form) {
                //设置锁定状态
                Laminas::$serviceManager->patientFormContentImg->update(['is_lock' => 1], ['form_id' => $form['id'], 'patient_id' => $this->patientId, 'checktime_id' => $this->checktimeId]);
                SDMHelper::app()->logic->setCloseMessage('常规识别数据更新锁定')->newopenRowError($form['id'], $this->patientId,$this->checktimeId,$this->itemId);
                $this->h()->log->setTraceAttach("当前是识别类表单, 同时也锁定了当前检查点下的表单`{$this->h()->form->getName($form['id'])}`。");
            }
        });
    }

    /**
     * 初始化日志数据
     * @throws \Exception
     */
    protected function initLoggerData()
    {
        // 因为删除操作没有传item_id参数，所以这里重新赋值，方便定位日志表
        if($this->itemId) Params::app()->setValue('item_id', $this->itemId);
        $this->logger->setEvent($this->event)->setPostData($this->postData)->setPostOriginData($this->postOriginData);
        if ($this->contentPrimaryKey) {
            $this->logger->setContentId($this->contentPrimaryKey);
        }
    }

    /**
     * 获取表单对应的版本数据
     * @param int $formId
     * @return array|mixed|null
     * @throws \Exception
     */
    private function _getVersionData()
    {
        return SDMHelper::app()->form->getVersionData($this->formId);
    }

    /**
     * 获取检查点信息
     * @return array|mixed|\phpDocumentor\Reflection\Types\Mixed|null
     */
    private function _getCheckTimeData()
    {
        if (!$this->checkTimeData) {
            $this->checkTimeData = Laminas::$serviceManager->itemChecktime->memoryCache()->fetchOne([
                'where' => ['id' => $this->validator->attributes['checktime_id']]
            ]);
        }

        return $this->checkTimeData;
    }

    /**
     * 获取当前操作的表单数据
     * @param int $formId
     * @return array
     */
    public function getItemFormData(int $formId = 0): array
    {
        if (!$this->formData) {
            $this->formData = Laminas::$serviceManager->itemForm->memoryCache()->fetchOne([
                'where' => ['id' => $formId ?: $this->validator->attributes['form_id']]
            ]);
        }

        return $this->formData ?: [];
    }

    /**
     * @param $itemId
     * @param $userId
     * @return string
     */
    public static function getUsingScoreRedisKey($itemId, $userId): string
    {
        return "USING_SCORE:{$itemId}:" . (in_array($userId, Laminas::$serviceManager->itemForm->getUsingScoreUser(true)) ? 'USER' : 'USER');
    }

    public function h()
    {
        return SDMHelper::app();
    }

    /**
     * 指定contentId
     * @param $contentId
     * @return $this
     */
    public function setContentId($contentId): PatientFormModel
    {
        if (!is_array($contentId)) {
            $this->contentId = (array)$contentId;
        } else {
            $this->contentId = $contentId;
        }

        return $this;
    }

    /**
     * 设置行为
     * @param BehaviorsEnum $behavior
     * @return $this
     */
    public function setBehavior(BehaviorsEnum $behavior): PatientFormModel
    {
        $this->behavior = $behavior;
        return $this;
    }

    /**
     * 设置是否属于逻辑核查
     * @param bool $isCheckLogic
     * @return $this
     */
    public function setCheckLogic(bool $isCheckLogic): PatientFormModel
    {
        $this->isCheckLogic = $isCheckLogic;
        return $this;
    }

    /**
     * 设置场景
     * @param string $scenario
     * @return $this
     */
    public function setScenario(string $scenario): PatientFormModel
    {
        $this->scenario = $scenario;
        return $this;
    }

    /**
     * 获取表单提交数据
     * @param array $postData
     * @return array|null
     */
    public function setPostData(array $postData): array
    {
        $this->postOriginData = $postData;

        unset($postData['old_data_str']);

        $this->postData = $postData;

        return $this->postData;
    }

    /**
     * 整合了提交数据
     * @param array $postValues
     */
    public function setPostValues(array $postValues = [])
    {
        $this->setPostData($postValues);
        $this->setAttributes($postValues);
    }

    /**
     * 获取手动填写数据
     * @return array
     */
    private function getSdtxData(): array
    {
        if (isset($this->postData[Form::ATTACH_SDTX])) {
            return StringHelper::jsonDecode($this->postData[Form::ATTACH_SDTX]);
        }

        return [];
    }

    /**
     * 设置手动填写数据
     * @param $data
     */
    private function setSdtxData($data)
    {
        $this->postData[Form::ATTACH_SDTX] = json_encode($data);
    }

    /**
     * 设置行为
     * @param string $eventName
     * @return $this
     */
    public function setEvent(string $eventName): PatientFormModel
    {
        $this->event = $eventName;
        return $this;
    }

    /**
     * 项目检查项名称设置表数据
     * @return array
     */
    private function getCheckNameData(): array
    {
        if (!$this->checkNameData) {
            $formData = $this->getItemFormData();

            $this->checkNameData = Laminas::$serviceManager->itemCheckname->fetchAll([
                'where' => [
                    'item_id' => $this->validator->attributes['item_id'],
                    'category_id' => $formData['checklist_id'],
                    'is_del' => 0
                ]
            ]);
        }

        return $this->checkNameData;
    }

    /**
     * 获取识别模板
     * @param int $itemId
     * @param $categoryId
     * @return mixed
     */
    private function getImgTxtDiscernData(int $itemId, $categoryId)
    {
        $imgTxtDiscernData = Laminas::$serviceManager->itemImgtxtdiscern->fetchOne([
            'where' => [
                'item_id' => $itemId,
                'category_id' => $categoryId,
                'is_del' => 0,
                'item_sign_id' => $this->validator->attributes['itemsig_id']
            ]
        ]);

//        if (!$imgTxtDiscernData) {
//            throw new InvalidArgumentException('没找到对应的识别模板。请移除化验单附件/手动填写数据。');
//        }

        return $imgTxtDiscernData;
    }

    /**
     * 当前是否是化验单解锁之后的状态
     * @return bool|null
     */
    private function getIsLockOperate(): ?bool
    {
        if ($this->isLockOperate === null) {
            $this->isLockOperate = Laminas::$serviceManager->patientFormUnlock->getStatus($this->contentPrimaryKey) == PatientFormUnlock::STATUS_ENSURE;
        }

        return $this->isLockOperate;
    }

    /**
     * 获取是否属于化验单类表单
     * @return int
     */
    private function getIsYc()
    {
        // 不是化验单或者医嘱类型的表单
        if (!in_array($this->getItemFormData()['group_id'], [FormGroup::CHECK_OCR, FormGroup::CHECK_DO])) {
            return -1;
        }

        $versionData = $this->_getVersionData();

        $checkField = ArrayHelper::index($versionData, 'var_name')['ISCHECK']['id'] ?? null;
        if (isset($this->postData[$checkField]) && $this->postData[$checkField] !== '') {
            return $this->postData[$checkField] == 2 ? 1 : 0;
        }

        return -1;
    }

    /**
     * @param array $versionData
     * @param string $fieldVarName
     * @return int|mixed
     */
    private function getThroughProcessDOVal(array $versionData, string $fieldVarName)
    {
        return $this->postData[$versionData[$fieldVarName]['id']] ?? 0;
    }

    /**
     * 更新计划外检查图片
     */
    private function updateOutPlanCheckContentImg($images, $field = null)
    {
        if (is_string($images)) {
            $images = StringHelper::jsonDecode($images);
        }

        // 把所有旧数据都清理掉
        Laminas::$serviceManager->patientFormContentImg->update(['is_del' => 1], [
            'item_id' => $this->validator->attributes['item_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'form_id' => $this->validator->attributes['form_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'img_type' => PatientFormContentImg::IMG_TYPE_OUTPLANCHECK
        ]);

        foreach ($images as $image) {
            $src = DataHelper::handleImageSrc($image['url']);
            $condition = [
                'item_id' => $this->validator->attributes['item_id'],
                'itemsig_id' => $this->validator->attributes['itemsig_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'form_id' => $this->validator->attributes['form_id'],
                'checktime_id' => $this->validator->attributes['checktime_id'],
                'img_src' => $src,
                'img_name' => $image['name'],
                'img_type' => PatientFormContentImg::IMG_TYPE_OUTPLANCHECK,
            ];

            $hasImg = Laminas::$serviceManager->patientFormContentImg->fetchOne([
                'where' => $condition
            ]);

            // 没有就insert, 有就把is_del 改成0
            if (!$hasImg) {
                $condition['content_id'] = $this->contentPrimaryKey;
                $condition['field_id'] = $field;
                Laminas::$serviceManager->patientFormContentImg->save($condition);
            } else {
                Laminas::$serviceManager->patientFormContentImg->update(['is_del' => 0], ['id' => $hasImg['id']]);
            }
        }
    }

    protected function handle($function)
    {
        if ($this->getItemFormData()['group_id'] == FormGroup::THROUGH_PROCESS && $this->getItemFormData()['is_through_process_do'] == 1) {
            return function() use ($function) {
                foreach ($this->_getVersionData() as $field) {
                    // 图片
                    if ($field['var_name'] === 'THROUGH_PROCESS_DO_IMAGE') {
                        $images = StringHelper::jsonDecode($this->postData[$field['id']], true);
                        foreach ($images as $image) {
                            $this->postData[$field['id']] = [$image];
                            $function();
                        }
                    }
                }

                return 0;
            };
        }

        return $function;
    }

    /**
     * @throws \Exception
     */
    public function getExecuteCore()
    {
        // 修改checkTime表操作人id.
        $this->updateOperateUserId();

        // 更新访视日期
        $this->_updateBookedTime();

        // 更新锚点日期
        $this->_updateAnchor();

        // 更新随机分组
        $this->_updateRandomGroup();

        // 更新关联表单
        $this->_updateFormRelation();

        $this->_triggerFieldLock();

        // 更新表单图片中间表
//        $this->updateContentImg();

        // 解除表单锁
        $this->contentUnlock();

        // 记录哪些字段修改了
        $this->setContentUpdatedFields();


        $resultId = Laminas::$serviceManager->patientFormContent->save([
            'data' => json_encode($this->getEditPostData()),
            'id' => $this->validator->attributes['id'],
            'update_time' => time(),
            'update_user_id' => Laminas::$serviceManager->identity->getId(),
            'is_yc' => $this->getIsYc(),
            'checktime_id' => $this->validator->attributes['checktime_id'], // 贯穿全程用
            'is_complete' => $this->getIsComplete($this->postData),
            'drug_id' => $this->getCmDrug($this->postData,$this->validator->attributes['form_id'])
        ]);

        if(!$this->validator->attributes['id']) {
            $this->contentPrimaryKey = $resultId;
        }

        // 更新关联表状态
        $this->_updateRelationStatus();

        // 更新化验单, 计划外检查点上传附件
        $this->_updateAttach();

        // 评分功能表单
        $this->_updateUsingScoreFormStatus();

        $this->changeExceedswindow();

        // 更新进度条
        /*if ($this->h()->item->getIsEdc($this->itemId) && $this->getContentData()['is_complete'] != $this->isComplete) {
            Laminas::$serviceManager->patientChecktimeList->isCompleteForm([
                'item_id' => $this->validator->attributes['item_id'],
                'itemsig_id' => $this->validator->attributes['itemsig_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'form_id' => $this->validator->attributes['form_id'],
                'checktime_id' => $this->validator->attributes['checktime_id'],
                'type' => $this->isComplete === false ? 3 : 1,
            ]);
        }*/
    }

    /**
     * 填写受试者表单
     * @param $postData
     * @return int
     * @throws Exception
     */
    public function createForm($postData): int
    {
        $this->setPostData($postData);
        $this->event = EventEnum::EVENT_FORM_CONTENT_CREATE;

        return (new Middleware($this))->beforeMiddleware([
            RateLimit::class,

            ValidIsRepeatCreate::class,

            Preprocessing::class,

            ValidPostData::class

        ])->afterMiddleware([
            HandleFormImages::class,
        ])->afterTransactionMiddleware([
            HandleLogic::class,
            HandlePatientWorkBatch::class,//异步处理访视进度情况信息
            HandleNormalFormOverField::class, //异步处理常规识别完成表单字段数量信息
            HandleCmFormPatientDrug::class //异步处理CM表单受试者药物信息
        ])->execute($this->handle($this->_create()));
    }


    public function createFormImport($postData)
    {
        $this->setPostData($postData);

        $this->event = EventEnum::EVENT_FORM_CONTENT_CREATE;

        $middleware = new Middleware($this,1);

        return $middleware->beforeMiddleware([
                Preprocessing::class,

                ValidPostData::class,
        ])->importexecute($this->handle($this->_importcreate()));
    }

    public function editFormImport($postData)
    {
        $this->setPostData($postData);

        if (!$this->event) {
            $this->event = EventEnum::EVENT_FORM_CONTENT_EDIT;
        }

        // 初始化表单内容主键id
        $this->contentPrimaryKey = (int)$this->validator->attributes['id'];

        // 判断的是主项目是否开启edc
        if (EdcHelper::isEdc($this->h()->item->getFid($this->validator->attributes['item_id'])) && SDMHelper::app()->setAttributes(['content_id' => $this->contentPrimaryKey])->formContent->getIsEdcLock()) {
            $this->importErrors[] = '此表单在EDC已锁定, 无法提交。';
        }

        return (new Middleware($this,1))
            ->beforeMiddleware([
                ValidPermission::class,
                Preprocessing::class,  // 提交的数据预处理,
                ValidPostData::class,  // 验证提交的数据是否正确
            ])->importexecute($this->handle($this->_importcreate()));
    }

    /**·
     * 【该功能暂时移除】
     * 【新系统】评分管理员提交表单后，表单进行锁定（蓝锁）--美
     * https://e.gitee.com/yikeen_project/dashboard?issue=I8PUXO
     */
    protected function autoLock()
    {
        if ($this->itemForm->is_using_score == 0) {
            return;
        }

        if (Laminas::$serviceManager->itemForm->getIsUsingScoreAdmin() === true) {
            foreach (Laminas::$serviceManager->patientFormContent->fetchAll([
                'where' => [
                    'form_id' => $this->formId,
                    'patient_id' => $this->patientId,
                    'item_id' => $this->itemId,
                    'itemsig_id' => $this->itemsigId,
                ]
            ]) as $item) {
                Laminas::$serviceManager->patientFormContent->lock($item['id']);
                $conditions = [
                    'form_id' => $this->formId,
                    'patient_id' => $this->patientId,
                    'item_id' => $this->itemId,
                    'itemsig_id' => $this->itemsigId,
                    'checktime_id' => $this->checktimeId,
                    'content_id' => $item['id'],
                    'is_ae' => 0
                ];
                $isLock = Laminas::$serviceManager->patientFormLock->fetchOne([
                    'where' => $conditions
                ]);

                if ($isLock) {
                    $conditions['is_del'] = 0;
                    $conditions['id'] = $isLock['id'];
                }

                Laminas::$serviceManager->patientFormLock->save($conditions);
            }
        }
    }

    protected function _create()
    {
        return function () {

            // 初始化日志
            $this->initLoggerData();

            // Db::beginTransaction();

            // 修改checkTime表操作人id.
            $this->updateOperateUserId();

            // 更新访视日期
            $this->_updateBookedTime();

            // 更新随机分组
            $this->_updateRandomGroup();

            // 更新锚点日期
            $this->_updateAnchor();

            // 更新关联表单
            $this->_updateFormRelation();

            $this->_triggerFieldLock();

            $this->contentPrimaryKey = (int)Laminas::$serviceManager->patientFormContent->save([
                'patient_id' => $this->validator->attributes['patient_id'] ?: 0,
                'form_id' => $this->validator->attributes['form_id'] ?: 0,
                'data' => json_encode($this->postData),
                'item_id' => $this->validator->attributes['item_id'] ?: 0,
                'checktime_id' => $this->validator->attributes['checktime_id'] ?: 0,
                'itemsig_id' => $this->validator->attributes['itemsig_id'] ?: 0,
                'update_time' => time(),
                'update_user_id' => Laminas::$serviceManager->identity->getId(),
                'is_yc' => $this->getIsYc(),
                'is_complete' => $this->getIsComplete($this->postData),
                'drug_id' => $this->getCmDrug($this->postData,$this->validator->attributes['form_id'])
            ]);

            //超窗
            $this->changeExceedswindow();

            // 更新表单图片中间表
//            $this->updateContentImg();

            // 更新关联表状态
            $this->_updateRelationStatus();

            // 更新化验单, 计划外检查点上传附件
            $this->_updateAttach();

            $this->_updateUsingScoreFormStatus();

            /*if (EdcHelper::isEdc($this->h()->item->getFid($this->itemId))) {
                Laminas::$serviceManager->patientChecktimeList->isCompleteForm([
                    'item_id' => $this->validator->attributes['item_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'form_id' => $this->validator->attributes['form_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'type' => $this->isComplete === true ? 1 : 2,
                ]);
            }*/

            Event::trigger(EventEnum::AFTER_EVENT_SUBMIT_PATIENT_FORM, [$this]);

            $this->logger->setContentId($this->contentPrimaryKey)->flush();

            $this->beforeCommit();

            $this->resubmit();

            // Db::commit();

            // 逻辑核查
            //$this->logicCheck();
            //运行逻辑核查公式自动发送质疑
            $this->logicexecute($this->contentPrimaryKey);

            return $this->contentPrimaryKey;
        };
    }

    protected function _importcreate()
    {
        return function () {
            // 更新随机分组
            $this->_importUpdateRandomGroup();

            // 更新关联表单
            $this->_importUpdateFormRelation();

            $this->contentPrimaryKey = 1;

            // 更新化验单, 计划外检查点上传附件
            $this->_importUpdateAttach();

            return $this->importErrors;
        };
    }
    //超窗处理
    private function changeExceedswindow()
    {
        $hyperwindowField = Laminas::$serviceManager->itemFormField->fetchCol('id',['is_del'=>0,'is_hyperwindow'=>1,'form_id'=>$this->validator->attributes['form_id']]);

        if(empty($hyperwindowField)) return true;


        $config = Laminas::$serviceManager->itemForm->getPreviewConfig($this->validator->attributes['form_id'],true);

        $handleDatas = [];
        foreach ($config['config']['form'] as $k=>$v){
            if(isset($hyperwindowField[$v['field_id']]) && isset($this->postData[$v['prop']]) && !empty($this->postData[$v['prop']])){
                $handleDatas[$v['field_id']] =$this->postData[$v['prop']];
            }
        }

        $form_type = 0;
        $formOrder = 1;
        if (SDMHelper::app()->form->getType($this->validator->attributes['form_id']) == Form::FORM_TYPE_MULTI) {
            $form_type = 1;
        }

        if($form_type == 1){
            //如果是一对多表单，获取当前一对标表单的排序值
            $contentDatas = Laminas::$serviceManager->patientFormContent->fetchAll([
                'where'=>[
                    'item_id' => $this->validator->attributes['item_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'form_id' => $this->validator->attributes['form_id'],
                    'is_del'=>0
                ],
                'columns'=>['id']
            ]);
            $contentid = array_column($contentDatas,'id');

            $formOrder = array_search($this->contentPrimaryKey, $contentid)+1;
        }


        Laminas::$serviceManager->projectExceedswindow->update(['is_del'=>1],[
            'is_del'=>0,
            'data_type'=>1,
            'content_id'=>$this->contentPrimaryKey
        ]);

        if(empty($handleDatas)) return true;

        Laminas::$serviceManager->swTaskClient->send([
            'svName' => 'projectExceedswindow',
            'methodName' => 'saveExceedswindow',
            'params' => [
                'item_id' => $this->validator->attributes['item_id'],
                'itemsig_id' => $this->validator->attributes['itemsig_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'checktime_id' => $this->validator->attributes['checktime_id'],
                'form_id' => $this->validator->attributes['form_id'],
                'handleDatas'=>$handleDatas,
                'data_type'=>1,
                'content_id'=>$this->contentPrimaryKey,
                'form_order'=>$formOrder
            ]
        ]);
    }


    /**
     * 【暂时移除】
     */
    private function _updateUsingScoreFormStatus()
    {
        if ($this->scenario == self::SCENARIO_USING_SCORE) {
            $key = "USING_SCORE:{$this->validator->attributes['item_id']}:USER";
            $completeStatus = intval($this->getIsComplete($this->postData));
            $usingScoreUser = Laminas::$serviceManager->itemForm->getUsingScoreUser(true);
            // 管理员要更新所有管理员填写的状态
            if (in_array(Laminas::$serviceManager->identity->getId(), $usingScoreUser)) {
                foreach ($usingScoreUser as $user) {
                    Laminas::$serviceManager->redisExtend->getRedisInstance()->hSet($key,
                        $user . ":{$this->validator->attributes['itemsig_id']}:{$this->validator->attributes['patient_id']}:{$this->validator->attributes['checktime_id']}:{$this->validator->attributes['form_id']}",
                        intval($this->getIsComplete($this->postData))
                    );
                }
            } else {
                Laminas::$serviceManager->redisExtend->getRedisInstance()->hSet($key,
                    Laminas::$serviceManager->identity->getId() . ":{$this->validator->attributes['itemsig_id']}:{$this->validator->attributes['patient_id']}:{$this->validator->attributes['checktime_id']}:{$this->validator->attributes['form_id']}",
                    intval($this->getIsComplete($this->postData))
                );
            }
        }
    }

    private function getContentData()
    {
        return $this->h()->formContent->getDecodeData($this->contentPrimaryKey);
    }

    /**
     * 填写受试者表单
     * @param $postData
     * @return int
     * @throws Exception
     */
    public function createFormByQA($postData): int
    {
        $dataArr = $this->setPostData($postData);

        Db::beginTransaction();

        $contentId = Laminas::$serviceManager->patientFormContent->save([
            'patient_id' => 0,
            'form_id' => $this->validator->attributes['form_id'] ?: 0,
            'data' => json_encode($dataArr),
            'item_id' => 0,
            'checktime_id' => 0,
            'itemsig_id' => 0,
            'update_time' => time(),
            'update_user_id' => 0,
            'is_yc' => 0
        ]);

        $this->changeExceedswindow();

        Db::commit();

        return $contentId;
    }

    /**
     * 展示关联的表单
     */
    private function _triggerFieldLock()
    {
        $allLock = Laminas::$serviceManager->itemPatientFormContentFieldLock->memoryCache()->fetchAll(['where' => ['lock_type' => 0, 'item_id' => $this->validator->attributes['item_id']]]);

        foreach ($allLock as $lockValue) {
            if ($lockValue['lock_conditions'] == $this->validator->attributes['form_id']) {
                Laminas::$serviceManager->itemPatientFormContentFieldLock->update(['is_del' => 0], ['id' => $lockValue['id']]);
            }
        }
    }

    /**
     * 处理贯穿全程类表单
     * 插入所有贯穿全程类的检查点
     */
    private function handleProcess(array $row)
    {
        $checkTimeData = Laminas::$serviceManager->itemPatientchecktime->fetchAll([
            'where' => [
                'item_id' => $this->validator->attributes['item_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
            ]
        ]);

        $checkTimeId = ArrayHelper::getColumn($checkTimeData, 'checktime_id');

        foreach ($checkTimeId as $value) {
            $hasCheckTime = Laminas::$serviceManager->patientForm->fetchAll([
                'where' => [
                    'item_id' => $this->validator->attributes['item_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'form_id' => $this->validator->attributes['form_id'],
                    'checktime_id' => $value,
                    'is_del' => 0
                ]
            ]);

            if (!$hasCheckTime) {
                Laminas::$serviceManager->patientForm->save(ArrayHelper::merge($row, ['checktime_id' => $value]));
            }
        }

        $this->updateCompleteStatus();
    }

    /**
     * 更新完成状态
     */
    public function updateCompleteStatus()
    {
        $patientFormId = ArrayHelper::getColumn(Laminas::$serviceManager->patientForm->fetchAll([
            'where' => [
                'item_id' => $this->validator->attributes['item_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'form_id' => $this->validator->attributes['form_id'],
                'is_del' => 0
            ]
        ]) ?: [], 'id');

        $condition = [
            'item_id' => $this->validator->attributes['item_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'form_id' => $this->validator->attributes['form_id'],
            'is_del' => 0,
            'checktime_id' => $this->checktimeId
        ];

        if ($this->getIsProcess()) {
            unset($condition['checktime_id']);
        }

        $content = Laminas::$serviceManager->patientFormContent->fetchAll([
            'where' => $condition
        ]);

        // 是否有未填写完的
        $hasUnComplete = false;
        $hasComplete = false;

        $isComplete = -1;
        if(!empty($content)) {
            $isComplete = 1; // 默认全完成
            foreach ($content as $v) {
                $data = StringHelper::jsonDecode($v['data']);
                if ($this->_getIsComplete($data) === false) {
                    $hasUnComplete = true;
                } else {
                    $hasComplete = true;
                }

                if ($this->getItemFormData()['finish_condition'] == Form::FORM_FINISH_CONDITION_ALL) { // 全部填写
                    if ($hasUnComplete) {
                        $isComplete = 0;
                        break;
                    }
                } else { // 任意一个
                    if (!$hasComplete) {
                        $isComplete = 0;
                        break;
                    }
                }
            }
        }

        $this->isComplete = $isComplete != 1;

        Laminas::$serviceManager->patientForm->update(['is_complete' => $isComplete], ['id' => $patientFormId]);

        return $isComplete;
    }

    /**
     * 更新表单关联
     * @param array $postData
     */
    private function _updateFormRelation()
    {
        $isAllProcess = false;
        $versionData = $this->_getVersionData();
        $allCheckTimeForm = function () {
            $checkTimeData = Laminas::$serviceManager->itemPatientchecktime->fetchAll([
                'where' => [
                    'item_id' => $this->validator->attributes['item_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                ]
            ]);
            return ArrayHelper::getColumn($checkTimeData, 'checktime_id');
        };

        $revertOriginData = function($formId) {
            // 是否还有已填写的表单
            $isWrite = Laminas::$serviceManager->patientFormContent->fetchOne([
                'columns' => ['id', 'data', 'form_id', 'checktime_id'],
                'where' => [
                    'form_id' => $formId,
                    'item_id' => $this->validator->attributes['item_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'is_del' => 1
                ]
            ]);
            Laminas::$serviceManager->patientForm->update([
                'is_del' => 0,
            ], ArrayHelper::filter([
                'item_id' => $this->validator->attributes['item_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'checktime_id' => SDMHelper::app()->form->getIsProcess($formId) ? null : ($isWrite['checktime_id'] ?? $this->validator->attributes['checktime_id']), // 贯穿全程的处理和一对一, 一对多的处理
                'itemsig_id' => $this->validator->attributes['itemsig_id'],
                'form_id' => SDMHelper::app()->form->getType($formId) == Form::FORM_TYPE_SINGLE ? $isWrite['form_id'] : $formId,
            ]));
            if (SDMHelper::app()->form->getType($formId) == Form::FORM_TYPE_MULTI) {
                return;
            }
            Laminas::$serviceManager->patientFormContent->update(['is_del' => 0], ['id' => $isWrite['id']]);
        };

        foreach ($this->postData as $k => $datum) {
            if (!DataHelper::isField($k)) {
                continue;
            }

            $postField = DataHelper::getFieldId($k);

            if (is_numeric($k) && in_array($versionData[$postField]['type'], [FormField::FORM_FIELD_TYPE_RADIO]) && $lockError = $this->_hasRadioLock($k, $datum)) {
                throw new InvalidArgumentException($lockError);
            }

            $dataBase = $this->_getDatabase();
            if (isset($versionData[$postField]) && isset($versionData[$postField]['children'])) {
                foreach ($versionData[$postField]['children'] as $child) {

                    $updateCheckTime = (array)$this->validator->attributes['checktime_id'];
                    // 表单关联, 并且选中的是需要展示关联表单的值
                    if ($child['value'] == $datum && $child['relation_classification'] == ItemFormFieldRadio::RELATION_CLASSIFICATION_FORM) {
                        foreach ($child['relation_information'] as $information) {
                            if (!$information) {
                                throw new InvalidArgumentException('请完善表单内容设置。');
                            }

                            // 计划外
                            if ($dataBase->getTableName() === Laminas::$serviceManager->itemPatientcheckcontent->getTableName()) {

                                $condition = [
                                    'form_id' => $information,
                                    'item_id' => $this->validator->attributes['item_id'],
                                    'patient_id' => $this->validator->attributes['patient_id'],
                                    'patientchecktime_id' => $this->validator->attributes['patientchecktime_id']
                                ];
                            } else {

                                $condition = [
                                    'form_id' => $information,
                                    'item_id' => $this->validator->attributes['item_id'],
                                    'check_id' => $this->validator->attributes['checktime_id'],
                                ];
                            }

//                            $dataBase->update(['is_hide' => 1], $condition);
                            $dataBase->update(['is_hide' => 0], $condition);

                            // 两个都是贯穿全程的, 关联起来也同理
                            if ($this->getIsAllProcess($information)) {
                                $isAllProcess = true;
                                unset($condition['check_id']);
                                $updateCheckTime = $allCheckTimeForm();
                            }

                            $this->_updateCheckTimeForm($information, 0, $updateCheckTime);

                            $query = Laminas::$serviceManager->itemPatientFormContentFieldLock->fetchOne([
                                'where' => [
                                    'lock_type' => 0,
                                    'field_id' => $postField,
                                    'form_id' => $this->validator->attributes['form_id'],
                                    'item_id' => $this->validator->attributes['item_id'],
                                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                                    'checktime_id' => $isAllProcess === true ? 0 : $this->validator->attributes['checktime_id'],
                                    'lock_conditions' => $information,
                                    'lock_value' => $datum
                                ]
                            ]);

                            if ($query) {

//                                Laminas::$serviceManager->itemPatientFormContentFieldLock->save(array_merge($query, ['is_del' => 1]));
                            } else {
                                // 增加一个未生效的表单字段锁
                                Laminas::$serviceManager->itemPatientFormContentFieldLock->insert([
                                    'lock_type' => 0,
                                    'field_id' => $postField,
                                    'form_id' => $this->validator->attributes['form_id'],
                                    'item_id' => $this->validator->attributes['item_id'],
                                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                                    'checktime_id' => $isAllProcess === true ? 0 : $this->validator->attributes['checktime_id'],
                                    'is_del' => 1,
                                    'lock_conditions' => $information,
                                    'lock_value' => $datum
                                ]);
                            }
                            $revertOriginData($information);
                        }
//                        return;

                    } elseif ($child['relation_classification'] == ItemFormFieldRadio::RELATION_CLASSIFICATION_FORM) { // 表单关联, 并且选中的不是需要展示关联表单的值
                        foreach ($child['relation_information'] as $information) {
                            if (!$information) {
                                throw new InvalidArgumentException('请完善表单内容设置。');
                            }

                            $dataBase = $this->_getDatabase();
                            if ($dataBase->getTableName() === Laminas::$serviceManager->itemPatientcheckcontent->getTableName()) {
                                $dataBase->update([
                                    'is_hide' => 1
                                ], [
                                    'form_id' => $information,
                                    'item_id' => $this->validator->attributes['item_id'],
                                    'patient_id' => $this->validator->attributes['patient_id'],
                                ]);


                            } else {
                                $condition = [
                                    'form_id' => $information,
                                    'item_id' => $this->validator->attributes['item_id'],
                                    'check_id' => $this->validator->attributes['checktime_id'],
                                ];

                                if ($this->getIsAllProcess($information)) {
                                    $isAllProcess = true;
                                    unset($condition['check_id']);
                                    $updateCheckTime = $allCheckTimeForm();
                                }

                                $dataBase->update([
                                    'is_hide' => 1
                                ], $condition);
                            }
                            $this->_updateCheckTimeForm($information, 1, $updateCheckTime);
                        }
                    }
                }
            }
        }
    }

    /**
     * @param int $information
     * @param int $isForce
     * @param array $updateCheckTime 需要更新哪些检查点
     */
    private function _updateCheckTimeForm(int $information, $isForce = 0, array $updateCheckTime = [])
    {
        foreach ($updateCheckTime as $checkTime) {
            $hasChecktimeForm = Laminas::$serviceManager->itemPatientChecktimeForm->fetchOne([
                'where' => [
                    'form_id' => $information,
                    'checktime_id' => $checkTime,
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'item_id' => $this->validator->attributes['item_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id']
                ]
            ]);


            if ($isForce) {
                if ($hasChecktimeForm) {
                    Laminas::$serviceManager->itemPatientChecktimeForm->update(['is_del' => 1], ['id' => $hasChecktimeForm['id']]);
                } else {
                    // TOOD
                }

                continue;
            }

            if ($hasChecktimeForm) {
                Laminas::$serviceManager->itemPatientChecktimeForm->update(['is_del' => 0], ['id' => $hasChecktimeForm['id']]);
            } else {
                Laminas::$serviceManager->itemPatientChecktimeForm->save([
                    'form_id' => $information,
                    'checktime_id' => $checkTime,
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'item_id' => $this->validator->attributes['item_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'is_del' => 0
                ]);
            }
        }
    }

    /**
     * @return AbstractDb
     */
    private function _getDatabase()
    {
        // 如果前端不传的话, 就自己取
        if (!$this->validator->attributes['is_copy']) {
            $this->validator->attributes['is_copy'] = Laminas::$serviceManager->itemChecktime->getchecktimestatus($this->validator->attributes['checktime_id']) ? 1 : 0;
        }
        return $this->validator->attributes['is_copy'] ? Laminas::$serviceManager->itemPatientcheckcontent : Laminas::$serviceManager->itemCheckcontent;
    }

    /**
     * 判断当前操作的表单和被操作的表单是否都属于贯穿全程类的表单
     * @param int $formId
     * @return bool
     */
    public function getIsAllProcess(int $formId): bool
    {
        $query = Laminas::$serviceManager->itemForm->fetchOne([
            'where' => ['id' => $formId]
        ]);

        return (($query['group_id'] == FormGroup::THROUGH_PROCESS) && $this->getIsProcess());
    }

    /**
     * 是否有表单锁
     * @param int $fieldId
     * @param $value
     * @return bool
     */
    private function _hasRadioLock(int $fieldId, $value)
    {

        $lockRow = Laminas::$serviceManager->itemPatientFormContentFieldLock->fetchOne(
            ['where' => ['item_id' => $this->validator->attributes['item_id'], 'is_del' => 0, 'field_id' => $fieldId]]
        );
        if (!$lockRow) {
            return false;
        }

        if ($lockRow['lock_value'] == $value) {
            return false;
        }

        $condition = [
            'form_id' => $lockRow['lock_conditions'],
            'item_id' => $this->validator->attributes['item_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'is_del' => 0
        ];

        // 都是贯穿全程类的表单
        if ($this->getIsAllProcess($lockRow['lock_conditions'])) {
            unset($condition['checktime_id']);
        }

        $method = SDMHelper::app()->form->getType($lockRow['lock_conditions']) === Form::FORM_TYPE_MULTI ? 'fetchAll' :  'fetchOne';
        // 是否还有已填写的表单
        $isWrite = Laminas::$serviceManager->patientFormContent->{$method}([
            'columns' => ['id', 'data', 'form_id', 'checktime_id'],
            'where' => $condition
        ]);

        $relationFormName = Laminas::$serviceManager->itemForm->fetchOne([
                'where' => ['id' => $lockRow['lock_conditions']]
            ])['name'] ?? '';

        // 【SDM】关于表单挂靠触发以及相关表单颜色标识--美，蒙
        //https://e.gitee.com/yikeen_project/issues/list?issue=IB5ZWF

        if (SDMHelper::app()->form->getType($lockRow['lock_conditions']) == Form::FORM_TYPE_MULTI) {
            // 被关联的表单时一对多的
            if ($isWrite) {
                return "被关联的表单 `{$relationFormName}` 已产生数据，无法修改选项。";
            }

            Laminas::$serviceManager->patientForm->update([
                'is_del' => 1,
            ], ArrayHelper::filter([
                'item_id' => $this->validator->attributes['item_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'checktime_id' => SDMHelper::app()->form->getIsProcess($lockRow['lock_conditions']) ? null : $this->validator->attributes['checktime_id'],
                'itemsig_id' => $this->validator->attributes['itemsig_id'],
                'form_id' => $lockRow['lock_conditions']
            ]));
        } elseif (SDMHelper::app()->form->getType($lockRow['lock_conditions']) == Form::FORM_TYPE_SINGLE) {
            // 一对一
            if ($isWrite) {
                $isDataEmpty = DataHelper::isEmpty(StringHelper::jsonDecode($isWrite['data']));
                if (!$isDataEmpty) {
                    return "被关联的表单 `{$relationFormName}` 已产生数据，无法修改选项。";
                }

                Laminas::$serviceManager->patientFormContent->update(['is_del' => 1], ['id' => $isWrite['id']]);
                Laminas::$serviceManager->patientForm->update([
                    'is_del' => 1,
                ], [
                    'item_id' => $this->validator->attributes['item_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'checktime_id' => SDMHelper::app()->form->getIsProcess($lockRow['lock_conditions']) ? null : $isWrite['checktime_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'form_id' => $isWrite['form_id']
                ]);
            }
        }


        return false;
    }

    /**
     * 更新锚点日期
     * @param array $postData
     * @throws \Exception
     */
    private function _updateAnchor()
    {
        $versionData = $this->_getVersionData();
        $checkTimeAnchorId = '';
        foreach ($this->postData as $k => $datum) {
            // 如果是锚点日期
            // 锚点日期不为空
            if (
                isset($versionData[$this->_getFieldId($k)]['is_anchor']) &&
                $versionData[$this->_getFieldId($k)]['is_anchor'] == 1 &&
                $datum
            ) {
                $checkTimeAnchorId = $this->_getFieldId($k);
                $attr = $this->validator->attributes;
                $res = Laminas::$serviceManager->itemPatientchecktime->EditAnchorDate($attr['item_id'], $attr['patient_id'], $checkTimeAnchorId, $datum);
                Event::trigger(EventEnum::BEFORE_EVENT_SUBMIT_ANCHOR_TIME, [$this, $datum]);
                if ($res === true) {
                    break;
                }

                throw new InvalidArgumentException("$res [e-sr-ua]");
            }
        }
        $attr = $this->validator->attributes;
        $checktimeArr = Laminas::$serviceManager->itemPatientchecktime->fetchCol('checktime_id',['item_id'=>$attr['item_id'],'patient_id'=>$attr['patient_id'],'anchor_id'=>$checkTimeAnchorId]);
        Laminas::$serviceManager->projectExceedswindow->saveExceedswindowFormAction($attr['item_id'], $attr['patient_id'],$checktimeArr);
    }

    /**
     * 更新关联状态
     * 更新表单完成状态
     */
    public function _updateRelationStatus(int $formId = null, ?int $status = null)
    {
        // 评分功能管理员填写的数据要更新表单颜色
        if ($this->scenario == self::SCENARIO_USING_SCORE) {
            // 非管理员 return
            if (!in_array(Laminas::$serviceManager->identity->getId(), Laminas::$serviceManager->itemForm->getUsingScoreUser(true))) {
                return;
            }
        }

        $hasData = Laminas::$serviceManager->patientForm->memoryCache()->fetchOne([
            'where' => [
                'form_id' => $formId ?: $this->validator->attributes['form_id'],
                'item_id' => $this->validator->attributes['item_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'checktime_id' => $this->validator->attributes['checktime_id'],
                'is_del' => 0
            ]
        ]);
        $id = $hasData['id'] ?? false;

        $fieldData = [
            'form_id' => $formId ?: $this->validator->attributes['form_id'],
            'item_id' => $this->validator->attributes['item_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'is_complete' => $status === null ? $this->getIsComplete($this->postData) : $status,
            'start_at' => $this->_getStartAt(),
            'end_at' => $this->_getEndAt(),
            'is_del' => 0
        ];

        // 不知道是干什么用的字段。其他人用得到。
        // 如果没传就不管, 防止不同入口编辑把值给顶掉了
        if ($this->validator->attributes['patientchecktime_id']) {
            $fieldData = ArrayHelper::merge($fieldData, [
                'patientchecktime_id' => $this->validator->attributes['patientchecktime_id']
            ]);
        }

        $condition = ['id' => ($hasData['id'] ?? false)];

        if ($hasData) {
            if (!$this->getIsProcess()) {
                Laminas::$serviceManager->patientForm->update($fieldData, $condition);
            }
        } else {
            $id = Laminas::$serviceManager->patientForm->save($fieldData);
        }

        if ($status !== null) {
            return $id;
        }
        // 一对多, 和贯穿全程都处理
        // 【新系统】所有一对多表单，每条数据，都是要全部填写，才算完成（目前只调了贯穿类型的，其他类型的请补充处理）--美
        // https://e.gitee.com/yikeen_project/dashboard?issue=I80JM3
        if ($this->getIsProcess()) {
            $this->handleProcess($fieldData);
        } elseif ($this->h()->form->getType($this->formId) == Form::FORM_TYPE_MULTI) {
            $this->updateCompleteStatus();
        }
    }

    /**
     * 获取检查点开始日期
     * @return false|int
     */
    private function _getStartAt()
    {
        $startTime = $this->_getCheckTimeData()['start_time'] ?? null;

        if ($startTime === null) {
            return false;
        }

        if ($startTime) {
            return strtotime($this->_getTimeUnit($startTime, $this->_getCheckTimeData()['time_unit']));
        }

        throw new InvalidArgumentException("检查点开始日期不能是 {$startTime}");
    }

    /**
     * 获取检查点结束日期
     * @return false|int
     */
    private function _getEndAt()
    {
        $endTime = $this->_getCheckTimeData()['end_time'] ?? null;

        if ($endTime === null) {
            return false;
        }

        if ($endTime) {
            return strtotime($this->_getTimeUnit($endTime, $this->_getCheckTimeData()['time_unit']));
        }

        throw new InvalidArgumentException("检查点开始日期不能是 {$endTime}");
    }

    /**
     * 0天 1周 2月 3年
     * @param $val
     * @param int $unit
     * @return string|void
     */
    private function _getTimeUnit($val, int $unit)
    {
        if ($unit == 0) {
            return "+$val day";
        } elseif ($unit == 1) {
            return "+$val week";
        } elseif ($unit == 2) {
            return "+$val month";
        } elseif ($unit == 3) {
            return "+$val year";
        }
    }

    /**
     * 修改checkTime表操作人id.
     * 石锐用到的
     */
    private function updateOperateUserId()
    {
        Laminas::$serviceManager->itemPatientchecktime->update([
            'update_user_id' => Laminas::$serviceManager->identity->getId(),
            'update_time' => time(),
        ], [
            'item_id' => $this->validator->attributes['item_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id']
        ]);
    }

    /**
     * 通过回复质疑来编辑表单内容。
     * @throws \Exception
     */
    public function editFormByQuestion()
    {
        $form = SDMHelper::app()->setAttributes([
            'form_id' => $this->validator->attributes['form_id']
        ])->form;

        if ( $form->getType() == Form::FORM_TYPE_MULTI && $form->getGroupId() == FormGroup::NORMAL_OCR ) {
            $this->editNormalOcrShareImageByQuestion();
        }else {
            $this->isEditFormByQuestion = true;
            $this->contentPrimaryKey = (int)$this->validator->attributes['id'];
            $this->event = EventEnum::EVENT_FORM_CONTENT_EDIT_BY_QUESTION;
            $this->setPostData($this->validator->attributes);

            return (new Middleware($this))->beforeMiddleware([
                Preprocessing::class,  // 提交的数据预处理,
                ValidPostData::class,  // 验证提交的数据是否正确
                ValidIsOcr::class,  // 验证遗嘱类型表单是否有识别数据
                ValidIsAnnexLock::class  // 验证是否锁定
            ])->afterMiddleware([
                HandleFormImages::class,
            ])->execute($this->handle(function() {

                $this->initLoggerData();

                // Db::beginTransaction();

                $this->getExecuteCore();

                $this->logger->flush();

                // Db::commit();
            }));
        }
    }

    /**
     * 通过回复质疑沟通的图片质疑修改常规识别表单的共享图片信息
     * @return void
     * @throws \Exception
     */
    public function editNormalOcrShareImageByQuestion()
    {
        $this->event =  EventEnumV2::getVal(EventEnumV2::EVENT_MULTI_SHARE_FORM_UPDATE_IMAGE);
        $shareFieldId = SDMHelper::app()->form->getShareFormField($this->validator->attributes['form_id'])['id'];

        Db::beginTransaction();

        $images = StringHelper::jsonDecode($this->validator->attributes[$shareFieldId], true);

        // 处理图片地址
        array_walk($images, function(&$image) {
            $image['url'] = DataHelper::handleImageSrc($image['url']);
        });

        // 共享表单id集合
        $shareFormIdList = ArrayHelper::getColumn(SDMHelper::app()->form->getGcoGroupForm($this->validator->attributes['form_id']), 'id');

        // 获取当前表单所有的共享图片列表
        $shareImgList = Laminas::$serviceManager->patientFormContentImg->fetchCol('img_src', [
            'item_id' => $this->validator->attributes['item_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'form_id' => $shareFormIdList,
            'is_del' => 0
        ]);

        $updateImageUrlList = array_column($images, 'url');
        $intersectImgList = array_intersect($shareImgList, $updateImageUrlList);

        // 先删除相同地址之外的图片
        Laminas::$serviceManager->patientFormContentImg->upDelState(ArrayUtils::merge([
            'item_id' => $this->validator->attributes['item_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'form_id' => $shareFormIdList,
        ], empty($intersectImgList) ? [] : [
            new NotIn('id', array_keys($intersectImgList)),
        ]), 1);

        // 新增不同地址的图片
        $diffImgList = array_diff($updateImageUrlList, $shareImgList);

        if(!empty($diffImgList)) {
            foreach ($diffImgList as $addImgIndex => $addImgUrl) {
                $addImg = $images[$addImgIndex];

                $save_annex = [
                    'item_id' => $this->validator->attributes['item_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'form_id' => $this->validator->attributes['form_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'img_src' => $addImgUrl,
                    'img_name' => $addImg['name'] ?? '',
                    'img_type' => PatientFormContentImg::IMG_TYPE_NORMAL,
                    'content_id' => 0, // 一对多这种的没有id,
                    'field_id' => $shareFieldId,
                    'gco_pool' => SDMHelper::app()->form->getGcoPool($this->validator->attributes['form_id']),
                    'info_collect_type' => SDMHelper::app()->form->getInfoCollectType($this->validator->attributes['form_id']),
                    'is_form_ocr' => 1
                ];
                if(!empty($addImg['collect_annex_id'])){
                    $save_annex['collect_annex_id'] = $addImg['collect_annex_id'];
                }
                Laminas::$serviceManager->patientFormContentImg->insert($save_annex);
            }
        }

        foreach ($shareFormIdList as $shareFormId) {
            if (SDMHelper::app()->form->getIdentificationEdit($shareFormId) == 0) {
                $this->_updateRelationStatus($shareFormId, 0);
            }
        }

        $this->logger->setEvent($this->event)->setPostOriginData($this->validator->attributes)->setPostData($this->validator->attributes)->flush($this->validator->attributes);

        Db::commit();

        // 异步处理工作信息
        Laminas::$serviceManager->swTaskClient->send([
            'svName' => 'projectPatientwork',
            'methodName' => 'updatePatientworkData',
            'params' => [
                'item_id' => $this->validator->attributes['item_id'],
                'itemsig_id' => $this->validator->attributes['itemsig_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'checktime_id' => $this->validator->attributes['checktime_id'],
                'form_id' => $this->validator->attributes['form_id'],
                'user_id' => Laminas::$serviceManager->identity->getId(),
                'content_id' => $this->contentPrimaryKey,
            ]
        ]);

    }

    /**
     * 编辑受试者表单
     * @param $postData
     * @return mixed
     */
    public function editForm($postData)
    {
        $this->setPostData($postData);

        // 初始化表单内容主键id
        $this->contentPrimaryKey = (int)$this->validator->attributes['id'];

        if (!$this->event) {
            $this->event = EventEnum::EVENT_FORM_CONTENT_EDIT;
        }

        // 判断的是主项目是否开启edc
        if (EdcHelper::isEdc($this->h()->item->getFid($this->validator->attributes['item_id'])) && SDMHelper::app()->setAttributes(['content_id' => $this->contentPrimaryKey])->formContent->getIsEdcLock()) {
            throw new InvalidArgumentException('此表单在EDC已锁定, 无法提交。');
        }

        return (new Middleware($this))
            ->beforeMiddleware([
                ValidPermission::class,
                Preprocessing::class,  // 提交的数据预处理,
                ValidPostData::class,  // 验证提交的数据是否正确
                ValidIsOcr::class,  // 验证遗嘱类型表单是否有识别数据
                ValidIsAnnexLock::class  // 验证是否锁定
            ])->afterMiddleware([
                HandleFormImages::class,
                HandleLogic::class,
                HandleAutoReplyQuestion::class,
            ])->afterTransactionMiddleware([
                HandlePatientWorkBatch::class, //异步处理访视进度情况信息
                HandleNormalFormOverField::class, //异步处理常规识别完成表单字段数量信息
                HandleCmFormPatientDrug::class //异步处理CM表单受试者药物信息
            ])->execute($this->handle($this->_edit()));
    }

    /**
     * @note 处理表单申请解锁
     * @return mixed
     */
    public function handleApplyUnlockForm()
    {
        $this->event = EventEnumV2::getVal(EventEnumV2::EVENT_FORM_CONTENT_CONFIRM_APPLY_UNLOCK);

        //初始化表单内容主键id
        $this->contentPrimaryKey =(int)$this->validator->attributes['id'];
        $this->isEditFormByQuestion = true;

        return (new Middleware($this))
            ->afterMiddleware([
                HandleFormImages::class,
            ])->execute($this->handle(function () {
                //更新表单patientFormContent内容信息
                Laminas::$serviceManager->patientFormContent->update(['data'=>json_encode($this->validator->attributes)],['id'=>$this->validator->attributes['id']]);

                // 更新化验单, 计划外检查点上传附件
                $this->_updateAttach();

                // 记录替换日志
                $this->initLoggerData();

                $this->logger->flush();
            }));
    }

    private function beforeCommit()
    {
        foreach ($this->beforeCommit as $callable) {
            $callable();
        }
    }


    public function setBeforeCommit(\Closure $callable)
    {
        $this->beforeCommit[] = $callable;
        return $this;
    }

    private function _edit(): \Closure
    {
        return function () {

            // 初始化日志数据
            $this->initLoggerData();

            // Db::beginTransaction();

            $this->getExecuteCore();

            Event::trigger(EventEnum::AFTER_EVENT_SUBMIT_PATIENT_FORM, [$this]);


            $this->beforeCommit();

            $this->logger->flush();

            $this->resubmit();

            // Db::commit();
            //运行逻辑核查公式自动发送质疑
            $this->logicexecute($this->contentPrimaryKey);

            return true;
        };
    }

    private function resubmit()
    {
        if(isset($this->validator->attributes['is_import'])) {
            return true;
        }
        $post_keys   = $this->validator->attributes['only_keys1'];
        $redis       = Laminas::$serviceManager->redisExtend->getRedisInstance();
        if(!$redis->exists($post_keys)){
            throw new InvalidArgumentException('重复提交!');
        }
        $redis->del($post_keys);  //验证完销毁
    }

    /**
     * Notes:表单提交时调用逻辑核查质疑公式
     * @param
     * @return
     * @author haojinhua
     * @date 2025-05-06
     */
    public function logicexecute($contentPrimaryKey){
        $compare_data = [];
        $note_arr = isset($this->validator->attributes['note'])&& !empty($this->validator->attributes['note']) ? json_decode($this->validator->attributes['note'],true) : [];
        $compare_data = array_column($note_arr,'filed_id');

        //当前检查点 表单变量名
        $checktime_varname = Laminas::$serviceManager->itemChecktime->getOneFieldVal('var_name',[
            'is_del' => 0,
            'id' => $this->checktimeId,
        ]);
        $form_varname = Laminas::$serviceManager->itemForm->getOneFieldVal('var_name',[
            'is_del' => 0,
            'id' => $this->formId,
        ]);
        $logic_where = [
            'is_del' => 0,
            'item_id' => $this->itemId,
        ];

        if($checktime_varname && $form_varname){
            $logic_string = $checktime_varname.'.'.$form_varname;
            $logic_where[] = new Like('expression', "%{$logic_string}%");
        }

        $query = Laminas::$serviceManager->itemPatientFormLogic->fetchAll([
            'where' => $logic_where,
        ]);

        foreach($query as $ex){
            $generator = unserialize($ex['generator']);
            $app = new CheckLogicApplication();
            $app::$debugMode = false;
            $app->setItemId($ex['item_id'])
                ->setPatientId($this->patientId)
                ->setContentId($contentPrimaryKey)
                ->setDatanote($compare_data)
                ->setGenerator($generator)
                ->execute();
        }

        return true;
    }

    private function setContentUpdatedFields()
    {
        // 不开启edc就跳过
        // 判断的是主项目是否开启edc
        if (!EdcHelper::isEdc($this->h()->item->getFid($this->itemId))) {
            return;
        }

        // 【EDC】EDC中一对多表单，按每一条数据来控制，当在EDC中进行锁定后，SDM这边单条数据将只开放数据查看权。SDM中新增权，不进行控制--美
        //https://e.gitee.com/yikeen_project/dashboard?issue=I9AEHF
        $isLock = SDMHelper::app()->setAttributes(['content_id' => $this->contentPrimaryKey])->formContent->getIsEdcLock();
        if ($isLock) {
            throw new InvalidArgumentException('此表单在EDC已锁定, 无法提交。');
        }

        $callable = function ($id, $autoReply = false, $pointer = null) {
            // 被关联的质疑自动关闭的时候要加一个自动回复
            if ($autoReply === true) {
                Laminas::$serviceManager->itemPatientFormLogicErrorQuery->save([
                    'content' => '上级菜单数据更新!',
                    'error_id' => $id,
                    'platform' => 1,
                    'is_reply' => 1,
                    'pointer_id' => $pointer,
                    'item_id' => $this->itemId,
                    'create_user_id' => 0 // 系统
                ]);
            }

            // 删除质疑
            Laminas::$serviceManager->itemPatientFormLogicError->update(['is_closed' => 1], ['id' => $id]);
            Laminas::$serviceManager->itemPatientFormLogicErrorLog->update(['is_closed' => 1], ['error_id' => $id]);
        };
        $originData = $this->getContentData();
        foreach ($this->postData as $k => $data) {
            if (DataHelper::isField($k)) {
                // 有数据修改再解锁
                if (is_array($data)) {
                    sort($data);
                }

                if (is_array($originData[$k])) {
                    sort($originData[$k]);
                }

                if (!isset($originData[$k]) || $data != $originData[$k]) {
                    $this->updatedFields[$k] = $originData[$k];
                }
            }
        }

        // 先注释掉
        if ($this->updatedFields) {
            foreach ($this->updatedFields as $field => $v) {
                $childError = Laminas::$serviceManager->itemPatientFormLogicErrorPointer->fetchAll([
                    'where' => [
                        'patient_id' => $this->patientId,
                        'checktime_id' => $this->checktimeId,
                        'form_id' => $this->formId,
                        new Like('prop', "%{$field}%"),
                        new Operator('prop', Operator::OP_NE, $field),
                        'is_del' => 0
                    ]
                ]) ?: [];

                foreach ($childError as $error) {
                    $callable($error['error_id'], true, $error['id']);
                }

                // 切换成不检查要移除手动填写的质疑
                if (isset(SDMHelper::app()->form->getVersionData($this->formId)[DataHelper::getFieldId($field)]['var_name']) && SDMHelper::app()->form->getVersionData($this->formId)[DataHelper::getFieldId($field)]['var_name'] == 'ISCHECK') {
                    // 不检查
                    if ($this->postData[DataHelper::getFieldId($field)] == '9') {
                        $childError = Laminas::$serviceManager->itemPatientFormLogicErrorPointer->fetchAll([
                            'where' => [
                                'patient_id' => $this->patientId,
                                'checktime_id' => $this->checktimeId,
                                'form_id' => $this->formId,
                                new Operator('prop', Operator::OP_EQ, 'sdtx'),
                                'is_del' => 0
                            ]
                        ]) ?: [];

                        foreach ($childError as $error) {
                            $callable($error['error_id'], true, $error['id']);
                        }
                    }
                }
            }
        }

        //判断是否操作过SDV或者REVIEW
        $sdv_review_where = [
            'is_del' => 0,
            'patient_id' => $this->patientId,
            'form_id' => $this->formId,
            'content_id' => $this->contentPrimaryKey,
            [
                'or' => [
                    'is_sdv' => 1,
                    'is_review' => 1,
                ]
            ]
        ];
        $sdv_review_count = Laminas::$serviceManager->projectPatientworkinfo->getCount($sdv_review_where);
        unset($sdv_review_where);
        if (empty($sdv_review_count)) {
            return;
        }
        unset($sdv_review_count);

        $has = Laminas::$serviceManager->patientFormContentUpdated->fetchOne([
            'where' => [
                'content_id' => $this->contentPrimaryKey,
                'form_id' => $this->formId
            ]
        ]);
        if ($has) {
            $update_fields = !empty($this->updatedFields) ? json_encode($this->updatedFields) : NULL;
            Laminas::$serviceManager->patientFormContentUpdated->update(['fields' => json_encode($this->updatedFields), 'is_del' => 0], ['id' => $has['id']]);
            unset($update_fields);
        } else {
            if(!empty($this->updatedFields)) {
                Laminas::$serviceManager->patientFormContentUpdated->insert([
                    'item_id' => $this->validator->attributes['item_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'form_id' => $this->validator->attributes['form_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'fields' => json_encode($this->updatedFields),
                    'content_id' => $this->validator->attributes['id'],
                    'is_multi' => $this->getItemFormData()['type'] == 1 ? 1 : 0
                ]);
            }
        }
    }

    private function pushMessage()
    {
        if ($this->h()::isUnitTest() === true) {
            return;
        }

        // is_edc
        // 使用 EdcHelper::isEdc 代替??
        $isEdc = Laminas::$serviceManager->itemInfo->memoryCache()->fetchOne([
                'where' => [
                    'id' => Laminas::$serviceManager->itemInfo->memoryCache()->fetchOne([
                            'where' => ['id' => $this->validator->attributes['item_id']]
                        ])['fid'] ?? 0
                ]
            ])['is_edc'] ?? false;

        if (!$isEdc) {
            return;
        }
    }

    /**
     * 表单内容解锁
     */
    private function contentUnlock()
    {
        if ($this->h()->formContent->getIsLock($this->contentPrimaryKey)) {
            $originData = $this->getContentData();
            foreach ($this->postData as $k => $data) {
                if (DataHelper::isField($k)) {
                    // 有数据修改再解锁
                    if (is_array($data)) {
                        sort($data);
                    }

                    if (is_array($originData[$k])) {
                        sort($originData[$k]);
                    }

                    if (!isset($originData[$k]) || $data != $originData[$k]) {
                        $this->h()->formContent->unlock($this->contentPrimaryKey);
                        break;
                    }
                }
            }
        }
    }

    protected function getEditPostData()
    {
        if (isset($this->postData['error_id'])) {
            $originData = StringHelper::jsonDecode(Laminas::$serviceManager->patientFormContent->fetchOne([
                'where' => [
                    'id' => $this->validator->attributes['id']
                ]
            ])['data']);
            $this->postData['reason_logic'] = $originData['reason_logic'];
            $this->postData['reason_logic'][$this->postData['error_id']] = $this->postData['reason'];
        }

        unset($this->postData['error_id']);

        return $this->postData;
    }


    /**
     * 获取图文识别数据
     * @return array
     */
    public function getAnnexData(): array
    {
        $patientFormContent = SDMHelper::app()->setAttributes(['contentId' => $this->contentPrimaryKey])->formContent;
        if ($this->getAnnexLock()) {
            $allCheckName = Laminas::$serviceManager->itemCheckname->fetchAll([
                'order' => ['checkname_order'],
                'columns' => ['name as item_name', 'max_val as reference_range_max', 'min_val as reference_range_min', 'id', 'unit','min_symbol','max_symbol'],
                'where' => [
                    'item_id' => $this->validator->attributes['item_id'] ?? $patientFormContent->getItemId(),
                    'category_id' => $this->h()->form->getCheckListId($this->formId ?? $patientFormContent->getFormId()),
                    'is_del' => 0
                ]
            ]);

            $c = ArrayHelper::index(Laminas::$serviceManager->itemIdentificationresultchange->fetchAll([
                'where' => [
                    'form_id' => $this->validator->attributes['form_id'] ?? $patientFormContent->getFormId(),
                    'lock_state' => 1,
                    'patient_id' => $this->validator->attributes['patient_id'] ?? $patientFormContent->getPatientId(),
                    'item_id' => $this->validator->attributes['item_id'] ?? $patientFormContent->getItemId(),
                    'checktime_id' => $this->validator->attributes['checktime_id'] ?? $patientFormContent->getChecktimeId(),
                    'itemsig_id' => $this->validator->attributes['itemsig_id'] ?? $patientFormContent->getItemsigId(),
                    'is_del' => 0,
                    'patientformcontent_id' => $this->contentPrimaryKey,
                ]
            ]), 'item_checkname_id');

            foreach ($allCheckName as &$checkName) {
                if (isset($c[$checkName['id']])) {
                    $checkName = $c[$checkName['id']];
                    $checkName['is_identification'] = $checkName['is_identification'] == 0;
                    $checkName['order'] = 1;
                } else {
                    $checkName['is_identification'] = false;
                    $checkName['order'] = 0;
                }
            }

            ArrayHelper::multisort($allCheckName, 'order', SORT_DESC);
            $res = array_values($allCheckName);
            //获取该副项目设置的采集时间类型
            $dateType = 1;
            if(!empty($this->validator->attributes['item_id'])){
                $dateType = Laminas::$serviceManager->itemCheckdate->getOneFieldVal('date_type',[
                    'is_del' => 0,
                    'item_id' => $this->validator->attributes['item_id'],
                ]);
                $dateType = empty($dateType) ? 1 : $dateType;
            }
            $max_symbol = [
                0=>'',
                1=>'<',
                2=>'≤'
            ];
            $min_symbol = [
                0=>'',
                1=>'>',
                2=>'≥'
            ];

            foreach ($res as &$value) {
                $value['reference_range_max'] = $value['reference_range_max'] === null ? '' : $max_symbol[$value['max_symbol']].$value['reference_range_max'];
                $value['reference_range_min'] = $value['reference_range_min'] === null ? '' : $min_symbol[$value['min_symbol']].$value['reference_range_min'];
                unset($value['max_symbol'],$value['min_symbol']);
            }
            unset($dateType);
            return $res;
        }

        return [];
    }

    /**
     * 判断图文识别是否已经锁定
     * @return bool
     */
    public function getAnnexLock(): bool
    {
        if (!$this->contentPrimaryKey) {
            return false;
        }

        $patientFormContent = SDMHelper::app()->setAttributes(['contentId' => $this->contentPrimaryKey])->formContent;

        if (SDMHelper::app()->form->getGroupId($this->validator->attributes['form_id'] ?? $patientFormContent->getFormId()) != FormGroup::CHECK_OCR) {
            return false;
        }

        return (bool)Laminas::$serviceManager->itemPatientworkannex->fetchOne([
            'columns' => ['id'], // 优化性能
            'where' => [
                'form_id' => $this->validator->attributes['form_id'] ?? $patientFormContent->getFormId(),
                'lock_state' => 1,
                'patient_id' => $this->validator->attributes['patient_id'] ?? $patientFormContent->getPatientId(),
                'item_id' => $this->validator->attributes['item_id'] ?? $patientFormContent->getItemId(),
                'checktime_id' => $this->validator->attributes['checktime_id'] ?? $patientFormContent->getCheckTimeId(),
                'itemsig_id' => $this->validator->attributes['itemsig_id'] ?? $patientFormContent->getItemsigId(),
                'is_del' => 0,
                'formcontent_id' => $this->validator->attributes['content_id'] ?? $this->contentPrimaryKey,
            ]
        ]);
    }

    /**
     * 图文识别是否正在申请解锁
     * @return bool
     * @throws \Exception
     */
    public function getAnnexIsWaitingUnlock(): bool
    {
        if ($this->h()->form->getGroupId($this->formId) == FormGroup::NORMAL_OCR && !$this->scenario && is_numeric($this->checktimeId)) {
            return $this->h()->formContent->getIsWaitingUnLock($this->patientId, $this->checktimeId, $this->formId);
        }

        $contentId = $this->contentPrimaryKey ?: ( Laminas::$serviceManager->patientFormContent->fetchOne([
                'where' => [
                    'form_id' => $this->validator->attributes['id'],
                    'item_id' => $this->validator->attributes['item_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                ]
            ])['id'] ?? false );

        if (!$contentId) {
            return false;
        }

        $query = Laminas::$serviceManager->patientFormUnlock->fetchOne([
            'where' => [
                'content_id' => $contentId,
            ]
        ]);

        if (!$query) {
            return false;
        }

        if ($query['is_del'] == 0) {
            return true;
        }

        if ($query['is_del'] == 1 && $query['is_confirm'] == 1) {
            return false;
        }

        return false;
    }

    /**
     * 验证是否能修改随机分层
     * @param array $versionData
     * @return void
     */
    private function validCanUpdateRandomGroup(array $versionData): void
    {
        // 研究分层字段的id
        $fieldId = ArrayHelper::index($versionData, 'var_name')['RANDOM_GROUP_SYSTEM']['id'] ?? false;
        if (!$fieldId) {
            $fieldId = ArrayHelper::index($versionData, 'var_name')['RANGCA']['id'] ?? false;
        }

        $patientData = Laminas::$serviceManager->patient->fetchOne([
            'where' => ['id' => $this->validator->attributes['patient_id']]
        ]);

        $randomDetails = Laminas::$serviceManager->itemRandomdetails->getRandomdetailsNumberPop(
            $this->validator->attributes['item_id'] ?? $_POST['item_id'],
            $this->validator->attributes['itemsig_id'] ?? $_POST['itemsig_id'],
            $this->validator->attributes['patient_id'] ?? $_POST['patient_id'],
        );

        $detailsData = ArrayHelper::index($randomDetails ?: [], 'id') ?? false;

        $levelId = $detailsData[$this->validator->attributes[$fieldId]]['rand_number']['randgroup_id'] ?? false;

        if ($patientData['randgroup_id'] !== $levelId) {
            if ($patientData['randgroup_id']) {
                $cid = Laminas::$serviceManager->itemChecktime->fetchAll([
                    'columns' => ['id'],
                    'where' => ['random_id' => $patientData['random_id']]
                ]);

                $allCheckId = ArrayHelper::getColumn($cid, 'id');

                // 如果写过当前检查点下的任意表单, 就不让切换。
                if (
                    Laminas::$serviceManager->patientFormContent->getCount([
                        'patient_id' => $this->validator->attributes['patient_id'],
                        'checktime_id' => array_values($allCheckId),
                        'item_id' => $this->validator->attributes['item_id'],
                        'itemsig_id' => $this->validator->attributes['itemsig_id']
                    ]) > 0
                ) {
                    throw new InvalidArgumentException(" `{$detailsData[$patientData['randgroup_id']]['group_name']}` 下已产生工作数据。不可切换研究分层。");
                }
            }
        }

    }

    /**
     * 验证是否能修改手写研究分层
     * @param int $randomGroupKey 随机分组的表单字段id
     * @param string $groupValue 当前填写的研究分层的值
     * @return void
     * @throws \Exception
     */
    private function validCanUpdateRandomGroupCustom(int $randomGroupKey, string $groupValue): void
    {
        $content = Laminas::$serviceManager->patientFormContent->fetchOne([
            'where' => ['id' => $this->validator->attributes['id']]
        ]);

        if (!$content) {
            throw new \Exception("验证研究分层出现了一个问题。没有找到对应的content数据");
        }

        $data = StringHelper::jsonDecode($content['data']);

        $originLevel = $data[$randomGroupKey];

        if (!$originLevel || $originLevel == $groupValue) {
            return;
        }

        $checkTime = array_values(Laminas::$serviceManager->itemChecktime->fetchCol('id', ['random_id' => $originLevel]));

        $writeCount = Laminas::$serviceManager->patientFormContent->getCount([
            'patient_id' => $this->validator->attributes['patient_id'],
            'checktime_id' => array_values($checkTime),
            'item_id' => $this->validator->attributes['item_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'is_del' => 0
        ]);

        $levelDataName = Laminas::$serviceManager->itemRandom->fetchOne(['where' => ['id' => $originLevel]])['random_name'] ?? '当前研究分层';

        $groupName = Laminas::$serviceManager->itemFormField->fetchOne(['where' => ['id' => $randomGroupKey]])['name'] ?? '方案分组';
        if ($writeCount > 0) {
            throw new InvalidArgumentException("`{$levelDataName}` 下已产生工作数据。不可切换{$groupName}。");
        }

    }

    /**
     * 更新随机分组
     * @throws \Exception
     */
    private function _updateRandomGroup()
    {
        if ($this->h()->form->getGroupId($this->formId) != FormGroup::RANDOM_GROUP) {
            return;
        }

        $versionData = $this->_getVersionData();

        $previewData = Laminas::$serviceManager->itemForm->setRequestParams($this->validator->attributes)->getPreviewConfig($this->validator->attributes['form_id']);

        // 获取变量名
        $getRandomContent = function ($k) use ($previewData, $versionData) {
            $field = explode('-', $k);
            if (count($field) > 1) {
                array_shift($field);
            } else {
                return $versionData[$k]['var_name'] ?? false;
            }

            if (count($field) > 1) {
                $attribute = ArrayHelper::getValue($previewData, implode('.', $field))[0]['var_name'] ?? '';
                if (stripos($attribute, 'CONTENT') !== false) {
                    return $attribute;
                }
            }

            return false;
        };


        $randomGroupValue = $randomGroupKey = null;

        // 是否已经更新过随机分组日期。
        // 如果有随即日期字段, 并且写值了就传。
        $isHasRandomDateField = false;

        foreach ($this->postData as $k => $datum) {
            // 如果是手写随机号, 研究分层需要存起来传过去
            if (in_array($getRandomContent($k), ['RANDOM_GROUP_CUSTOM', 'RANGC'])) {
                $randomGroupValue = $datum;
                $randomGroupKey = $k;
            }

            if (in_array($getRandomContent($k), ['RANDOM_GROUP_CUSTOM', 'RANGC'])) {
                if (!$datum) {
                    throw new InvalidArgumentException("请选择正确的研究分层。");
                }

            } elseif ($getRandomContent($k) == 'RANDOM_GROUP_SYSTEM' || $getRandomContent($k) == 'RANGCA') { // 系统的研究分层
                if (!$datum) {
                    throw new InvalidArgumentException("请选择研究分层。");
                }
            } elseif ( (SDMHelper::app()->getFormHelper()->getSystemRandomFieldId() && $k == $this->systemRandomFieldKey ) || $getRandomContent($k) == 'RANDOM_GROUP_SYSTEM_CONTENT') { // 系统分配
                if (!$datum) {
                    throw new InvalidArgumentException("请选择正确的随机号。");
                }

                if ($this->event === EventEnum::EVENT_FORM_CONTENT_EDIT) {
                    $this->validCanUpdateRandomGroup($versionData);
                }

                $res = Laminas::$serviceManager->itemRandomdetails->setRandomdetailsNumber($datum, $this->validator->attributes['itemsig_id'], $this->validator->attributes['patient_id']);

                if ($res !== true) {
                    throw new InvalidArgumentException("请重新选择随机号");
                }

            } elseif ($getRandomContent($k) == 'RANDOM_GROUP_CUSTOM_CONTENT') { // 手动填写

                if (!$datum) {
                    throw new InvalidArgumentException("请输入正确的随机号");
                }

                // 手写先判断能否切换研究分层
                if ($this->event === EventEnum::EVENT_FORM_CONTENT_EDIT) {
                    $this->validCanUpdateRandomGroupCustom($randomGroupKey, $randomGroupValue);
                }

                $isUsed = Laminas::$serviceManager->itemRandomdetails->fetchOne([
                    'where' => (new Where())
                        ->nest()
                        ->equalTo('is_del', 1)->or->equalTo('is_use', 1)
                        ->unnest()
                        ->equalTo('item_id', $this->validator->attributes['item_id'])
                        ->equalTo('item_sign_id', $this->validator->attributes['itemsig_id'])
                        ->equalTo('randomdetails_name', $datum)
                ]);

                if ($isUsed) {
                    throw new InvalidArgumentException('同方案分组被调用/作废');
                }

                $hasRandomNumber = Laminas::$serviceManager->patient->fetchOne([
                    'where' => (new Where())
                        ->equalTo('item_id', $this->validator->attributes['item_id'])
                        ->equalTo('itemsig_id', $this->validator->attributes['itemsig_id'])
                        ->equalTo('random_number', $datum)
                ]);

                if ($hasRandomNumber && $hasRandomNumber['id'] != $this->validator->attributes['patient_id']) {
                    throw new InvalidArgumentException("随机号重复啦!!!");
                }

                Laminas::$serviceManager->patient->update([
                    'random_number' => $datum
                ], ['id' => $this->validator->attributes['patient_id']]);

                if ($randomGroupValue) {
                    Laminas::$serviceManager->itemRandomdetails->setRandom($randomGroupValue, $this->validator->attributes['itemsig_id'], $this->validator->attributes['patient_id'], $datum);
                }
            }

            // 如果有随机日期, 并且有值。
            if (DataHelper::isField($k) && $this->h()->form->field->getVarName($k) === 'RANDDAT') {
                $isHasRandomDateField = true;
                if ($datum) {
                    Event::trigger(EventEnum::BEFORE_EVENT_SUBMIT_RANDOM_TIME, [$this, strtotime($datum)]);
                }
            }
        }

        if ($isHasRandomDateField === false) {
            // 没随即日期字段就传一个时间戳。
            Event::trigger(EventEnum::BEFORE_EVENT_SUBMIT_RANDOM_TIME, [$this, time()]);
        }
    }

    /**
     * 获取 post key值的field id
     * @param $postField
     * @return string
     */
    private function _getFieldId($postField): string
    {
        return $this->_handlePostField($postField)[0] ?? '';
    }

    /**
     * 处理 post 字段名称
     * @param $postField
     * @return false|string[]
     */
    private function _handlePostField($postField)
    {
        return explode('-', $postField);
    }

    /**
     * 更新访视日期时间
     * @throws \Exception
     */
    private function _updateBookedTime()
    {
        $formVersion = $this->_getVersionData();

        foreach ($this->postData as $k => $v) {
            // 如果当前字段为访视日期字段
            if (isset($formVersion[$this->_getFieldId($k)]) && $formVersion[$this->_getFieldId($k)]['is_booked_time'] == 1) {
                $yesBookTime = !empty($v) ? strtotime($v) : NULL;
                //if ($yesBookTime = strtotime($v)) {
                Laminas::$serviceManager->itemPatientchecktime->update([
                    'yes_booked_time' => $yesBookTime
                ], [
                    'item_id' => $this->validator->attributes['item_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id']
                ]);
                //}
            }
        }
    }

    /**
     * 移除已经添加的数据
     * @param int $type
     * @param array $imgData
     */
    private function deleteAllAnnexFile(int $type, array $imgData = [])
    {
        $this->isScreen = 0;

        // 把补图的也算上
        $type = [$type, self::ANNEX_TYPE_REPLACEMENT_ORDER];

        $deleteId = Laminas::$serviceManager->itemPatientworkannex->fetchAll([
            'where' => [
                'annex_type' => $type,
                'is_del' => 0,
                'item_id' => $this->validator->attributes['item_id'],
                'itemsig_id' => $this->validator->attributes['itemsig_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'checktime_id' => $this->validator->attributes['checktime_id'],
                'researchstage_id' => $this->validator->attributes['stage_id'] ?? 0,
                'form_id' => $this->validator->attributes['form_id'],
                'category_id' => $this->getItemFormData()['checklist_id'],
                'formcontent_id' => $this->contentPrimaryKey,
            ]
        ]);

        foreach ($deleteId as $item) {
            // 如果这个字段是1, 说明已经被识别过了
            if ($item['change_type']) {
                $this->isScreen = 1;
            }

            // 锁定后的操作
            if ($this->isEditFormByQuestion === false && $this->getIsLockOperate()) {
                Laminas::$serviceManager->itemPatientworkannex->update(['is_lock_operate' => 1], ['id' => $item['id']]);
            }

            // 手动填写
            if ($item['annex_type'] == self::ANNEX_TYPE_SDTX) {
                $sdtxData = $this->getSdtxData();

                // 如果未填写手动填写数据, 就把所有的手动填写数据删除。
                if (!$sdtxData && $this->isReplacementOrder === false) {
                    // 清理好像是识别结果表
                    Laminas::$serviceManager->itemIdentificationresult->update(['is_del' => 1], [
                        'is_del' => 0,
                        'workannex_id' => $item['id'],
                    ]);

                    // 清理指标
                    Laminas::$serviceManager->itemIdentificationresultchange->update(['is_del' => 1], [
                        'is_del' => 0,
                        "FIND_IN_SET({$item['id']}, patientworkannex_id)",
                        'annex_type' => $type
                    ]);

                    // 清理附件。
                    Laminas::$serviceManager->itemPatientworkannex->update(['is_del' => 1], [
                        'is_del' => 0,
                        'id' => $item['id']
                    ]);
                } else {
                    $this->keepAnnex[] = Form::ATTACH_SDTX_ANNEX_PATH;
                    // 存储手动填写保存的图片主键
                    $this->sdtxAnnexID = $item['id'];
                }
            }
        }

        $originAnnexImg = ArrayHelper::getColumn($deleteId, 'annex_path');

        // 计划外检查
        if ($type == 2) {
            return ;
        }

        // 不动的图片
        $originAnnexImgStr = implode(',', $originAnnexImg);
        foreach ($imgData as $datum) {
            if (isset($datum['url']) && stripos($datum['url'], 'blob:') === false) {
                $parseUrl = parse_url($datum['url']);
                $path = explode('=', $parseUrl['query'])[1];
                if (stripos($path, '&') !== false) {
                    $path = strtok($path, '&');
                }

                if (stripos($originAnnexImgStr, $path) !== false) {
                    // 说明这张图片之前上传过了
                    // 上传过的图片不处理
                    $this->keepAnnex[] = $datum['url'];
                } else {
                    // 没上传过的图 就应该插入
                    $this->insertAnnexArray[] = $datum['url'];
                }
            }
        }

        // originAnnexImg 存储的是相对路径 好像有的数据有问题 存的是带域名的路径, 需要处理一下
        foreach ($originAnnexImg as $item) {
            $originalUrl = parse_url($item);
            $query = isset($originalUrl['query']) ? explode('=', $originalUrl['query'])[1] : '';
            if ($query) {
                $url = $query;
            } else{
                $url = $originalUrl['path'];
            }

            // 由于可能域名不一样, 转成字符串处理一下。
            $insertStr = $this->getInsertAnnexString();
            $keepStr = $this->getKeepAnnexString();
            if (stripos($insertStr, $url) === false && stripos($keepStr, $url) === false) {
                // 补单不允许删除图片
                if ($this->isReplacementOrder === true) {
                    throw new InvalidArgumentException('原图不允许删除', 10009);
                }
                // 表单图片中间表需要删除掉的
                $this->deleteFormContentImg($type, $item);

                // 需要被删除的附件
                $effect = Laminas::$serviceManager->itemPatientworkannex->update(['is_del' => 1], [
                    'annex_type' => $type,
                    'is_del' => 0,
                    'item_id' => $this->validator->attributes['item_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'researchstage_id' => $this->validator->attributes['stage_id'] ?? 0,
                    'form_id' => $this->validator->attributes['form_id'],
                    'category_id' => $this->getItemFormData()['checklist_id'],
                    'annex_path' => $item,
                    'is_lock_operate' => (int)$this->getIsLockOperate()
                ]);
            }

            if (!$insertStr && !$keepStr)  {
                $this->deleteAllWorkAnnex();
            }
        }

    }

    /**
     * 图片都被删除掉了, 或者选择了不检查, 则需要删除掉按时间展示的数据。
     * 选择了不检查, 手动填写的数据要进行清空。
     */
    private function deleteAllWorkAnnex()
    {
        $condition = [
            'item_id' => $this->validator->attributes['item_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'researchstage_id' => $this->validator->attributes['stage_id'] ?? 0,
            'form_id' => $this->validator->attributes['form_id'],
        ];

        Laminas::$serviceManager->itemPatientworkannex->update(['is_del' => 1], ArrayUtils::merge($condition, [
            'formcontent_id' => $this->contentPrimaryKey,
        ]));

        Laminas::$serviceManager->itemIdentificationresultchange->update(['is_del' => 1], ArrayUtils::merge($condition, [
            'patientformcontent_id' => $this->contentPrimaryKey,
        ]));
    }

    /**
     * 删除表单图片中间表附件
     * @param $type
     * @param string $path
     */
    private function deleteFormContentImg($type, string $path)
    {
        Laminas::$serviceManager->patientFormContentImg->update(['is_del' => 1], [
            'img_type' => $type,
            'is_del' => 0,
            'item_id' => $this->validator->attributes['item_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'form_id' => $this->validator->attributes['form_id'],
            'img_src' => $path
        ]);
    }

    /**
     * 将插入的附件数组转成字符串
     * @return string
     */
    private function getInsertAnnexString(): string
    {
        return implode(',', $this->insertAnnexArray);
    }

    /**
     * 将不变的附件数组转成字符串
     * @return string
     */
    private function getKeepAnnexString(): string
    {
        return implode(',', $this->keepAnnex);
    }

    /**
     * 根据变量名来判断是化验单还是计划外检查
     * 1 => 化验单, 2 => 计划外检查
     * @param $data
     * @return int
     */
    public function getFieldType($data): int
    {
        if ($data['type'] != FormField::FORM_FIELD_TYPE_UPLOAD_IMAGE) {
            return 0;
        }

        if ($data['var_name'] == 'CHECKIMG') {
            if ($this->getItemFormData()['group_id'] == FormGroup::CHECK_DO) {
                return self::ANNEX_TYPE_DO;
            }
            return 1;
        } elseif (in_array($data['var_name'], ['OUTPLANCHECK', 'OPCH'])) {
            return 2;
        }

        return 0;
    }

    /**
     * 更新上传附件
     */
    private function _updateAttach()
    {
        $isYc = $this->getIsYc();

        if (!in_array($this->h()->form->getGroupId($this->formId), [FormGroup::CHECK_OCR, FormGroup::CHECK_DO])) {
            return;
        }

        //支持化验单导入
//        if ($this->scenario === self::SCENARIO_EXCEL_IMPORT) {
//            return;
//        }

        $formVersion = $this->_getVersionData();

        // 已开具 并且不是补图
        if (in_array($isYc, [0, -1])) {
            $this->deleteAllWorkAnnex();
        }

        foreach ($this->postData as $k => $datum) {
            $type = 0;

            $field = $this->_getFieldId($k);

            if (isset($formVersion[$field])) {
                $type = $this->getFieldType($formVersion[$field]);
                // 计划外检查存到图片表
                if ($type == 2) {
                    $this->updateOutPlanCheckContentImg($datum, $k);
                }
            }

            // 手动填写
            if ($k === Form::ATTACH_SDTX) {
                $type = 3;
            }

            // 如果是化验单或者手动填写或者医嘱
            if (in_array($type, [1, 3, self::ANNEX_TYPE_DO])) {
                // 上传图片的数据
                $imgData = StringHelper::jsonDecode($datum) ?: [];

                // 清理旧数据
                $this->deleteAllAnnexFile($type, $imgData);

                if ($type == 3) {
//                    // 化验单手动填写, 需要向附件表插入个固定的附件
                    if ($k == Form::ATTACH_SDTX && isset($this->postData[Form::ATTACH_SDTX]) && $this->postData[Form::ATTACH_SDTX] != '[]') {
                        $imgData = [];
                        $imgData[] = [
                            'name' => Form::ATTACH_SDTX_ANNEX_TITLE,
                            'url' => Form::ATTACH_SDTX_ANNEX_PATH,
                        ];
                    }
                }

                // 没上传图片, 并且没有手动填写就跳过呗
                if (!$imgData) {
                    continue;
                }

                // 检查项id
                $categoryId = $this->getItemFormData()['checklist_id'];

                // 找模板需要将小项目id转换成大项目id
                $mainItemId = Laminas::$serviceManager->itemInfo->fetchOne(['where' => ['id' => $this->validator->attributes['item_id']]])['fid'] ?: $this->validator->attributes['item_id'];

                // 获取化验单类型
                $reportType = $this->getReportType($categoryId);

                if (in_array($this->getItemFormData()['group_id'], [FormGroup::CHECK_OCR, FormGroup::CHECK_DO])) {
                    // 识别结果模板数据
                    $imgTxtDiscernData = $this->getImgTxtDiscernData($this->validator->attributes['item_id'], $categoryId);
                }

                // 表单数据关联表
                $patientFormId = $this->h()->setAttributes(['patient_id' => $this->patientId])->patient->getPatientFormId($this->formId, $this->checktimeId);

                foreach ($imgData as $checkImgDatum) {

                    if (stripos($this->getInsertAnnexString(), $checkImgDatum['url']) === false && $checkImgDatum['url'] != Form::ATTACH_SDTX_ANNEX_PATH) {
                        continue;
                    }

                    $annexPath = $this->_getAnnexPath($checkImgDatum['url']);

                    // 识别附件表
                    $this->saveAnnex($type, [
                        'annex_title' => $checkImgDatum['name'],
                        'annex_path' => $annexPath,
                        'annex_type' => $this->getAnnexType($checkImgDatum['name'], $type), // 3是手动填写
                        'up_annex_date' => time(),
                        'is_del' => 0,
                        'item_id' => $this->validator->attributes['item_id'],
                        'itemsig_id' => $this->validator->attributes['itemsig_id'],
                        'patient_id' => $this->validator->attributes['patient_id'],
                        'checktime_id' => $this->validator->attributes['checktime_id'],
                        'researchstage_id' => $this->validator->attributes['stage_id'] ?? 0,
                        'form_id' => $this->validator->attributes['form_id'],
                        'patientchecktime_id' => $this->validator->attributes['checktime_id'],
                        'category_id' => $categoryId,
                        'ocr_id' => $imgTxtDiscernData['ocr_id'] ?? -1,
                        'patient_form_id' => $patientFormId,
                        'report_type' => $reportType,
                        'is_lock_operate' => $this->isEditFormByQuestion === true ? 0 :$this->getIsLockOperate(),
                        'formcontent_id' => $this->contentPrimaryKey,
                    ]);
                }
            }
        }
    }

    /**
     * @param string $name 附件名
     * @param int $type 附件类型
     * @return int
     */
    private function getAnnexType(string $name = '', int $type = 0): int
    {
        if ($this->isReplacementOrder === true) {
            return self::ANNEX_TYPE_REPLACEMENT_ORDER;
        }

        if ($this->getItemFormData()['group_id'] == FormGroup::CHECK_DO) {
            return self::ANNEX_TYPE_DO;
        }

        return $name == Form::ATTACH_SDTX_ANNEX_TITLE ? self::ANNEX_TYPE_SDTX : $type;
    }

    /**
     * 表单图片存入中间表
     * @param string $name
     * @param string $path
     * @param int $type
     */
    private function saveFormContentImg(string $name, string $path, int $type, $fieldId)
    {
        // 手动填写不存
        if ($type == 3) {
            return;
        }

        Laminas::$serviceManager->patientFormContentImg->save([
            'item_id' => $this->validator->attributes['item_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'form_id' => $this->validator->attributes['form_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'img_src' => $path,
            'img_name' => $name,
            'img_type' => $type,
            'content_id' => $this->contentPrimaryKey,
            'field_id' => intval($fieldId)
        ]);
    }

    /**
     * 保存相应的数据
     * @param int $type
     * @param array $rowData
     * @return bool|void
     */
    private function saveAnnex(int $type, array $rowData)
    {
        $dataBase = $this->getAnnexDatabase($type);

        // 手动填写
        if ($rowData['annex_title'] === Form::ATTACH_SDTX_ANNEX_TITLE) {
            $rowData = ArrayHelper::merge($rowData, [
                'change_type' => 1,
                'is_result' => 1,
                'ocr_state' => 1,
                'collect_date' => strtotime(($this->getSdtxData()['check_date'] ?? false)) ?: 0
            ]);

            // 编辑手动填写
            if (stripos($this->getKeepAnnexString(), $rowData['annex_path']) === false) {
                $annexId = $dataBase->save($rowData);
                $this->checkImgArray[] = $annexId;
                // 新增手动填写结果
                Laminas::$serviceManager->itemIdentificationresult->save([
                    'content' => $this->generateIdentificationResultContent(),
                    'workannex_id' => $annexId
                ]);
            }
            $this->saveIdentificationResultChange($rowData);
        } else {
            if ($this->getSdtxData()) {
                $rowData = ArrayHelper::merge($rowData, [
                    'change_type' => 1,
                    'is_result' => 1,
                    'ocr_state' => 1,
                    'collect_date' => strtotime($this->getSdtxData()['check_date']) ?: 0
                ]);
            } else {
                $rowData = ArrayHelper::merge($rowData, [
                    'change_type' => $this->isReplacementOrder === true ? 0 : $this->isScreen,
                    'lock_state' => $this->isReplacementOrder === true ? 1 : 0,
                    'is_result' => 0,
                    'ocr_state' => 0,
                    'collect_date' => 0
                ]);
            }
            // 向附件表新增数据
            $annexId = $dataBase->save($rowData);
            $this->checkImgArray[] = $annexId;
        }

        // 补单的处理一下
        if ($this->isReplacementOrder === true && $annexId) {
            Laminas::$serviceManager->itemIdentificationresultchange->reidentification($annexId);
        }
    }

    /**
     * 获取附件存储数据库对象
     * 本来打算用不同的表来区分化验单和计划外检查。暂时还没区分。
     * @param int $type
     * @return Patientworkannex|mixed|void
     */
    private function getAnnexDatabase(int $type)
    {
        return Laminas::$serviceManager->itemPatientworkannex;
    }

    /**
     * 表单是否为贯穿全程表单
     */
    private function getIsProcess(): bool
    {
        return SDMHelper::app()->setAttributes(['form_id' => $this->formId])->form->getIsProcess();
    }

    /**
     * 获取化验单类型 0：普通类；1：特殊类
     * @param int $categoryId 检查项id
     * @return int|mixed
     */
    public function getReportType(int $categoryId)
    {
        if(!$categoryId) return 0;
        return Laminas::$serviceManager->dictionaryCheckcategory->getOneFieldVal('report_type', [
            'id' => $categoryId
        ]) ?: 0;
    }

    /**
     * 生成识别结果
     */
    private function generateIdentificationResultContent()
    {
        $data = $this->getSdtxData();

        $infoData = [];

        if (isset($data['note'])) {
            return json_encode([
                'user' => [
                    'result' => $data['note'],
                    'accept_date' => '',
                    'result_type' => 1,
                    'collect_date' => strtotime($data['check_date']) ?: strtotime(date('Y-m-d : H:i:s', time())),
                ]
            ]);
        }

        foreach ($data['content'] ?? [] as $k => $v) {
            $infoData[$k] = [
                "unit" => $v['unit'],
                "result" => $v['result'],
                "item_en" => "",
                "item_name" => "",
                "reference_range" => "",
                "reference_range_max" => intval($v['max_val']),
                "reference_range_min" => intval($v['min_val'])
            ];
        }
        return json_encode([
            'user' => [
                'age' => '',
                'info' => $infoData,
                'type' => '',
                'title' => '',
                'doctor' => '',
                'number' => '',
                'diagnosis"' => '',
                'user_name' => '',
                'Department' => '',
                'accept_date' => '',
                'report_date' => '',
                'user_number' => '',
                'collect_date' => strtotime($data['check_date'] ?? false) ?: strtotime(date('Y-m-d : H:i:s', time())),
                'specimen_type' => '',
            ]
        ]);
    }

    /**
     * 获取最大值符号
     * @param int $symbol
     * @return string
     */
    private function getMaxSymbol($symbol): string
    {
        if ($symbol == 1) {
            return '>';
        } elseif ($symbol == 2) {
            return '≥';
        }

        return '';
    }

    /**
     * 获取最小值符号
     * @param int $symbol
     * @return string
     */
    private function getMinSymbol($symbol): string
    {
        if ($symbol == 1) {
            return '<';//
        } elseif ($symbol == 2) {
            return '≤';
        }

        return '';
    }

    private function editIdentificationResultChange()
    {
        $data = $this->getSdtxData();

        foreach ($data['content'] as $value) {
            $originData = Laminas::$serviceManager->itemIdentificationresultchange->fetchOne([
                'where' => [
                    'item_checkname_id' => $value['id'],
                    'item_id' => $this->validator->attributes['item_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'researchstage_id' => $this->validator->attributes['stage_id'] ?? 0,
                    'form_id' => $this->validator->attributes['form_id'],
                    'category_id' => $this->getItemFormData()['checklist_id'],
                ]
            ]);

            if ($originData['result'] != $value['result']) {
                Laminas::$serviceManager->itemIdentificationresultchange->update(['result' => $value['result']], ['id' => $originData['id']]);
            }
        }
    }

    /**
     * 将数据写入胜哥的表
     * @param array $rowData
     */
    private function saveIdentificationResultChange(array $rowData): void
    {
        $data = $this->getSdtxData();

        $checkNameData = ArrayHelper::index($this->getCheckNameData(), 'id');

        foreach ($data['content'] ?? [] as $k => &$value) {
            $row = [];

            $currentCheckNameData = $checkNameData[$value['id']];
            // 检查值类型1:整数 2:一位小数 3:两位小数 4:三位小数 5:文本
            // https://e.gitee.com/yikeen_project/projects/188221/requirements/table?issue=I5TY3T
            $checkType = $checkNameData[$value['id']]['check_type'];

            // 最小值不允许输入非数字类型的值
            if ($value['min_val'] && !ValidatorHelper::isNumber($value['min_val'])) {
                throw new InvalidArgumentException('最小值不允许输入非数字的类型');
            }

            // 如果类型不是文本, 最大值只能输入数字
            if ( $value['max_val'] && $checkType != 5 && !ValidatorHelper::isNumber($value['max_val'])) {
                throw new InvalidArgumentException('最大值不允许输入非数字的类型');
            }

            $row['unit'] = $value['unit'];
            $handleResult = function (&$res) use ($checkType) {
                // 不是5
                if ($checkType != 5 && ValidatorHelper::isNumber($res)) {
                    $res = Laminas::$serviceManager->itemIdentificationresultchange->resultCheckType($res, $checkType);
                }

                return $res;
            };

            $row['result'] = $value['result'] = ($data['note'] ?? $handleResult($value['result']));

            $row['item_name'] = $value['check_item'];
            // 同步数据时 同步修改表单内的值
            $row['reference_range_max'] = $value['max_val'];
            $row['reference_range_min'] = $value['min_val'];
            $row['flag_color'] = 1;
            $row['lock_state_small'] = 1;
            // 如果填写了汉字, 上限下限就为空字符串
            $row['min_range'] = !ValidatorHelper::isNumber($value['min_val']) ? '' : ($currentCheckNameData['min_range'] ? ($currentCheckNameData['min_val'] - intval($currentCheckNameData['min_val'] * ($currentCheckNameData['min_range'] * 0.01))) : $value['min_val']);
            $row['max_range'] = !ValidatorHelper::isNumber($value['max_val']) ? '' : ($currentCheckNameData['max_range'] ? ($currentCheckNameData['max_val'] + intval($currentCheckNameData['max_val'] * ($currentCheckNameData['max_range'] * 0.01))) : $value['max_val']);
            $row['item_max_val'] = $currentCheckNameData['max_val'] ?: 0;
            $row['item_min_val'] = $currentCheckNameData['min_val'] ?: 0;
            $row['item_unit'] = $currentCheckNameData['unit'];
            $row['min_symbol'] = $this->getMinSymbol($currentCheckNameData['min_symbol']);
            $row['max_symbol'] = $this->getMaxSymbol($currentCheckNameData['max_symbol']);
            $row['check_type'] = $currentCheckNameData['check_type'];
            $row['patientworkannex_id'] = $this->sdtxAnnexID ?: implode(',', $this->checkImgArray);
            $row['checkname_id'] = $currentCheckNameData['checkname_id'];
            $row['item_id'] = $this->validator->attributes['item_id'];
            $row['itemsig_id'] = $this->validator->attributes['itemsig_id'];
            $row['patient_id'] = $this->validator->attributes['patient_id'];
            $row['checktime_id'] = $this->validator->attributes['checktime_id'];
            $row['researchstage_id'] = $this->validator->attributes['stage_id'] ?? 0;
            $row['item_variable'] = $currentCheckNameData['variable'];
            $row['form_id'] = $this->validator->attributes['form_id'];
            $row['category_id'] = $this->getItemFormData()['checklist_id'];
            $row['ocr_id'] = $rowData['ocr_id'];
            $row['annex_path'] = Oss::getUploadDomain() . Form::ATTACH_SDTX_ANNEX_PATH;
            $row['collect_date'] = strtotime($data['check_date']);
            $row['patient_form_id'] = $rowData['patient_form_id'];
            $row['patientformcontent_id'] = $this->contentPrimaryKey;
            $row['item_checkname_id'] = $currentCheckNameData['id'];
            $row['item_min_range'] = $currentCheckNameData['min_range'];
            $row['item_max_range'] = $currentCheckNameData['max_range'];
            $row['annex_type'] = 3;
            $row['is_lock_operate'] = $this->getIsLockOperate();
            // 不是通过质疑来修改的数据
            // 通过质疑修改的数据不要修改识别结果锁定的状态
            if ($this->isEditFormByQuestion === false) {
                $row['lock_state'] = 0; // 未锁定
            }
            $row['report_type'] = $rowData['report_type'];

            // 手动填写, 如果填写的指标已经被图文识别识别出结果了, 就变为修改已经识别的识别结果。防止出现多个指标的问题。
            if ($isScreen = Laminas::$serviceManager->itemIdentificationresultchange->fetchOne([
                'columns' => ['id'],
                'where' => [
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'item_checkname_id' => $currentCheckNameData['id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'patientformcontent_id' => $this->contentPrimaryKey,
                ]
            ])) {
                $row['id'] = $isScreen['id'];
                $row['is_lock_operate'] = 0;
            }

            // 没有结果值的就不要保存了
            if( $row['result'] == '' ) {
                // 空数据就删掉把
                $row['is_del'] = 1;
                $row['is_identification'] = 1;
            }else {
                $row['is_del'] = 0;
                $row['is_identification'] = 0;
            }

            Laminas::$serviceManager->itemIdentificationresultchange->save($row);
        }

        $this->setSdtxData($data);
    }

    /**
     * 处理附件路径
     * @param string $url
     * @return string
     */
    private function _getAnnexPath(string $url)
    {
        if (stripos($url, 'http') === false) {
            return trim($url, '/');
        }

        $parseUrl = parse_url($url);
        return strtr($parseUrl['query'], ['path=' => '']);
    }

    /**
     * 获取当前表单完成状态
     * @param array $postData
     * @return bool
     * @throws \Exception
     */
    public function getIsComplete(array $postData): bool
    {
        // 共享识别类表单的判断
        if ($this->formId && $this->h()->form->getGroupId($this->formId) == FormGroup::NORMAL_OCR) {
            // 没锁定的就用共享的完成状态。
            // 锁定了就走默认的完成状态. 因为有表单的配置，配置上了即使锁定也能编辑
            if (!SDMHelper::app()->form->getIsShareFormLock($this->formId, $this->patientId, $this->checktimeId) && SDMHelper::app()->form->getIdentificationEdit($this->formId) != 2) {
                return false;
            }
        }

        if (!is_bool($this->isComplete)) {
            $this->isComplete = $this->_getIsComplete($postData);
        }

        return $this->isComplete;
    }

    /**
     * 表单是否填写完成
     * @param array $postData
     * @return bool
     * @throws \Exception
     */
    private function _getIsComplete(array $postData): bool
    {
        $helper = SDMHelper::app()->setAttributes(['form_id' => $postData['form_id']])->form;
        $versionData = $helper->getVersionData();

        $skipField = 0;
        foreach ($postData as $k => $v) {
            if (($this->_getVersionData()[$this->_getFieldId($k)]['type'] ?? '') == FormField::FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE) {
                continue;
            }

            // 是否为特殊值
            $isSpecial = false;

            // 排除掉id等其他参数
            if (!isset($versionData[$this->_getFieldId($k)]) || $k == Form::ATTACH_SDTX) {
                $skipField++;
                continue;
            }

            //如果是常规识别类的并且字段是隐私字段 不参与完整性判断
            if(SDMHelper::app()->form->getGroupId($this->formId) == FormGroup::NORMAL_OCR && ($this->_getVersionData()[$this->_getFieldId($k)]['is_hide'] ?? 0 )== 1){
                $skipField++;
                continue;
            }

            // 对传过来空图片数据做处理
            if ($v == '[]') {
                $v = '';
            } elseif ($v === 'null') {
                $v = null;
            } elseif ($v === '0') { // 对特殊数据做处理, 有些值写成特殊值后判断成了false
                $isSpecial = true;
            }

            if (is_array($v)) {
                // 防止notice错误, 有多维的数组和一维的, 还有空数组
                $v = $v ? json_encode($v) : implode(',', $v);
//                $v = json_encode($v);//implode(',', $v);
            }

            if (trim($v) || $isSpecial) {
                // 表单完成条件为任意一个
                if ($helper->getFinishCondition($this->formId) == Form::FORM_FINISH_CONDITION_ANYONE) {
                    return true;
                }
            } else {
                // 空值
                $skipField++;
                // 表单完成条件为全部填写
                // 如果不在排除的表单内
                if (
                    !in_array($versionData[$this->_getFieldId($k)]['var_name'], $this->_exceptCode) &&
                    $helper->getFinishCondition() == Form::FORM_FINISH_CONDITION_ALL &&
                    !$v // 如果没写值, 并且不是特殊值 就算填写了数据
                ) {

                    // 化验单和手动填写写了任意一个就算完成
                    if ($versionData[$this->_getFieldId($k)]['var_name'] === 'CHECKIMG' && $this->getSdtxData()) {
                        continue;
                    }

                    return false;
                }
            }
        }

        // 全跳过了 说明一个字段都没写
        // && $formData['finish_condition'] == Form::FORM_FINISH_CONDITION_ANYONE
        if (count($postData) == $skipField) {
            return false;
        }

        return true;
    }

    /**
     * 获取识别表单原始数据
     */
    private function _getShareFormOriginData(): array
    {

        $forms = ArrayHelper::getColumn($this->h()->form->getGcoGroupForm($this->formId * -1), 'id');
        $allImage = Laminas::$serviceManager->patientFormContentImg->fetchAll([
            'where' => [
                'form_id' => $forms,
                'patient_id' => $this->patientId,
                'checktime_id' => $this->checktimeId,
                'is_del' => 0,
            ]
        ]) ?: [];
        $allImageId = ArrayHelper::getColumn($allImage, 'id');

        $res = [];
        $allOriginData = ArrayHelper::index(Laminas::$serviceManager->collectText->fetchAll([
            'is_del' => 0,
            'annex_id' => $allImageId
        ]), 'annex_id');

        foreach ($allImage as $image) {
            if (isset($allOriginData[$image['id']])) {
                $res[] = [
                    'url' => [
                        [
                            'url' => Oss::getUploadDomain() . DataHelper::handleImageSrc(Oss::getUploadDomain() . $image['img_src']),
                            'name' => ''
                        ]
                    ],
                    'content' => implode(PHP_EOL, StringHelper::jsonDecode($allOriginData[$image['id']]['content']))
                ];
            }
        }
        return $res;
    }

    /**
     * 表单预览
     * @return array|mixed|void
     * @throws \Exception
     */
    public function view()
    {
        if(!isset($this->validator->attributes['checktime_id']) ||
            $this->validator->attributes['checktime_id'] == 'undefined' ||
            empty($this->validator->attributes['checktime_id'])
        ){
            $this->validator->attributes['checktime_id'] = 0;
        }

        $this->event = EventEnum::EVENT_FORM_CONTENT_VIEW;
        $h = $this->h()->setAttributes(['form_id' => $this->formId])->form;

        $content = [];
        $isSkip = false;
        // 一对一
        if ($h->getType() == Form::FORM_TYPE_SINGLE) {
            $content = $this->getSingleView();
            $isSkip = true;
        } elseif ($h->getType() == Form::FORM_TYPE_MULTI) { // 一对多
            $content = $this->getMultiView();
        }
        // 评分功能。
        // 如果管理员没填写评分表单的数据, 则展示的数据为所有评分人员的数据(如果数据相同的话). 反之空着
        if ($_POST['scenario'] === Form::SCENARIO_PREVIEW_USING_SCORE && !$content) {
            // 管理员
            if (Laminas::$serviceManager->itemForm->getIsUsingScoreAdmin()) {
                Laminas::$serviceManager->itemForm->setRequestParams($this->validator->attributes);
                $usingScoreUser = (Laminas::$serviceManager->itemForm->getUsingScoreUser());
                $formData = Laminas::$serviceManager->itemForm->getContentData([
                    'create_user_id' => $usingScoreUser,
                    'form_id' => $this->validator->attributes['form_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id']
                ], 'view');

                if ($formData && count($formData) > 1) {
                    $mergeVal = false;
                    foreach ($formData[0] as $k => $v) {
                        if (DataHelper::getFieldId($k) && $h->getVersionData($this->formId)[$k]['type'] == FormField::FORM_FIELD_TYPE_CHECKBOX) {
                            $allCheckbox = ArrayHelper::getColumn($formData, $k);
                            foreach ($allCheckbox as &$checkbox) {
                                $checkbox = is_array($checkbox) ? $checkbox : (stripos($checkbox, ',') === false ? (array)$checkbox : explode(',', $checkbox));
                            }
                            // 有相同的选项
                            $commonCheckbox = array_intersect(...$allCheckbox) ?: false;
                            if ($commonCheckbox) {
                                $mergeVal[$k] = implode(',', $commonCheckbox);

                            }
                        }
                    }

                    $content = (array_intersect_assoc(...$formData));
                    if ($mergeVal) {
                        $content = ArrayHelper::merge($content, $mergeVal);
                    }
                } else {
                    $content = $formData[0] ?? [];
                }
            }
        }
        return (new Middleware($this))->afterMiddleware([
            PreProcessResponse::class // 返回结果预处理
        ])->execute(function() use ($content, $isSkip) {
            if (!$content) {
                return [];
            }

            // 一对多
            if (SDMHelper::app()->form->getType($this->formId) == Form::FORM_TYPE_MULTI) {
                return $content;
            }
            return $this->getSingleView(['data' => json_encode($content), 'id' => $content['id']], $isSkip);
        });
    }

    /**
     * 获取一对多表单表单总数
     * @return int
     */
    public function getFormMultiTotalCount(): int
    {
        return intval($this->totalCount);
    }

    /**
     * AE表单数据预览
     * @param array $content
     * @return array|mixed|void
     * @throws \Exception
     */
    public function viewAe(array $content = [])
    {
        $aeForm = $this->h()->setAttributes(['form_id' => $this->formId])->form->getAeForm($this->itemId);

        // 构建formId
        $this->validator->attributes['form_id'] = $this->formId = $aeForm['id'];

        // 一对一
        if ($aeForm['type'] == Form::FORM_TYPE_SINGLE) {
            return $this->getSingleView();
        } elseif ($aeForm['type'] == Form::FORM_TYPE_MULTI) { // 一对多
            return $this->getMultiView('itemPatientAeContent', $content);
        }
    }

    /**
     * 通过主键获取表单数据
     * @param string $id
     * @param array $content
     * @return array|mixed
     * @throws \Exception
     */
    public function viewById(string $id = '', array $content = [])
    {
        $this->event = EventEnum::EVENT_FORM_CONTENT_VIEW;

        // 兼容前端传的undefined
        if (!is_numeric($id)) {
            $id = '';
        }

        if ($id) {
            $this->contentPrimaryKey = (int)$id;
        }

        $this->h()->setAttributes([
            'content_id' => $id
        ]);
        if (!$content) {
            $content = Laminas::$serviceManager->patientFormContent->fetchOne([
                'where' => ['id' => $id]
            ]);
        }

        $this->formId = $this->formId ?: ($content['form_id'] ?? null);
        $this->patientId = $this->patientId ?: ($content['patient_id'] ?? null);
        $this->checktimeId = $this->checktimeId ?: ($content['checktime_id'] ?? null);

        return (new Middleware($this))->afterMiddleware([
            PreProcessResponse::class
        ])->execute(function () use ($content) {
            if (!$content) {
                return [];
            }

            return $this->getSingleView($content);
        });
    }

    /**
     * 获取表单内容数据
     * @param string $method
     * @param string $dbTable
     * @param bool $isHaveDel
     * @return array
     */
    private function getViewFormContentData(string $method = 'fetchOne', string $dbTable = 'patientFormContent'): array
    {
        $params = [
            'columns' => ['data', 'id', 'is_complete'],
            'where' => $this->getViewCondition($this->getItemFormData())
        ];
        if(isset($this->validator->attributes['serch_where']) && !empty($this->validator->attributes['serch_where'])){
            $params['where'] = $this->validator->attributes['serch_where'];
        }
        if(isset($this->validator->attributes['serch_columns']) && !empty($this->validator->attributes['serch_columns'])){
            $params['columns'] = $this->validator->attributes['serch_columns'];

        }
        if ($this->scenario == self::SCENARIO_CM_LIST) {
            $params['order'] = ['patient_id'];
        }

        array_push($params['columns'], 'is_del');
        $data = Laminas::$serviceManager->{$dbTable}->$method($params) ?: [];

        if (!$data) {
            return [];
        }

        return $data;
    }

    /**
     * 获取一对一表单数据
     * @param array $row
     * @param bool $isSkip
     * @return array|mixed
     * @throws \Exception
     */
    private function getSingleView($row = [], $isSkip = false,$isMany = false)
    {
        $this->event = EventEnum::EVENT_FORM_CONTENT_VIEW;
        $data = $row;
        if (!$row) {
            if (!$data = $this->setDataHaveDel(false)->getViewFormContentData()) {
                return [];
            }
        }

        $this->contentPrimaryKey = $data['id'];

        $decodeData = StringHelper::jsonDecode($data['data'], true);

        if(isset($decodeData['result_id']) && $decodeData['result_id'] == ''){
            $decodeData['result_id'] = $data['id'];
        }

        // 处理有些数据id不对的问题
        $decodeData['id'] = $data['id'];

        // 删除的状态is_del 不以data中的is_del为准，以字段is_del 为标准
        if($data['is_del']) $decodeData['is_del'] = $data['is_del'];

        if ($isSkip === true) {

            return $decodeData;
        }

        // 手写签名数据
        if (isset($decodeData['form_id']) && $this->h()->form->getIsHandwrittenSignature($decodeData['form_id'])) {
            $decodeData['handwritten_signature'] = $this->getHandwrittenSignature();
        }

        // 有的接口没有form_id
        $versionData = [];
        if (isset($this->validator->attributes['form_id']) && $this->validator->attributes['form_id']) {
            $versionData = $this->h()->form->getVersionData($this->validator->attributes['form_id']);
        }
//        var_dump($decodeData);die;
        foreach ($decodeData as $field => &$v) {
//            if($field <> 266100) continue;
            if(!in_array($field,['childData'])){//非异常判断数据处理
                $fieldId = $this->_getFieldId($field);
//                FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE
                if(isset($versionData[$fieldId]['type']) && $isMany == true && in_array($versionData[$fieldId]['type'], [
                        FormField::FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE, FormField::FORM_FIELD_TYPE_UPLOAD_IMAGE,FormField::FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE])){
                    $tmpV = StringHelper::jsonDecode($v);
                    $v = !empty($tmpV) ? '已上传图片/附件' : '';
                }
                if(!empty($v) && isset($versionData[$fieldId]['type']) && in_array($versionData[$fieldId]['type'],[FormField::FORM_FIELD_TYPE_INTEGER,FormField::FORM_FIELD_TYPE_FLOAT_1,FormField::FORM_FIELD_TYPE_FLOAT_2,FormField::FORM_FIELD_TYPE_FLOAT_3])){
                    $v = StringHelper::convertToNumber($v);
                }

                // 文件的url需要特殊处理一下, 文件的地址不需要加域名
                if (isset($versionData[$fieldId]['type']) && $versionData[$fieldId]['type'] == FormField::FORM_FIELD_TYPE_UPLOAD_FILE && is_string($v)) {
                    $tmpV = StringHelper::jsonDecode($v);
                        if($isMany == true){
                            $v = !empty($tmpV) ? '已上传图片/附件' : '';
                        }else{
                            Formatter::formatUploadFile($tmpV);
                            $v = json_encode($tmpV);
                        }
                }
                if ($v && !is_numeric($v)) {
                    // 图片不要进行排序
                    if (is_array($v) && $field !== 'reason_logic' && !in_array($versionData[$fieldId]['type'], [FormField::FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE, FormField::FORM_FIELD_TYPE_UPLOAD_IMAGE])) {
                        sort($v);
                    }
                    $isJsonData = StringHelper::jsonDecode(strval($v), false);
                    // 如果是json数据, 需要给前端转成数组格式
                    if ($isJsonData !== false && !is_bool($v)) {
                        $v = $isJsonData;
                    }
                }

                // 上传附件处理
                if (stripos($field, 'attach') !== false) {
                    if (!$v) {
                        $v = [];
                    }
                }
            }
        }

        if ($error_id = Laminas::$serviceManager->request->getPost('error_id')) {
            $decodeData['reason'] = !in_array($decodeData['reason_logic'][$error_id], ['null', '']) ? $decodeData['reason_logic'][$error_id] : '';
        }

        // 当前表单是否锁定
        $decodeData['is_content_lock'] = Laminas::$serviceManager->patientFormLock->getIsLock(['content_id' => ($data['id'] ?? 0), 'is_del' => 0]);

        //获取EDC锁定信息
        $edclockWhere = [
            'is_del' => 0,
            'content_id' => $data['id'],
        ];
        if(isset($data['form_id']) && !empty($data['form_id'])){
            $edclockWhere['form_id'] = $data['form_id'];
        }else{
            $edclockWhere['form_id'] = $this->validator->attributes['form_id'];
        }

        if(isset($this->validator->attributes['patient_id']) && !empty($this->validator->attributes['patient_id'])){
            $edclockWhere['patient_id'] = $this->validator->attributes['patient_id'];
        }elseif(isset($data['patient_id']) && !empty($data['patient_id'])){
            $edclockWhere['patient_id'] = $data['patient_id'];
        }elseif(isset($decodeData['patient_id']) && !empty($decodeData['patient_id'])){
            $edclockWhere['patient_id'] = $decodeData['patient_id'];
        }
        $patientWorkEdcLoc = Laminas::$serviceManager->projectPatientworkinfo->getOneFieldVal('edc_lock',$edclockWhere);
        unset($edclockWhere);
        $decodeData['is_edc_lock'] = in_array($patientWorkEdcLoc, [1,2]) ? true : false;
        unset($patientWorkEdcLoc);

        $decodeData['is_complete'] = (bool)($data['is_complete'] ?? false);

        unset($decodeData['reason_logic']);

        // 移除data
        unset($data['data']);

        // 移除旧数据
        unset($decodeData['old_data_str']);

        if (isset($decodeData['sdtx']) && $decodeData['sdtx']) {
            // 手动填写的信息通过接口调用，表单不需要返回信息（后期这部分数据是可以不存入表单内容表的）
            $decodeData['sdtx'] = [];
            $decodeData['is_sdtx'] = true;
        }

        // 移除手动填写数据
//        unset($decodeData['sdtx']);

        // 逻辑核查化验单
        if ($this->getItemFormData()['group_id'] == FormGroup::CHECK_OCR && $this->isCheckLogic) {
            $ocr_check_date = Laminas::$serviceManager->itemIdentificationresultchange->fetchOne([
                'where' => [
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'item_id' => $this->validator->attributes['item_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'is_del' => 0,
                    'form_id' => $this->validator->attributes['form_id'],
                ]
            ])['collect_date'];
            //获取该副项目设置的采集时间类型
            $dateType = 1;
            if(!empty($this->validator->attributes['item_id'])){
                $dateType = Laminas::$serviceManager->itemCheckdate->getOneFieldVal('date_type',[
                    'is_del' => 0,
                    'item_id' => $this->validator->attributes['item_id']
                ]);
                $dateType = empty($dateType) ? 1 : $dateType;
            }
            $data['OCR_CHECK_TIME'] = $ocr_check_date != '' ? $ocr_check_date : '';

            unset($ocr_check_date);
            unset($dateType);
        }

        return ArrayUtils::merge($data, $decodeData, true);
    }

    /**
     * 获取手写签名地址
     * @return string
     */
    private function getHandwrittenSignature(): string
    {
        $annexPath = Laminas::$serviceManager->itemFormpatientsign->fetchOne([
                'where' => [
                    'patient_id' => $this->validator->attributes['patient_id'] ?? 0,
                    'item_id' => $this->validator->attributes['item_id'] ?? 0,
                    'itemsig_id' => $this->validator->attributes['itemsig_id'] ?? 0,
                    'checktime_id' => $this->validator->attributes['checktime_id'] ?? 0,
                    'form_id' => $this->validator->attributes['form_id'] ?? 0,
                ]
            ])['annex_path'] ?? '';

        return $annexPath ? Oss::getUploadDomain() . $annexPath : '';
    }

    public function setDataHaveDel($dataHaveDel = false): PatientFormModel
    {
        $this->dataHaveDel = $dataHaveDel;
        return $this;
    }

    /**
     * 获取一对多数据
     * @param string $dbTable
     * @param array $content
     * @return array
     * @throws \Exception
     */
    public function getMultiView(string $dbTable = 'patientFormContent', array $content = []): array
    {
        if ($content) {
            $data = $content;
        } else {
            $method = 'fetchAllWithPagination';
            if ($this->scenario === self::SCENARIO_VIEW_SHARE_FORM_UNLOCK) {
                $method = 'fetchAll';
            }
            $data = $this->getViewFormContentData($method, $dbTable);

            if (!$data) {
                return [];
            }

            if ($method === 'fetchAll') {
                $this->totalCount = count($data);
            } else {
                $this->totalCount = $data['count'];
                $data = $data['data'];
            }

        }

        $versionData = $this->h()->setAttributes(['form_id' => $this->formId])->form->getVersionData();
        $getLabel = function ($fieldId) use ($versionData) {
            if (isset($versionData[$fieldId]) && isset($versionData[$fieldId]['children'])) {
                return ArrayHelper::index($versionData[$fieldId]['children'], 'value');
            }

            return [];
        };

        // 处理选项值
        // 需要将0,1 转换成是否
        // 遍历所有一对多的数据
        foreach ($data as &$datum) {
            $originData = StringHelper::jsonDecode($datum['data'] ?? $datum);
            foreach ($originData as $field => &$fieldValue) {
                if (!DataHelper::isField($field)) {
                    continue;
                }
                if(!in_array($field,['childData'])){//非异常判断信息数据处理
                    $id = (explode('-', $field)[0] ?: $field);
                    $fieldValue = SDMHelper::app()->form->field->getValueLabel($fieldValue, $id);
                }

            }

            $datum['data'] = json_encode($originData);
        }

        $res = [];

        // 一对多表单 需要把表格展示的信息做一下处理
        // 多级嵌套的需要把字段的id单独提取出来
        foreach ($data as $item) {
            $singleData = $this->getSingleView($item,false,true);

            foreach ($singleData as $k => $v) {
                if (stripos($k, '-') !== false) {
                    $key = explode('-', $k)[0];
                    $singleData[$key] = $v;
                }
            }

            $res[] = $singleData;
        }

        return $res;
    }

    /**
     * 获取预览条件
     * @param $form
     * @param int $is_del
     * @return array
     */
    private function getViewCondition($form): array
    {
        $condition = [
            'form_id' => $this->validator->attributes['form_id'],
        ];

        if(!$this->dataHaveDel) $condition['is_del'] = 0;

        // 非贯穿全程类
        if ($form['group_id'] != FormGroup::THROUGH_PROCESS && $this->validator->attributes['checktime_id']) {
            $condition['checktime_id'] = $this->validator->attributes['checktime_id'];
        }

        if ($this->contentId && $form['type'] == Form::FORM_TYPE_MULTI) {
            $condition['id'] = $this->contentId;
        }

        if (isset($this->validator->attributes['operate_user'])) {
            $condition['update_user_id'] = $this->validator->attributes['operate_user'];
        }

        if (isset($this->validator->attributes['patient_id'])) {
            $condition['patient_id'] = $this->validator->attributes['patient_id'];
        }

        //CM合并用药表单增加药物检索查询
        if (isset($this->validator->attributes['drug_id']) && !empty($this->validator->attributes['drug_id'])) {
            $condition['drug_id'] = $this->validator->attributes['drug_id'];
        }

        if ($form['is_using_score'] == 1) {
            // 进度管理要展示管理员填写的数据
            if ($this->validator->attributes['scenario'] == 'progressManage') {
                $condition['create_user_id'] = Laminas::$serviceManager->itemForm->getUsingScoreUser(true);
            } else {
                if (Laminas::$serviceManager->itemForm->getIsUsingScoreAdmin()) {
                    $condition['create_user_id'] = Laminas::$serviceManager->itemForm->getUsingScoreUser(true);
                } else {
                    $condition['create_user_id'] = Laminas::$serviceManager->identity->getId();
                }
            }
        }

        return $condition;
    }

    /**
     * 获取受试者表单锁主键
     * @return false|mixed
     */
    public function getPatientFormLockData()
    {
        return Laminas::$serviceManager->patientFormLock->fetchOne([
            'columns' => ['id', 'is_del'],
            'where' => [
                'patient_id' => $this->validator->attributes['patient_id'],
                'form_id' => $this->validator->attributes['form_id'],
                'item_id' => $this->validator->attributes['item_id'],
                'itemsig_id' => $this->validator->attributes['itemsig_id'],
                'checktime_id' => $this->validator->attributes['checktime_id']
            ]]);
    }

    /**
     * 表单申请解锁, 表单取消解锁。
     */
    public function unlock()
    {
        $this->event = EventEnumV2::getVal(EventEnumV2::EVENT_FORM_CONTENT_APPLY_UNLOCK);

        // 申请解锁一定是有解锁原因的, 所以没填写解锁原因就是取消申请解锁
        if ($this->validator->attributes['note'] === '未填写') {
            $this->event = EventEnumV2::getVal(EventEnumV2::EVENT_FORM_CONTENT_REVOKE_UNLOCK);
        }

        $this->contentPrimaryKey = (int)$this->validator->attributes['content_id'];

        // 常规识别类表单
        if ($this->h()->form->getGroupId($this->formId) == FormGroup::NORMAL_OCR) {
            $shareFormPool = $this->h()->form->getGcoPool($this->formId);
            $key = "UNLOCK_SHARE_FORM:{$this->itemId}";
            $hashKey = "{$this->patientId}:{$this->checktimeId}:{$shareFormPool}";
            // 申请解锁, 和取消申请解锁
            $val = Laminas::$serviceManager->redisExtend->getRedisInstance()->hGet($key, $hashKey);
            if (!$val) {
                $val = [];
            }
            $data = StringHelper::jsonDecode($val);

            if ($data) {
                // 取消解锁
                $data = [];
            }else {
                $data[$this->formId] = $this->validator->attributes['note'];
            }

            if (count($data) == 0) {
                Laminas::$serviceManager->redisExtend->getRedisInstance()->hDel($key, $hashKey);
            } else {
                Laminas::$serviceManager->redisExtend->getRedisInstance()->hSet($key, $hashKey, json_encode($data));
            }
        }

        $this->initLoggerData();
        $this->logger->setUnlockReason($this->validator->attributes['note'])->setIsChangeStr(false)->flush();
        return (Laminas::$serviceManager->patientFormUnlock->unlock($this->validator->attributes['content_id'], $this->validator->attributes['note']));
    }

    /**
     * 是否展示重置表单按钮
     */
    public function isShowResetBtn(): bool
    {
        $formData = $this->getItemFormData();

        // OCR 和 一对多表单不展示此按钮
        if ($formData['group_id'] == FormGroup::CHECK_OCR || $formData['type'] == Form::FORM_TYPE_MULTI || $formData['group_id'] == FormGroup::NORMAL_OCR) {
            return false;
        }


        $versionData = $this->_getVersionData();

        foreach ($versionData as $v) {
            // 方式日期 锚点日期 不让重置
            if ($v['is_anchor'] == 1 || $v['is_booked_time'] == 1) {
                return false;
            }
        }

        return true;
    }

    /**
     * 重置表单填写数据
     */
    public function flushContent()
    {
        $this->event = EventEnum::EVENT_FORM_CONTENT_FLUSH;
        $this->contentPrimaryKey = (int)$this->validator->attributes['id'];

        if ($this->h()->form->getGroupId($this->formId) != FormGroup::NORMAL) {
            throw new InvalidArgumentException('只有常规类表单才能重置填写数据。');
        }
        $this->validator->attributes['note'] = "录入错误";  //表单重置的修改原因默认为录入错误
        $lockRow = Laminas::$serviceManager->itemPatientFormContentFieldLock->fetchOne(
            ['where' => ['item_id' => $this->validator->attributes['item_id'], 'form_id' => $this->validator->attributes['form_id'], 'is_del' => 0]]
        );
        if ($lockRow) {
            // 是否还有已填写的表单
            $isWrite = Laminas::$serviceManager->patientFormContent->fetchOne([
                'where' => [
                    'form_id' => $lockRow['lock_conditions'],
                    'item_id' => $this->validator->attributes['item_id'],
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'checktime_id' => $this->validator->attributes['checktime_id'],
                    'itemsig_id' => $this->validator->attributes['itemsig_id'],
                    'is_del' => 0
                ]
            ]);

            $relationFormName = Laminas::$serviceManager->itemForm->fetchOne([
                    'where' => ['id' => $lockRow['lock_conditions']]
                ])['name'] ?? '';


            if ($isWrite) {
                throw new InvalidArgumentException("被关联的表单 `{$relationFormName}` 已产生数据，无法重置。", 1001);
            }
        }

        Db::beginTransaction();

        foreach ($this->h()->form->getVersionData($this->formId) as $v) {
            if (isset($v['children']) && is_array($v['children'])) {
                foreach ($v['children'] as $child) {
                    // 有挂靠的表单
                    if ($child['relation_information'] && $child['relation_classification'] == 1) {
                        // 删除痕迹
                        $this->flushTrace($child['relation_information']);

                        // 隐藏挂靠表单
                        Laminas::$serviceManager->itemPatientChecktimeForm->update(['is_del' => 1], [
                            'item_id' => $this->validator->attributes['item_id'],
                            'patient_id' => $this->validator->attributes['patient_id'],
                            'checktime_id' => $this->validator->attributes['checktime_id'],
                            'itemsig_id' => $this->validator->attributes['itemsig_id'],
                            'form_id' => $child['relation_information'],
                            'is_del' => 0
                        ]);

                        break;
                    }
                }
            }
        }

        $this->flushTrace($this->validator->attributes['form_id']);
        // 推送进度条
        $originData = Laminas::$serviceManager->patientFormContent->fetchOne([
            'where' => ['id' => $this->validator->attributes['id']]
        ]);

        // 胜哥让调用的。
        // 看着像推送颜色。
        /*Laminas::$serviceManager->patientChecktimeList->isCompleteForm([
            'item_id' => $this->validator->attributes['item_id'],
            'itemsig_id' => $this->validator->attributes['itemsig_id'],
            'patient_id' => $this->validator->attributes['patient_id'],
            'form_id' => $this->validator->attributes['form_id'],
            'checktime_id' => $this->validator->attributes['checktime_id'],
            'type' => $originData['is_complete'] == 1 ? 4 : 5,
        ]);*/


        // 现在修改成置空表单数据
        $query = StringHelper::jsonDecode(Laminas::$serviceManager->patientFormContent->fetchOne([
                'where' => [
                    'id' => $this->validator->attributes['id']
                ]
            ])['data'] ?? []);

        foreach ($query as $k => &$v) {
            if (DataHelper::isField($k)) {
                $v = '';
            }
        }
        // 重置表单 is_complete = 0，未完成
        Laminas::$serviceManager->patientFormContent->update(['data' => json_encode($query), 'is_complete' => 0], ['id' => $this->validator->attributes['id']]);

        // 清空图片表
        Laminas::$serviceManager->patientFormContentImg->update(['is_del' => 1], ['content_id' => $this->validator->attributes['id']]);

        // 删除表单锁
        Laminas::$serviceManager->patientFormContent->unlock($this->validator->attributes['id']);

        // 删除表单锁表
        Laminas::$serviceManager->patientFormLock->setUnlock($this->validator->attributes['id']);

        // 重置日志
        $this->logger->setContentId($this->validator->attributes['id'])
            ->setPostOriginData($this->validator->attributes)
            ->setPostData($this->validator->attributes)
            ->setEvent($this->event)
            ->flush();

        Db::commit();

        //异步处理访视进度情况信息
        $this->contentPrimaryKey = (int)$this->validator->attributes['id'];
        (new HandlePatientWorkBatch([
            'owner' => $this,
            'operate_type' => 11,
        ]))->execute();
    }

    /**
     * 移除表单痕迹
     * @param int|array $formId
     */
    private function flushTrace($formId)
    {
        // 删除表单颜色数据 [已废弃]
        // 重置了强制置成黄色
        Laminas::$serviceManager->patientForm->update(
            ['is_complete' => 0],
            [
                'item_id' => $this->validator->attributes['item_id'],
                'patient_id' => $this->validator->attributes['patient_id'],
                'checktime_id' => $this->validator->attributes['checktime_id'],
                'itemsig_id' => $this->validator->attributes['itemsig_id'],
                'form_id' => $formId,
                'is_del' => 0
            ]);
    }

    /**
     * 获取填写指南
     */
    public function getGuide(): string
    {
        return strtr($this->getItemFormData()['guide'] ?: '', [PHP_EOL => '<br>']);
    }

    /**
     * @note 恢复删除的表单数据
     * @return void
     * @throws \Exception
     */
    public function recoveryDelContent()
    {
        $this->event = EventEnumV2::getVal(EventEnumV2::EVENT_FORM_CONTENT_RECOVERY);

        $formContent = $this->h()->setAttributes([
            'content_id' => $this->validator->attributes['id']
        ])->formContent;

        if(! $formContent->isDel()) {
            throw new InvalidArgumentException('无效操作，请勿对未删除的数据进行数据恢复的操作！');
        }

        $this->validator->setAttributes([
            'form_id' => $formContent->getFormId(),
            'item_id' => $formContent->getItemId(),
            'checktime_id' => $formContent->getCheckTimeId(),
            'patient_id' => $formContent->getPatientId(),
            'itemsig_id' => $formContent->getItemsigId()
        ]);
        $this->setAttributes($this->validator->attributes);

        $recoveryAfterDataJsonStr = $formContent->getData(); // 恢复后的数据

        $this->postData = Json::decode($recoveryAfterDataJsonStr, Json::TYPE_ARRAY);
        if(isset($this->postData['note']) && !empty($this->postData['note'])){
            unset($this->postData['note']);
        }
        $recoveryPreData = DataHelper::handleFormData($this->postData, $this->formId);
        $recoveryPreData = ArrayUtils::merge($recoveryPreData, array_fill_keys(array_diff( array_keys($recoveryPreData), [
            'item_id',
            'patient_id',
            'checktime_id',
            'itemsig_id',
            'stage_id',
            'patientchecktime_id',
            'form_id'
        ] ), ''), true);

        $this->postOriginData = ArrayUtils::merge($this->postData, [
            'old_data_str' => Json::encode($recoveryPreData)
        ]);

        if(isset($this->postOriginData['note']) && !empty($this->postOriginData['note'])){
            unset($this->postOriginData['note']);
        }

        // 初始日志信息
        $this->initLoggerData();

        Db::beginTransaction();

        // 表单内容恢复
        Laminas::$serviceManager->patientFormContent->upDelState([
            'id' => $formContent->getContentId()
        ], 0);

        $formContentDelete = $formContent->getDelete();

        if ( !empty($formContentDelete['img_id_list']) ) {
            // 表单图片恢复（删除时记录的图片集合）
            Laminas::$serviceManager->patientFormContentImg->upDelState([
                'id' => $formContentDelete['img_id_list']
            ], 0);
            // 恢复之后要清空删除的记录数据
            Laminas::$serviceManager->itemPatientFormContentDelete->updateField($formContentDelete['id'], 'img_id_list', []);
        }

        // 更新patientForm状态
        $this->updateCompleteStatus();

        $this->logger->setContentId($this->validator->attributes['id'])->flush();

        Db::commit();

        //异步处理访视进度情况信息
        $this->contentPrimaryKey = (int)$this->validator->attributes['id'];
        (new HandlePatientWorkBatch([
            'owner' => $this,
            'operate_type' => 13,
        ]))->execute();


        //异步处理CM表单受试者药物信息
        (new HandleCmFormPatientDrug([
            'owner' => $this
        ]))->execute();
    }

    /**
     * 一对多表单删除
     */
    public function delete()
    {
        $this->contentPrimaryKey = (int)$this->validator->attributes['id'];
        return (new Middleware($this))->execute($this->_delete());
    }

    private function _delete(): \Closure
    {
        if (SDMHelper::app()->form->getType($this->formId) === Form::FORM_TYPE_SINGLE) {
            // 一对一表单，暂时控制不可删除
            throw new InvalidArgumentException('一对一表单尚未开放删除功能！');
        }

        $this->event = EventEnumV2::getVal(EventEnumV2::EVENT_FORM_CONTENT_DELETE);

        return function () {
            $formContent = SDMHelper::app()->setAttributes(['content_id' => $this->contentPrimaryKey, 'patient_id' => $this->patientId])->formContent;

            if($formContent->isDel()) {
                throw new InvalidArgumentException('此表单已删除，请无重复操作！');
            }

            if ($this->skipEDCValid === false && $formContent->getIsEdcLock()) {
                throw new InvalidArgumentException('此表单在EDC已锁定, 无法删除。');
            }

            // 常规识别一对多的表单
            if (SDMHelper::app()->form->getGroupId($this->formId) == FormGroup::NORMAL_OCR) {
                if (SDMHelper::app()->form->getIdentificationEdit($this->formId) == 0) {
                    throw new InvalidArgumentException('此表单无法删除。');
                } else {
                    if (!SDMHelper::app()->form->getIsShareFormLock($this->formId, $this->patientId, $this->checktimeId)) {
                        if (SDMHelper::app()->form->getIdentificationEdit($this->formId) != 2) {
                            throw new InvalidArgumentException('此表单无法删除。');
                        }
                    }
                }
            }else if (SDMHelper::app()->form->getGroupId($this->formId) == FormGroup::CHECK_OCR && SDMHelper::app()->form->getType() === Form::FORM_TYPE_MULTI) {
                // 检查项（化验单）类一对多表单，暂时控制不可删除
                throw new InvalidArgumentException('一对多化验单类表单尚未开放删除功能！');
            }

            $delPreDataJsonStr = $formContent->getData();
            $delPreData = DataHelper::handleFormData(Json::decode($delPreDataJsonStr, Json::TYPE_ARRAY), $this->formId);
            $this->postData = ArrayUtils::merge($delPreData, array_fill_keys(array_diff( array_keys($delPreData), [
                'item_id',
                'patient_id',
                'checktime_id',
                'itemsig_id',
                'stage_id',
                'patientchecktime_id',
                'form_id'
            ] ), ''), true);

            $this->postOriginData = ArrayUtils::merge($this->postData, [
                'old_data_str' => $delPreDataJsonStr
            ]);
            // 初始日志
            $this->initLoggerData();

            // 使用事务提交
            // Db::beginTransaction();

            Laminas::$serviceManager->patientFormContent->update(['is_del' => 1], ['id' => $this->validator->attributes['id']]);

            // 更新patientForm状态
            $this->updateCompleteStatus();

            // 如果有图片就把图片表的数据删除掉（删除之前先记录删除的图片id，方便后续的数据恢复）
            $patientFormContentImgIdList = Laminas::$serviceManager->patientFormContentImg->fetchCol('id', [
               'content_id' => $this->validator->attributes['id'],
               'is_del' => 0
            ]);

            Laminas::$serviceManager->patientFormContentImg->update(['is_del' => 1], ['content_id' => $this->validator->attributes['id']]);
            // 将删除的图片id集合记录到表中
            $formContentDelete = $formContent->getDelete();

            Laminas::$serviceManager->itemPatientFormContentDelete->save([
                'id' => $formContentDelete ? $formContentDelete['id'] : 0,
                'content_id' => $this->validator->attributes['id'],
                'img_id_list' => $patientFormContentImgIdList ?: [],
            ]);

            if ($versionData = ArrayHelper::index($this->h()->form->getVersionData($this->formId), 'var_name')) {
                if (isset($versionData[DictionaryVarNameEnum::COLLECT_MEDICAL_TAKE_CMINDC])) {
                    Laminas::$serviceManager->patientFormContentCm->update(['is_del' => 1], ['content_id' => $this->validator->attributes['id']]);
                    $cmindcStatus = Laminas::$serviceManager->patientFormContentCm->fetchOne([
                        'where' => ['content_id' => $this->validator->attributes['id']]
                    ])['cmindc_status'];

                    $q = Laminas::$serviceManager->itemCsaeRelation->fetchOne([
                        'where' => ['cm_content_id' => $this->validator->attributes['id']]
                    ]);

                    if ($q) {
                        // 新增AE
                        // 新增AE删除了, 把新增AE转移到受试者新增AE
                        if ($cmindcStatus == 1) {
                            Laminas::$serviceManager->itemCsaeRelation->update(['cm_content_id' => 0], ['cm_content_id' => $q['id']]);
                            Laminas::$serviceManager->itemPatientAeContent->update(['ae_type' => 0], ['id' => $q['content_id']]);
                        } else {
                            Laminas::$serviceManager->itemCsaeChecked->update(['is_del' => 1], ['cm_content_id' => $this->validator->attributes['id']]);
                        }
                    }
                }
            }
            // 自动关闭质疑
            if ($this->h()->form->getType($this->formId) == Form::FORM_TYPE_MULTI) {
                $this->h()->logic->closeRowError($this->contentPrimaryKey, $this->itemId);
            }

            // 记录删除日志
            $this->logger->setContentId($this->contentPrimaryKey)->flush();

            // Db::commit();

            //异步处理访视进度情况信息
            (new HandlePatientWorkBatch([
                'owner' => $this,
                'operate_type' => 12,
            ]))->execute();

            //异步处理CM表单受试者药物信息
            (new HandleCmFormPatientDrug([
                'owner' => $this
            ]))->execute();

            return true;
        };
    }

    /**
     * 对表单的数据进行暂存处理
     */
    public function tempStorage(): bool
    {
        $this->event = EventEnum::EVENT_FORM_CONTENT_TEMP_STORAGE;

        // 一对多
        if ($this->h()->form->getType($this->formId) == Form::FORM_TYPE_MULTI) {
            return $this->tempStorageMulti();
        }

        $forms = $this->h()->form->getGcoGroupForm($this->formId);

        if (isset($this->postOriginData['id']) && $this->postOriginData['id']) {
            $this->logger->setContentId($this->postOriginData['id']);
            $this->contentPrimaryKey = (int)$this->postOriginData['id'];
        }

        // 看看当前图片是否已经锁定了
        $allImages = Laminas::$serviceManager->patientFormContentImg->fetchAll([
            'where' => [
                'patient_id' => $this->patientId,
                'checktime_id' => $this->checktimeId,
                'form_id' => ArrayHelper::getColumn($forms, 'id'),
                'is_del' => 0
            ]
        ]);

        if (array_sum(ArrayHelper::getColumn($allImages, 'is_lock')) > 0) {
            throw new InvalidArgumentException("当前数据已经被锁定。");
        }

        $origin_childDatas = isset($this->postOriginData['childData']) && !empty($this->postOriginData['childData']) ? json_decode($this->postOriginData['childData'],true):[];
        if(!empty($origin_childDatas)){
            foreach ($origin_childDatas as $field=>$origin_childData){
                if(isset($origin_childData['normal_type']) && !empty($origin_childData['normal_type'])){
                    $key = $field.'-normal-type';
                    $this->postOriginData[$key] = $origin_childData['normal_type'];
                }
            }
            unset($origin_childDatas);
        }

        $childDatas = isset($this->postData['childData']) && !empty($this->postData['childData']) ? json_decode($this->postData['childData'],true):[];
        if(!empty($childDatas)){
            foreach ($childDatas as $field=>$childData){
                if(isset($childData['normal_type']) && !empty($childData['normal_type'])){
                    $key = $field.'-normal-type';
                    $this->postData[$key] = $childData['normal_type'];
                }
            }
            unset($childDatas);
        }
        $this->logger->setPostData($this->postData)->setPostOriginData($this->postOriginData)->setEvent($this->event)->flush($this->postOriginData);

        // 数据验证
        $middleware = new Preprocessing();
        $middleware->owner = $this;
        $middleware->execute();

        // 数据验证
        $middleware = new ValidPostData();
        $middleware->owner = $this;
        $middleware->execute();
        return $this->h()->formContent->setTempStorage(...[[
            'data' => $this->postData,
            'create_user_id' => Laminas::$serviceManager->identity->getId(),
            'create_time' => time(),
        ], $this->patientId, $this->checktimeId, $this->formId]);
    }

    /**
     * 对一对多表单的数据进行暂存处理
     */
    public function tempStorageMulti(bool $valid = true): bool
    {
        $forms = $this->h()->form->getGcoGroupForm($this->formId);

        if (isset($this->postOriginData['id']) && $this->postOriginData['id']) {
            $this->logger->setContentId($this->postOriginData['id']);
            $this->contentPrimaryKey = (int)$this->postOriginData['id'];
        }

        // 看看当前图片是否已经锁定了
        $allImages = Laminas::$serviceManager->patientFormContentImg->fetchAll([
            'where' => [
                'patient_id' => $this->patientId,
                'checktime_id' => $this->checktimeId,
                'form_id' => ArrayHelper::getColumn($forms, 'id')
            ]
        ]);

        if (array_sum(ArrayHelper::getColumn($allImages, 'is_lock')) > 0) {
            throw new InvalidArgumentException("当前表单已经被锁定。");
        }

        $this->logger->setPostData($this->postData)->setPostOriginData($this->postOriginData)->setEvent($this->event)->flush($this->postOriginData);

        if ($valid === true) {
            // 数据验证
            $middleware = new ValidPostData();
            $middleware->owner = $this;
            $middleware->execute();
        }

        if ($this->postOriginData['old_data_str']) {
            $originContentId = StringHelper::jsonDecode($this->postOriginData['old_data_str']);
            if (isset($originContentId['content_id'])) {
                $this->postData['content_id'] = $originContentId['content_id'];
            }
        }
        return $this->h()->formContent->setMultiTempStorage(...[[
            'data' => $this->postData,
            'create_user_id' => Laminas::$serviceManager->identity->getId(),
            'create_time' => time(),
        ], $this->patientId, $this->checktimeId, $this->formId, $this->contentPrimaryKey]);
    }

    /**
     * 锁定暂存数据
     */
    public function lockShareForm()
    {
        Db::beginTransaction();

        $this->event = EventEnum::EVENT_LOCK_SHARE_FORM_CONTENT;
        $this->logger->setEvent($this->event);
        $forms = $this->h()->form->getGcoGroupForm($this->formId);

        // 【SDM】识别结果锁定时，如果还有后台发的质疑未关闭，不可让锁定。
        //https://e.gitee.com/yikeen_project/issues/list?issue=IAXFDX
        if (Laminas::$serviceManager->itemQuestion->fetchAll([
            'where' => [
                'form_id' => ArrayHelper::getColumn($forms, 'id'),
                'question_status' => [0, 1],
                'checktime_id' => $this->checktimeId,
                'patient_id' => $this->patientId,
                'is_del' => 0
            ]
        ])) {
            throw new InvalidArgumentException('请关闭图片质疑。');
        }

        // 看看当前图片是否已经锁定了。
        $allImages = Laminas::$serviceManager->patientFormContentImg->fetchAll([
            'where' => [
                'patient_id' => $this->patientId,
                'checktime_id' => $this->checktimeId,
                'form_id' => ArrayHelper::getColumn($forms, 'id'),
                'is_del' => 0
            ]
        ]);

        if (array_sum(ArrayHelper::getColumn($allImages, 'is_lock')) > 0) {
            throw new InvalidArgumentException("当前数据已经被锁定。");
        }

        $afterExec = [];
        $send_form_data = [];
        $only_keys1 = $this->validator->attributes['only_keys1'];
        $form_delete_content_arr = [];
        foreach ($forms as $k=>$form) {
//            if($k != 2) continue;
            $method = $form['type'] == Form::FORM_TYPE_SINGLE ? 'getTempStorage' : 'getMultiTempStorage';
            $tempData = $this->h()->formContent->{$method}($this->patientId, $this->checktimeId, $form['id']);
            $form_id = $form['id'];

            // 判断当前检查点是否有这个表单存在, 不存在就直接跳过。
            if ($this->h()->checkTime->getHasForm($form['id'], $this->checktimeId) === false) {
                continue;
            }

            if (!$tempData && $form['type'] == Form::FORM_TYPE_SINGLE) {
                Db::rollback();
                throw new InvalidArgumentException("`{$form['name']}`未保存，请保存后锁定。");
            }
            if (is_array($tempData)) {
                $form_delete_content_arr = Laminas::$serviceManager->patientFormContent->fetchCol('id',[
                    'is_del' => 0,
                    'patient_id' => $this->patientId,
                    'checktime_id' => $this->checktimeId,
                    'form_id' => $form['id']
                ]);
                // 先把所有的数据删除, 因为一对多是可以删除的
                Laminas::$serviceManager->patientFormContent->update(['is_del' => 1], ['patient_id' => $this->patientId, 'checktime_id' => $this->checktimeId, 'form_id' => $form['id']]);
                foreach ($tempData as $temp) {
                    $afterExec[] = $this->insertTempVal($temp, $form);
                    $temp_value = StringHelper::jsonDecode($temp);
                    $temp_data = !empty($temp_value) && isset($temp_value['data']) && !empty($temp_value['data']) ? $temp_value['data'] : [];
                    $temp_data['patientformcontent_id'] = $this->contentPrimaryKey;
                    $send_form_data[$form_id]['content_data'][] = $temp_data;
                    unset($temp_value);
                    unset($temp_data);
                    if(isset($form_delete_content_arr[$this->contentPrimaryKey]) && !empty($form_delete_content_arr[$this->contentPrimaryKey])){
                        unset($form_delete_content_arr[$this->contentPrimaryKey]);
                    }
                }
            } else {
                $afterExec[] = $this->insertTempVal($tempData, $form);
                $temp_value = StringHelper::jsonDecode($tempData);
                $temp_data = !empty($temp_value) && isset($temp_value['data']) && !empty($temp_value['data']) ? $temp_value['data'] : [];
                $temp_data['patientformcontent_id'] = $this->contentPrimaryKey;
                $send_form_data[$form_id]['content_data'] = $temp_data;
                unset($temp_value);
                unset($temp_data);
            }
        }

        $this->validator->attributes['only_keys1'] = $only_keys1;

        Event::trigger(EventEnum::EVENT_LOCK_SHARE_FORM_CONTENT, [$this]);

        // 统计
        $gcoHash = current(ArrayHelper::getColumn($forms, 'gco_pool'));

        if (!$gcoHash) {
            throw new \Exception('分组获取失败。');
        }

        $lockTime = time();
        Laminas::$serviceManager->redisExtend->getRedisInstance()->hSetNx('lockShareFormAnalyze', $this->patientId . $this->checktimeId . $gcoHash, json_encode([
            'time' => $lockTime,
            'user' => Laminas::$serviceManager->identity->getId(),
            'patient_id' => $this->patientId,
            'checktime_id' => $this->checktimeId,
//            'gco_hash' => $gcoHash,
            'forms' => ArrayHelper::getColumn($forms, 'id')
        ]));

        Laminas::$serviceManager->redisExtend->getRedisInstance()->zAdd('lockShareFormAnalyze' . 'SortSet', ['NX'], $lockTime, $this->patientId . $this->checktimeId . $gcoHash);

        foreach ($afterExec as $exec) {
            $exec();
        }

        //锁定后自动添加异常值判断数据
        $send_formcs_data = [
            'item_id'=>$this->itemId,
            'itemsig_id'=>$this->itemsigId,
            'patient_id'=>$this->patientId,
            'checktime_id'=>$this->checktimeId,
            'patientchecktime_id'=>0,
            'form_data'=>$send_form_data
        ];
        Laminas::$serviceManager->itemIdentificationresultchange->saveFormCs($send_formcs_data);
        unset($send_form_data);
        unset($send_formcs_data);

        $this->resubmit(); //锁定判断重复提交
        Db::commit();

        //异步处理访视进度情况信息
        $patient_form_content_arr = [];
        $patient_form_contents = Laminas::$serviceManager->patientFormContent->fetchAll([
            'where'=> [
                'is_del' => 0,
                'patient_id' => $this->validator->attributes['patient_id'],
                'checktime_id' => $this->validator->attributes['checktime_id'],
                'form_id' => StringHelper::toArray(array_values(array_column($forms,'id'))),
            ],
            'columns'=>['id','form_id']
        ]);
        if(!empty($patient_form_contents)){
            foreach($patient_form_contents as $patient_form_content_key=>$patient_form_content){
                $patient_form_content_arr[$patient_form_content['form_id']][] = $patient_form_content['id'];
                unset($patient_form_contents[$patient_form_content_key]);
            }
        }
        unset($patient_form_contents);
        //异步处理访视进度情况信息
        foreach ($forms as $formInfo) {
            //获取常规类识别表单完成的字段数量
            $over_num = SDMHelper::app()->patient->getShareFormOverFieldCount($formInfo['id'], $this->checktimeId, $this->patientId);
            Laminas::$serviceManager->patientForm->update(['complete_filed_num'=>$over_num],[
                'is_del'=>0,
                'patient_id'=>$this->patientId,
                'checktime_id'=>$this->checktimeId,
                'form_id'=>$formInfo['id'],
            ]);
            unset($over_num);

            //更新已删除的明细进度信息
            if(isset($form_delete_content_arr[$formInfo['id']]) && !empty($form_delete_content_arr[$formInfo['id']])){
                Laminas::$serviceManager->swTaskClient->send([
                    'svName' => 'projectPatientworkbatch',
                    'methodName' => 'multipleUpdateData',
                    'params' => [
                        'item_id' => $this->itemId,
                        'itemsig_id' => 0,
                        'patient_id' => $this->patientId,
                        'checktime_id' => $this->checktimeId,
                        'form_id' => $formInfo['id'],
                        'operate_type'=>12,
                        'content_id'=>array_values($form_delete_content_arr[$formInfo['id']]),
                        'user_id' => Laminas::$serviceManager->identity->getId()
                    ]
                ]);
            }
            //异步处理访视进度情况信息
            $form_content_arr = isset($patient_form_content_arr[$formInfo['id']]) && !empty($patient_form_content_arr[$formInfo['id']]) ? $patient_form_content_arr[$formInfo['id']] : [];
            Laminas::$serviceManager->swTaskClient->send([
                'svName' => 'projectPatientworkbatch',
                'methodName' => 'multipleUpdateData',
                'params' => [
                    'item_id' => $this->itemId,
                    'itemsig_id' => 0,
                    'patient_id' => $this->patientId,
                    'checktime_id' => $this->checktimeId,
                    'form_id' => $formInfo['id'],
                    'operate_type'=>11,
                    'content_id'=>!empty($form_content_arr) ? $form_content_arr : [],
                    'user_id' => Laminas::$serviceManager->identity->getId()
                ]
            ]);
            unset($form_content_arr);
        }
        unset($form_delete_content_arr);
        unset($patient_form_content_arr);

        return true;
    }

    /**
     * 把暂存数据插入到正式表单中
     * @param $tempData
     * @param $currentForm
     * @return \Closure
     * @throws \Exception
     */
    protected function insertTempVal($tempData, $currentForm)
    {
        $shareGcoPool = $this->h()->form->getGcoPool($this->formId);

        $tempValue = StringHelper::jsonDecode($tempData);
        $insertVal = $tempValue['data'] ?? false;

        if (!$insertVal) {
            Db::rollback();
            throw new InvalidArgumentException("未找到暂存数据。");
        }

        // 因为缓存数据没有存共享的图片信息，导致锁定数据是一对一表单上传的共享图片丢失，这里再锁定的时候重新赋值一下
        if ( $this->h()->form->getType($this->formId) == Form::FORM_TYPE_SINGLE ) {
            // 一对一实际表单是有id的
            $shareFieldId = $this->h()->form->getShareFormField($this->formId)['id'] ?? 0;
            if ($shareFieldId && !empty($insertVal['id'])) {
                $insertVal[$shareFieldId] = $this->h()->formContent->getUploadFiles((int)$insertVal['id'], $shareFieldId);
            }
        }

        $this->setPostValues($insertVal);
        $this->itemsigId = $this->validator->attributes['itemsig_id'] = $insertVal['itemsig_id'] ?? 0;
        $this->itemId = $this->validator->attributes['item_id'] = $insertVal['item_id'] ?? 0;

        // 新增
        $completeStatus = $this->_getIsComplete($tempValue['data']);
        if ((isset($insertVal['id']) && (!$insertVal['id'] || $insertVal['id'] < 100)) || !isset($insertVal['id'])) {
            $this->contentPrimaryKey = (int)Laminas::$serviceManager->patientFormContent->save([
                'patient_id' => $insertVal['patient_id'] ?? 0,
                'form_id' => $insertVal['form_id'] ?? 0,
                'data' => json_encode($insertVal),
                'item_id' => $insertVal['item_id'] ?? 0,
                'checktime_id' => $insertVal['checktime_id'],
                'itemsig_id' => $insertVal['itemsig_id'] ?? 0,
                'update_time' => time(),
                'update_user_id' => $completeStatus,
                'is_yc' => $this->getIsYc(),
                'is_complete' => $this->_getIsComplete($tempValue['data']),
                'is_lock' => 1
            ]);

        } else {
            $this->contentPrimaryKey = (int)$insertVal['id'];
            // 记录哪些字段修改了
            $this->setContentUpdatedFields();
            $oldData = Laminas::$serviceManager->patientFormContent->getOneFieldVal('data','id = '.$this->contentPrimaryKey);
            $oldData = json_decode($oldData,true);
            if(isset($oldData['note']) && !empty($oldData['note'])){
                unset($oldData['note']);
            }
            $insertVal =  ArrayUtils::merge($oldData,$insertVal, true);
            Laminas::$serviceManager->patientFormContent->update([
                'data' => json_encode($insertVal),
                'update_time' => time(),
                'update_user_id' => Laminas::$serviceManager->identity->getId(),
                'is_yc' => $this->getIsYc(),
                'is_complete' => $completeStatus,
                'is_lock' => 1,
                'is_del' => 0
            ], ['id' => $this->contentPrimaryKey]);
        }

        // 关联状态
        $this->_updateRelationStatus();

        // 基点日期
        $this->_updateAnchor();

        // 更新关联表单
        $this->_updateFormRelation();

        $this->_triggerFieldLock();

        // 更新进度条
        /*if ($this->h()->item->getIsEdc($this->itemId) && $this->getContentData()['is_complete'] != $this->isComplete) {
            Laminas::$serviceManager->patientChecktimeList->isCompleteForm([
                'item_id' => $this->itemId,
                'itemsig_id' => $this->itemsigId,
                'patient_id' => $this->patientId,
                'form_id' => $currentForm['id'],
                'checktime_id' => $this->checktimeId,
                'type' => $this->isComplete === false ? 3 : 1,
            ]);
        }*/

        if (in_array(SDMHelper::app()->form->getIdentificationEdit($currentForm['id']), [0, 1])) {
            // 设置表单颜色。锁定了就是绿色
            $this->h()->patient->withoutCache()->setPatientFormCompleteStatus(1, $currentForm['id'], $this->checktimeId, $this->patientId);
        }elseif($completeStatus == 1){
            $this->h()->patient->withoutCache()->setPatientFormCompleteStatus(1, $currentForm['id'], $this->checktimeId, $this->patientId);
        }

        Laminas::$serviceManager->patientFormContentImg->update(['is_lock' => 1], ['form_id' => $currentForm['id'], 'patient_id' => $this->patientId, 'checktime_id' => $this->checktimeId]);

        $handleLogic = new HandleStorageLogic();
        $handleLogic->setOwner($this);
        $handleLogic->insertVal = $insertVal;
        $handleLogic->execute();

        // 如果有解锁已更新的状态就删掉
        $key = "SHARE_FORM_IS_UNLOCK_IS_UPDATED:{$this->itemId}";
        $hashKey = "{$this->patientId}:{$this->checktimeId}:{$shareGcoPool}";
        Laminas::$serviceManager->redisExtend->getRedisInstance()->hDel($key, $hashKey);

        // 申请解锁的状态也删掉
        $key = "UNLOCK_SHARE_FORM:{$this->itemId}";
        $hashKey = "{$this->patientId}:{$this->checktimeId}:{$shareGcoPool}";
        Laminas::$serviceManager->redisExtend->getRedisInstance()->hDel($key, $hashKey);

        // 删除历史解锁原因
        $key = "UNLOCK_SHARE_FORM_HISTORY:{$this->itemId}";
        $hashKey = "{$this->patientId}:{$this->checktimeId}:{$shareGcoPool}";
        Laminas::$serviceManager->redisExtend->getRedisInstance()->hDel($key, $hashKey);

        $childDatas = isset($insertVal['childData']) && !empty($insertVal['childData']) ? json_decode($insertVal['childData'],true):[];
        if(!empty($childDatas)){
            foreach ($childDatas as $field=>$childData){
                if(isset($childData['normal_type']) && !empty($childData['normal_type'])){
                    $key = $field.'-normal-type';
                    $insertVal[$key] = $childData['normal_type'];
                }
            }
        }
        $this->logger->setPostOriginData($insertVal)->setPostData($insertVal)->setContentId($this->contentPrimaryKey)->flush();

        // 如果覆盖成功就删除缓存内容
        return function() use ($currentForm) {
            // 一对一的才删掉。
            // 一对多的可能还涉及到解锁后的编辑和删除。
//            if ($this->h()->form->getType($currentForm['id']) == Form::FORM_TYPE_SINGLE) {
            $this->h()->formContent->removeTempStorage($this->patientId, $this->checktimeId, $currentForm['id']);
//            }
        };
    }

    /**
     * 解锁共享识别表单
     * @throws \Exception
     */
    public function unlockShareForm()
    {
        $this->event = EventEnum::EVENT_UNLOCK_SHARE_FORM_CONTENT;
        $forms = $this->h()->form->getGcoGroupForm($this->formId);
        $shareFormGcoPool = $this->h()->form->getGcoPool($this->formId);

        //判断是否存在AE数据【不存在的话直接删除异常值判断数据】
        $send_checkae_data = [
            'item_id'=>$this->itemId,
            'patient_id'=>$this->patientId,
            'checktime_id'=>$this->checktimeId,
            'form_ids'=>!empty($forms) ? array_values(array_column($forms,'id')) : [],
            'is_delete'=>1
        ];
        $checkAe = Laminas::$serviceManager->itemIdentificationresultchange->checkFormAe($send_checkae_data);
        if($checkAe['code'] == 1){
            throw new InvalidArgumentException($checkAe['mes']);
        }
        unset($send_checkae_data);
        unset($checkAe);

        $patient_form_content_arr = $all_patientformcontent_arr = [];
        foreach ($forms as $v) {
            // 判断当前检查点是否有这个表单存在, 不存在就直接跳过。
            if ($this->h()->checkTime->getHasForm($v['id'], $this->checktimeId) === false) {
                continue;
            }

            $allContent = Laminas::$serviceManager->patientFormContent->fetchAll([
                'where' => ['form_id' => $v['id'], 'patient_id' => $this->patientId, 'checktime_id' => $this->checktimeId]
            ]);

            if ($allContent) {
                // 设置锁定状态
                Laminas::$serviceManager->patientFormContent->update(['is_lock' => 0], ['form_id' => $v['id'], 'patient_id' => $this->patientId, 'checktime_id' => $this->checktimeId]);
                foreach ($allContent as $allContentKey=>$contentItem) {
                    // 关闭所有的质疑
                    SDMHelper::app()->logic->setCloseMessage('常规识别数据解锁更新')->newcloseRowError($contentItem['id'], $contentItem['item_id']);
                    $this->contentPrimaryKey = (int)$contentItem['id'];
                    if($contentItem['is_del'] == 0){
                        $patient_form_content_arr[$v['id']][] = $contentItem['id'];
                        $all_patientformcontent_arr[] = $contentItem['id'];
                    }
                }
            }

            if (in_array(SDMHelper::app()->form->getIdentificationEdit($v['id']), [0, 1])) {
                // 设置表单颜色状态
                $this->h()->patient->withoutCache()->setAutoPatientFormCompleteStatus(0, $v['id'], $this->checktimeId, $this->patientId);
            }

            // 重新构建临时存储数据
            if (SDMHelper::app()->form->getType($v['id']) == Form::FORM_TYPE_MULTI) {
                $this->h()->formContent->removeTempStorage($this->patientId, $this->checktimeId, $v['id']);
                $query = Laminas::$serviceManager->patientFormContent->fetchAll([
                    'where' => [
                        'form_id' => $v['id'],
                        'patient_id' => $this->patientId,
                        'checktime_id' => $this->checktimeId,
                        'is_del' => 0
                    ]
                ]) ?: [];
                foreach ($query as $item) {
                    // 关闭所有的质疑
//                    SDMHelper::app()->logic->setCloseMessage('常规识别数据更新')->closeRowError($item['id'], $item['item_id']);
                    $this->contentPrimaryKey = (int)$item['id'];
                    $this->h()->formContent->setMultiTempStorage(...[[
                        'data' => ArrayHelper::merge(StringHelper::jsonDecode($item['data']), [
                            'content_id' => $this->contentPrimaryKey,
                            'id' => $this->contentPrimaryKey,
                        ]), // 把主键给带上, 要不一直可编辑的一对多没法编辑
                        'create_user_id' => Laminas::$serviceManager->identity->getId(),
                        'create_time' => time(),
                    ], $this->patientId, $this->checktimeId, $v['id']]);

                    // 解锁记录日志(每个表单都要记录)
                    $this->logger->setContentId($this->contentPrimaryKey)->setEvent($this->event)->setPostOriginData($this->postOriginData)->setPostData($this->postData)->flush([
                        'item_id' => $this->itemId,
                        'patient_id' => $this->patientId,
                        'form_id' => $v['id'],
                        'checktime_id' => $this->checktimeId,
                        'itemsig_id' => $this->itemsigId,
                    ]);
                }
            }else {
                // 解锁记录日志(每个表单都要记录)
                $this->logger->setContentId($this->contentPrimaryKey)->setEvent($this->event)->setPostOriginData($this->postOriginData)->setPostData($this->postData)->flush([
                    'item_id' => $this->itemId,
                    'patient_id' => $this->patientId,
                    'form_id' => $v['id'],
                    'checktime_id' => $this->checktimeId,
                    'itemsig_id' => $this->itemsigId,
                ]);
            }
        }

        //更新申请解锁信息状态
        if(!empty($all_patientformcontent_arr)){
            //获取未确认的申请解锁信息
            $newApplyUnlock = Laminas::$serviceManager->patientFormUnlock->fetchAll([
                'where'=>['is_del'=>0,'is_confirm'=>0,'content_id'=>$all_patientformcontent_arr],
                'columns'=>['content_id'],
                'order'=>['update_time desc','id desc']
            ]);
            if(!empty($newApplyUnlock)){
                Laminas::$serviceManager->patientFormUnlock->confirmApplyunlock($newApplyUnlock[0]['content_id']);
                Laminas::$serviceManager->patientFormUnlock->update(['is_del'=>1,'is_confirm'=>1],['is_del'=>0,'is_confirm'=>0,'content_id'=>$all_patientformcontent_arr]);
            }
            unset($newApplyUnlock);
        }
        unset($all_patientformcontent_arr);

        // 将图片内的数据解除锁定
        Laminas::$serviceManager->patientFormContentImg->update([
            'is_lock' => 0
        ], ['form_id' => ArrayHelper::getColumn($forms, 'id'), 'patient_id' => $this->patientId, 'checktime_id' => $this->checktimeId]);

        $this->resubmit(); //解锁判断重复提交

        Db::commit();

        // 记录历史申请解锁原因
        $originReason = Laminas::$serviceManager->redisExtend->getRedisInstance()->hGet("UNLOCK_SHARE_FORM:{$this->itemId}", "{$this->patientId}:{$this->checktimeId}:{$shareFormGcoPool}");
        // 历史申请过解锁的, 解锁了才存在历史解锁的原因中
        if ($originReason) {
            Laminas::$serviceManager->redisExtend->getRedisInstance()->hSet("UNLOCK_SHARE_FORM_HISTORY:{$this->itemId}", "{$this->patientId}:{$this->checktimeId}:{$shareFormGcoPool}", $originReason);
        }

        // 删除申请解锁状态
        Laminas::$serviceManager->redisExtend->getRedisInstance()->hDel("UNLOCK_SHARE_FORM:{$this->itemId}", "{$this->patientId}:{$this->checktimeId}:{$shareFormGcoPool}");

        // 设置解锁未更新的状态
        Laminas::$serviceManager->redisExtend->getRedisInstance()->hSet("SHARE_FORM_IS_UNLOCK_NOT_UPDATED:{$this->itemId}", "{$this->patientId}:{$this->checktimeId}:{$shareFormGcoPool}", '1');



        //异步处理访视进度情况信息
        foreach ($forms as $formInfo) {
            //获取常规类识别表单完成的字段数量
            $over_num = SDMHelper::app()->patient->getShareFormOverFieldCount($formInfo['id'], $this->checktimeId, $this->patientId);
            Laminas::$serviceManager->patientForm->update(['complete_filed_num'=>$over_num],[
                'is_del'=>0,
                'patient_id'=>$this->patientId,
                'checktime_id'=>$this->checktimeId,
                'form_id'=>$formInfo['id'],
            ]);
            unset($over_num);

            $form_content_arr = isset($patient_form_content_arr[$formInfo['id']]) && !empty($patient_form_content_arr[$formInfo['id']]) ? $patient_form_content_arr[$formInfo['id']] : [];
            Laminas::$serviceManager->swTaskClient->send([
                'svName' => 'projectPatientworkbatch',
                'methodName' => 'multipleUpdateData',
                'params' => [
                    'item_id' => $this->itemId,
                    'itemsig_id' => 0,
                    'patient_id' => $this->patientId,
                    'checktime_id' => $this->checktimeId,
                    'form_id' => $formInfo['id'],
                    'operate_type'=>11,
                    'content_id'=>!empty($form_content_arr) ? $form_content_arr : [],
                    'user_id' => Laminas::$serviceManager->identity->getId()
                ]
            ]);
            unset($form_content_arr);
        }
        unset($patient_form_content_arr);
    }

    public function deleteShareFormMulti($index)
    {
        $forms = $this->h()->form->getGcoGroupForm($this->formId);

        // 看看当前图片是否已经锁定了
        $allImages = Laminas::$serviceManager->patientFormContentImg->fetchAll([
            'where' => [
                'patient_id' => $this->patientId,
                'checktime_id' => $this->checktimeId,
                'form_id' => ArrayHelper::getColumn($forms, 'id'),
                'is_del' => 0
            ]
        ]);

        if (array_sum(ArrayHelper::getColumn($allImages, 'is_lock')) > 0) {
            throw new InvalidArgumentException("当前数据已经被锁定。");
        }

        $redis = Laminas::$serviceManager->redisExtend->getRedisInstance();
        $key = RedisEnum::PATIENT_FORM_TEMP_STORAGE . md5("{$this->patientId}{$this->checktimeId}{$this->formId}");

        // 批量删除
        if (stripos($index, ',') !== false) {
            $originData = $redis->lRange($key, 0, -1);
            $deleteIndex = explode(',', $index);
            if (array_sum($deleteIndex) > 10000) {
                throw new InvalidArgumentException('请刷新列表重试。');
            }
            SDMHelper::app()->formContent->removeTempStorage($this->patientId, $this->checktimeId, $this->formId);
            foreach ($originData as $originDataIndex => $originDataItem) {
                if (!in_array($originDataIndex + 1, $deleteIndex)) {
                    $this->h()->formContent->setMultiTempStorage(...[[
                        'data' => StringHelper::jsonDecode($originDataItem)['data'],
                        'create_user_id' => Laminas::$serviceManager->identity->getId(),
                        'create_time' => time(),
                    ], $this->patientId, $this->checktimeId, $this->formId]);
                }
            }
        } else {
            Laminas::$serviceManager->redisExtend->getRedisInstance()->lset($key, $index - 1, 'TO_BE_REMOVED');
            Laminas::$serviceManager->redisExtend->getRedisInstance()->lRem($key, 'TO_BE_REMOVED', -1);
        }
    }

    /**
     * Notes: 获取CM合并用药表单用药ID
     * User: lltyy
     * DateTime: 2025/8/27 20:51
     *
     * @param $data //提交数据
     * @param $form_id //表单ID
     * @return int
     */
    public function getCmDrug($data,$form_id){
        $drug_id = 0;
        //判断该表单是否为CM合并用药表单
        $is_cm_form = Laminas::$serviceManager->itemForm->getCount(['id' =>$form_id,'is_del' => 0,'type' => 1,'var_name' => 'CM']);
        if(!empty($is_cm_form)){
            //获取该表单下对应的药物名称字段ID
            $cm_name_id = Laminas::$serviceManager->itemFormField->getOneFieldVal('id',[
                'form_id' => $form_id,
                'is_del' => 0,
                'var_name' => 'CMNAM'
            ]);
            if(!empty($cm_name_id)){
                //获取药物名称
                $drug_name = isset($data[$cm_name_id]) && !is_null($data[$cm_name_id]) && $data[$cm_name_id] != '' ? trim($data[$cm_name_id]) : '';
                if($drug_name != ''){
                    $drug_id = Laminas::$serviceManager->collectDrug->getOneFieldVal('id',['is_del'=>0,'name'=>$drug_name]);
                    $drug_id = !empty($drug_id) ? $drug_id : 0;
                }
                unset($drug_name);
            }
            unset($cm_name_id);
        }
        unset($is_cm_form);
        return $drug_id;
    }


    /**
     * @return void
     * @throws \Exception
     * 导入更新随机分组 判断
     */
    private function _importUpdateRandomGroup()
    {
        if ($this->h()->form->getGroupId($this->formId) != FormGroup::RANDOM_GROUP) {
            return;
        }

        $versionData = $this->_getVersionData();

        $previewData = Laminas::$serviceManager->itemForm->setRequestParams($this->validator->attributes)->getPreviewConfig($this->validator->attributes['form_id']);

        // 获取变量名
        $getRandomContent = function ($k) use ($previewData, $versionData) {
            $field = explode('-', $k);
            if (count($field) > 1) {
                array_shift($field);
            } else {
                return $versionData[$k]['var_name'] ?? false;
            }

            if (count($field) > 1) {
                $attribute = ArrayHelper::getValue($previewData, implode('.', $field))[0]['var_name'] ?? '';
                if (stripos($attribute, 'CONTENT') !== false) {
                    return $attribute;
                }
            }

            return false;
        };


        $randomGroupValue = $randomGroupKey = null;

        // 是否已经更新过随机分组日期。
        // 如果有随即日期字段, 并且写值了就传。
        $isHasRandomDateField = false;

        foreach ($this->postData as $k => $datum) {
            // 如果是手写随机号, 研究分层需要存起来传过去
            if (in_array($getRandomContent($k), ['RANDOM_GROUP_CUSTOM', 'RANGC'])) {
                $randomGroupValue = $datum;
                $randomGroupKey = $k;
            }

            if (in_array($getRandomContent($k), ['RANDOM_GROUP_CUSTOM', 'RANGC'])) {
                if (!$datum) {
                    $this->importErrors[] = "请选择正确的研究分层";
                }

            } elseif ($getRandomContent($k) == 'RANDOM_GROUP_SYSTEM' || $getRandomContent($k) == 'RANGCA') { // 系统的研究分层
                if (!$datum) {
                    $this->importErrors[] = "请选择研究分层";
                }
            } elseif ( (SDMHelper::app()->getFormHelper()->getSystemRandomFieldId() && $k == $this->systemRandomFieldKey ) || $getRandomContent($k) == 'RANDOM_GROUP_SYSTEM_CONTENT') { // 系统分配
                if (!$datum) {
                    $this->importErrors[] = "请选择正确的随机号。";
                }

                if ($this->event === EventEnum::EVENT_FORM_CONTENT_EDIT) {
                    $this->validCanUpdateRandomGroup($versionData);
                }

//                $res = Laminas::$serviceManager->itemRandomdetails->setRandomdetailsNumber($datum, $this->validator->attributes['itemsig_id'], $this->validator->attributes['patient_id']);
//
//                if ($res !== true) {
//                    throw new InvalidArgumentException("请重新选择随机号");
//                }

            } elseif ($getRandomContent($k) == 'RANDOM_GROUP_CUSTOM_CONTENT') { // 手动填写

                if (!$datum) {
                    $this->importErrors[] = "请输入正确的随机号。";
                }

                // 手写先判断能否切换研究分层
                if ($this->event === EventEnum::EVENT_FORM_CONTENT_EDIT) {
                    $this->validCanUpdateRandomGroupCustom($randomGroupKey, $randomGroupValue);
                }

                $isUsed = Laminas::$serviceManager->itemRandomdetails->fetchOne([
                    'where' => (new Where())
                        ->nest()
                        ->equalTo('is_del', 1)->or->equalTo('is_use', 1)
                        ->unnest()
                        ->equalTo('item_id', $this->validator->attributes['item_id'])
                        ->equalTo('item_sign_id', $this->validator->attributes['itemsig_id'])
                        ->equalTo('randomdetails_name', $datum)
                ]);

                if ($isUsed) {
                    $this->importErrors[] = "同方案分组被调用/作废";
                }

                $hasRandomNumber = Laminas::$serviceManager->patient->fetchOne([
                    'where' => (new Where())
                        ->equalTo('item_id', $this->validator->attributes['item_id'])
                        ->equalTo('itemsig_id', $this->validator->attributes['itemsig_id'])
                        ->equalTo('random_number', $datum)
                ]);

                if ($hasRandomNumber && $hasRandomNumber['id'] != $this->validator->attributes['patient_id']) {
                    $this->importErrors[] = "随机号重复啦!!!";
                }

//                Laminas::$serviceManager->patient->update([
//                    'random_number' => $datum
//                ], ['id' => $this->validator->attributes['patient_id']]);
//
//                if ($randomGroupValue) {
//                    Laminas::$serviceManager->itemRandomdetails->setRandom($randomGroupValue, $this->validator->attributes['itemsig_id'], $this->validator->attributes['patient_id'], $datum);
//                }
            }

            // 如果有随机日期, 并且有值。
//            if (DataHelper::isField($k) && $this->h()->form->field->getVarName($k) === 'RANDDAT') {
//                $isHasRandomDateField = true;
//                if ($datum) {
//                    Event::trigger(EventEnum::BEFORE_EVENT_SUBMIT_RANDOM_TIME, [$this, strtotime($datum)]);
//                }
//            }
        }

//        if ($isHasRandomDateField === false) {
//            // 没随即日期字段就传一个时间戳。
//            Event::trigger(EventEnum::BEFORE_EVENT_SUBMIT_RANDOM_TIME, [$this, time()]);
//        }
    }


    /**
     * @return void
     * @throws \Exception
     * 导入 更新表单关联判断
     */
    private function _importUpdateFormRelation()
    {
        $versionData = $this->_getVersionData();

        foreach ($this->postData as $k => $datum) {
            if (!DataHelper::isField($k)) {
                continue;
            }

            $postField = DataHelper::getFieldId($k);

            if (is_numeric($k) && in_array($versionData[$postField]['type'], [FormField::FORM_FIELD_TYPE_RADIO]) && $lockError = $this->_hasRadioLock($k, $datum)) {
                throw new InvalidArgumentException($lockError);
            }

            if (isset($versionData[$postField]) && isset($versionData[$postField]['children'])) {
                foreach ($versionData[$postField]['children'] as $child) {

                    $updateCheckTime = (array)$this->validator->attributes['checktime_id'];
                    // 表单关联, 并且选中的是需要展示关联表单的值
                    if ($child['value'] == $datum && $child['relation_classification'] == ItemFormFieldRadio::RELATION_CLASSIFICATION_FORM) {
                        foreach ($child['relation_information'] as $information) {
                            if (!$information) {
                                $this->importErrors[] = '请完善表单内容设置。';
                            }
                        }

                    } elseif ($child['relation_classification'] == ItemFormFieldRadio::RELATION_CLASSIFICATION_FORM) { // 表单关联, 并且选中的不是需要展示关联表单的值
                        foreach ($child['relation_information'] as $information) {
                            if (!$information) {
                                $this->importErrors[] = '请完善表单内容设置。';
                            }
                        }
                    }
                }
            }
        }
    }


    /**
     * 导入 更新上传附件 判断
     */
    private function _importUpdateAttach()
    {
        $isYc = $this->getIsYc();

        if (!in_array($this->h()->form->getGroupId($this->formId), [FormGroup::CHECK_OCR, FormGroup::CHECK_DO])) {
            return;
        }


        $formVersion = $this->_getVersionData();

        // 已开具 并且不是补图
        if (in_array($isYc, [0, -1])) {
            $this->deleteAllWorkAnnex();
        }

        foreach ($this->postData as $k => $datum) {
            $type = 0;

            $field = $this->_getFieldId($k);

            if (isset($formVersion[$field])) {
                $type = $this->getFieldType($formVersion[$field]);
                // 计划外检查存到图片表
//                if ($type == 2) {
//                    $this->updateOutPlanCheckContentImg($datum, $k);
//                }
            }
            // 手动填写
            if ($k === Form::ATTACH_SDTX) {
                $type = 3;
            }

            // 如果是化验单或者手动填写或者医嘱
            if (in_array($type, [1, 3, self::ANNEX_TYPE_DO])) {
                // 上传图片的数据
                $imgData = StringHelper::jsonDecode($datum) ?: [];

                // 清理旧数据
                $this->deleteAllAnnexFile($type, $imgData);

                if ($type == 3) {
//                    // 化验单手动填写, 需要向附件表插入个固定的附件
                    if ($k == Form::ATTACH_SDTX && isset($this->postData[Form::ATTACH_SDTX]) && $this->postData[Form::ATTACH_SDTX] != '[]') {
                        $imgData = [];
                        $imgData[] = [
                            'name' => Form::ATTACH_SDTX_ANNEX_TITLE,
                            'url' => Form::ATTACH_SDTX_ANNEX_PATH,
                        ];
                    }
                }

                // 没上传图片, 并且没有手动填写就跳过呗
                if (!$imgData) {
                    continue;
                }
                // 检查项id
                $categoryId = $this->getItemFormData()['checklist_id'];

                // 找模板需要将小项目id转换成大项目id
                $mainItemId = Laminas::$serviceManager->itemInfo->fetchOne(['where' => ['id' => $this->validator->attributes['item_id']]])['fid'] ?: $this->validator->attributes['item_id'];

                // 获取化验单类型
                $reportType = $this->getReportType($categoryId);

                if (in_array($this->getItemFormData()['group_id'], [FormGroup::CHECK_OCR, FormGroup::CHECK_DO])) {
                    // 识别结果模板数据
                    $imgTxtDiscernData = $this->getImgTxtDiscernData($this->validator->attributes['item_id'], $categoryId);
                }
                // 表单数据关联表
//                $patientFormId = $this->h()->setAttributes(['patient_id' => $this->patientId])->patient->getPatientFormId($this->formId, $this->checktimeId);
                $patientFormId = 0;

                foreach ($imgData as $checkImgDatum) {

                    if (stripos($this->getInsertAnnexString(), $checkImgDatum['url']) === false && $checkImgDatum['url'] != Form::ATTACH_SDTX_ANNEX_PATH) {
                        continue;
                    }

                    $annexPath = $this->_getAnnexPath($checkImgDatum['url']);

                    // 识别附件表
                    $this->importSaveAnnex($type, [
                        'annex_title' => $checkImgDatum['name'],
                        'annex_path' => $annexPath,
                        'annex_type' => $this->getAnnexType($checkImgDatum['name'], $type), // 3是手动填写
                        'up_annex_date' => time(),
                        'is_del' => 0,
                        'item_id' => $this->validator->attributes['item_id'],
                        'itemsig_id' => $this->validator->attributes['itemsig_id'],
                        'patient_id' => $this->validator->attributes['patient_id'],
                        'checktime_id' => $this->validator->attributes['checktime_id'],
                        'researchstage_id' => $this->validator->attributes['stage_id'] ?? 0,
                        'form_id' => $this->validator->attributes['form_id'],
                        'patientchecktime_id' => $this->validator->attributes['checktime_id'],
                        'category_id' => $categoryId,
                        'ocr_id' => $imgTxtDiscernData['ocr_id'] ?? -1,
                        'patient_form_id' => $patientFormId,
                        'report_type' => $reportType,
                        'is_lock_operate' => $this->isEditFormByQuestion === true ? 0 :$this->getIsLockOperate(),
                        'formcontent_id' => $this->contentPrimaryKey,
                    ]);
                }
            }
        }
    }

    /**
     * 保存相应的数据
     * @param int $type
     * @param array $rowData
     * @return bool|void
     */
    private function importSaveAnnex(int $type, array $rowData)
    {
        $dataBase = $this->getAnnexDatabase($type);

        // 手动填写
        if ($rowData['annex_title'] === Form::ATTACH_SDTX_ANNEX_TITLE) {
            $rowData = ArrayHelper::merge($rowData, [
                'change_type' => 1,
                'is_result' => 1,
                'ocr_state' => 1,
                'collect_date' => strtotime(($this->getSdtxData()['check_date'] ?? false)) ?: 0
            ]);

            // 编辑手动填写
            if (stripos($this->getKeepAnnexString(), $rowData['annex_path']) === false) {
                $annexId = $dataBase->save($rowData);
                $this->checkImgArray[] = $annexId;
                // 新增手动填写结果
//                Laminas::$serviceManager->itemIdentificationresult->save([
//                    'content' => $this->generateIdentificationResultContent(),
//                    'workannex_id' => $annexId
//                ]);
            }
            $this->importSaveIdentificationResultChange($rowData);
        }
    }

    /**
     * 手动填写添加验证
     * @param array $rowData
     */
    private function importSaveIdentificationResultChange(array $rowData): void
    {
        $data = $this->getSdtxData();

        $checkNameData = ArrayHelper::index($this->getCheckNameData(), 'id');

        foreach ($data['content'] ?? [] as $k => &$value) {

            // 检查值类型1:整数 2:一位小数 3:两位小数 4:三位小数 5:文本
            // https://e.gitee.com/yikeen_project/projects/188221/requirements/table?issue=I5TY3T
            $checkType = $checkNameData[$value['id']]['check_type'];

            // 最小值不允许输入非数字类型的值
            if ($value['min_val'] && !ValidatorHelper::isNumber($value['min_val'])) {
                $this->importErrors[] = '最小值不允许输入非数字的类型';
            }

            // 如果类型不是文本, 最大值只能输入数字
            if ( $value['max_val'] && $checkType != 5 && !ValidatorHelper::isNumber($value['max_val'])) {
                $this->importErrors[] = '最大值不允许输入非数字的类型';
            }
        }
    }
}
