337 lines
14 KiB
PHP
337 lines
14 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
/**
|
|
* The thinkStepBase widget class file of zin module of ZenTaoPMS.
|
|
*
|
|
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
|
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
|
* @author Zemei Wang<wangzemei@easycorp.ltd>
|
|
* @package zin
|
|
* @link http://www.zentao.net
|
|
*/
|
|
namespace zin;
|
|
|
|
/**
|
|
* 思引师基础节点内容。
|
|
* thinmory basic node content.
|
|
*/
|
|
|
|
class thinkStepBase extends wg
|
|
{
|
|
protected static array $defineProps = array(
|
|
'title?: string', // 标题
|
|
'desc?: string', // 描述
|
|
'isRun?: bool=false', // 是否是分析活动
|
|
'step?: object', // 整个步骤的对象
|
|
'mode?: string="detail"', // detail|create|edit
|
|
'type?: string="node"', // node|transition/question
|
|
'quoteQuestions?: array'. // 引用的问题
|
|
'quotedQuestions?: attay', // 被引用的问题
|
|
'isResult?: bool=false', // 是否是结果页
|
|
'wizard?: object', // 模型数据
|
|
);
|
|
|
|
public static function getPageCSS(): ?string
|
|
{
|
|
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
|
}
|
|
|
|
protected function buildDetail(): array
|
|
{
|
|
global $lang, $app;
|
|
$app->loadLang('thinkrun');
|
|
$app->loadLang('thinkstep');
|
|
list($step, $mode, $wizard) = $this->prop(array('step', 'mode', 'wizard'));
|
|
if($mode != 'detail') return array();
|
|
|
|
$options = $step->options;
|
|
if($step->type == 'question')
|
|
{
|
|
$questionType = $options->questionType;
|
|
$tips = $lang->thinkstep->$questionType;
|
|
$setOption = empty($options->setOption) || $options->setOption == 0;
|
|
if(!empty($options->required) && $questionType == 'checkbox' && $setOption)
|
|
{
|
|
$tips = $lang->thinkrun->requiredTitle[$questionType];
|
|
$tips = str_replace(array('%min%', '%max%'), array($options->minCount, $options->maxCount), $tips);
|
|
}
|
|
if(!empty($options->required) && $questionType == 'tableInput')
|
|
{
|
|
if($wizard->model == 'bcg' && empty($options->requiredRows)) $options->requiredRows = 3;
|
|
if($options->supportAdd) $tips = sprintf($lang->thinkrun->tableInputTitle->notSupportAdd, count($options->fields), $options->requiredRows);
|
|
if(!$options->supportAdd) $tips = sprintf($lang->thinkrun->tableInputTitle->supportAdd, $options->requiredRows);
|
|
}
|
|
}
|
|
|
|
$requiredSymbal = !empty($options->required) ? span(setClass('text-danger mr-0.5 h-5'), '*') : null;
|
|
$questionTips = !empty($tips) ? span(setClass('text-gray mx-1'), '(' . $tips . ')') : null;
|
|
$errorText = isset($options->questionType) && !empty($lang->thinkrun->error->requiredType[$options->questionType]) ? span
|
|
(
|
|
setClass('run-error-msg h-5 inline-block text-canvas text-md px-2 ml-0.5 rounded-md hidden'),
|
|
setStyle('background', 'var(--color-danger-600)'),
|
|
$lang->thinkrun->error->requiredType[$options->questionType]
|
|
) : null;
|
|
|
|
return array
|
|
(
|
|
div
|
|
(
|
|
setClass('flex items-start justify-between mb-2 step-title'),
|
|
$step->type == 'question' ? div
|
|
(
|
|
setClass('h-full text-fore text-lg'),
|
|
$requiredSymbal,
|
|
isset($step->index) ? $step->index . '. ' : '',
|
|
$step->title,
|
|
$questionTips,
|
|
$errorText
|
|
) : div
|
|
(
|
|
setClass('text-2xl'),
|
|
$step->title
|
|
)
|
|
),
|
|
div
|
|
(
|
|
setClass('run-desc mb-3.5'),
|
|
setStyle(array('margin-top' => '-28px')),
|
|
section
|
|
(
|
|
setClass('break-words'),
|
|
set::content(!empty($step->desc) ? htmlspecialchars_decode($step->desc) : ''),
|
|
set::useHtml(true)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
protected function buildDetailTip(): array
|
|
{
|
|
global $lang, $app, $config;
|
|
$app->loadLang('thinkstep');
|
|
$app->loadLang('thinkrun');
|
|
list($quoteQuestions, $quotedQuestions, $step, $isRun, $wizard) = $this->prop(array('quoteQuestions', 'quotedQuestions', 'step', 'isRun', 'wizard'));
|
|
|
|
$preViewModel = in_array($wizard->model, $config->thinkwizard->hiddenMenuModel);
|
|
if(!empty($step->options->fields)) $step->options->fields = is_string($step->options->fields) ? explode(', ', $step->options->fields) : array_values((array)$step->options->fields);
|
|
|
|
$questionType = !empty($step) && $step->type == 'question' ? $step->options->questionType : '';
|
|
$isCheckBox = !empty($step) && $step->type == 'question' && in_array($questionType, $config->thinkstep->quoteQuestionType);
|
|
$isQuoteItem = $isCheckBox && !empty($step->options->setOption) && $step->options->setOption == 1;
|
|
$quoteTitleList = !empty($step->options->quoteTitle) ? explode(", ", $step->options->quoteTitle) : array();
|
|
$detailTip = array();
|
|
$quotedItems = array();
|
|
$sourceQuestion = array();
|
|
$sourceItems = array();
|
|
|
|
$wizard->config = !empty($wizard->config) ? $wizard->config : array();
|
|
$wizard->config = is_string($wizard->config) ? json_decode($wizard->config, true) : $wizard->config;
|
|
$configureObjects = !empty($wizard->config['configureObjects']) ? json_decode($wizard->config['configureObjects'], true) : array();
|
|
$isAssignedObject = !empty($configureObjects['isAssignedObject']) ? $configureObjects['isAssignedObject'] : 0;
|
|
$showBuiltTip = isset($step->options->canConfigureRatio) && $step->options->canConfigureRatio == 0;
|
|
|
|
if(!empty($quotedQuestions))
|
|
{
|
|
foreach($quotedQuestions as $item)
|
|
{
|
|
$quotedItems[] = a
|
|
(
|
|
setClass('block text-primary-500 leading-relaxed'),
|
|
set::href(createLink('thinkstep', 'view', "marketID=0&&wizardID=$item->wizard&&stepID=$item->id&&from=detail")),
|
|
setData('toggle', 'modal'),
|
|
setData('dismiss', 'modal'),
|
|
setData('size', 'sm'),
|
|
$item->index . '. ' . $item->title
|
|
);
|
|
}
|
|
}
|
|
|
|
if($isQuoteItem && !empty($quoteQuestions))
|
|
{
|
|
foreach($quoteQuestions as $item)
|
|
{
|
|
if(!$isRun && in_array($item->id, $quoteTitleList)) $sourceQuestion[] = $item;
|
|
if($isRun && in_array($item->origin, $quoteTitleList)) $sourceQuestion[] = $item;
|
|
}
|
|
}
|
|
if(!empty($sourceQuestion))
|
|
{
|
|
foreach ($sourceQuestion as $sourceQuestionItem)
|
|
{
|
|
$sourceItems[] = a
|
|
(
|
|
setClass('block text-primary-500 leading-relaxed'),
|
|
set::href(createLink('thinkstep', 'view', "marketID=0&&wizardID=$sourceQuestionItem->wizard&&stepID=$sourceQuestionItem->id&&from=detail")),
|
|
setData('toggle', 'modal'),
|
|
setData('dismiss', 'modal'),
|
|
setData('size', 'sm'),
|
|
$sourceQuestionItem->index . '. ' . $sourceQuestionItem->title
|
|
);
|
|
}
|
|
}
|
|
$runSourceTip = !empty($sourceQuestion) && !$preViewModel;
|
|
|
|
if($isRun && (!empty($quotedQuestions) || $runSourceTip))
|
|
{
|
|
$tipType = $lang->thinkstep->label->option;
|
|
$sourceQuestionTip = array();
|
|
if($runSourceTip)
|
|
{
|
|
foreach ($sourceQuestion as $sourceQuestionItem)
|
|
{
|
|
$sourceQuestionType = is_string($sourceQuestionItem->options) ? json_decode($sourceQuestionItem->options)->questionType : $sourceQuestionItem->options->questionType;
|
|
if($sourceQuestionType == 'multicolumn') $tipType = sprintf($lang->thinkstep->entry, $step->options->selectColumn);
|
|
$sourceQuestionTip[] = div
|
|
(
|
|
setClass('ml-4 pl-0.5'),
|
|
sprintf($lang->thinkstep->tips->checkbox, $lang->thinkstep->tips->options[$questionType], ($sourceQuestionItem->index . '. ' . $sourceQuestionItem->title)),
|
|
$tipType
|
|
);
|
|
}
|
|
}
|
|
$showRunTips = ((!empty($quotedQuestions) && empty($isAssignedObject)) || !empty($runSourceTip));
|
|
$detailTip[] = $showRunTips ? div
|
|
(
|
|
setClass('bg-primary-50 text-gray p-2 mt-3 leading-normal'),
|
|
(!empty($quotedQuestions) && empty($isAssignedObject)) ? div
|
|
(
|
|
setClass('flex items-center'),
|
|
icon(setClass('font text-warning mr-1'), 'about'),
|
|
$lang->thinkrun->tips->quotedTip
|
|
) : null,
|
|
!empty($runSourceTip) ? $sourceQuestionTip : null
|
|
) : null;
|
|
}
|
|
if(!$isRun)
|
|
{
|
|
/* 以下类型引用其他没有答案的问题,底部需提示信息。The following types of questions refer to other unanswered questions, and prompt information is required at the bottom. */
|
|
$quoteTipsType = array('multicolumn', 'score', 'tableInput');
|
|
if(!empty($sourceQuestion) && !empty($questionType) && in_array($questionType, $quoteTipsType))
|
|
{
|
|
$quoteTips = empty($step->options->fields) ? div(setClass('text-sm text-gray-400 leading-loose mt-2'), $lang->thinkstep->tips->{$questionType}) : null;
|
|
}
|
|
$detailTip[] = array
|
|
(
|
|
!empty($sourceQuestion) ? array(
|
|
div
|
|
(
|
|
setClass('bg-primary-50 leading-normal p-2 mt-3'),
|
|
div(sprintf($lang->thinkstep->tips->sourceofOptions, $lang->thinkstep->tips->options[$questionType])),
|
|
$sourceItems
|
|
),
|
|
!empty($quoteTips) ? $quoteTips : null
|
|
) : null,
|
|
(!empty($quotedQuestions) && !$preViewModel) ? div
|
|
(
|
|
setClass('bg-primary-50 leading-normal p-2 mt-3'),
|
|
div(sprintf($lang->thinkstep->tips->optionsAreReferenced, $questionType == 'multicolumn' ? $lang->thinkstep->inputItem : $lang->thinkstep->label->option)),
|
|
$quotedItems
|
|
) : null
|
|
);
|
|
}
|
|
if($preViewModel)
|
|
{
|
|
if((!empty($quotedQuestions) && !empty($isAssignedObject)) || $showBuiltTip) $detailTip[] = $this->buildTipsNode($lang->thinkwizard->previewSteps->quotedTips);
|
|
if(isset($step->options->isPreset) && $step->options->isPreset == 1) $detailTip[] = $this->buildTipsNode($lang->thinkwizard->previewSteps->presetDataTips);
|
|
}
|
|
return $detailTip;
|
|
}
|
|
|
|
protected function buildTipsNode(string $message): node
|
|
{
|
|
return div
|
|
(
|
|
setClass('flex text-gray-400 mt-2 items-center text-sm ml-2'),
|
|
icon(setClass('text-important mr-2'), 'about'),
|
|
span(setClass('leading-6'), $message)
|
|
);
|
|
}
|
|
|
|
protected function buildFormItem(): array
|
|
{
|
|
global $lang, $app;
|
|
$app->loadLang('thinkstep');
|
|
list($step, $title, $desc, $type, $mode) = $this->prop(array('step', 'title', 'desc', 'type', 'mode'));
|
|
if($mode == 'create') $title = $lang->thinkstep->untitled . $lang->thinkstep->$type;
|
|
if($step)
|
|
{
|
|
$title = $step->title;
|
|
$desc = htmlspecialchars_decode($step->desc);
|
|
}
|
|
|
|
return array(
|
|
formGroup
|
|
(
|
|
set::width('full'),
|
|
set::label($lang->thinkstep->label->title),
|
|
set::labelClass('required'),
|
|
input
|
|
(
|
|
setClass('is-required'),
|
|
set::value($title ?? ''),
|
|
set::name('title'),
|
|
set::placeholder($lang->thinkstep->placeholder->inputContent)
|
|
)
|
|
),
|
|
formGroup
|
|
(
|
|
set::width('full'),
|
|
set::label($lang->thinkstep->label->desc),
|
|
editor
|
|
(
|
|
setClass('desc'),
|
|
set::name('desc'),
|
|
set::placeholder($lang->thinkstep->placeholder->pleaseInput),
|
|
html($desc ?? ''),
|
|
set::rows(3)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
protected function buildForm(): wg
|
|
{
|
|
global $lang;
|
|
$actions = array(array(
|
|
'text' => $lang->save,
|
|
'btnType' => 'submit',
|
|
'class' => 'primary h-7 ring-0 submit-btn px-4',
|
|
'style' => array('min-width' => '0')
|
|
));
|
|
|
|
return formPanel
|
|
(
|
|
setClass('think-step-panel py-4 px-0'),
|
|
set::formClass('form-watched gap-3'),
|
|
set::bodyClass('think-step-form'),
|
|
set::actions($actions),
|
|
formHidden('type', $this->prop('type')),
|
|
$this->buildFormItem()
|
|
);
|
|
}
|
|
|
|
protected function build(): wg|node|array
|
|
{
|
|
list($isResult, $step, $isRun) = $this->prop(array('isResult', 'step', 'isRun'));
|
|
$questionType = '';
|
|
if($isResult && isset($step->options->questionType)) $questionType = $step->options->questionType;
|
|
|
|
$content = $isRun ? div
|
|
(
|
|
setClass('w-full col bg-white items-center pt-4 pb-10 px-8 mb-4'),
|
|
div
|
|
(
|
|
setStyle(array('max-width' => '878px')),
|
|
setClass('w-full'),
|
|
$this->buildDetail(),
|
|
$this->buildDetailTip()
|
|
)
|
|
) : div
|
|
(
|
|
$questionType == 'tableInput' ? setStyle(array('min-width' => '220px')) : null,
|
|
$this->buildDetail(),
|
|
$this->buildDetailTip()
|
|
);
|
|
return $this->prop('mode') == 'detail' ? $content : $this->buildForm();
|
|
}
|
|
}
|