feat: 统一管理端弹窗与内容区交互样式
- 收敛管理端公共 Modal 链路,新增表单弹窗与普通内容弹窗包装\n- 迁移 Bot、知识库、插件、工作流、资源、MCP、数据中枢与系统管理页面级弹窗\n- 统一内容区工具栏、列表容器、导航与顶部按钮的视觉密度和交互节奏
This commit is contained in:
@@ -8,7 +8,10 @@ import {
|
||||
} from 'vue-element-plus-x';
|
||||
|
||||
import { registerAccessDirective } from '@easyflow/access';
|
||||
import { registerLoadingDirective } from '@easyflow/common-ui';
|
||||
import {
|
||||
registerLoadingDirective,
|
||||
setDefaultModalProps,
|
||||
} from '@easyflow/common-ui';
|
||||
import { preferences } from '@easyflow/preferences';
|
||||
import { initStores } from '@easyflow/stores';
|
||||
import '@easyflow/styles';
|
||||
@@ -31,10 +34,12 @@ async function bootstrap(namespace: string) {
|
||||
// 初始化表单组件
|
||||
await initSetupEasyFlowForm();
|
||||
|
||||
// // 设置弹窗的默认配置
|
||||
// setDefaultModalProps({
|
||||
// fullscreenButton: false,
|
||||
// });
|
||||
// 设置弹窗的默认配置
|
||||
setDefaultModalProps({
|
||||
bordered: true,
|
||||
fullscreenButton: false,
|
||||
overlayBlur: 0,
|
||||
});
|
||||
// // 设置抽屉的默认配置
|
||||
// setDefaultDrawerProps({
|
||||
// zIndex: 2000,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { ArrowDown } from '@element-plus/icons-vue';
|
||||
import { ArrowDown, Search } from '@element-plus/icons-vue';
|
||||
import {
|
||||
ElButton,
|
||||
ElDropdown,
|
||||
@@ -14,9 +14,7 @@ import {
|
||||
import { hasPermission } from '#/api/common/hasPermission.ts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
// 按钮配置数组
|
||||
buttons: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
@@ -29,40 +27,43 @@ const props = defineProps({
|
||||
});
|
||||
},
|
||||
},
|
||||
// 最大显示按钮数量(不包括下拉菜单)
|
||||
maxVisibleButtons: {
|
||||
type: Number,
|
||||
default: 3,
|
||||
},
|
||||
// 搜索框占位符
|
||||
searchPlaceholder: {
|
||||
type: String,
|
||||
default: $t('common.searchPlaceholder'),
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['search', 'button-click', 'buttonClick']);
|
||||
const emit = defineEmits(['search', 'buttonClick']);
|
||||
|
||||
// 搜索值
|
||||
const searchValue = ref('');
|
||||
|
||||
// 计算显示的按钮
|
||||
const visibleButtons = computed(() => {
|
||||
return props.buttons.slice(0, props.maxVisibleButtons);
|
||||
});
|
||||
|
||||
// 计算下拉菜单中的按钮
|
||||
const dropdownButtons = computed(() => {
|
||||
const dropdownButtonsTemp = props.buttons.slice(props.maxVisibleButtons);
|
||||
if (dropdownButtonsTemp.length === 0) {
|
||||
return [];
|
||||
}
|
||||
return dropdownButtonsTemp.value.filter((action) => {
|
||||
return hasPermission([action.permission]);
|
||||
const filterButtonsByPermission = (buttons) => {
|
||||
return buttons.filter((button) => {
|
||||
return !button.permission || hasPermission([button.permission]);
|
||||
});
|
||||
};
|
||||
|
||||
const visibleButtons = computed(() => {
|
||||
return filterButtonsByPermission(props.buttons).slice(
|
||||
0,
|
||||
props.maxVisibleButtons,
|
||||
);
|
||||
});
|
||||
|
||||
// 处理搜索
|
||||
const dropdownButtons = computed(() => {
|
||||
return filterButtonsByPermission(props.buttons).slice(
|
||||
props.maxVisibleButtons,
|
||||
);
|
||||
});
|
||||
|
||||
const emitButtonEvent = (payload) => {
|
||||
emit('buttonClick', payload);
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
emit('search', searchValue.value);
|
||||
};
|
||||
@@ -72,9 +73,8 @@ const handleReset = () => {
|
||||
emit('search', '');
|
||||
};
|
||||
|
||||
// 处理按钮点击
|
||||
const handleButtonClick = (button) => {
|
||||
emit('buttonClick', {
|
||||
emitButtonEvent({
|
||||
type: 'button',
|
||||
key: button.key,
|
||||
button,
|
||||
@@ -82,9 +82,8 @@ const handleButtonClick = (button) => {
|
||||
});
|
||||
};
|
||||
|
||||
// 处理下拉菜单点击
|
||||
const handleDropdownClick = (button) => {
|
||||
emit('buttonClick', {
|
||||
emitButtonEvent({
|
||||
type: 'dropdown',
|
||||
key: button.key,
|
||||
button,
|
||||
@@ -95,34 +94,34 @@ const handleDropdownClick = (button) => {
|
||||
|
||||
<template>
|
||||
<div class="custom-header">
|
||||
<!-- 左侧搜索区域 -->
|
||||
<div class="header-left">
|
||||
<div class="search-container">
|
||||
<div>
|
||||
<ElInput
|
||||
v-model="searchValue"
|
||||
:placeholder="$t('common.searchPlaceholder')"
|
||||
class="search-input"
|
||||
@keyup.enter="handleSearch"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<ElButton type="primary" auto-insert-space @click="handleSearch">
|
||||
{{ $t('button.query') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
<div>
|
||||
<ElButton auto-insert-space @click="handleReset">
|
||||
{{ $t('button.reset') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
<div class="search-group">
|
||||
<ElInput
|
||||
v-model="searchValue"
|
||||
:placeholder="searchPlaceholder"
|
||||
class="search-input"
|
||||
clearable
|
||||
@keyup.enter="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<ElIcon class="search-prefix">
|
||||
<Search />
|
||||
</ElIcon>
|
||||
</template>
|
||||
</ElInput>
|
||||
<ElButton type="primary" auto-insert-space @click="handleSearch">
|
||||
{{ $t('button.query') }}
|
||||
</ElButton>
|
||||
<ElButton auto-insert-space @click="handleReset">
|
||||
{{ $t('button.reset') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧按钮区域 -->
|
||||
<div class="header-right">
|
||||
<!-- 显示的按钮(最多3个) -->
|
||||
<div
|
||||
v-if="visibleButtons.length > 0 || dropdownButtons.length > 0"
|
||||
class="header-right"
|
||||
>
|
||||
<template
|
||||
v-for="(button, index) in visibleButtons"
|
||||
:key="button.key || index"
|
||||
@@ -138,14 +137,13 @@ const handleDropdownClick = (button) => {
|
||||
</ElButton>
|
||||
</template>
|
||||
|
||||
<!-- 下拉菜单(隐藏的按钮) -->
|
||||
<ElDropdown
|
||||
v-if="dropdownButtons.length > 0"
|
||||
@command="handleDropdownClick"
|
||||
>
|
||||
<ElButton>
|
||||
{{ $t('button.more')
|
||||
}}<ElIcon class="el-icon--right"><ArrowDown /></ElIcon>
|
||||
{{ $t('button.more') }}
|
||||
<ElIcon class="el-icon--right"><ArrowDown /></ElIcon>
|
||||
</ElButton>
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
@@ -158,7 +156,7 @@ const handleDropdownClick = (button) => {
|
||||
<ElIcon v-if="button.icon">
|
||||
<component :is="button.icon" />
|
||||
</ElIcon>
|
||||
<span style="margin-left: 8px">{{ button.text }}</span>
|
||||
<span class="dropdown-label">{{ button.text }}</span>
|
||||
</ElDropdownItem>
|
||||
</ElDropdownMenu>
|
||||
</template>
|
||||
@@ -168,54 +166,109 @@ const handleDropdownClick = (button) => {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.custom-header {
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.header-left,
|
||||
.header-right {
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
.header-left,
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
.header-left {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search-group {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 300px;
|
||||
border-radius: 4px;
|
||||
width: min(360px, 100%);
|
||||
}
|
||||
|
||||
.search-input :deep(.el-input__wrapper) {
|
||||
min-height: 40px;
|
||||
background: hsl(var(--surface-contrast-soft) / 0.92);
|
||||
border-radius: 14px;
|
||||
box-shadow:
|
||||
inset 0 1px 0 hsl(var(--glass-border) / 0.44),
|
||||
0 10px 24px -24px hsl(var(--foreground) / 0.24);
|
||||
}
|
||||
|
||||
.search-input :deep(.el-input__wrapper:hover),
|
||||
.search-input :deep(.el-input__wrapper.is-focus) {
|
||||
background: hsl(var(--surface-subtle) / 0.98);
|
||||
box-shadow:
|
||||
inset 0 1px 0 hsl(var(--glass-border) / 0.56),
|
||||
0 0 0 3px hsl(var(--primary) / 0.08),
|
||||
0 12px 24px -24px hsl(var(--foreground) / 0.24);
|
||||
}
|
||||
|
||||
.search-prefix {
|
||||
color: hsl(var(--text-muted));
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-right :deep(.el-button),
|
||||
.search-group :deep(.el-button) {
|
||||
min-width: 64px;
|
||||
height: 32px;
|
||||
min-height: 32px;
|
||||
padding-inline: 18px;
|
||||
border-radius: 10px;
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.header-right :deep(.el-button:not(.el-button--primary)),
|
||||
.search-group :deep(.el-button:not(.el-button--primary)) {
|
||||
color: hsl(var(--text-strong));
|
||||
background: hsl(var(--surface-contrast-soft) / 0.86);
|
||||
border-color: transparent;
|
||||
box-shadow:
|
||||
inset 0 1px 0 hsl(var(--glass-border) / 0.34),
|
||||
0 10px 24px -24px hsl(var(--foreground) / 0.2);
|
||||
}
|
||||
|
||||
.header-right :deep(.el-button--primary),
|
||||
.search-group :deep(.el-button--primary) {
|
||||
box-shadow: 0 16px 28px -22px hsl(var(--primary) / 0.48);
|
||||
}
|
||||
|
||||
.dropdown-label {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.custom-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
227
easyflow-ui-admin/app/src/components/page/ListPageShell.vue
Normal file
227
easyflow-ui-admin/app/src/components/page/ListPageShell.vue
Normal file
@@ -0,0 +1,227 @@
|
||||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
|
||||
import { computed, useSlots } from 'vue';
|
||||
|
||||
interface Props {
|
||||
contentPadding?: number | string;
|
||||
dense?: boolean;
|
||||
stickyToolbar?: boolean;
|
||||
surface?: 'panel' | 'subtle';
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
contentPadding: 0,
|
||||
dense: false,
|
||||
stickyToolbar: false,
|
||||
surface: 'panel',
|
||||
});
|
||||
|
||||
const slots = useSlots();
|
||||
|
||||
const hasToolbar = computed(() => Boolean(slots.filters || slots.actions));
|
||||
|
||||
const contentStyle = computed((): CSSProperties => {
|
||||
const padding =
|
||||
typeof props.contentPadding === 'number'
|
||||
? `${props.contentPadding}px`
|
||||
: props.contentPadding;
|
||||
|
||||
return padding ? { '--list-page-shell-content-padding': padding } : {};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section
|
||||
:class="[
|
||||
'list-page-shell',
|
||||
`is-${surface}`,
|
||||
{
|
||||
'is-dense': dense,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div
|
||||
v-if="hasToolbar"
|
||||
:class="[
|
||||
'list-page-shell__toolbar',
|
||||
{
|
||||
'is-sticky': stickyToolbar,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div v-if="$slots.filters" class="list-page-shell__filters">
|
||||
<slot name="filters"></slot>
|
||||
</div>
|
||||
<div v-if="$slots.actions" class="list-page-shell__actions">
|
||||
<slot name="actions"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-page-shell__content" :style="contentStyle">
|
||||
<slot></slot>
|
||||
<slot name="empty"></slot>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.list-page-shell {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.list-page-shell.is-dense {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.list-page-shell__toolbar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 8px 6px 2px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.list-page-shell__toolbar.is-sticky {
|
||||
position: sticky;
|
||||
top: 12px;
|
||||
z-index: 5;
|
||||
padding: 10px 10px 6px;
|
||||
background: hsl(var(--glass-tint) / 0.7);
|
||||
border: 1px solid hsl(var(--glass-border) / 0.44);
|
||||
border-radius: 20px;
|
||||
box-shadow: var(--shadow-toolbar);
|
||||
backdrop-filter: blur(var(--glass-blur)) saturate(155%);
|
||||
}
|
||||
|
||||
.list-page-shell__filters,
|
||||
.list-page-shell__actions {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.list-page-shell__filters {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.list-page-shell__content {
|
||||
--list-page-shell-content-padding: 0px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
padding: var(--list-page-shell-content-padding);
|
||||
background: hsl(var(--surface-panel));
|
||||
border: none;
|
||||
border-radius: 24px;
|
||||
box-shadow: var(--shadow-subtle);
|
||||
}
|
||||
|
||||
.list-page-shell.is-subtle .list-page-shell__content {
|
||||
background: hsl(var(--surface-contrast-soft));
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.page-data-container) {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-empty) {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table) {
|
||||
--el-table-bg-color: transparent;
|
||||
--el-table-tr-bg-color: transparent;
|
||||
--el-table-header-bg-color: hsl(var(--table-header-bg));
|
||||
--el-table-border-color: hsl(var(--table-row-border));
|
||||
--el-table-current-row-bg-color: hsl(var(--table-row-hover));
|
||||
--el-fill-color-blank: transparent;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table--border),
|
||||
.list-page-shell__content :deep(.el-table__inner-wrapper),
|
||||
.list-page-shell__content :deep(.el-table__header-wrapper),
|
||||
.list-page-shell__content :deep(.el-table__body-wrapper) {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table__inner-wrapper::before),
|
||||
.list-page-shell__content :deep(.el-table--border::before),
|
||||
.list-page-shell__content :deep(.el-table--border::after) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table th.el-table__cell) {
|
||||
padding: 12px 0;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: hsl(var(--text-strong));
|
||||
background: hsl(var(--table-header-bg) / 0.86);
|
||||
border-bottom: 1px solid hsl(var(--divider-faint) / 0.38);
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table th.el-table__cell:first-child) {
|
||||
border-top-left-radius: 12px;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table th.el-table__cell:last-child) {
|
||||
border-top-right-radius: 12px;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table td.el-table__cell),
|
||||
.list-page-shell__content :deep(.el-table--border .el-table__cell) {
|
||||
padding: 14px 0;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid hsl(var(--divider-faint) / 0.46);
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table__row:hover > td.el-table__cell) {
|
||||
background: hsl(var(--table-row-hover)) !important;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-tag) {
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-pagination) {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-pagination button),
|
||||
.list-page-shell__content :deep(.el-pager li) {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.list-page-shell__toolbar :deep(.custom-header) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.list-page-shell {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.list-page-shell__toolbar {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
padding: 2px 0 0;
|
||||
}
|
||||
|
||||
.list-page-shell__actions {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -23,7 +23,7 @@ const props = withDefaults(defineProps<PageDataProps>(), {
|
||||
// 响应式数据
|
||||
const pageList = ref([]);
|
||||
const loading = ref(false);
|
||||
const queryParams = ref({});
|
||||
const queryParams = ref<Record<string, any>>({});
|
||||
|
||||
const pageInfo = reactive({
|
||||
pageNumber: 1,
|
||||
@@ -32,7 +32,7 @@ const pageInfo = reactive({
|
||||
});
|
||||
|
||||
// 模拟 API 调用 - 这里需要根据你的实际 API 调用方式调整
|
||||
const doGet = async (params: any) => {
|
||||
const doGet = async (params: Record<string, any>) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
// 这里替换为你的实际 API 调用
|
||||
@@ -76,7 +76,7 @@ const handleCurrentChange = (newPage: number) => {
|
||||
};
|
||||
|
||||
// 暴露给父组件的方法 (替代 useImperativeHandle)
|
||||
const setQuery = (newQueryParams: string) => {
|
||||
const setQuery = (newQueryParams: Record<string, any>) => {
|
||||
pageInfo.pageNumber = 1;
|
||||
pageInfo.pageSize = props.pageSize;
|
||||
queryParams.value = newQueryParams;
|
||||
@@ -85,6 +85,7 @@ const setQuery = (newQueryParams: string) => {
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
reload: getPageList,
|
||||
setQuery,
|
||||
});
|
||||
|
||||
@@ -106,10 +107,13 @@ onMounted(() => {
|
||||
<template>
|
||||
<div class="page-data-container" v-loading="loading">
|
||||
<template v-if="pageList.length > 0">
|
||||
<div>
|
||||
<div class="page-data-container__body">
|
||||
<slot :page-list="pageList"></slot>
|
||||
</div>
|
||||
<div v-if="pageInfo.total > pageInfo.pageSize" class="mx-auto mt-8 w-fit">
|
||||
<div
|
||||
v-if="pageInfo.total > pageInfo.pageSize"
|
||||
class="page-data-container__pagination mx-auto mt-6 w-fit"
|
||||
>
|
||||
<ElPagination
|
||||
v-model:current-page="pageInfo.pageNumber"
|
||||
v-model:page-size="pageInfo.pageSize"
|
||||
@@ -121,9 +125,36 @@ onMounted(() => {
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<ElEmpty
|
||||
:image="`/empty${preferences.theme.mode === 'dark' ? '-dark' : ''}.png`"
|
||||
v-else
|
||||
/>
|
||||
<slot v-else name="empty">
|
||||
<ElEmpty
|
||||
:image="`/empty${preferences.theme.mode === 'dark' ? '-dark' : ''}.png`"
|
||||
/>
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.page-data-container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
padding: 18px 20px 18px;
|
||||
}
|
||||
|
||||
.page-data-container__body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.page-data-container__pagination {
|
||||
flex-shrink: 0;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.page-data-container {
|
||||
padding: 14px 14px 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -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) => {
|
||||
<template>
|
||||
<ElUpload
|
||||
class="avatar-uploader"
|
||||
:class="[
|
||||
`avatar-uploader--${props.theme}`,
|
||||
{ 'avatar-uploader--rounded': props.shape === 'rounded' },
|
||||
]"
|
||||
:style="{ '--avatar-size': `${props.size}px` }"
|
||||
:action="`${apiURL}${props.action}`"
|
||||
:headers="headers"
|
||||
:show-file-list="false"
|
||||
@@ -96,30 +113,65 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
|
||||
<style scoped>
|
||||
.avatar-uploader .avatar {
|
||||
display: block;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
width: var(--avatar-size);
|
||||
height: var(--avatar-size);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.avatar-uploader .el-upload {
|
||||
width: var(--avatar-size);
|
||||
height: var(--avatar-size);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 1px solid #e6e9ee;
|
||||
border: 1px solid hsl(var(--input) / 0.92);
|
||||
border-radius: 50%;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
background: hsl(var(--modal-surface-strong) / 0.92);
|
||||
box-shadow:
|
||||
inset 0 1px 0 hsl(0 0% 100% / 0.72),
|
||||
0 16px 28px -24px hsl(var(--foreground) / 0.24);
|
||||
transition:
|
||||
transform var(--el-transition-duration-fast),
|
||||
border-color var(--el-transition-duration-fast),
|
||||
box-shadow var(--el-transition-duration-fast);
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
border-color: hsl(var(--primary) / 0.52);
|
||||
transform: translateY(-1px);
|
||||
box-shadow:
|
||||
inset 0 1px 0 hsl(0 0% 100% / 0.76),
|
||||
0 20px 36px -26px hsl(var(--modal-preview-glow) / 0.3);
|
||||
}
|
||||
|
||||
.avatar-uploader--soft-panel .el-upload {
|
||||
background:
|
||||
radial-gradient(
|
||||
circle at top,
|
||||
hsl(var(--modal-preview-glow) / 0.14),
|
||||
transparent 60%
|
||||
),
|
||||
linear-gradient(
|
||||
145deg,
|
||||
hsl(var(--modal-preview-surface) / 0.98),
|
||||
hsl(var(--modal-preview-surface-strong) / 0.9)
|
||||
);
|
||||
border-color: hsl(var(--modal-preview-border) / 0.9);
|
||||
}
|
||||
|
||||
.avatar-uploader--rounded .el-upload {
|
||||
border-radius: 26px;
|
||||
}
|
||||
|
||||
.el-icon.avatar-uploader-icon {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
width: var(--avatar-size);
|
||||
height: var(--avatar-size);
|
||||
font-size: 28px;
|
||||
color: var(--el-text-color-secondary);
|
||||
color: hsl(var(--text-muted));
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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助手,请根据用户的问题给出清晰、准确的回答。",
|
||||
|
||||
@@ -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 () => {
|
||||
<!-- 创建&编辑Bot弹窗 -->
|
||||
<Modal ref="modalRef" @success="pageDataRef.setQuery({})" />
|
||||
|
||||
<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
|
||||
@@ -330,15 +334,6 @@ const getSideList = async () => {
|
||||
/>
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -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<InstanceType<typeof ElForm>>();
|
||||
const formData = ref<SaveBotParams | UpdateBotParams>(initialFormData);
|
||||
const rules = {
|
||||
title: [{ required: true, message: $t('message.required'), trigger: 'blur' }],
|
||||
alias: [{ required: true, message: $t('message.required'), trigger: 'blur' }],
|
||||
};
|
||||
const formData = ref<SaveBotParams | UpdateBotParams>(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,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
:title="`${$t(`button.${dialogType}`)}${$t('bot.chatAssistant')}`"
|
||||
draggable
|
||||
align-center
|
||||
<EasyFlowFormModal
|
||||
v-model:open="dialogVisible"
|
||||
:confirm-loading="loading"
|
||||
:confirm-text="$t('button.save')"
|
||||
:description="dialogDescription"
|
||||
:submitting="loading"
|
||||
:title="dialogTitle"
|
||||
width="lg"
|
||||
@confirm="handleSubmit"
|
||||
>
|
||||
<ElForm ref="formRef" :model="formData" :rules="rules" label-width="150px">
|
||||
<ElFormItem :label="$t('common.avatar')" prop="icon">
|
||||
<UploadAvatar v-model="formData.icon" />
|
||||
</ElFormItem>
|
||||
<ElFormItem prop="categoryId" :label="$t('aiWorkflow.categoryId')">
|
||||
<DictSelect v-model="formData.categoryId" dict-code="aiBotCategory" />
|
||||
</ElFormItem>
|
||||
<ElFormItem :label="$t('aiWorkflow.title')" prop="title">
|
||||
<ElInput v-model="formData.title" />
|
||||
</ElFormItem>
|
||||
<ElFormItem :label="$t('plugin.alias')" prop="alias">
|
||||
<ElInput v-model="formData.alias" />
|
||||
</ElFormItem>
|
||||
<ElFormItem :label="$t('plugin.description')" prop="description">
|
||||
<ElInput type="textarea" :rows="3" v-model="formData.description" />
|
||||
</ElFormItem>
|
||||
<ElFormItem prop="status" :label="$t('aiWorkflow.status')">
|
||||
<DictSelect v-model="formData.status" dict-code="showOrNot" />
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<ElForm
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
class="bot-modal-form"
|
||||
label-position="top"
|
||||
status-icon
|
||||
>
|
||||
<section class="bot-modal-section">
|
||||
<header class="bot-modal-section__header">
|
||||
<div>
|
||||
<h4 class="bot-modal-section__title">
|
||||
{{ $t('bot.modal.sectionAppearanceTitle') }}
|
||||
</h4>
|
||||
<p class="bot-modal-section__description">
|
||||
{{ $t('bot.modal.sectionAppearanceDescription') }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<template #footer>
|
||||
<ElButton @click="dialogVisible = false">
|
||||
{{ $t('button.cancel') }}
|
||||
</ElButton>
|
||||
<ElButton
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
:disabled="loading"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
{{ $t('button.save') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
<div class="bot-modal-appearance-grid">
|
||||
<ElFormItem
|
||||
class="bot-modal-avatar-field"
|
||||
:label="$t('common.avatar')"
|
||||
prop="icon"
|
||||
>
|
||||
<UploadAvatar
|
||||
v-model="formData.icon"
|
||||
:size="88"
|
||||
theme="soft-panel"
|
||||
/>
|
||||
</ElFormItem>
|
||||
|
||||
<div class="bot-modal-appearance-fields">
|
||||
<ElFormItem :label="$t('aiWorkflow.title')" prop="title">
|
||||
<ElInput v-model="formData.title" />
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem :label="$t('aiWorkflow.categoryId')" prop="categoryId">
|
||||
<DictSelect
|
||||
v-model="formData.categoryId"
|
||||
dict-code="aiBotCategory"
|
||||
/>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem
|
||||
class="bot-modal-grid__full"
|
||||
:label="$t('plugin.alias')"
|
||||
prop="alias"
|
||||
>
|
||||
<ElInput v-model="formData.alias" />
|
||||
<div class="bot-modal-field-tip">
|
||||
{{ $t('bot.modal.aliasHint') }}
|
||||
</div>
|
||||
</ElFormItem>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="bot-modal-section bot-modal-section--compact">
|
||||
<header class="bot-modal-section__header">
|
||||
<div>
|
||||
<h4 class="bot-modal-section__title">
|
||||
{{ $t('bot.modal.sectionPublishTitle') }}
|
||||
</h4>
|
||||
<p class="bot-modal-section__description">
|
||||
{{ $t('bot.modal.sectionPublishDescription') }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="bot-modal-publish-grid">
|
||||
<ElFormItem :label="$t('plugin.description')" prop="description">
|
||||
<ElInput v-model="formData.description" :rows="3" type="textarea" />
|
||||
<div class="bot-modal-field-tip">
|
||||
{{ $t('bot.modal.descriptionHint') }}
|
||||
</div>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem
|
||||
class="bot-modal-publish-field"
|
||||
:label="$t('aiWorkflow.status')"
|
||||
prop="status"
|
||||
>
|
||||
<DictSelect v-model="formData.status" dict-code="showOrNot" />
|
||||
<div class="bot-modal-field-tip">
|
||||
{{ $t('bot.modal.statusHint') }}
|
||||
</div>
|
||||
</ElFormItem>
|
||||
</div>
|
||||
</section>
|
||||
</ElForm>
|
||||
</EasyFlowFormModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.bot-modal-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.bot-modal-section {
|
||||
border-radius: 14px;
|
||||
border: 1px solid hsl(var(--modal-divider));
|
||||
background: hsl(var(--modal-content-surface-strong));
|
||||
box-shadow: none;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.bot-modal-section--compact {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.bot-modal-section__header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.bot-modal-section__title {
|
||||
margin: 0;
|
||||
color: hsl(var(--text-strong));
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.bot-modal-section__description {
|
||||
margin: 3px 0 0;
|
||||
color: hsl(var(--text-muted));
|
||||
font-size: 11px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.bot-modal-appearance-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 112px minmax(0, 1fr);
|
||||
gap: 14px 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.bot-modal-appearance-fields {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 14px 16px;
|
||||
}
|
||||
|
||||
.bot-modal-grid__full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.bot-modal-publish-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 220px);
|
||||
gap: 14px 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.bot-modal-publish-field {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.bot-modal-avatar-field {
|
||||
align-items: flex-start;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.bot-modal-avatar-field :deep(.el-form-item__content) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.bot-modal-field-tip {
|
||||
margin-top: 4px;
|
||||
color: hsl(var(--text-muted));
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.bot-modal-form :deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.bot-modal-form :deep(.el-form-item__label) {
|
||||
padding-bottom: 6px;
|
||||
color: hsl(var(--text-strong));
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.bot-modal-form :deep(.el-input__wrapper),
|
||||
.bot-modal-form :deep(.el-select__wrapper),
|
||||
.bot-modal-form :deep(.el-textarea__inner) {
|
||||
border-radius: 12px;
|
||||
background: hsl(var(--input-background));
|
||||
box-shadow: inset 0 0 0 1px hsl(var(--input) / 0.92);
|
||||
transition:
|
||||
box-shadow 0.2s ease,
|
||||
transform 0.2s ease,
|
||||
border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.bot-modal-form :deep(.el-input__wrapper),
|
||||
.bot-modal-form :deep(.el-select__wrapper) {
|
||||
min-height: 42px;
|
||||
}
|
||||
|
||||
.bot-modal-form :deep(.el-input__wrapper:hover),
|
||||
.bot-modal-form :deep(.el-select__wrapper:hover),
|
||||
.bot-modal-form :deep(.el-textarea__inner:hover) {
|
||||
box-shadow: inset 0 0 0 1px hsl(var(--primary) / 0.18);
|
||||
}
|
||||
|
||||
.bot-modal-form :deep(.el-input__wrapper.is-focus),
|
||||
.bot-modal-form :deep(.el-select__wrapper.is-focused),
|
||||
.bot-modal-form :deep(.el-textarea__inner:focus) {
|
||||
box-shadow:
|
||||
inset 0 0 0 1px hsl(var(--primary) / 0.72),
|
||||
0 0 0 4px hsl(var(--primary) / 0.12);
|
||||
}
|
||||
|
||||
.bot-modal-form :deep(.el-textarea__inner) {
|
||||
min-height: 88px;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
.bot-modal-form :deep(.el-form-item.is-error .el-input__wrapper),
|
||||
.bot-modal-form :deep(.el-form-item.is-error .el-select__wrapper),
|
||||
.bot-modal-form :deep(.el-form-item.is-error .el-textarea__inner) {
|
||||
box-shadow:
|
||||
inset 0 0 0 1px hsl(var(--destructive) / 0.8),
|
||||
0 0 0 4px hsl(var(--destructive) / 0.08);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.bot-modal-appearance-grid,
|
||||
.bot-modal-appearance-fields,
|
||||
.bot-modal-publish-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import { ElButton, ElDialog, ElForm, ElFormItem, ElInput } from 'element-plus';
|
||||
import { ElButton, ElForm, ElFormItem, ElInput } from 'element-plus';
|
||||
|
||||
import { sseClient } from '#/api/request';
|
||||
|
||||
@@ -58,14 +59,21 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
<EasyFlowPanelModal
|
||||
v-model:open="dialogVisible"
|
||||
:title="$t('bot.aiOptimizedPrompts')"
|
||||
draggable
|
||||
align-center
|
||||
width="550px"
|
||||
:centered="true"
|
||||
:show-cancel-button="false"
|
||||
:show-confirm-button="false"
|
||||
>
|
||||
<ElForm ref="formRef" :model="formData" :rules="rules">
|
||||
<ElForm
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact"
|
||||
>
|
||||
<ElFormItem prop="prompt">
|
||||
<ElInput type="textarea" :rows="20" v-model="formData.prompt" />
|
||||
</ElFormItem>
|
||||
@@ -87,5 +95,5 @@ defineExpose({
|
||||
{{ loading ? $t('button.optimizing') : $t('button.regenerate') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</EasyFlowPanelModal>
|
||||
</template>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -19,6 +19,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';
|
||||
|
||||
@@ -107,12 +108,14 @@ const refreshLoadingMap = ref<Record<number | string, boolean>>({});
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 p-6">
|
||||
<McpModal ref="saveDialog" @reload="reset" />
|
||||
<HeaderSearch
|
||||
:buttons="headerButtons"
|
||||
@search="handleSearch"
|
||||
@button-click="handleHeaderButtonClick"
|
||||
/>
|
||||
<div class="bg-background border-border flex-1 rounded-lg border p-5">
|
||||
<ListPageShell>
|
||||
<template #filters>
|
||||
<HeaderSearch
|
||||
:buttons="headerButtons"
|
||||
@search="handleSearch"
|
||||
@button-click="handleHeaderButtonClick"
|
||||
/>
|
||||
</template>
|
||||
<PageData ref="pageDataRef" page-url="/api/v1/mcp/page" :page-size="10">
|
||||
<template #default="{ pageList }">
|
||||
<ElTable :data="pageList" border>
|
||||
@@ -198,7 +201,7 @@ const refreshLoadingMap = ref<Record<number | string, boolean>>({});
|
||||
</ElTable>
|
||||
</template>
|
||||
</PageData>
|
||||
</div>
|
||||
</ListPageShell>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
@@ -149,21 +149,25 @@ const activeName = ref('config');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowPanelModal
|
||||
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"
|
||||
>
|
||||
<ElTabs v-model="activeName" class="demo-tabs">
|
||||
<ElTabPane :label="$t('mcp.modal.config')" name="config">
|
||||
<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="title" :label="$t('mcp.title')">
|
||||
<ElInput v-model.trim="entity.title" />
|
||||
@@ -176,7 +180,8 @@ const activeName = ref('config');
|
||||
type="textarea"
|
||||
:rows="15"
|
||||
v-model.trim="entity.configJson"
|
||||
:placeholder="$t('mcp.example') + jsonPlaceholder" />
|
||||
:placeholder="$t('mcp.example') + jsonPlaceholder"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem prop="status" :label="$t('mcp.status')">
|
||||
<ElSwitch v-model="entity.status" />
|
||||
@@ -249,20 +254,7 @@ const activeName = ref('config');
|
||||
</ElTabPane>
|
||||
</div>
|
||||
</ElTabs>
|
||||
<template #footer>
|
||||
<ElButton @click="closeDialog">
|
||||
{{ $t('button.cancel') }}
|
||||
</ElButton>
|
||||
<ElButton
|
||||
type="primary"
|
||||
@click="save"
|
||||
:loading="btnLoading"
|
||||
:disabled="btnLoading"
|
||||
>
|
||||
{{ $t('button.save') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</EasyFlowPanelModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -3,15 +3,9 @@ import type { ModelAbilityItem } from '#/views/ai/model/modelUtils/model-ability
|
||||
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
ElMessage,
|
||||
ElTag,
|
||||
} from 'element-plus';
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import { ElForm, ElFormItem, ElInput, ElMessage, ElTag } from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import { $t } from '#/locales';
|
||||
@@ -274,21 +268,25 @@ const showMoreFields = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowFormModal
|
||||
v-model:open="dialogVisible"
|
||||
:centered="true"
|
||||
:closable="!btnLoading"
|
||||
:title="isAdd ? $t('button.add') : $t('button.edit')"
|
||||
:before-close="closeDialog"
|
||||
:close-on-click-modal="false"
|
||||
align-center
|
||||
width="482"
|
||||
:confirm-loading="btnLoading"
|
||||
:confirm-text="$t('button.save')"
|
||||
:submitting="btnLoading"
|
||||
@confirm="save"
|
||||
>
|
||||
<ElForm
|
||||
label-width="100px"
|
||||
ref="formDataRef"
|
||||
:model="formData"
|
||||
status-icon
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact"
|
||||
>
|
||||
<ElFormItem prop="title" :label="$t('llm.title')">
|
||||
<ElInput v-model.trim="formData.title" />
|
||||
@@ -340,20 +338,7 @@ const showMoreFields = ref(false);
|
||||
<ElInput v-model.trim="formData.requestPath" />
|
||||
</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>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
@@ -111,21 +111,25 @@ const handleChangeProvider = (val: string) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowFormModal
|
||||
v-model:open="dialogVisible"
|
||||
:centered="true"
|
||||
:closable="!btnLoading"
|
||||
:title="isAdd ? $t('button.add') : $t('button.edit')"
|
||||
:before-close="closeDialog"
|
||||
:close-on-click-modal="false"
|
||||
align-center
|
||||
width="482"
|
||||
:confirm-loading="btnLoading"
|
||||
:confirm-text="$t('button.save')"
|
||||
:submitting="btnLoading"
|
||||
@confirm="save"
|
||||
>
|
||||
<ElForm
|
||||
label-width="100px"
|
||||
ref="formDataRef"
|
||||
:model="formData"
|
||||
status-icon
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact"
|
||||
>
|
||||
<ElFormItem
|
||||
prop="icon"
|
||||
@@ -138,7 +142,10 @@ const handleChangeProvider = (val: string) => {
|
||||
<ElInput v-model.trim="formData.providerName" />
|
||||
</ElFormItem>
|
||||
<ElFormItem prop="provider" :label="$t('llmProvider.apiType')">
|
||||
<ElSelect v-model="formData.providerType" @change="handleChangeProvider">
|
||||
<ElSelect
|
||||
v-model="formData.providerType"
|
||||
@change="handleChangeProvider"
|
||||
>
|
||||
<ElOption
|
||||
v-for="item in providerOptions"
|
||||
:key="item.value"
|
||||
@@ -163,20 +170,7 @@ const handleChangeProvider = (val: string) => {
|
||||
<ElInput v-model.trim="formData.embedPath" />
|
||||
</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>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { nextTick, reactive, ref } from 'vue';
|
||||
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
|
||||
import {
|
||||
CirclePlus,
|
||||
Loading,
|
||||
@@ -10,7 +12,6 @@ import {
|
||||
import {
|
||||
ElCollapse,
|
||||
ElCollapseItem,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElIcon,
|
||||
@@ -215,14 +216,13 @@ const handleRefresh = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowPanelModal
|
||||
v-model:open="dialogVisible"
|
||||
:centered="true"
|
||||
:title="`${providerInfo?.providerName}${$t('llmProvider.model')}`"
|
||||
:before-close="closeDialog"
|
||||
:close-on-click-modal="false"
|
||||
align-center
|
||||
width="762"
|
||||
:show-footer="false"
|
||||
>
|
||||
<div class="manage-llm-container">
|
||||
<div class="form-container">
|
||||
@@ -311,7 +311,7 @@ const handleRefresh = () => {
|
||||
</ElTabs>
|
||||
</div>
|
||||
</div>
|
||||
</ElDialog>
|
||||
</EasyFlowPanelModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElMessage,
|
||||
@@ -65,9 +65,6 @@ const save = async () => {
|
||||
});
|
||||
};
|
||||
const btnLoading = ref(false);
|
||||
const closeDialog = () => {
|
||||
dialogVisible.value = false;
|
||||
};
|
||||
const getModelInfo = (id: string) => {
|
||||
options.value.forEach((item: any) => {
|
||||
if (item.id === id) {
|
||||
@@ -78,15 +75,25 @@ const getModelInfo = (id: string) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowFormModal
|
||||
v-model:open="dialogVisible"
|
||||
:centered="true"
|
||||
:closable="!btnLoading"
|
||||
:title="$t('llm.verifyLlmTitle')"
|
||||
:close-on-click-modal="false"
|
||||
align-center
|
||||
width="482"
|
||||
:confirm-loading="btnLoading"
|
||||
:confirm-text="$t('button.confirm')"
|
||||
:submitting="btnLoading"
|
||||
@confirm="save"
|
||||
>
|
||||
<ElForm ref="formDataRef" :model="formData" status-icon :rules="rules">
|
||||
<ElForm
|
||||
ref="formDataRef"
|
||||
:model="formData"
|
||||
status-icon
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact"
|
||||
>
|
||||
<ElFormItem prop="llmId" :label="$t('llm.modelToBeTested')">
|
||||
<ElSelect v-model="formData.llmId" @change="getModelInfo">
|
||||
<ElOption
|
||||
@@ -105,20 +112,7 @@ const getModelInfo = (id: string) => {
|
||||
{{ vectorDimension }}
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<template #footer>
|
||||
<ElButton @click="closeDialog">
|
||||
{{ $t('button.cancel') }}
|
||||
</ElButton>
|
||||
<ElButton
|
||||
type="primary"
|
||||
@click="save"
|
||||
:loading="btnLoading"
|
||||
:disabled="btnLoading"
|
||||
>
|
||||
{{ $t('button.confirm') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</EasyFlowFormModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -3,10 +3,10 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import { Plus, Remove } from '@element-plus/icons-vue';
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElIcon,
|
||||
@@ -156,20 +156,24 @@ function removeHeader(index: number) {
|
||||
</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
|
||||
:confirm-loading="btnLoading"
|
||||
:confirm-text="$t('button.save')"
|
||||
:submitting="btnLoading"
|
||||
width="lg"
|
||||
@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"
|
||||
@@ -251,20 +255,7 @@ function removeHeader(index: number) {
|
||||
<ElInput v-model.trim="entity.tokenValue" />
|
||||
</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>
|
||||
|
||||
@@ -3,14 +3,9 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, reactive, 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';
|
||||
@@ -150,21 +145,24 @@ defineExpose({
|
||||
</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="600px"
|
||||
@closed="closeDialog"
|
||||
:confirm-loading="btnLoading"
|
||||
:confirm-text="$t('button.save')"
|
||||
:submitting="btnLoading"
|
||||
@confirm="save"
|
||||
>
|
||||
<ElForm
|
||||
ref="saveForm"
|
||||
:model="entity"
|
||||
:rules="rules"
|
||||
label-width="80px"
|
||||
status-icon
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact"
|
||||
>
|
||||
<ElFormItem :label="$t('pluginItem.name')" prop="name">
|
||||
<ElInput v-model.trim="entity.name" />
|
||||
@@ -176,21 +174,7 @@ defineExpose({
|
||||
<ElInput v-model.trim="entity.description" type="textarea" :rows="4" />
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
|
||||
<template #footer>
|
||||
<ElButton @click="closeDialog" :disabled="btnLoading">
|
||||
{{ $t('button.cancel') }}
|
||||
</ElButton>
|
||||
<ElButton
|
||||
type="primary"
|
||||
:loading="btnLoading"
|
||||
:disabled="btnLoading"
|
||||
@click="save"
|
||||
>
|
||||
{{ $t('button.save') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</EasyFlowFormModal>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -3,9 +3,9 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElMessage,
|
||||
@@ -87,16 +87,25 @@ function closeDialog() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowFormModal
|
||||
v-model:open="dialogVisible"
|
||||
:centered="true"
|
||||
:closable="!btnLoading"
|
||||
width="500px"
|
||||
:title="$t('plugin.placeholder.categorize')"
|
||||
:before-close="closeDialog"
|
||||
:close-on-click-modal="false"
|
||||
align-center
|
||||
:confirm-loading="btnLoading"
|
||||
:confirm-text="$t('button.save')"
|
||||
:submitting="btnLoading"
|
||||
@confirm="save"
|
||||
>
|
||||
<ElForm ref="saveForm" :model="entity" status-icon>
|
||||
<ElForm
|
||||
ref="saveForm"
|
||||
:model="entity"
|
||||
status-icon
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact"
|
||||
>
|
||||
<ElFormItem prop="authType" :label="$t('plugin.category')">
|
||||
<ElSelect
|
||||
v-model="entity.categoryIds"
|
||||
@@ -114,20 +123,7 @@ function closeDialog() {
|
||||
</ElSelect>
|
||||
</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>
|
||||
|
||||
@@ -4,12 +4,11 @@ import type { ActionButton } from '#/components/page/CardList.vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import { Delete, Edit, Plus } from '@element-plus/icons-vue';
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
@@ -276,27 +275,24 @@ const handleClickCategory = (item: PluginCategory) => {
|
||||
</div>
|
||||
<AddPluginModal ref="aiPluginModalRef" @reload="handleSearch" />
|
||||
<CategoryPluginModal ref="categoryCategoryModal" @reload="handleSearch" />
|
||||
<ElDialog
|
||||
<EasyFlowFormModal
|
||||
:title="isEdit ? `${$t('button.edit')}` : `${$t('button.add')}`"
|
||||
v-model="dialogVisible"
|
||||
v-model:open="dialogVisible"
|
||||
:confirm-text="$t('button.confirm')"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
@confirm="handleSubmit"
|
||||
>
|
||||
<ElForm :model="formData" status-icon>
|
||||
<ElForm
|
||||
:model="formData"
|
||||
status-icon
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact"
|
||||
>
|
||||
<ElFormItem>
|
||||
<ElInput v-model.trim="formData.name" />
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
|
||||
<template #footer>
|
||||
<ElButton @click="dialogVisible = false">
|
||||
{{ $t('button.cancel') }}
|
||||
</ElButton>
|
||||
<ElButton type="primary" @click="handleSubmit">
|
||||
{{ $t('button.confirm') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</EasyFlowFormModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
import { $t } from '@easyflow/locales';
|
||||
import { preferences } from '@easyflow/preferences';
|
||||
|
||||
import { VideoPlay } from '@element-plus/icons-vue';
|
||||
import { ElButton, ElDialog, ElMenu, ElMenuItem } from 'element-plus';
|
||||
import { ElButton, ElMenu, ElMenuItem } from 'element-plus';
|
||||
import { JsonViewer } from 'vue3-json-viewer';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
@@ -77,14 +78,13 @@ function handleSubmitRun() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
<EasyFlowPanelModal
|
||||
v-model:open="dialogVisible"
|
||||
width="80%"
|
||||
align-center
|
||||
class="run-test-dialog"
|
||||
:title="$t('pluginItem.pluginToolEdit.trialRun')"
|
||||
:before-close="() => (dialogVisible = false)"
|
||||
>
|
||||
<div class="run-test-container">
|
||||
<div class="run-test-params">
|
||||
@@ -147,7 +147,7 @@ function handleSubmitRun() {
|
||||
{{ $t('pluginItem.pluginToolEdit.run') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</EasyFlowPanelModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import { ElButton, ElDialog } from 'element-plus';
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
|
||||
import { ElButton } from 'element-plus';
|
||||
|
||||
import PageData from '#/components/page/PageData.vue';
|
||||
import { $t } from '#/locales';
|
||||
@@ -40,14 +42,11 @@ watch(
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowPanelModal
|
||||
v-model:open="dialogVisible"
|
||||
:title="$t('aiResource.choose')"
|
||||
:before-close="closeDialog"
|
||||
:close-on-click-modal="false"
|
||||
width="80%"
|
||||
destroy-on-close
|
||||
>
|
||||
<PageData
|
||||
ref="pageDataRef"
|
||||
@@ -67,7 +66,7 @@ watch(
|
||||
{{ $t('button.confirm') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</EasyFlowPanelModal>
|
||||
<ElButton @click="openDialog()">
|
||||
{{ $t('button.choose') }}
|
||||
</ElButton>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { ElDialog, ElImage } from 'element-plus';
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
|
||||
import { ElImage } from 'element-plus';
|
||||
|
||||
defineExpose({
|
||||
openDialog,
|
||||
@@ -18,13 +20,12 @@ function closeDialog() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowPanelModal
|
||||
v-model:open="dialogVisible"
|
||||
:title="$t('message.preview')"
|
||||
:before-close="closeDialog"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
width="md"
|
||||
:show-footer="false"
|
||||
>
|
||||
<div class="flex justify-center">
|
||||
<ElImage
|
||||
@@ -41,7 +42,7 @@ function closeDialog() {
|
||||
{{ $t('message.notAudio') }}
|
||||
</audio>
|
||||
</div>
|
||||
</ElDialog>
|
||||
</EasyFlowPanelModal>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
import { formatBytes } from '@easyflow/utils';
|
||||
|
||||
import {
|
||||
@@ -15,7 +16,6 @@ import {
|
||||
import {
|
||||
ElAvatar,
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElDropdown,
|
||||
ElDropdownItem,
|
||||
ElDropdownMenu,
|
||||
@@ -418,16 +418,21 @@ const getSideList = async () => {
|
||||
</PageData>
|
||||
</div>
|
||||
</div>
|
||||
<ElDialog
|
||||
v-model="sideDialogVisible"
|
||||
<EasyFlowFormModal
|
||||
v-model:open="sideDialogVisible"
|
||||
:closable="!sideSaveLoading"
|
||||
:title="sideFormData.id ? `${$t('button.edit')}` : `${$t('button.add')}`"
|
||||
:close-on-click-modal="false"
|
||||
:confirm-loading="sideSaveLoading"
|
||||
:confirm-text="$t('button.confirm')"
|
||||
:submitting="sideSaveLoading"
|
||||
@confirm="handleSideSubmit"
|
||||
>
|
||||
<ElForm
|
||||
ref="sideFormRef"
|
||||
:model="sideFormData"
|
||||
:rules="sideFormRules"
|
||||
label-width="120px"
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact"
|
||||
>
|
||||
<!-- 动态生成表单项 -->
|
||||
<ElFormItem
|
||||
@@ -449,19 +454,6 @@ const getSideList = async () => {
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
|
||||
<template #footer>
|
||||
<ElButton @click="sideDialogVisible = false">
|
||||
{{ $t('button.cancel') }}
|
||||
</ElButton>
|
||||
<ElButton
|
||||
type="primary"
|
||||
@click="handleSideSubmit"
|
||||
:loading="sideSaveLoading"
|
||||
>
|
||||
{{ $t('button.confirm') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</EasyFlowFormModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -3,16 +3,10 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
import { getResourceType } from '@easyflow/utils';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
ElMessage,
|
||||
} from 'element-plus';
|
||||
import { ElForm, ElFormItem, ElInput, ElMessage } from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import DictSelect from '#/components/dict/DictSelect.vue';
|
||||
@@ -116,19 +110,23 @@ function uploadSuccess(res: 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="md"
|
||||
@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="resourceUrl" :label="$t('aiResource.resourceUrl')">
|
||||
<Upload @before-upload="beforeUpload" @success="uploadSuccess" />
|
||||
@@ -149,20 +147,7 @@ function uploadSuccess(res: any) {
|
||||
/>
|
||||
</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>
|
||||
|
||||
@@ -5,6 +5,8 @@ import type { ActionButton } from '#/components/page/CardList.vue';
|
||||
|
||||
import { computed, markRaw, onMounted, ref } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import {
|
||||
CopyDocument,
|
||||
Delete,
|
||||
@@ -16,8 +18,6 @@ import {
|
||||
VideoPlay,
|
||||
} from '@element-plus/icons-vue';
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
@@ -404,16 +404,21 @@ function handleHeaderButtonClick(data: any) {
|
||||
</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
|
||||
@@ -435,16 +440,7 @@ function handleHeaderButtonClick(data: 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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -3,15 +3,9 @@ import type { FormInstance, UploadInstance, UploadProps } from 'element-plus';
|
||||
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
ElMessage,
|
||||
ElUpload,
|
||||
} from 'element-plus';
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import { ElForm, ElFormItem, ElInput, ElMessage, ElUpload } from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import DictSelect from '#/components/dict/DictSelect.vue';
|
||||
@@ -148,9 +142,8 @@ function closeDialog() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowFormModal
|
||||
v-model:open="dialogVisible"
|
||||
:title="
|
||||
isImport
|
||||
? $t('button.import')
|
||||
@@ -159,14 +152,19 @@ function closeDialog() {
|
||||
: $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="isImport ? { ...entity, jsonFile: jsonFileModel } : entity"
|
||||
status-icon
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact"
|
||||
>
|
||||
<ElFormItem v-if="isImport" prop="jsonFile" label="JSON文件" required>
|
||||
<ElUpload
|
||||
@@ -212,20 +210,7 @@ function closeDialog() {
|
||||
<DictSelect v-model="entity.status" dict-code="showOrNot" />
|
||||
</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>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { ElDialog } from 'element-plus';
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
|
||||
import SysApiKeyList from '#/views/config/apikey/SysApiKeyList.vue';
|
||||
import SysApiKeyResourcePermissionList from '#/views/config/apikey/SysApiKeyResourcePermissionList.vue';
|
||||
@@ -11,14 +11,14 @@ const dialogVisible = ref(false);
|
||||
<template>
|
||||
<div class="sys-apikey-container">
|
||||
<SysApiKeyList />
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
align-center
|
||||
<EasyFlowPanelModal
|
||||
v-model:open="dialogVisible"
|
||||
:centered="true"
|
||||
width="xl"
|
||||
:show-footer="false"
|
||||
>
|
||||
<SysApiKeyResourcePermissionList />
|
||||
</ElDialog>
|
||||
</EasyFlowPanelModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { markRaw, ref } from 'vue';
|
||||
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
|
||||
import { Delete, MoreFilled, Plus } from '@element-plus/icons-vue';
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElDropdown,
|
||||
ElDropdownItem,
|
||||
ElDropdownMenu,
|
||||
@@ -19,6 +20,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 SysApiKeyResourcePermissionList from '#/views/config/apikey/SysApiKeyResourcePermissionList.vue';
|
||||
@@ -112,13 +114,14 @@ function addNewApiKey() {
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 p-6">
|
||||
<SysApiKeyModal ref="saveDialog" @reload="reset" />
|
||||
<HeaderSearch
|
||||
:buttons="headerButtons"
|
||||
@search="handleSearch"
|
||||
@button-click="headerButtonClick"
|
||||
/>
|
||||
|
||||
<div class="bg-background border-border flex-1 rounded-lg border p-5">
|
||||
<ListPageShell>
|
||||
<template #filters>
|
||||
<HeaderSearch
|
||||
:buttons="headerButtons"
|
||||
@search="handleSearch"
|
||||
@button-click="headerButtonClick"
|
||||
/>
|
||||
</template>
|
||||
<PageData
|
||||
ref="pageDataRef"
|
||||
page-url="/api/v1/sysApiKey/page"
|
||||
@@ -188,14 +191,15 @@ function addNewApiKey() {
|
||||
</ElTable>
|
||||
</template>
|
||||
</PageData>
|
||||
</div>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
</ListPageShell>
|
||||
<EasyFlowPanelModal
|
||||
v-model:open="dialogVisible"
|
||||
:title="$t('sysApiKeyResourcePermission.addPermission')"
|
||||
draggable
|
||||
:close-on-click-modal="false"
|
||||
:centered="true"
|
||||
width="xl"
|
||||
:show-footer="false"
|
||||
>
|
||||
<SysApiKeyResourcePermissionList />
|
||||
</ElDialog>
|
||||
</EasyFlowPanelModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -3,13 +3,13 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import {
|
||||
ElAlert,
|
||||
ElButton,
|
||||
ElCheckbox,
|
||||
ElCheckboxGroup,
|
||||
ElDatePicker,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElMessage,
|
||||
@@ -157,21 +157,23 @@ 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"
|
||||
:confirm-loading="btnLoading"
|
||||
:confirm-text="$t('button.save')"
|
||||
:submitting="btnLoading"
|
||||
width="50%"
|
||||
@confirm="save"
|
||||
>
|
||||
<ElForm
|
||||
label-width="120px"
|
||||
ref="saveForm"
|
||||
:model="entity"
|
||||
status-icon
|
||||
:rules="rules"
|
||||
class="form-container"
|
||||
label-position="top"
|
||||
class="easyflow-modal-form easyflow-modal-form--compact form-container"
|
||||
>
|
||||
<!-- 状态选择 -->
|
||||
<ElFormItem prop="status" :label="$t('sysApiKey.status')">
|
||||
@@ -217,21 +219,7 @@ defineExpose({
|
||||
</ElCheckboxGroup>
|
||||
</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>
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
} from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import ListPageShell from '#/components/page/ListPageShell.vue';
|
||||
import PageData from '#/components/page/PageData.vue';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
@@ -77,81 +78,83 @@ function remove(row: any) {
|
||||
<template>
|
||||
<div class="page-container !m-0 !pl-0">
|
||||
<SysApiKeyResourcePermissionModal ref="saveDialog" @reload="reset" />
|
||||
<div class="flex items-center justify-between">
|
||||
<ElForm ref="formRef" :inline="true" :model="formInline">
|
||||
<ElFormItem prop="title" class="!mr-3">
|
||||
<ElInput
|
||||
v-model="formInline.title"
|
||||
:placeholder="$t('sysApiKeyResourcePermission.title')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem>
|
||||
<ElButton @click="search(formRef)" type="primary">
|
||||
{{ $t('button.query') }}
|
||||
<ListPageShell dense>
|
||||
<template #filters>
|
||||
<div class="flex items-center justify-between gap-4">
|
||||
<ElForm ref="formRef" :inline="true" :model="formInline">
|
||||
<ElFormItem prop="title" class="!mr-3">
|
||||
<ElInput
|
||||
v-model="formInline.title"
|
||||
:placeholder="$t('sysApiKeyResourcePermission.title')"
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem>
|
||||
<ElButton @click="search(formRef)" type="primary">
|
||||
{{ $t('button.query') }}
|
||||
</ElButton>
|
||||
<ElButton @click="reset(formRef)">
|
||||
{{ $t('button.reset') }}
|
||||
</ElButton>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<ElButton @click="showDialog({})" type="primary">
|
||||
<ElIcon class="mr-1">
|
||||
<Plus />
|
||||
</ElIcon>
|
||||
{{ $t('button.add') }}
|
||||
</ElButton>
|
||||
<ElButton @click="reset(formRef)">
|
||||
{{ $t('button.reset') }}
|
||||
</ElButton>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<div class="mb-5">
|
||||
<ElButton @click="showDialog({})" type="primary">
|
||||
<ElIcon class="mr-1">
|
||||
<Plus />
|
||||
</ElIcon>
|
||||
{{ $t('button.add') }}
|
||||
</ElButton>
|
||||
</div>
|
||||
</div>
|
||||
<PageData
|
||||
ref="pageDataRef"
|
||||
page-url="/api/v1/sysApiKeyResourcePermission/page"
|
||||
:page-size="10"
|
||||
>
|
||||
<template #default="{ pageList }">
|
||||
<ElTable :data="pageList" border>
|
||||
<ElTableColumn
|
||||
prop="requestInterface"
|
||||
:label="$t('sysApiKeyResourcePermission.requestInterface')"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row.requestInterface }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn
|
||||
prop="title"
|
||||
:label="$t('sysApiKeyResourcePermission.title')"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row.title }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn :label="$t('common.handle')" width="90" align="right">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center gap-3">
|
||||
<ElButton link type="primary" @click="showDialog(row)">
|
||||
{{ $t('button.edit') }}
|
||||
</ElButton>
|
||||
|
||||
<ElDropdown>
|
||||
<ElButton link :icon="MoreFilled" />
|
||||
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
<ElDropdownItem @click="remove(row)">
|
||||
<ElButton link :icon="Delete" type="danger">
|
||||
{{ $t('button.delete') }}
|
||||
</ElButton>
|
||||
</ElDropdownItem>
|
||||
</ElDropdownMenu>
|
||||
</template>
|
||||
</ElDropdown>
|
||||
</div>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</ElTable>
|
||||
</div>
|
||||
</template>
|
||||
</PageData>
|
||||
<PageData
|
||||
ref="pageDataRef"
|
||||
page-url="/api/v1/sysApiKeyResourcePermission/page"
|
||||
:page-size="10"
|
||||
>
|
||||
<template #default="{ pageList }">
|
||||
<ElTable :data="pageList" border>
|
||||
<ElTableColumn
|
||||
prop="requestInterface"
|
||||
:label="$t('sysApiKeyResourcePermission.requestInterface')"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row.requestInterface }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn
|
||||
prop="title"
|
||||
:label="$t('sysApiKeyResourcePermission.title')"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row.title }}
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn :label="$t('common.handle')" width="90" align="right">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center gap-3">
|
||||
<ElButton link type="primary" @click="showDialog(row)">
|
||||
{{ $t('button.edit') }}
|
||||
</ElButton>
|
||||
|
||||
<ElDropdown>
|
||||
<ElButton link :icon="MoreFilled" />
|
||||
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
<ElDropdownItem @click="remove(row)">
|
||||
<ElButton link :icon="Delete" type="danger">
|
||||
{{ $t('button.delete') }}
|
||||
</ElButton>
|
||||
</ElDropdownItem>
|
||||
</ElDropdownMenu>
|
||||
</template>
|
||||
</ElDropdown>
|
||||
</div>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</ElTable>
|
||||
</template>
|
||||
</PageData>
|
||||
</ListPageShell>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -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';
|
||||
@@ -73,19 +68,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="requestInterface"
|
||||
@@ -97,20 +96,7 @@ function closeDialog() {
|
||||
<ElInput v-model.trim="entity.title" />
|
||||
</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>
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDatePicker,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElMessage,
|
||||
} from 'element-plus';
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import { ElDatePicker, ElForm, ElFormItem, ElMessage } from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import DictSelect from '#/components/dict/DictSelect.vue';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const emit = defineEmits(['reload']);
|
||||
// vue
|
||||
onMounted(() => {});
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
@@ -74,35 +67,26 @@ function closeDialog() {
|
||||
entity.value = {};
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
const resourcePermissionList = ref([]);
|
||||
function getResourcePermissionList() {
|
||||
api.get('/api/v1/sysApiKeyResourcePermission/list').then((res) => {
|
||||
console.log('资源');
|
||||
console.log(res);
|
||||
if (res.errorCode === 0) {
|
||||
resourcePermissionList.value = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
onMounted(() => {
|
||||
getResourcePermissionList();
|
||||
});
|
||||
</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="status" :label="$t('sysApiKey.status')">
|
||||
<DictSelect v-model="entity.status" dict-code="dataStatus" />
|
||||
@@ -111,20 +95,7 @@ onMounted(() => {
|
||||
<ElDatePicker v-model="entity.expiredAt" type="datetime" />
|
||||
</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>
|
||||
|
||||
@@ -3,15 +3,10 @@ import type { UploadFile } from 'element-plus';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
import { downloadFileFromBlob } from '@easyflow/utils';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElMessage,
|
||||
ElMessageBox,
|
||||
ElUpload,
|
||||
} from 'element-plus';
|
||||
import { ElButton, ElMessage, ElMessageBox, ElUpload } from 'element-plus';
|
||||
|
||||
import { api } from '#/api/request';
|
||||
import uploadIcon from '#/assets/datacenter/upload.png';
|
||||
@@ -99,12 +94,13 @@ function handleUpload() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
draggable
|
||||
<EasyFlowPanelModal
|
||||
v-model:open="dialogVisible"
|
||||
:closable="!btnLoading"
|
||||
:title="props.title"
|
||||
:before-close="closeDialog"
|
||||
:close-on-click-modal="false"
|
||||
:show-cancel-button="false"
|
||||
:show-confirm-button="false"
|
||||
>
|
||||
<ElUpload
|
||||
:file-list="fileList"
|
||||
@@ -148,7 +144,7 @@ function handleUpload() {
|
||||
</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</EasyFlowPanelModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -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 { router } from '#/router';
|
||||
@@ -95,13 +96,14 @@ function toDetailPage(row: any) {
|
||||
<template>
|
||||
<div class="flex h-full flex-col gap-6 p-6">
|
||||
<DatacenterTableModal 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/datacenterTable/page"
|
||||
@@ -168,7 +170,7 @@ function toDetailPage(row: any) {
|
||||
</ElTable>
|
||||
</template>
|
||||
</PageData>
|
||||
</div>
|
||||
</ListPageShell>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import {
|
||||
ElButton,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElIcon,
|
||||
@@ -184,20 +185,24 @@ function getYesOrNo() {
|
||||
</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="800px"
|
||||
: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="tableName" :label="$t('datacenterTable.tableName')">
|
||||
<ElInput :disabled="!isAdd" v-model.trim="entity.tableName" />
|
||||
@@ -205,7 +210,7 @@ function getYesOrNo() {
|
||||
<ElFormItem prop="tableDesc" :label="$t('datacenterTable.tableDesc')">
|
||||
<ElInput v-model.trim="entity.tableDesc" />
|
||||
</ElFormItem>
|
||||
<ElFormItem prop="fields" label-width="0">
|
||||
<ElFormItem prop="fields" :label="$t('datacenterTable.fields')">
|
||||
<div v-loading="loadFields" class="w-full">
|
||||
<ElTable :data="fieldsData">
|
||||
<ElTableColumn :label="$t('datacenterTable.fieldName')">
|
||||
@@ -261,20 +266,7 @@ function getYesOrNo() {
|
||||
</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>
|
||||
|
||||
@@ -3,10 +3,10 @@ import type { FormInstance } from 'element-plus';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { EasyFlowFormModal } from '@easyflow/common-ui';
|
||||
|
||||
import {
|
||||
ElButton,
|
||||
ElDatePicker,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
@@ -80,20 +80,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="800px"
|
||||
: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
|
||||
v-for="item in props.formItems"
|
||||
@@ -135,20 +139,7 @@ function closeDialog() {
|
||||
/>
|
||||
</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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user