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

@@ -19,6 +19,7 @@ import {
import { api } from '#/api/request';
import defaultAvatar from '#/assets/defaultUserAvatar.png';
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
import ListPageShell from '#/components/page/ListPageShell.vue';
import PageData from '#/components/page/PageData.vue';
import { $t } from '#/locales';
import { useDictStore } from '#/store';
@@ -91,13 +92,14 @@ function isAdmin(data: any) {
<template>
<div class="flex h-full flex-col gap-6 p-6">
<SysAccountModal ref="saveDialog" @reload="reset" />
<HeaderSearch
:buttons="headerButtons"
@search="handleSearch"
@button-click="showDialog({})"
/>
<div class="bg-background border-border flex-1 rounded-lg border p-5">
<ListPageShell>
<template #filters>
<HeaderSearch
:buttons="headerButtons"
@search="handleSearch"
@button-click="showDialog({})"
/>
</template>
<PageData
ref="pageDataRef"
page-url="/api/v1/sysAccount/page"
@@ -207,7 +209,7 @@ function isAdmin(data: any) {
</ElTable>
</template>
</PageData>
</div>
</ListPageShell>
</div>
</template>

View File

@@ -3,14 +3,9 @@ import type { FormInstance } from 'element-plus';
import { onMounted, ref } from 'vue';
import {
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElInput,
ElMessage,
} from 'element-plus';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { ElForm, ElFormItem, ElInput, ElMessage } from 'element-plus';
import { api } from '#/api/request';
import DictSelect from '#/components/dict/DictSelect.vue';
@@ -101,19 +96,23 @@ function closeDialog() {
</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"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
width="xl"
@confirm="save"
>
<ElForm
label-width="120px"
ref="saveForm"
:model="entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem prop="avatar" :label="$t('sysAccount.avatar')">
<!-- <Cropper v-model="entity.avatar" crop /> -->
@@ -151,23 +150,14 @@ function closeDialog() {
<DictSelect multiple v-model="entity.roleIds" dict-code="sysRole" />
</ElFormItem>
<ElFormItem prop="positionIds" :label="$t('sysAccount.positionIds')">
<DictSelect multiple v-model="entity.positionIds" dict-code="sysPosition" />
<DictSelect
multiple
v-model="entity.positionIds"
dict-code="sysPosition"
/>
</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

@@ -3,14 +3,9 @@ import type { FormInstance } from 'element-plus';
import { onMounted, ref } from 'vue';
import {
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElInput,
ElMessage,
} from 'element-plus';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { ElForm, ElFormItem, ElInput, ElMessage } from 'element-plus';
import { api } from '#/api/request';
import DictSelect from '#/components/dict/DictSelect.vue';
@@ -87,19 +82,23 @@ function closeDialog() {
</script>
<template>
<ElDialog
v-model="dialogVisible"
draggable
<EasyFlowFormModal
v-model:open="dialogVisible"
:closable="!btnLoading"
:title="isAdd ? $t('button.add') : $t('button.edit')"
:before-close="closeDialog"
:close-on-click-modal="false"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
@confirm="save"
>
<ElForm
label-width="120px"
ref="saveForm"
:model="entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem prop="parentId" :label="$t('sysDept.parentId')">
<DictSelect
@@ -125,20 +124,7 @@ function closeDialog() {
<ElInput v-model.trim="entity.remark" />
</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

@@ -24,6 +24,7 @@ import { tryit } from 'radash';
import { api } from '#/api/request';
import DictSelect from '#/components/dict/DictSelect.vue';
import ListPageShell from '#/components/page/ListPageShell.vue';
import PageData from '#/components/page/PageData.vue';
import { $t } from '#/locales';
import { router } from '#/router';
@@ -102,41 +103,42 @@ async function markStatus(row: any, status: number) {
<template>
<div class="flex h-full flex-col gap-1.5 p-6">
<ElForm ref="formRef" inline :model="formData">
<ElFormItem prop="feedbackType" class="!mr-3">
<ElSelect
v-model="formData.feedbackType"
:options="feedbackTypeOptions"
:placeholder="$t('sysFeedback.feedbackType')"
clearable
filterable
immediate
/>
</ElFormItem>
<ElFormItem prop="status" class="!mr-3">
<DictSelect
v-model="formData.status"
dict-code="feedbackType"
:placeholder="$t('sysFeedback.processingStatus')"
/>
</ElFormItem>
<ElFormItem prop="feedbackContent" class="!mr-3">
<ElInput
v-model="formData.feedbackContent"
:placeholder="$t('common.searchPlaceholder')"
/>
</ElFormItem>
<ElFormItem>
<ElButton @click="search(formRef)" type="primary">
{{ $t('button.query') }}
</ElButton>
<ElButton @click="reset(formRef)">
{{ $t('button.reset') }}
</ElButton>
</ElFormItem>
</ElForm>
<div class="bg-background border-border flex-1 rounded-lg border p-5">
<ListPageShell>
<template #filters>
<ElForm ref="formRef" inline :model="formData">
<ElFormItem prop="feedbackType" class="!mr-3">
<ElSelect
v-model="formData.feedbackType"
:options="feedbackTypeOptions"
:placeholder="$t('sysFeedback.feedbackType')"
clearable
filterable
immediate
/>
</ElFormItem>
<ElFormItem prop="status" class="!mr-3">
<DictSelect
v-model="formData.status"
dict-code="feedbackType"
:placeholder="$t('sysFeedback.processingStatus')"
/>
</ElFormItem>
<ElFormItem prop="feedbackContent" class="!mr-3">
<ElInput
v-model="formData.feedbackContent"
:placeholder="$t('common.searchPlaceholder')"
/>
</ElFormItem>
<ElFormItem>
<ElButton @click="search(formRef)" type="primary">
{{ $t('button.query') }}
</ElButton>
<ElButton @click="reset(formRef)">
{{ $t('button.reset') }}
</ElButton>
</ElFormItem>
</ElForm>
</template>
<PageData
ref="pageDataRef"
page-url="/api/v1/sysUserFeedback/page"
@@ -236,6 +238,6 @@ async function markStatus(row: any, status: number) {
</ElTable>
</template>
</PageData>
</div>
</ListPageShell>
</div>
</template>

View File

@@ -24,6 +24,7 @@ import {
import { api } from '#/api/request';
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
import ListPageShell from '#/components/page/ListPageShell.vue';
import PageData from '#/components/page/PageData.vue';
import { $t } from '#/locales';
import { router } from '#/router';
@@ -149,13 +150,14 @@ function toLogPage(row: any) {
<template>
<div class="flex h-full flex-col gap-6 p-6">
<SysJobModal ref="saveDialog" @reload="reset" />
<HeaderSearch
:buttons="headerButtons"
@search="handleSearch"
@button-click="showDialog({})"
/>
<div class="bg-background border-border flex-1 rounded-lg border p-5">
<ListPageShell>
<template #filters>
<HeaderSearch
:buttons="headerButtons"
@search="handleSearch"
@button-click="showDialog({})"
/>
</template>
<PageData
ref="pageDataRef"
page-url="/api/v1/sysJob/page"
@@ -271,7 +273,7 @@ function toLogPage(row: any) {
</ElTable>
</template>
</PageData>
</div>
</ListPageShell>
</div>
</template>

View File

@@ -3,15 +3,9 @@ import type { FormInstance } from 'element-plus';
import { onMounted, ref } from 'vue';
import {
ElAlert,
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElInput,
ElMessage,
} from 'element-plus';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { ElAlert, ElForm, ElFormItem, ElInput, ElMessage } from 'element-plus';
import { api } from '#/api/request';
import CronPicker from '#/components/cron/CronPicker.vue';
@@ -139,20 +133,24 @@ const str = '"param"';
</script>
<template>
<ElDialog
v-model="dialogVisible"
draggable
<EasyFlowFormModal
v-model:open="dialogVisible"
:closable="!btnLoading"
:title="isAdd ? $t('button.add') : $t('button.edit')"
:before-close="closeDialog"
:close-on-click-modal="false"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
@confirm="save"
>
<ElForm
v-loading="paramsLoading"
label-width="120px"
ref="saveForm"
:model="entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem prop="jobName" :label="$t('sysJob.jobName')">
<ElInput v-model.trim="entity.jobName" />
@@ -225,20 +223,7 @@ const str = '"param"';
<ElInput v-model.trim="entity.remark" />
</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

@@ -6,6 +6,7 @@ import { ref } from 'vue';
import { ElTable, ElTableColumn } from 'element-plus';
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
import ListPageShell from '#/components/page/ListPageShell.vue';
import PageData from '#/components/page/PageData.vue';
import { $t } from '#/locales';
@@ -25,9 +26,10 @@ function reset(formEl?: FormInstance) {
<template>
<div class="flex h-full flex-col gap-6 p-6">
<SysLogModal ref="saveDialog" @reload="reset" />
<HeaderSearch @search="handleSearch" />
<div class="bg-background border-border flex-1 rounded-lg border p-5">
<ListPageShell>
<template #filters>
<HeaderSearch @search="handleSearch" />
</template>
<PageData
ref="pageDataRef"
page-url="/api/v1/sysLog/page"
@@ -76,7 +78,7 @@ function reset(formEl?: FormInstance) {
</ElTable>
</template>
</PageData>
</div>
</ListPageShell>
</div>
</template>

View File

@@ -3,14 +3,9 @@ import type { FormInstance } from 'element-plus';
import { onMounted, ref } from 'vue';
import {
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElInput,
ElMessage,
} from 'element-plus';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { ElForm, ElFormItem, ElInput, ElMessage } from 'element-plus';
import { api } from '#/api/request';
import { $t } from '#/locales';
@@ -79,19 +74,23 @@ function closeDialog() {
</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"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
width="lg"
@confirm="save"
>
<ElForm
label-width="120px"
ref="saveForm"
:model="entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem prop="accountId" :label="$t('sysLog.accountId')">
<ElInput v-model.trim="entity.accountId" />
@@ -124,20 +123,7 @@ function closeDialog() {
<ElInput v-model.trim="entity.status" />
</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

@@ -3,11 +3,9 @@ import type { FormInstance } from 'element-plus';
import { onMounted, ref } from 'vue';
import { IconPicker } from '@easyflow/common-ui';
import { EasyFlowFormModal, IconPicker } from '@easyflow/common-ui';
import {
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElInput,
@@ -103,20 +101,24 @@ function closeDialog() {
</script>
<template>
<ElDialog
v-model="dialogVisible"
draggable
<EasyFlowFormModal
v-model:open="dialogVisible"
:closable="!btnLoading"
:title="isAdd ? $t('button.add') : $t('button.edit')"
:before-close="closeDialog"
:close-on-click-modal="false"
:z-index="1999"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
@confirm="save"
>
<ElForm
label-width="120px"
ref="saveForm"
:model="entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem prop="parentId" :label="$t('sysMenu.parentId')">
<DictSelect
@@ -168,20 +170,7 @@ function closeDialog() {
<ElInput v-model.trim="entity.remark" />
</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

@@ -17,6 +17,7 @@ import {
import { api } from '#/api/request';
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
import ListPageShell from '#/components/page/ListPageShell.vue';
import PageData from '#/components/page/PageData.vue';
import { $t } from '#/locales';
import { useDictStore } from '#/store';
@@ -124,13 +125,14 @@ function remove(row: any) {
<template>
<div class="flex h-full flex-col gap-6 p-6">
<SysPositionModal ref="saveDialog" @reload="reset" />
<HeaderSearch
:buttons="headerButtons"
@search="handleSearch"
@button-click="showDialog({})"
/>
<div class="bg-background border-border flex-1 rounded-lg border p-5">
<ListPageShell>
<template #filters>
<HeaderSearch
:buttons="headerButtons"
@search="handleSearch"
@button-click="showDialog({})"
/>
</template>
<PageData
ref="pageDataRef"
page-url="/api/v1/sysPosition/page"
@@ -231,7 +233,7 @@ function remove(row: any) {
</ElTable>
</template>
</PageData>
</div>
</ListPageShell>
</div>
</template>

View File

@@ -3,9 +3,9 @@ import type { FormInstance } from 'element-plus';
import { ref } from 'vue';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import {
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElInput,
@@ -94,20 +94,24 @@ function closeDialog() {
</script>
<template>
<ElDialog
v-model="dialogVisible"
draggable
<EasyFlowFormModal
v-model:open="dialogVisible"
:closable="!btnLoading"
:title="isAdd ? $t('button.add') : $t('button.edit')"
:before-close="closeDialog"
:close-on-click-modal="false"
width="500px"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
@confirm="save"
>
<ElForm
label-width="100px"
ref="saveForm"
:model="entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem
prop="positionName"
@@ -142,20 +146,7 @@ function closeDialog() {
<ElInput v-model.trim="entity.remark" type="textarea" :rows="3" />
</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

@@ -17,6 +17,7 @@ import {
import { api } from '#/api/request';
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
import ListPageShell from '#/components/page/ListPageShell.vue';
import PageData from '#/components/page/PageData.vue';
import { $t } from '#/locales';
import { useDictStore } from '#/store';
@@ -89,13 +90,14 @@ function remove(row: any) {
<template>
<div class="flex h-full flex-col gap-6 p-6">
<SysRoleModal ref="saveDialog" @reload="reset" />
<HeaderSearch
:buttons="headerButtons"
@search="handleSearch"
@button-click="showDialog({ menuCheckStrictly: true })"
/>
<div class="bg-background border-border flex-1 rounded-lg border p-5">
<ListPageShell>
<template #filters>
<HeaderSearch
:buttons="headerButtons"
@search="handleSearch"
@button-click="showDialog({ menuCheckStrictly: true })"
/>
</template>
<PageData
ref="pageDataRef"
page-url="/api/v1/sysRole/page"
@@ -160,7 +162,7 @@ function remove(row: any) {
</ElTable>
</template>
</PageData>
</div>
</ListPageShell>
</div>
</template>

View File

@@ -3,15 +3,9 @@ import type { FormInstance } from 'element-plus';
import { onMounted, ref } from 'vue';
import {
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElInput,
ElMessage,
ElSwitch,
} from 'element-plus';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { ElForm, ElFormItem, ElInput, ElMessage, ElSwitch } from 'element-plus';
import { api } from '#/api/request';
import DictSelect from '#/components/dict/DictSelect.vue';
@@ -95,19 +89,23 @@ function getDeptIds(roleId: any) {
</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"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
width="xl"
@confirm="save"
>
<ElForm
label-width="120px"
ref="saveForm"
:model="entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem prop="roleName" :label="$t('sysRole.roleName')">
<ElInput v-model.trim="entity.roleName" />
@@ -157,20 +155,7 @@ function getDeptIds(roleId: any) {
</div>
</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>