* add icon selector for the assistant edit.
This commit is contained in:
+23
-5
@@ -411,20 +411,33 @@ class ai extends control
|
||||
if(strtolower($this->server->request_method) == 'post')
|
||||
{
|
||||
$assistant = fixer::input('post')->get();
|
||||
|
||||
if(empty($assistant->name))
|
||||
{
|
||||
dao::$errors['name'][] = sprintf($this->lang->ai->validate->noEmpty, $this->lang->ai->assistants->name);
|
||||
}
|
||||
if(empty($assistant->modelId))
|
||||
{
|
||||
dao::$errors['modelId'][] = sprintf($this->lang->ai->validate->noEmpty, $this->lang->ai->models->common);
|
||||
}
|
||||
if(empty($assistant->systemMessage))
|
||||
{
|
||||
dao::$errors['systemMessage'][] = sprintf($this->lang->ai->validate->noEmpty, $this->lang->ai->assistants->systemMessage);
|
||||
}
|
||||
if(empty($assistant->greetings))
|
||||
{
|
||||
dao::$errors['greetings'][] = sprintf($this->lang->ai->validate->noEmpty, $this->lang->ai->assistants->greetings);
|
||||
}
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
$exists = $this->ai->checkAssistantDuplicate($assistant->name, $assistant->modelId);
|
||||
if($exists) return $this->send(array('result' => 'fail', 'message' => array('name' => $this->lang->ai->assistants->duplicateTip)));
|
||||
|
||||
$assistant->id = $assistantId;
|
||||
|
||||
$exists = $this->ai->checkAssistantDuplicate($assistant->name, $assistant->modelId);
|
||||
if($exists && $exists->id != $assistantId) return $this->send(array('result' => 'fail', 'message' => array('name' => $this->lang->ai->assistants->duplicateTip)));
|
||||
|
||||
$assistant->icon = "$assistant->iconName-$assistant->iconTheme";
|
||||
unset($assistant->iconName, $assistant->iconTheme);
|
||||
|
||||
$this->ai->updateAssistant($assistant);
|
||||
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
@@ -439,9 +452,14 @@ class ai extends control
|
||||
}, array());
|
||||
|
||||
$assistant = $this->ai->getAssistantById($assistantId);
|
||||
$this->view->models = $models;
|
||||
|
||||
list($iconName, $iconTheme) = explode('-', $assistant->icon);
|
||||
|
||||
$this->view->models = $models;
|
||||
$this->view->assistant = $assistant;
|
||||
$this->view->title = $this->lang->ai->assistants->edit;
|
||||
$this->view->iconName = $iconName;
|
||||
$this->view->iconTheme = $iconTheme;
|
||||
$this->view->title = $this->lang->ai->assistants->edit;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#ai-edit-icon {position: relative; overflow: hidden; display: flex; justify-content: center; align-items: center;}
|
||||
#ai-edit-icon #edit-icon {display: none; position: absolute; inset: 0; background-color: rgba(230, 240, 255, 0.7);}
|
||||
#ai-edit-icon:hover {border: 1px solid #EDEEF1;}
|
||||
#ai-edit-icon:hover #edit-icon {display: flex; justify-content: center; align-items: center;}
|
||||
#icon-buttons svg {cursor: pointer;}
|
||||
.theme-checked {display: flex; justify-content: center; align-items: center;}
|
||||
|
||||
#ai-edit-icon > svg {width: 30px; height: 30px;}
|
||||
#preview-icon > svg {width: 30px; height: 30px;}
|
||||
@@ -15,9 +15,6 @@
|
||||
});
|
||||
})();
|
||||
|
||||
let selectedIcon;
|
||||
let selectedTheme;
|
||||
|
||||
function changeMiniProgramTheme(event)
|
||||
{
|
||||
const $icon = $('#preview-icon');
|
||||
@@ -53,29 +50,6 @@ function saveMiniProgramIcon()
|
||||
$('input[name="iconName"]').prop('value', selectedIcon);
|
||||
}
|
||||
|
||||
function saveMiniProgram()
|
||||
{
|
||||
$('[name="toNext"]').prop('value', '0');
|
||||
}
|
||||
|
||||
function toConfiguredMiniProgram()
|
||||
{
|
||||
$('[name="toNext"]').prop('value', '1');
|
||||
}
|
||||
|
||||
function toEditMiniProgramIcon()
|
||||
{
|
||||
const $button = $('#ai-edit-icon');
|
||||
const iconName = $button.find('svg').prop('id');
|
||||
const iconTheme = $button.css('background-color');
|
||||
const $container = $('.icon-setting-container');
|
||||
$container.find(`#${iconName}`).click();
|
||||
$container.find('.btn-icon').each(function()
|
||||
{
|
||||
if($(this).css('background-color') === iconTheme) $(this).click();
|
||||
});
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('#theme-buttons button').on('click', changeMiniProgramTheme);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
function changeMiniProgramTheme(event)
|
||||
{
|
||||
const $icon = $('#preview-icon');
|
||||
const $button = $(event.target).closest('button');
|
||||
const $prev = $('.theme-checked');
|
||||
$prev.removeClass('theme-checked');
|
||||
$button.addClass('theme-checked');
|
||||
$prev.empty();
|
||||
$button.append(iconCheck);
|
||||
$icon.css('background-color', $button.css('background-color'));
|
||||
$icon.css('border', $button.css('border'));
|
||||
selectedTheme = $button.index();
|
||||
}
|
||||
|
||||
function changeMiniProgramIcon(event)
|
||||
{
|
||||
const $icon = $('#preview-icon');
|
||||
const $svg = $(event.target).closest('svg').clone();
|
||||
$icon.empty();
|
||||
$icon.append($svg);
|
||||
selectedIcon = $svg.prop('id');
|
||||
}
|
||||
|
||||
function saveMiniProgramIcon()
|
||||
{
|
||||
const $editIcon = $('#ai-edit-icon');
|
||||
$editIcon.children().first('svg').remove();
|
||||
const $icon = $('#preview-icon');
|
||||
$editIcon.prepend($icon.find('svg').clone());
|
||||
$editIcon.css('background-color', $icon.css('background-color'));
|
||||
$editIcon.css('border', $icon.css('border'));
|
||||
$('input[name="iconTheme"]').prop('value', selectedTheme);
|
||||
$('input[name="iconName"]').prop('value', selectedIcon);
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('#theme-buttons button').on('click', changeMiniProgramTheme);
|
||||
$('#icon-buttons svg').on('click', changeMiniProgramIcon);
|
||||
$('#save-icon-button').on('click', saveMiniProgramIcon);
|
||||
});
|
||||
+1
-1
@@ -2830,7 +2830,7 @@ class aiModel extends model
|
||||
* @param string $AssistantName
|
||||
* @param int $modelId
|
||||
* @access public
|
||||
* @return bool
|
||||
* @return object
|
||||
*/
|
||||
public function checkAssistantDuplicate($AssistantName, $modelId)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
namespace zin;
|
||||
|
||||
jsVar('iconCheck', $config->ai->miniPrograms->iconCheck);
|
||||
jsVar('iconName', $iconName);
|
||||
jsVar('iconTheme', $iconTheme);
|
||||
|
||||
formPanel
|
||||
(
|
||||
|
||||
@@ -3,6 +3,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
jsVar('iconCheck', $config->ai->miniPrograms->iconCheck);
|
||||
jsVar('iconName', $iconName);
|
||||
jsVar('iconTheme', $iconTheme);
|
||||
|
||||
formPanel
|
||||
(
|
||||
set::title($lang->ai->assistants->edit),
|
||||
@@ -46,6 +50,7 @@ formPanel
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->ai->assistants->systemMessage),
|
||||
set::required(true),
|
||||
textarea
|
||||
(
|
||||
set::name('systemMessage'),
|
||||
@@ -61,12 +66,177 @@ formPanel
|
||||
textarea
|
||||
(
|
||||
set::name('greetings'),
|
||||
set::required(true),
|
||||
set::rows(3),
|
||||
set::placeholder($lang->ai->assistants->greetingsPlaceholder),
|
||||
set::value($assistant->greetings)
|
||||
)
|
||||
)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->ai->miniPrograms->icon),
|
||||
set::width('1/2'),
|
||||
set::hight('50px'),
|
||||
button
|
||||
(
|
||||
set('id', 'ai-edit-icon'),
|
||||
setClass('btn btn-icon'),
|
||||
setStyle(array(
|
||||
'width' => '46px',
|
||||
'height' => '46px',
|
||||
'border-radius' => '50%',
|
||||
'border' => "1px solid {$config->ai->miniPrograms->themeList[$iconTheme][1]}",
|
||||
'background-color' => $config->ai->miniPrograms->themeList[$iconTheme][0],
|
||||
'padding' => '0',
|
||||
)),
|
||||
setData('toggle', 'modal'),
|
||||
setData('target', '#edit-icon-modal'),
|
||||
html($config->ai->assistants->iconList[$iconName]),
|
||||
div
|
||||
(
|
||||
setID('edit-icon'),
|
||||
html($config->ai->miniPrograms->iconEdit)
|
||||
)
|
||||
)
|
||||
),
|
||||
input
|
||||
(
|
||||
set::name('iconName'),
|
||||
set::type('hidden'),
|
||||
set::value($iconName)
|
||||
),
|
||||
input
|
||||
(
|
||||
set::name('iconTheme'),
|
||||
set::type('hidden'),
|
||||
set::value($iconTheme)
|
||||
),
|
||||
);
|
||||
|
||||
render();
|
||||
$ai = $config->ai;
|
||||
|
||||
div(
|
||||
setClass('modal fade"'),
|
||||
setData('backdrop', 'static'),
|
||||
setID('edit-icon-modal'),
|
||||
div(
|
||||
setClass('modal-dialog shadow size-sm bd-none'),
|
||||
div(
|
||||
setClass('modal-content'),
|
||||
div(
|
||||
setClass('modal-header items-center'),
|
||||
span
|
||||
(
|
||||
setStyle(array(
|
||||
'font-size' => '20px',
|
||||
'font-weight' => 'bold',
|
||||
)),
|
||||
$lang->ai->miniPrograms->iconModification
|
||||
),
|
||||
span
|
||||
(
|
||||
setClass('text-muted'),
|
||||
'Emoji icons by Twemoji with CC-BY4.0'
|
||||
)
|
||||
),
|
||||
div(
|
||||
setClass('modal-body'),
|
||||
div
|
||||
(
|
||||
setStyle(array(
|
||||
'display' => 'flex',
|
||||
'gap' => '42px',
|
||||
)),
|
||||
div
|
||||
(
|
||||
setClass('icon-preview-container p-1'),
|
||||
button
|
||||
(
|
||||
setID('preview-icon'),
|
||||
setClass('btn btn-icon'),
|
||||
setStyle(array(
|
||||
'width' => '46px',
|
||||
'height' => '46px',
|
||||
'border-radius' => '50%',
|
||||
'border' => "1px solid {$ai->miniPrograms->themeList[$iconTheme][1]}",
|
||||
'background-color' => $ai->miniPrograms->themeList[$iconTheme][0],
|
||||
'padding' => '0',
|
||||
)),
|
||||
setData('toggle', 'modal'),
|
||||
setData('target', '#edit-icon-modal'),
|
||||
html($config->ai->assistants->iconList[$iconName])
|
||||
)
|
||||
),
|
||||
div
|
||||
(
|
||||
setClass('icon-setting-container'),
|
||||
div
|
||||
(
|
||||
setClass('mb-4'),
|
||||
$lang->ai->miniPrograms->customBackground
|
||||
),
|
||||
div
|
||||
(
|
||||
setID('theme-buttons'),
|
||||
setStyle(array(
|
||||
'display' => 'flex',
|
||||
'gap' => '20px',
|
||||
'width' => '400px'
|
||||
)
|
||||
),
|
||||
array_map(function ($theme) use($iconTheme, $ai)
|
||||
{
|
||||
return button
|
||||
(
|
||||
setClass('btn btn-icon theme-checked'),
|
||||
setStyle(array(
|
||||
'width' => '32px',
|
||||
'height' => '32px',
|
||||
'border-radius' => '50%',
|
||||
'border' => "1px solid {$theme[1]}",
|
||||
'background-color' => $theme[0],
|
||||
)),
|
||||
$ai->miniPrograms->themeList[$iconTheme][0] === $theme[0] ? html($ai->miniPrograms->iconCheck) : null
|
||||
);
|
||||
},$config->ai->miniPrograms->themeList)
|
||||
),
|
||||
div
|
||||
(
|
||||
setClass('mt-6'),
|
||||
div
|
||||
(
|
||||
setClass('mb-4'),
|
||||
$lang->ai->miniPrograms->customIcon
|
||||
),
|
||||
div
|
||||
(
|
||||
setID('icon-buttons'),
|
||||
setStyle(array(
|
||||
'display' => 'grid',
|
||||
'column-gap' => '20px',
|
||||
'row-gap' => '16px',
|
||||
'grid-template-columns' => 'repeat(8, 1fr)',
|
||||
'justify-items'=> 'center',
|
||||
'align-items' => 'center',
|
||||
)
|
||||
),
|
||||
array_map(function ($icon)
|
||||
{
|
||||
return html($icon);
|
||||
},$config->ai->assistants->iconList)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
div(
|
||||
setClass('modal-footer flex items-center justify-center'),
|
||||
btn(
|
||||
setID('save-icon-button'),
|
||||
setClass('btn btn-wide primary'),
|
||||
setData('dismiss', 'modal'),
|
||||
$lang->save
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user