* add miniprogram chat page.
This commit is contained in:
@@ -36,6 +36,7 @@ class textarea extends wg
|
||||
return h::textarea
|
||||
(
|
||||
set($this->props->pick(array('name', 'id', 'class', 'required', 'placeholder', 'rows', 'cols', 'disabled'))),
|
||||
set($this->getRestProps()),
|
||||
$this->prop('value'),
|
||||
$this->children()
|
||||
);
|
||||
|
||||
@@ -135,6 +135,20 @@ class ai extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mini program chat.
|
||||
*
|
||||
* @param string $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function miniProgramChat($id)
|
||||
{
|
||||
$this->view->miniProgram = $this->ai->getMiniProgramByID($id);
|
||||
$this->view->fields = $this->ai->getMiniProgramFields($id);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mini program square.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
.mini-program {
|
||||
top: 66px;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
left: 16px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.mini-program .detail {
|
||||
flex-basis: 390px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mini-program .detail .header {
|
||||
padding: 24px 20px 20px 20px;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
color: var(--color-slate-800);
|
||||
flex: none;
|
||||
border-bottom: 1px solid var(--color-gray-200);
|
||||
}
|
||||
|
||||
.mini-program .detail .header .program-avatar {
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.mini-program .detail .header .content {
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.mini-program .detail .header .content .title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.mini-program .detail .header .content .desc {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.mini-program .detail .body {
|
||||
flex: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 20px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.mini-program .detail .body .language-model {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.mini-program .detail .body .language-model .btn {
|
||||
color: var(--color-slate-700);
|
||||
}
|
||||
|
||||
.mini-program .detail .body .language-model .btn:hover {
|
||||
background: var(--color-gray-300);
|
||||
}
|
||||
|
||||
.mini-program .detail .body .form-container {
|
||||
flex: auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mini-program .detail .footer {
|
||||
padding: 20px 20px 24px 20px;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.mini-program .chat {
|
||||
flex: auto;
|
||||
flex-basis: 67%;
|
||||
background: #fff;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
if(!window.aiMiniProgramChat) window.aiMiniProgramChat = {};
|
||||
|
||||
function getFormValue()
|
||||
{
|
||||
/**
|
||||
* @type {Map<string, string>}
|
||||
*/
|
||||
const fieldValueMap = new Map();
|
||||
fieldNames.forEach(name =>
|
||||
{
|
||||
const $field = $(`[data-name="${name}"]`);
|
||||
if(!$field.hasClass('picker-box'))
|
||||
{
|
||||
fieldValueMap.set(name, $field.prop('value'));
|
||||
}
|
||||
else
|
||||
{
|
||||
fieldValueMap.set(name, $field.zui('picker').$.value);
|
||||
}
|
||||
});
|
||||
return fieldValueMap;
|
||||
}
|
||||
|
||||
function generatePrompt()
|
||||
{
|
||||
let promptStr = prompt;
|
||||
const map = getFormValue();
|
||||
map.forEach((value, key) =>
|
||||
{
|
||||
promptStr = promptStr.replace(new RegExp(`\\s<${key}>\\s`, 'g'), value);
|
||||
});
|
||||
return promptStr;
|
||||
}
|
||||
|
||||
window.aiMiniProgramChat.startAIChat = function()
|
||||
{
|
||||
const promptStr = generatePrompt();
|
||||
console.log(promptStr);
|
||||
};
|
||||
@@ -31,6 +31,7 @@ $lang->prompt->editedDate = 'Edited Date';
|
||||
$lang->prompt->deleted = 'Deleted';
|
||||
|
||||
/* Lang for privs, keys are paired with privlang items. */
|
||||
$lang->ai->modelCurrent = 'Current Model';
|
||||
$lang->ai->modelBrowse = 'Browse Models';
|
||||
$lang->ai->modelEdit = 'Edit Models';
|
||||
$lang->ai->modelTestConnection = 'Test Model Connection';
|
||||
@@ -475,6 +476,10 @@ $lang->ai->miniPrograms->field->default = array(
|
||||
'As a <Role>, I hope to <Objective> in <Scene>.'
|
||||
);
|
||||
|
||||
$lang->ai->miniPrograms->field->emptyNameWarning = 'Field name cannot be empty';
|
||||
$lang->ai->miniPrograms->field->duplicatedNameWarning = 'Duplicate field name';
|
||||
$lang->ai->miniPrograms->field->emptyOptionWarning = 'Please configure at least one option';
|
||||
|
||||
$lang->ai->miniPrograms->statuses = array(
|
||||
'' => 'all',
|
||||
'draft' => 'unpublished',
|
||||
@@ -487,10 +492,7 @@ $lang->ai->miniPrograms->optionName = 'Option name';
|
||||
$lang->ai->miniPrograms->promptTemplate = 'Prompt template';
|
||||
$lang->ai->miniPrograms->fieldConfiguration = 'Field configuration';
|
||||
$lang->ai->miniPrograms->summary = 'There are %s small programs on this page.';
|
||||
|
||||
$lang->ai->miniPrograms->field->emptyNameWarning = 'Field name cannot be empty';
|
||||
$lang->ai->miniPrograms->field->duplicatedNameWarning = 'Duplicate field name';
|
||||
$lang->ai->miniPrograms->field->emptyOptionWarning = 'Please configure at least one option';
|
||||
$lang->ai->miniPrograms->generate = 'Generate';
|
||||
|
||||
$lang->ai->models = new stdclass();
|
||||
$lang->ai->models->title = 'Language Model Configuration';
|
||||
|
||||
@@ -31,6 +31,7 @@ $lang->prompt->editedDate = 'Edited Date';
|
||||
$lang->prompt->deleted = 'Deleted';
|
||||
|
||||
/* Lang for privs, keys are paired with privlang items. */
|
||||
$lang->ai->modelCurrent = 'Current Model';
|
||||
$lang->ai->modelBrowse = 'Browse Models';
|
||||
$lang->ai->modelEdit = 'Edit Models';
|
||||
$lang->ai->modelTestConnection = 'Test Model Connection';
|
||||
@@ -475,6 +476,10 @@ $lang->ai->miniPrograms->field->default = array(
|
||||
'As a <Role>, I hope to <Objective> in <Scene>.'
|
||||
);
|
||||
|
||||
$lang->ai->miniPrograms->field->emptyNameWarning = 'Field name cannot be empty';
|
||||
$lang->ai->miniPrograms->field->duplicatedNameWarning = 'Duplicate field name';
|
||||
$lang->ai->miniPrograms->field->emptyOptionWarning = 'Please configure at least one option';
|
||||
|
||||
$lang->ai->miniPrograms->statuses = array(
|
||||
'' => 'all',
|
||||
'draft' => 'unpublished',
|
||||
@@ -487,10 +492,7 @@ $lang->ai->miniPrograms->optionName = 'Option name';
|
||||
$lang->ai->miniPrograms->promptTemplate = 'Prompt template';
|
||||
$lang->ai->miniPrograms->fieldConfiguration = 'Field configuration';
|
||||
$lang->ai->miniPrograms->summary = 'There are %s small programs on this page.';
|
||||
|
||||
$lang->ai->miniPrograms->field->emptyNameWarning = 'Field name cannot be empty';
|
||||
$lang->ai->miniPrograms->field->duplicatedNameWarning = 'Duplicate field name';
|
||||
$lang->ai->miniPrograms->field->emptyOptionWarning = 'Please configure at least one option';
|
||||
$lang->ai->miniPrograms->generate = 'Generate';
|
||||
|
||||
$lang->ai->models = new stdclass();
|
||||
$lang->ai->models->title = 'Language Model Configuration';
|
||||
|
||||
@@ -31,6 +31,7 @@ $lang->prompt->editedDate = 'Edited Date';
|
||||
$lang->prompt->deleted = 'Deleted';
|
||||
|
||||
/* Lang for privs, keys are paired with privlang items. */
|
||||
$lang->ai->modelCurrent = 'Current Model';
|
||||
$lang->ai->modelBrowse = 'Browse Models';
|
||||
$lang->ai->modelEdit = 'Edit Models';
|
||||
$lang->ai->modelTestConnection = 'Test Model Connection';
|
||||
@@ -491,6 +492,7 @@ $lang->ai->miniPrograms->optionName = 'Option name';
|
||||
$lang->ai->miniPrograms->promptTemplate = 'Prompt template';
|
||||
$lang->ai->miniPrograms->fieldConfiguration = 'Field configuration';
|
||||
$lang->ai->miniPrograms->summary = 'There are %s small programs on this page.';
|
||||
$lang->ai->miniPrograms->generate = 'Generate';
|
||||
|
||||
$lang->ai->models = new stdclass();
|
||||
$lang->ai->models->title = 'Language Model Configuration';
|
||||
|
||||
@@ -31,6 +31,7 @@ $lang->prompt->editedDate = '编辑时间';
|
||||
$lang->prompt->deleted = '是否已删除';
|
||||
|
||||
/* Lang for privs, keys are paired with privlang items. */
|
||||
$lang->ai->modelCurrent = '当前语言模型';
|
||||
$lang->ai->modelBrowse = '浏览语言模型';
|
||||
$lang->ai->modelEdit = '编辑语言模型';
|
||||
$lang->ai->modelTestConnection = '测试连接';
|
||||
@@ -491,6 +492,7 @@ $lang->ai->miniPrograms->optionName = '选项名称';
|
||||
$lang->ai->miniPrograms->promptTemplate = '提词模板';
|
||||
$lang->ai->miniPrograms->fieldConfiguration = '字段配置';
|
||||
$lang->ai->miniPrograms->summary = '本页共 %s 个小程序。';
|
||||
$lang->ai->miniPrograms->generate = '生成';
|
||||
|
||||
$lang->ai->models = new stdclass();
|
||||
$lang->ai->models->title = '语言模型配置';
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
jsVar('prompt', $miniProgram->prompt);
|
||||
|
||||
$formGroups = array();
|
||||
$fieldNames = array();
|
||||
foreach($fields as $field)
|
||||
{
|
||||
if($field->type === 'textarea')
|
||||
{
|
||||
$control = textarea(
|
||||
set::rows(1),
|
||||
set::name("field-{$field->id}"),
|
||||
set::placeholder($field->placeholder),
|
||||
setData('name', $field->name)
|
||||
);
|
||||
}
|
||||
elseif($field->type === 'radio')
|
||||
{
|
||||
$options = explode(',', $field->options);
|
||||
$control = picker(
|
||||
set::name("field-{$field->id}"),
|
||||
set::items(array_combine($options, $options)),
|
||||
setData('name', $field->name)
|
||||
);
|
||||
}
|
||||
elseif($field->type === 'checkbox')
|
||||
{
|
||||
$options = explode(',', $field->options);
|
||||
$control = picker(
|
||||
set::name("field-{$field->id}"),
|
||||
set::items(array_combine($options, $options)),
|
||||
set::multiple(true),
|
||||
setData('name', $field->name)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$control = input(
|
||||
set::name("field-{$field->id}"),
|
||||
set::placeholder($field->placeholder),
|
||||
setData('name', $field->name)
|
||||
);
|
||||
}
|
||||
|
||||
$formGroups[] = formGroup(
|
||||
set::label($field->name),
|
||||
set::required($field->required === '1'),
|
||||
$control
|
||||
);
|
||||
|
||||
$fieldNames[] = $field->name;
|
||||
}
|
||||
|
||||
jsVar('fieldNames', $fieldNames);
|
||||
|
||||
list($iconName, $iconTheme) = explode('-', $miniProgram->icon);
|
||||
|
||||
div(
|
||||
setClass('mini-program fixed flex'),
|
||||
div(
|
||||
setClass('detail col shadow-md'),
|
||||
div(
|
||||
setClass('header'),
|
||||
div(
|
||||
setClass('program-avatar center'),
|
||||
setStyle(array('border' => "1px solid {$config->ai->miniPrograms->themeList[$iconTheme][1]}", 'background-color' => $config->ai->miniPrograms->themeList[$iconTheme][0])),
|
||||
html($config->ai->miniPrograms->iconList[$iconName])
|
||||
),
|
||||
div(
|
||||
setClass('content'),
|
||||
div(
|
||||
setClass('title pb-2'),
|
||||
$miniProgram->name
|
||||
),
|
||||
div(
|
||||
setClass('desc'),
|
||||
set::title($miniProgram->desc),
|
||||
$miniProgram->desc
|
||||
)
|
||||
)
|
||||
),
|
||||
div(
|
||||
setClass('body'),
|
||||
div(
|
||||
setClass('language-model'),
|
||||
div(
|
||||
setClass('content flex gap-2.5'),
|
||||
span(
|
||||
setStyle(array('color' => 'var(--color-slate-700)')),
|
||||
$lang->ai->modelCurrent
|
||||
),
|
||||
span($lang->ai->miniPrograms->modelList[$miniProgram->model]),
|
||||
),
|
||||
btn(
|
||||
setClass('ghost'),
|
||||
set::icon('trash'),
|
||||
$lang->ai->chatReset
|
||||
),
|
||||
),
|
||||
div(
|
||||
setClass('form-container p-1'),
|
||||
form(
|
||||
set::grid(false),
|
||||
set::actions(array()),
|
||||
$formGroups
|
||||
),
|
||||
)
|
||||
),
|
||||
div(
|
||||
setClass('footer'),
|
||||
btn(
|
||||
setClass('primary block w-full'),
|
||||
$lang->ai->miniPrograms->generate,
|
||||
on::click('window.aiMiniProgramChat.startAIChat')
|
||||
)
|
||||
)
|
||||
),
|
||||
div(
|
||||
setClass('chat')
|
||||
)
|
||||
);
|
||||
|
||||
render();
|
||||
@@ -66,7 +66,8 @@ $miniProgramCard = function($miniProgram) use ($categoryList, $collectedIDs)
|
||||
$star = in_array($miniProgram->id, $collectedIDs) ? 'star' : 'star-empty';
|
||||
$delete = $star === 'star' ? 'true' : 'false';
|
||||
|
||||
return div(
|
||||
return a(
|
||||
set::href(createLink('ai', 'miniProgramChat', "id={$miniProgram->id}#app=ai")),
|
||||
setClass('miniprogram-card'),
|
||||
div(
|
||||
setClass('program-content'),
|
||||
|
||||
Reference in New Issue
Block a user