feat: 统一管理端弹窗与内容区交互样式

- 收敛管理端公共 Modal 链路,新增表单弹窗与普通内容弹窗包装\n- 迁移 Bot、知识库、插件、工作流、资源、MCP、数据中枢与系统管理页面级弹窗\n- 统一内容区工具栏、列表容器、导航与顶部按钮的视觉密度和交互节奏
This commit is contained in:
2026-03-06 19:58:26 +08:00
parent 76c2954a70
commit b191d1aaed
99 changed files with 3148 additions and 1623 deletions

View File

@@ -1,12 +1,12 @@
<script setup lang="ts">
import { ref } from 'vue';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { $t } from '@easyflow/locales';
import { Delete, MoreFilled } from '@element-plus/icons-vue';
import {
ElButton,
ElDialog,
ElDropdown,
ElDropdownItem,
ElDropdownMenu,
@@ -129,30 +129,27 @@ const form = ref({
</ElTable>
</template>
</PageData>
<ElDialog v-model="dialogVisible" :title="$t('button.edit')" width="50%">
<EasyFlowFormModal
v-model:open="dialogVisible"
:closable="!btnLoading"
:title="$t('button.edit')"
width="50%"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
@confirm="save"
>
<ElForm
ref="basicFormRef"
style="width: 100%; margin-top: 20px"
:model="form"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem>
<ElInput v-model="form.content" :rows="20" type="textarea" />
</ElFormItem>
</ElForm>
<template #footer>
<ElButton @click="closeDialog">
{{ $t('button.cancel') }}
</ElButton>
<ElButton
type="primary"
@click="save"
:loading="btnLoading"
:disabled="btnLoading"
>
{{ $t('button.save') }}
</ElButton>
</template>
</ElDialog>
</EasyFlowFormModal>
</div>
</template>

View File

@@ -1,8 +1,16 @@
<script setup lang="ts">
import type {FormInstance} from 'element-plus';
import type { FormInstance } from 'element-plus';
import type { ActionButton } from '#/components/page/CardList.vue';
import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { $t } from '@easyflow/locales';
import { Delete, Edit, Notebook, Plus, Search } from '@element-plus/icons-vue';
import {
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElInput,
@@ -10,21 +18,12 @@ import {
ElMessage,
ElMessageBox,
} from 'element-plus';
import { tryit } from 'radash';
import type {ActionButton} from '#/components/page/CardList.vue';
import CardPage from '#/components/page/CardList.vue';
import {computed, onMounted, ref} from 'vue';
import {useRouter} from 'vue-router';
import {$t} from '@easyflow/locales';
import {Delete, Edit, Notebook, Plus, Search} from '@element-plus/icons-vue';
import {tryit} from 'radash';
import {api} from '#/api/request';
import { api } from '#/api/request';
import defaultIcon from '#/assets/ai/knowledge/book.svg';
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
import CardPage from '#/components/page/CardList.vue';
import PageData from '#/components/page/PageData.vue';
import PageSide from '#/components/page/PageSide.vue';
import DocumentCollectionModal from '#/views/ai/documentCollection/DocumentCollectionModal.vue';
@@ -321,16 +320,21 @@ function changeCategory(category: any) {
</PageData>
</div>
</div>
<ElDialog
v-model="dialogVisible"
<EasyFlowFormModal
v-model:open="dialogVisible"
:closable="!saveLoading"
:title="formData.id ? `${$t('button.edit')}` : `${$t('button.add')}`"
:close-on-click-modal="false"
:confirm-loading="saveLoading"
:confirm-text="$t('button.confirm')"
:submitting="saveLoading"
@confirm="handleSubmit"
>
<ElForm
ref="formRef"
:model="formData"
:rules="formRules"
label-width="120px"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<!-- 动态生成表单项 -->
<ElFormItem
@@ -352,16 +356,7 @@ function changeCategory(category: any) {
/>
</ElFormItem>
</ElForm>
<template #footer>
<ElButton @click="dialogVisible = false">
{{ $t('button.cancel') }}
</ElButton>
<ElButton type="primary" @click="handleSubmit" :loading="saveLoading">
{{ $t('button.confirm') }}
</ElButton>
</template>
</ElDialog>
</EasyFlowFormModal>
<!-- 新增知识库模态框-->
<DocumentCollectionModal ref="aiKnowledgeModalRef" @reload="handleSearch" />

View File

@@ -1,8 +1,12 @@
<script setup lang="ts">
import type {FormInstance} from 'element-plus';
import type { FormInstance } from 'element-plus';
import { onMounted, ref } from 'vue';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { InfoFilled } from '@element-plus/icons-vue';
import {
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElIcon,
@@ -14,14 +18,10 @@ import {
ElTooltip,
} from 'element-plus';
import {onMounted, ref} from 'vue';
import {InfoFilled} from '@element-plus/icons-vue';
import {api} from '#/api/request';
import { api } from '#/api/request';
import DictSelect from '#/components/dict/DictSelect.vue';
import UploadAvatar from '#/components/upload/UploadAvatar.vue';
import {$t} from '#/locales';
import { $t } from '#/locales';
const emit = defineEmits(['reload']);
const embeddingLlmList = ref<any>([]);
@@ -93,7 +93,7 @@ const defaultEntity = {
const normalizeEntity = (raw: any = {}) => {
const options = {
canUpdateEmbeddingModel: true,
...(raw.options || {}),
...raw.options,
};
if (options.rerankEnable === undefined || options.rerankEnable === null) {
options.rerankEnable = !!raw.rerankModelId;
@@ -203,20 +203,24 @@ defineExpose({
</script>
<template>
<ElDialog
v-model="dialogVisible"
draggable
<EasyFlowFormModal
v-model:open="dialogVisible"
:title="isAdd ? $t('button.add') : $t('button.edit')"
:before-close="closeDialog"
:close-on-click-modal="false"
align-center
:centered="true"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
width="xl"
@confirm="save"
>
<ElForm
label-width="150px"
ref="saveForm"
:model="entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem
prop="icon"
@@ -413,20 +417,7 @@ defineExpose({
<ElSwitch v-model="entity.searchEngineEnable" />
</ElFormItem>
</ElForm>
<template #footer>
<ElButton @click="closeDialog">
{{ $t('button.cancel') }}
</ElButton>
<ElButton
type="primary"
@click="save"
:loading="btnLoading"
:disabled="btnLoading"
>
{{ $t('button.save') }}
</ElButton>
</template>
</ElDialog>
</EasyFlowFormModal>
</template>
<style scoped></style>

View File

@@ -1,16 +1,10 @@
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { $t } from '@easyflow/locales';
import {
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElInput,
ElTreeSelect,
} from 'element-plus';
import { ElForm, ElFormItem, ElInput, ElTreeSelect } from 'element-plus';
const props = defineProps({
modelValue: {
@@ -97,14 +91,22 @@ const handleSubmit = () => {
</script>
<template>
<ElDialog
:model-value="modelValue"
<EasyFlowFormModal
:open="modelValue"
:title="title"
width="520px"
:close-on-click-modal="false"
@close="closeDialog"
:confirm-text="$t('button.save')"
@update:open="emit('update:modelValue', $event)"
@cancel="closeDialog"
@confirm="handleSubmit"
>
<ElForm ref="formRef" :model="form" :rules="rules" label-position="top">
<ElForm
ref="formRef"
:model="form"
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem
:label="$t('documentCollection.faq.categoryName')"
prop="categoryName"
@@ -130,12 +132,5 @@ const handleSubmit = () => {
/>
</ElFormItem>
</ElForm>
<template #footer>
<ElButton @click="closeDialog">{{ $t('button.cancel') }}</ElButton>
<ElButton type="primary" @click="handleSubmit">
{{ $t('button.save') }}
</ElButton>
</template>
</ElDialog>
</EasyFlowFormModal>
</template>

View File

@@ -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(() => {
</script>
<template>
<ElDialog
<EasyFlowFormModal
class="faq-edit-dialog"
:model-value="modelValue"
:open="modelValue"
:title="form.id ? $t('button.edit') : $t('button.add')"
width="min(920px, 92vw)"
:close-on-click-modal="false"
@close="closeDialog"
:confirm-text="$t('button.save')"
@update:open="emit('update:modelValue', $event)"
@cancel="closeDialog"
@confirm="handleSubmit"
>
<ElForm class="faq-form" label-position="top">
<ElForm
class="faq-form easyflow-modal-form easyflow-modal-form--compact"
label-position="top"
>
<ElFormItem :label="$t('documentCollection.faq.category')">
<ElTreeSelect
v-model="form.categoryId"
@@ -233,17 +237,7 @@ onBeforeUnmount(() => {
</div>
</ElFormItem>
</ElForm>
<template #footer>
<div class="dialog-footer">
<ElButton class="footer-btn" @click="closeDialog">
{{ $t('button.cancel') }}
</ElButton>
<ElButton class="footer-btn" type="primary" @click="handleSubmit">
{{ $t('button.save') }}
</ElButton>
</div>
</template>
</ElDialog>
</EasyFlowFormModal>
</template>
<style scoped>

View File

@@ -3,8 +3,10 @@ import type { UploadFile } from 'element-plus';
import { computed, ref, watch } from 'vue';
import { EasyFlowPanelModal } from '@easyflow/common-ui';
import { $t } from '@easyflow/locales';
import { downloadFileFromBlob } from '@easyflow/utils';
import {
CircleCloseFilled,
Document,
@@ -16,7 +18,6 @@ import {
} from '@element-plus/icons-vue';
import {
ElButton,
ElDialog,
ElIcon,
ElMessage,
ElTable,
@@ -128,12 +129,15 @@ const handleImport = async () => {
</script>
<template>
<ElDialog
<EasyFlowPanelModal
:model-value="modelValue"
width="min(980px, 92vw)"
:title="$t('documentCollection.faq.import.title')"
:close-on-click-modal="true"
@close="closeDialog"
:show-cancel-button="false"
:show-confirm-button="false"
@update:model-value="emit('update:modelValue', $event)"
@cancel="closeDialog"
>
<div class="faq-import-dialog">
<ElUpload
@@ -148,12 +152,18 @@ const handleImport = async () => {
:show-file-list="false"
class="faq-upload-area"
>
<div class="upload-box flex flex-col items-center justify-center p-8 text-center">
<ElIcon class="text-4xl text-gray-400 mb-4"><UploadFilled /></ElIcon>
<div class="upload-title text-[15px] font-semibold text-[var(--el-text-color-primary)] mb-2">
<div
class="upload-box flex flex-col items-center justify-center p-8 text-center"
>
<ElIcon class="mb-4 text-4xl text-gray-400"><UploadFilled /></ElIcon>
<div
class="upload-title mb-2 text-[15px] font-semibold text-[var(--el-text-color-primary)]"
>
{{ $t('documentCollection.faq.import.uploadTitle') }}
</div>
<div class="upload-desc text-[13px] text-[var(--el-text-color-secondary)]">
<div
class="upload-desc text-[13px] text-[var(--el-text-color-secondary)]"
>
{{ $t('documentCollection.faq.import.uploadDesc') }}
</div>
</div>
@@ -183,7 +193,10 @@ const handleImport = async () => {
>
<WarningFilled />
</ElIcon>
<ElIcon v-else class="result-state-icon text-[var(--el-color-success)]">
<ElIcon
v-else
class="result-state-icon text-[var(--el-color-success)]"
>
<SuccessFilled />
</ElIcon>
<span class="result-title-text">
@@ -193,15 +206,23 @@ const handleImport = async () => {
</div>
<div class="result-stats">
<div class="stat-item">
<div class="stat-label">{{ $t('documentCollection.faq.import.totalCount') }}</div>
<div class="stat-label">
{{ $t('documentCollection.faq.import.totalCount') }}
</div>
<div class="stat-value">{{ importResult.totalCount || 0 }}</div>
</div>
<div class="stat-item">
<div class="stat-label">{{ $t('documentCollection.faq.import.successCount') }}</div>
<div class="stat-value success-text">{{ importResult.successCount || 0 }}</div>
<div class="stat-label">
{{ $t('documentCollection.faq.import.successCount') }}
</div>
<div class="stat-value success-text">
{{ importResult.successCount || 0 }}
</div>
</div>
<div class="stat-item">
<div class="stat-label">{{ $t('documentCollection.faq.import.errorCount') }}</div>
<div class="stat-label">
{{ $t('documentCollection.faq.import.errorCount') }}
</div>
<div class="stat-value" :class="hasErrors ? 'danger-text' : ''">
{{ importResult.errorCount || 0 }}
</div>
@@ -263,7 +284,7 @@ const handleImport = async () => {
</ElButton>
</div>
</template>
</ElDialog>
</EasyFlowPanelModal>
</template>
<style scoped>