-
+
-
+
-
+
+
+
+
+
diff --git a/easyflow-ui-admin/app/src/components/upload/UploadAvatar.vue b/easyflow-ui-admin/app/src/components/upload/UploadAvatar.vue
index fec20ad..710f96a 100644
--- a/easyflow-ui-admin/app/src/components/upload/UploadAvatar.vue
+++ b/easyflow-ui-admin/app/src/components/upload/UploadAvatar.vue
@@ -25,6 +25,18 @@ const props = defineProps({
default: () => ['image/gif', 'image/jpeg', 'image/png', 'image/webp'],
},
modelValue: { type: String, default: '' },
+ shape: {
+ type: String,
+ default: 'circle',
+ },
+ size: {
+ type: Number,
+ default: 100,
+ },
+ theme: {
+ type: String,
+ default: 'default',
+ },
});
const emit = defineEmits(['success', 'update:modelValue']);
@@ -77,6 +89,11 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
{
diff --git a/easyflow-ui-admin/app/src/locales/langs/en-US/bot.json b/easyflow-ui-admin/app/src/locales/langs/en-US/bot.json
index b321963..a41ceb5 100644
--- a/easyflow-ui-admin/app/src/locales/langs/en-US/bot.json
+++ b/easyflow-ui-admin/app/src/locales/langs/en-US/bot.json
@@ -45,6 +45,25 @@
"publicChatCopySuccess": "Copied",
"publicChatCopyFail": "Copy failed",
"basicInfo": "Basic Info",
+ "modal": {
+ "createDescription": "Set the assistant appearance, identity and base availability.",
+ "editDescription": "Update the assistant presentation and base availability.",
+ "previewEyebrow": "Assistant Preview",
+ "previewTitleFallback": "Untitled Assistant",
+ "previewAliasFallback": "The alias will appear here after it is filled in",
+ "previewDescriptionFallback": "Describe the tasks this assistant is good at in one sentence.",
+ "previewStatusEnabled": "Enabled",
+ "previewStatusDisabled": "Disabled",
+ "sectionAppearanceTitle": "Basic Info",
+ "sectionAppearanceDescription": "Define the avatar, name and category.",
+ "sectionIdentityTitle": "Identity",
+ "sectionIdentityDescription": "Configure a stable alias and an external description.",
+ "sectionPublishTitle": "Availability",
+ "sectionPublishDescription": "Control whether the assistant is currently available.",
+ "aliasHint": "Use letters, numbers or hyphens for a stable access identifier.",
+ "descriptionHint": "This summary helps teammates understand when to use the assistant.",
+ "statusHint": "When disabled, the assistant configuration is kept but shown as inactive."
+ },
"placeholder": {
"welcome": "Please enter welcome message",
"prompt": "You are an AI assistant. Please provide clear and accurate answers based on the user's questions.",
diff --git a/easyflow-ui-admin/app/src/locales/langs/zh-CN/bot.json b/easyflow-ui-admin/app/src/locales/langs/zh-CN/bot.json
index 0866280..7c050a8 100644
--- a/easyflow-ui-admin/app/src/locales/langs/zh-CN/bot.json
+++ b/easyflow-ui-admin/app/src/locales/langs/zh-CN/bot.json
@@ -45,6 +45,25 @@
"publicChatCopySuccess": "复制成功",
"publicChatCopyFail": "复制失败",
"basicInfo": "基础信息",
+ "modal": {
+ "createDescription": "设置助手的外观、标识和基础发布状态。",
+ "editDescription": "更新助手的展示信息与基础状态。",
+ "previewEyebrow": "助手预览",
+ "previewTitleFallback": "未命名助手",
+ "previewAliasFallback": "填写别名后会展示访问标识",
+ "previewDescriptionFallback": "用一句话描述这个助手擅长处理的问题场景。",
+ "previewStatusEnabled": "启用中",
+ "previewStatusDisabled": "未启用",
+ "sectionAppearanceTitle": "基础信息",
+ "sectionAppearanceDescription": "确定助手头像、名称和所属分类。",
+ "sectionIdentityTitle": "标识信息",
+ "sectionIdentityDescription": "配置稳定的访问别名与对外说明。",
+ "sectionPublishTitle": "发布设置",
+ "sectionPublishDescription": "控制助手当前是否对外可用。",
+ "aliasHint": "建议使用英文、数字或短横线,便于作为访问标识。",
+ "descriptionHint": "这段介绍会帮助成员快速判断助手适用的任务。",
+ "statusHint": "关闭后助手配置会保留,但不会作为启用状态展示。"
+ },
"placeholder": {
"welcome": "请输入欢迎语",
"prompt": "你是一个AI助手,请根据用户的问题给出清晰、准确的回答。",
diff --git a/easyflow-ui-admin/app/src/views/ai/bots/index.vue b/easyflow-ui-admin/app/src/views/ai/bots/index.vue
index 5b65238..1015205 100644
--- a/easyflow-ui-admin/app/src/views/ai/bots/index.vue
+++ b/easyflow-ui-admin/app/src/views/ai/bots/index.vue
@@ -8,12 +8,11 @@ import type { ActionButton } from '#/components/page/CardList.vue';
import { computed, markRaw, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
+import { EasyFlowFormModal } from '@easyflow/common-ui';
import { $t } from '@easyflow/locales';
import { Delete, Edit, Plus, Setting } from '@element-plus/icons-vue';
import {
- ElButton,
- ElDialog,
ElForm,
ElFormItem,
ElInput,
@@ -299,16 +298,21 @@ const getSideList = async () => {
-
{
/>
-
-
-
- {{ $t('button.cancel') }}
-
-
- {{ $t('button.confirm') }}
-
-
-
+
diff --git a/easyflow-ui-admin/app/src/views/ai/bots/modal.vue b/easyflow-ui-admin/app/src/views/ai/bots/modal.vue
index ed782d6..a152e05 100644
--- a/easyflow-ui-admin/app/src/views/ai/bots/modal.vue
+++ b/easyflow-ui-admin/app/src/views/ai/bots/modal.vue
@@ -3,18 +3,12 @@ import type { BotInfo } from '@easyflow/types';
import type { SaveBotParams, UpdateBotParams } from '#/api/ai/bot';
-import { ref } from 'vue';
+import { computed, nextTick, ref } from 'vue';
+import { EasyFlowFormModal } from '@easyflow/common-ui';
import { $t } from '@easyflow/locales';
-import {
- ElButton,
- ElDialog,
- ElForm,
- ElFormItem,
- ElInput,
- ElMessage,
-} from 'element-plus';
+import { ElForm, ElFormItem, ElInput, ElMessage } from 'element-plus';
import { tryit } from 'radash';
import { saveBot, updateBotApi } from '#/api/ai/bot';
@@ -23,98 +17,334 @@ import UploadAvatar from '#/components/upload/UploadAvatar.vue';
const emit = defineEmits(['success']);
-const initialFormData = {
- icon: '',
- title: '',
+const createInitialFormData = (): SaveBotParams => ({
alias: '',
- description: '',
categoryId: '',
+ description: '',
+ icon: '',
status: 1,
-};
+ title: '',
+});
+
const dialogVisible = ref(false);
const dialogType = ref<'create' | 'edit'>('create');
const formRef = ref
>();
-const formData = ref(initialFormData);
-const rules = {
- title: [{ required: true, message: $t('message.required'), trigger: 'blur' }],
- alias: [{ required: true, message: $t('message.required'), trigger: 'blur' }],
-};
+const formData = ref(createInitialFormData());
const loading = ref(false);
-const handleSubmit = async () => {
+const rules = {
+ alias: [{ required: true, message: $t('message.required'), trigger: 'blur' }],
+ title: [{ required: true, message: $t('message.required'), trigger: 'blur' }],
+};
+
+const dialogTitle = computed(() => {
+ return `${$t(`button.${dialogType.value}`)}${$t('bot.chatAssistant')}`;
+});
+
+const dialogDescription = computed(() => {
+ return dialogType.value === 'create'
+ ? $t('bot.modal.createDescription')
+ : $t('bot.modal.editDescription');
+});
+
+async function handleSubmit() {
+ const valid = await formRef.value?.validate().catch(() => false);
+ if (!valid) {
+ return;
+ }
+
loading.value = true;
const [err, res] = await tryit(
dialogType.value === 'create' ? saveBot : updateBotApi,
- )(formData.value as any);
+ )(formData.value as SaveBotParams & UpdateBotParams);
if (!err && res.errorCode === 0) {
emit('success');
- ElMessage.success($t('message.saveOkMessage'));
+ ElMessage.success(res.message || $t('message.saveOkMessage'));
dialogVisible.value = false;
+ loading.value = false;
+ return;
}
+
+ ElMessage.error(res?.message || $t('message.saveFail'));
loading.value = false;
-};
+}
+
+async function open(type: 'create' | 'edit', bot?: BotInfo) {
+ formData.value = bot
+ ? {
+ ...createInitialFormData(),
+ alias: bot.alias,
+ categoryId: bot.categoryId,
+ description: bot.description,
+ icon: bot.icon,
+ id: bot.id,
+ status: bot.status,
+ title: bot.title,
+ }
+ : createInitialFormData();
+ dialogType.value = type;
+ dialogVisible.value = true;
+
+ await nextTick();
+ formRef.value?.clearValidate();
+}
defineExpose({
- open(type: typeof dialogType.value, bot?: BotInfo) {
- formData.value = bot
- ? {
- id: bot.id,
- icon: bot.icon,
- title: bot.title,
- alias: bot.alias,
- description: bot.description,
- categoryId: bot.categoryId,
- status: bot.status,
- }
- : initialFormData;
- dialogType.value = type;
- dialogVisible.value = true;
- },
+ open,
});
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
- {{ $t('button.cancel') }}
-
-
- {{ $t('button.save') }}
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('bot.modal.aliasHint') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('bot.modal.descriptionHint') }}
+
+
+
+
+
+
+ {{ $t('bot.modal.statusHint') }}
+
+
+
+
+
+
+
+
diff --git a/easyflow-ui-admin/app/src/views/ai/bots/pages/setting/PromptChoreChatModal.vue b/easyflow-ui-admin/app/src/views/ai/bots/pages/setting/PromptChoreChatModal.vue
index 7f3a174..8944942 100644
--- a/easyflow-ui-admin/app/src/views/ai/bots/pages/setting/PromptChoreChatModal.vue
+++ b/easyflow-ui-admin/app/src/views/ai/bots/pages/setting/PromptChoreChatModal.vue
@@ -1,9 +1,10 @@
-
-
+
@@ -87,5 +95,5 @@ defineExpose({
{{ loading ? $t('button.optimizing') : $t('button.regenerate') }}
-
+
diff --git a/easyflow-ui-admin/app/src/views/ai/documentCollection/ChunkDocumentTable.vue b/easyflow-ui-admin/app/src/views/ai/documentCollection/ChunkDocumentTable.vue
index fc3889b..ed9f25b 100644
--- a/easyflow-ui-admin/app/src/views/ai/documentCollection/ChunkDocumentTable.vue
+++ b/easyflow-ui-admin/app/src/views/ai/documentCollection/ChunkDocumentTable.vue
@@ -1,12 +1,12 @@
-
-
-
- {{ $t('button.cancel') }}
-
-
- {{ $t('button.save') }}
-
-
-
+
diff --git a/easyflow-ui-admin/app/src/views/ai/documentCollection/FaqCategoryDialog.vue b/easyflow-ui-admin/app/src/views/ai/documentCollection/FaqCategoryDialog.vue
index a483b58..b507e72 100644
--- a/easyflow-ui-admin/app/src/views/ai/documentCollection/FaqCategoryDialog.vue
+++ b/easyflow-ui-admin/app/src/views/ai/documentCollection/FaqCategoryDialog.vue
@@ -1,16 +1,10 @@
-
-
+
{
/>
-
-
- {{ $t('button.cancel') }}
-
- {{ $t('button.save') }}
-
-
-
+
diff --git a/easyflow-ui-admin/app/src/views/ai/documentCollection/FaqEditDialog.vue b/easyflow-ui-admin/app/src/views/ai/documentCollection/FaqEditDialog.vue
index 711909c..ef531a6 100644
--- a/easyflow-ui-admin/app/src/views/ai/documentCollection/FaqEditDialog.vue
+++ b/easyflow-ui-admin/app/src/views/ai/documentCollection/FaqEditDialog.vue
@@ -3,13 +3,12 @@ import type { IDomEditor } from '@wangeditor/editor';
import { nextTick, onBeforeUnmount, ref, shallowRef, watch } from 'vue';
+import { EasyFlowFormModal } from '@easyflow/common-ui';
import { $t } from '@easyflow/locales';
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import DOMPurify from 'dompurify';
import {
- ElButton,
- ElDialog,
ElForm,
ElFormItem,
ElInput,
@@ -189,15 +188,20 @@ onBeforeUnmount(() => {
-
-
+
{
-