* add miniprogram chat page.

This commit is contained in:
dingyongliang
2024-02-19 14:35:38 +08:00
parent ed9a070623
commit 6650521499
10 changed files with 285 additions and 9 deletions
+1
View File
@@ -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()
);
+14
View File
@@ -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.
*
+86
View File
@@ -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;
}
+39
View File
@@ -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&lt;${key}&gt;\\s`, 'g'), value);
});
return promptStr;
}
window.aiMiniProgramChat.startAIChat = function()
{
const promptStr = generatePrompt();
console.log(promptStr);
};
+6 -4
View File
@@ -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';
+6 -4
View File
@@ -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';
+2
View File
@@ -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';
+2
View File
@@ -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 = '语言模型配置';
+127
View File
@@ -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();
+2 -1
View File
@@ -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'),