Files
EasyFlow/easyflow-ui-admin/app/src/views/datacenter/DatacenterTableModal.vue
陈子默 b191d1aaed feat: 统一管理端弹窗与内容区交互样式
- 收敛管理端公共 Modal 链路,新增表单弹窗与普通内容弹窗包装\n- 迁移 Bot、知识库、插件、工作流、资源、MCP、数据中枢与系统管理页面级弹窗\n- 统一内容区工具栏、列表容器、导航与顶部按钮的视觉密度和交互节奏
2026-03-06 19:58:26 +08:00

273 lines
7.3 KiB
Vue

<script setup lang="ts">
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,
ElForm,
ElFormItem,
ElIcon,
ElInput,
ElMessage,
ElMessageBox,
ElOption,
ElSelect,
ElTable,
ElTableColumn,
} from 'element-plus';
import { api } from '#/api/request';
import { $t } from '#/locales';
const emit = defineEmits(['reload']);
// vue
onMounted(() => {
getFieldType();
getYesOrNo();
});
defineExpose({
openDialog,
});
const saveForm = ref<FormInstance>();
// variables
const dialogVisible = ref(false);
const isAdd = ref(true);
const entity = ref<any>({
deptId: '',
tableName: '',
tableDesc: '',
actualTable: '',
status: '',
options: '',
});
const btnLoading = ref(false);
const rules = ref({
tableName: [
{ required: true, message: $t('message.required'), trigger: 'blur' },
{
pattern: /^[a-z][a-z0-9_]*$/,
message: $t('datacenterTable.nameRegx'),
},
],
fields: [
{
required: true,
validator: (_: any, value: any, callback: any) => {
if (!value || value.length === 0) {
callback(new Error($t('datacenterTable.noFieldError')));
} else {
// 检查字段数组中的fieldName和fieldDesc字段
value.forEach((field: any) => {
if (!field.fieldName || !field.fieldDesc) {
callback(new Error($t('datacenterTable.fieldInfoError')));
}
if (!/^[a-z][a-z0-9_]*$/.test(field.fieldName)) {
callback(new Error($t('datacenterTable.nameRegx')));
}
});
callback();
}
},
trigger: 'blur',
},
],
});
const fieldsData = ref();
const removeFields = ref<any[]>([]);
const loadFields = ref(false);
const fieldTypes = ref<any>([]);
const yesOrNoDict = ref<any>([]);
watch(
() => fieldsData.value,
(newVal) => {
entity.value.fields = newVal;
},
{ deep: true },
);
// functions
function getDetailInfo(tableId: any) {
loadFields.value = true;
api
.get(`/api/v1/datacenterTable/detailInfo?tableId=${tableId}`)
.then((res) => {
loadFields.value = false;
fieldsData.value = res.data.fields;
});
}
function openDialog(row: any) {
fieldsData.value = [];
removeFields.value = [];
if (row.id) {
getDetailInfo(row.id);
isAdd.value = false;
}
entity.value = row;
dialogVisible.value = true;
}
function save() {
saveForm.value?.validate((valid) => {
if (valid) {
if (fieldsData.value.length === 0) {
ElMessage.error($t('message.required'));
return;
}
const obj = {
...entity.value,
fields: [...fieldsData.value, ...removeFields.value],
};
btnLoading.value = true;
api
.post('/api/v1/datacenterTable/saveTable', obj)
.then((res) => {
btnLoading.value = false;
if (res.errorCode === 0) {
ElMessage.success(res.message);
emit('reload');
closeDialog();
}
})
.catch(() => {
btnLoading.value = false;
});
}
});
}
function closeDialog() {
saveForm.value?.resetFields();
isAdd.value = true;
entity.value = {};
dialogVisible.value = false;
}
function addField() {
fieldsData.value.push({
fieldName: '',
fieldDesc: '',
fieldType: 1,
required: 0,
handleDelete: false,
rowKey: Date.now().toString(),
});
}
function deleteField(row: any, $index: number) {
ElMessageBox.confirm($t('message.deleteAlert'), $t('message.noticeTitle'), {
confirmButtonText: $t('message.ok'),
cancelButtonText: $t('message.cancel'),
type: 'warning',
beforeClose: (action, _, done) => {
if (action === 'confirm') {
if (row.id) {
row.handleDelete = true;
removeFields.value.push(row);
}
fieldsData.value.splice($index, 1);
done();
} else {
done();
}
},
}).catch(() => {});
}
function getFieldType() {
api.get('/api/v1/dict/items/fieldType').then((res) => {
fieldTypes.value = res.data;
});
}
function getYesOrNo() {
api.get('/api/v1/dict/items/yesOrNo').then((res) => {
yesOrNoDict.value = res.data;
});
}
</script>
<template>
<EasyFlowFormModal
v-model:open="dialogVisible"
:closable="!btnLoading"
:title="isAdd ? $t('button.add') : $t('button.edit')"
:before-close="closeDialog"
width="800px"
:confirm-loading="btnLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
@confirm="save"
>
<ElForm
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" />
</ElFormItem>
<ElFormItem prop="tableDesc" :label="$t('datacenterTable.tableDesc')">
<ElInput v-model.trim="entity.tableDesc" />
</ElFormItem>
<ElFormItem prop="fields" :label="$t('datacenterTable.fields')">
<div v-loading="loadFields" class="w-full">
<ElTable :data="fieldsData">
<ElTableColumn :label="$t('datacenterTable.fieldName')">
<template #default="{ row }">
<ElInput v-model.trim="row.fieldName" />
</template>
</ElTableColumn>
<ElTableColumn :label="$t('datacenterTable.fieldDesc')">
<template #default="{ row }">
<ElInput v-model.trim="row.fieldDesc" />
</template>
</ElTableColumn>
<ElTableColumn :label="$t('datacenterTable.fieldType')">
<template #default="{ row }">
<ElSelect v-model.trim="row.fieldType" :disabled="!!row.id">
<ElOption
v-for="item in fieldTypes"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</ElSelect>
</template>
</ElTableColumn>
<ElTableColumn :label="$t('datacenterTable.required')">
<template #default="{ row }">
<ElSelect v-model.trim="row.required">
<ElOption
v-for="item in yesOrNoDict"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</ElSelect>
</template>
</ElTableColumn>
<ElTableColumn :label="$t('common.handle')" width="80">
<template #default="{ row, $index }">
<ElButton link type="danger" @click="deleteField(row, $index)">
{{ $t('button.delete') }}
</ElButton>
</template>
</ElTableColumn>
</ElTable>
<div class="mt-3">
<ElButton plain type="primary" @click="addField">
<ElIcon class="mr-1">
<Plus />
</ElIcon>
{{ $t('button.add') }}
</ElButton>
</div>
</div>
</ElFormItem>
</ElForm>
</EasyFlowFormModal>
</template>
<style scoped></style>