feat: 添加新功能
This commit is contained in:
parent
87ef39f072
commit
4e83383d07
@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @Description: 文件内容描述
|
||||||
|
* @Author: 陈益
|
||||||
|
* @Date: 2025-06-19 22:14:51
|
||||||
|
* @LastEditors: 陈益
|
||||||
|
*/
|
||||||
import type { RouteRecordRaw } from 'vue-router';
|
import type { RouteRecordRaw } from 'vue-router';
|
||||||
|
|
||||||
import { BasicLayout } from '#/layouts';
|
import { BasicLayout } from '#/layouts';
|
||||||
@ -14,68 +20,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
},
|
},
|
||||||
name: 'code',
|
name: 'code',
|
||||||
path: '/code',
|
path: '/code',
|
||||||
children: [
|
children: [],
|
||||||
{
|
|
||||||
name: 'project',
|
|
||||||
path: 'project',
|
|
||||||
component: () => import('#/views/code/project/index.vue'),
|
|
||||||
meta: {
|
|
||||||
icon: 'ant-design:profile-outlined',
|
|
||||||
title: $t('abp.menu.code-project'),
|
|
||||||
authority: ['AbpCodeManagement.Project'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'template',
|
|
||||||
path: 'template',
|
|
||||||
component: () => import('#/views/code/template/index.vue'),
|
|
||||||
meta: {
|
|
||||||
icon: 'ant-design:file-markdown-filled',
|
|
||||||
title: $t('abp.menu.code-template'),
|
|
||||||
authority: ['AbpCodeManagement.Template'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'generate',
|
|
||||||
path: 'generate',
|
|
||||||
component: () => import('#/views/code/generate/index.vue'),
|
|
||||||
meta: {
|
|
||||||
icon: 'ant-design:copyright-circle-filled',
|
|
||||||
title: $t('abp.menu.code-genarate'),
|
|
||||||
authority: ['AbpCodeManagement.Generator'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'EntityModel',
|
|
||||||
path: 'entityModel',
|
|
||||||
component: () => import('#/views/code/project/entityModel/index.vue'),
|
|
||||||
meta: {
|
|
||||||
icon: 'ant-design:file-markdown-filled',
|
|
||||||
title: $t('abp.menu.code-entity'),
|
|
||||||
hideInMenu: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'TemplateDetail',
|
|
||||||
path: 'templateDetail',
|
|
||||||
component: () => import('#/views/code/template/TemplateDetail.vue'),
|
|
||||||
meta: {
|
|
||||||
icon: 'ant-design:file-markdown-filled',
|
|
||||||
title: $t('abp.menu.code-template-detail'),
|
|
||||||
hideInMenu: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'preview',
|
|
||||||
path: 'Preview',
|
|
||||||
component: () => import('#/views/code/generate/preview.vue'),
|
|
||||||
meta: {
|
|
||||||
icon: 'ant-design:file-markdown-filled',
|
|
||||||
title: $t('abp.menu.code-Preview'),
|
|
||||||
hideInMenu: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @Description: 文件内容描述
|
||||||
|
* @Author: 陈益
|
||||||
|
* @Date: 2025-06-19 22:14:51
|
||||||
|
* @LastEditors: 陈益
|
||||||
|
*/
|
||||||
import type { RouteRecordRaw } from 'vue-router';
|
import type { RouteRecordRaw } from 'vue-router';
|
||||||
|
|
||||||
import { BasicLayout } from '#/layouts';
|
import { BasicLayout } from '#/layouts';
|
||||||
@ -14,18 +20,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
},
|
},
|
||||||
name: 'TextTemplate',
|
name: 'TextTemplate',
|
||||||
path: '/TextTemplate',
|
path: '/TextTemplate',
|
||||||
children: [
|
children: [],
|
||||||
{
|
|
||||||
path: 'page',
|
|
||||||
name: 'TextTemplatePage',
|
|
||||||
component: () => import('#/views/textTemplate/index.vue'),
|
|
||||||
meta: {
|
|
||||||
icon: 'ant-design:file-markdown-filled',
|
|
||||||
title: $t('textTemplate.templateList'),
|
|
||||||
authority: ['AbpTemplateManagement.Template'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -1,132 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { onMounted } from 'vue';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
|
|
||||||
import { Page } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { Card, message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import {
|
|
||||||
// postGeneratorDown,
|
|
||||||
// postProjectsAll,
|
|
||||||
// postTemplatesAll,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const [BaseForm, baseFormApi] = useVbenForm({
|
|
||||||
// 所有表单项共用,可单独在表单内覆盖
|
|
||||||
commonConfig: {
|
|
||||||
// 所有表单项
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// 提交函数
|
|
||||||
handleSubmit: onSubmit,
|
|
||||||
submitButtonOptions: {
|
|
||||||
content: $t('code.download'),
|
|
||||||
},
|
|
||||||
handleReset: onPreview,
|
|
||||||
resetButtonOptions: {
|
|
||||||
content: $t('code.preview'),
|
|
||||||
},
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
componentProps: {
|
|
||||||
allowClear: true,
|
|
||||||
filterOption: true,
|
|
||||||
options: [],
|
|
||||||
showSearch: true,
|
|
||||||
},
|
|
||||||
fieldName: 'projectId',
|
|
||||||
label: $t('code.project'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
componentProps: {
|
|
||||||
allowClear: true,
|
|
||||||
filterOption: true,
|
|
||||||
options: [],
|
|
||||||
showSearch: true,
|
|
||||||
},
|
|
||||||
fieldName: 'templateId',
|
|
||||||
label: $t('code.template'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
onMounted(async () => {
|
|
||||||
// const res = await postProjectsAll();
|
|
||||||
// baseFormApi.updateSchema([
|
|
||||||
// {
|
|
||||||
// componentProps: {
|
|
||||||
// options: res?.data?.map((item) => ({
|
|
||||||
// label: item.projectName,
|
|
||||||
// value: item.id,
|
|
||||||
// })),
|
|
||||||
// },
|
|
||||||
// fieldName: 'projectId',
|
|
||||||
// },
|
|
||||||
// ]);
|
|
||||||
// const res2 = await postTemplatesAll();
|
|
||||||
// baseFormApi.updateSchema([
|
|
||||||
// {
|
|
||||||
// componentProps: {
|
|
||||||
// options: res2?.data?.map((item) => ({
|
|
||||||
// label: item.name,
|
|
||||||
// value: item.id,
|
|
||||||
// })),
|
|
||||||
// },
|
|
||||||
// fieldName: 'templateId',
|
|
||||||
// },
|
|
||||||
// ]);
|
|
||||||
});
|
|
||||||
async function onSubmit() {
|
|
||||||
try {
|
|
||||||
baseFormApi.setState({ submitButtonOptions: { loading: true } });
|
|
||||||
const formValues = await baseFormApi.getValues();
|
|
||||||
// const { data } = await postGeneratorDown({
|
|
||||||
// body: { ...formValues },
|
|
||||||
// responseType: 'blob',
|
|
||||||
// });
|
|
||||||
// const url = window.URL.createObjectURL(new Blob([data as Blob]));
|
|
||||||
// const link = document.createElement('a');
|
|
||||||
// link.href = url;
|
|
||||||
message.success('功能暂时不可用');
|
|
||||||
} catch (error) {
|
|
||||||
message.error('操作失败');
|
|
||||||
} finally {
|
|
||||||
baseFormApi.setState({ submitButtonOptions: { loading: false } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onPreview() {
|
|
||||||
baseFormApi.setState({ resetButtonOptions: { loading: true } });
|
|
||||||
const formValues = await baseFormApi.getValues();
|
|
||||||
router.push({
|
|
||||||
name: 'preview',
|
|
||||||
query: {
|
|
||||||
templateId: formValues.templateId,
|
|
||||||
projectId: formValues.projectId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Page
|
|
||||||
:description="$t('code.description')"
|
|
||||||
:title="$t('code.autoGenerate')"
|
|
||||||
content-class="flex flex-col gap-4"
|
|
||||||
>
|
|
||||||
<Card title="">
|
|
||||||
<BaseForm />
|
|
||||||
</Card>
|
|
||||||
</Page>
|
|
||||||
</template>
|
|
||||||
@ -1,186 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { DataNode, TreeProps } from 'ant-design-vue/es/tree';
|
|
||||||
|
|
||||||
import { onMounted, ref, watch } from 'vue';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
|
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
|
|
||||||
import { Button, Dropdown, Input, Menu, Spin, Tree } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { postGeneratorPreViewCode } from '#/api-client/index';
|
|
||||||
|
|
||||||
// 定义一个响应式变量,用于存储展开的节点
|
|
||||||
const expandedKeys = ref<(number | string)[]>([]);
|
|
||||||
// 定义一个响应式变量,用于存储搜索框的值
|
|
||||||
const searchValue = ref<string>('');
|
|
||||||
// 定义一个响应式变量,用于控制是否自动展开父节点
|
|
||||||
const autoExpandParent = ref<boolean>(true);
|
|
||||||
// 定义一个响应式变量,用于存储树形数据
|
|
||||||
const gData = ref<Array<DataNode>>([]);
|
|
||||||
// 定义一个响应式的变量,用于存储当前选中的节点的key
|
|
||||||
const currentSelectedKey = ref('');
|
|
||||||
const codeText = ref();
|
|
||||||
const route = useRoute();
|
|
||||||
const loading = ref<boolean>(true);
|
|
||||||
onMounted(() => {
|
|
||||||
getTreeData().then(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const dataList = ref<DataNode[]>([]);
|
|
||||||
const generateList = (data: TreeProps['treeData']) => {
|
|
||||||
if (!data) return;
|
|
||||||
for (const node of data) {
|
|
||||||
const { key, title, children } = node;
|
|
||||||
dataList.value.push({ key, title });
|
|
||||||
if (children) {
|
|
||||||
generateList(children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getParentKey = (
|
|
||||||
key: number | string,
|
|
||||||
tree: TreeProps['treeData'],
|
|
||||||
): number | string | undefined => {
|
|
||||||
if (!tree) return undefined;
|
|
||||||
let parentKey;
|
|
||||||
for (const node of tree) {
|
|
||||||
if (node.children) {
|
|
||||||
if (node.children.some((item) => item.key === key)) {
|
|
||||||
parentKey = node.key;
|
|
||||||
} else if (getParentKey(key, node.children)) {
|
|
||||||
parentKey = getParentKey(key, node.children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parentKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取所有节点的key
|
|
||||||
const getAllKeys = (tree: TreeProps['treeData']): (number | string)[] => {
|
|
||||||
const keys: (number | string)[] = [];
|
|
||||||
const traverse = (nodes: TreeProps['treeData']) => {
|
|
||||||
if (!nodes) return;
|
|
||||||
nodes.forEach((node) => {
|
|
||||||
if (node.key) {
|
|
||||||
keys.push(node.key);
|
|
||||||
}
|
|
||||||
if (node.children) {
|
|
||||||
traverse(node.children);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
traverse(tree);
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 展开所有节点
|
|
||||||
const expandAll = () => {
|
|
||||||
expandedKeys.value = getAllKeys(gData.value as TreeProps['treeData']);
|
|
||||||
autoExpandParent.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 折叠所有节点
|
|
||||||
const collapseAll = () => {
|
|
||||||
expandedKeys.value = [];
|
|
||||||
autoExpandParent.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 添加 onExpand 方法处理节点展开/折叠
|
|
||||||
const onExpand = (keys: (number | string)[], info: any) => {
|
|
||||||
expandedKeys.value = keys;
|
|
||||||
autoExpandParent.value = false;
|
|
||||||
};
|
|
||||||
// 定义一个响应式变量,用于控制是否是否显示保存按钮
|
|
||||||
const showSaveContentBtn = ref<boolean>(false);
|
|
||||||
const onSelect = (keys: any[], event: any) => {
|
|
||||||
codeText.value = '';
|
|
||||||
showSaveContentBtn.value = false;
|
|
||||||
if (event.node.templateType === 10) return;
|
|
||||||
showSaveContentBtn.value = true;
|
|
||||||
currentSelectedKey.value = keys[0] ?? '';
|
|
||||||
codeText.value = event.node.content || '';
|
|
||||||
if (!keys[0]) return '';
|
|
||||||
};
|
|
||||||
|
|
||||||
async function getTreeData() {
|
|
||||||
const { data = [] } = await postGeneratorPreViewCode({
|
|
||||||
body: {
|
|
||||||
templateId: route.query.templateId as string,
|
|
||||||
projectId: route.query.projectId as string,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
gData.value = data as DataNode[];
|
|
||||||
dataList.value = [];
|
|
||||||
generateList(data as TreeProps['treeData']);
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(searchValue, (value) => {
|
|
||||||
if (!value) {
|
|
||||||
expandedKeys.value = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const expanded = dataList.value
|
|
||||||
.map((item) => {
|
|
||||||
if (
|
|
||||||
typeof item.title === 'string' &&
|
|
||||||
item.title.toLowerCase().includes(value.toLowerCase())
|
|
||||||
) {
|
|
||||||
return getParentKey(item.key, gData.value as TreeProps['treeData']);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
})
|
|
||||||
.filter(
|
|
||||||
(item, i, self): item is number | string =>
|
|
||||||
item !== null && item !== undefined && self.indexOf(item) === i,
|
|
||||||
);
|
|
||||||
|
|
||||||
expandedKeys.value = expanded;
|
|
||||||
autoExpandParent.value = true;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Spin :spinning="loading" tip="loading...">
|
|
||||||
<div class="m-4 grid min-h-[calc(100vh-120px)] grid-cols-12 gap-4">
|
|
||||||
<div class="bg-card col-span-4 xl:col-span-3">
|
|
||||||
<div class="bg-card flex items-center justify-between p-3">
|
|
||||||
<Input.Search v-model:value="searchValue" class="ml-1 flex-1" />
|
|
||||||
<Dropdown class="ml-1">
|
|
||||||
<Button class="font-bold">......</Button>
|
|
||||||
<template #overlay>
|
|
||||||
<Menu>
|
|
||||||
<Menu.Item @click="expandAll">
|
|
||||||
{{ $t('common.expandAll') }}
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item @click="collapseAll">
|
|
||||||
{{ $t('common.collapseAll') }}
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
</template>
|
|
||||||
</Dropdown>
|
|
||||||
</div>
|
|
||||||
<Tree
|
|
||||||
:auto-expand-parent="autoExpandParent"
|
|
||||||
:block-node="true"
|
|
||||||
:expanded-keys="expandedKeys"
|
|
||||||
:tree-data="gData"
|
|
||||||
class="mt-3"
|
|
||||||
@expand="onExpand"
|
|
||||||
@select="onSelect"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-card col-span-8 xl:col-span-9">
|
|
||||||
<div class="bg-card">
|
|
||||||
<Codemirror v-model:value="codeText" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Spin>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
// import { postProjectsCreate } from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
import { addFormSchema } from './schema';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
// 所有表单项共用,可单独在表单内覆盖
|
|
||||||
commonConfig: {
|
|
||||||
// 所有表单项
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showDefaultActions: false,
|
|
||||||
// 垂直布局,label和input在不同行,值为vertical
|
|
||||||
// 水平布局,label和input在同一行
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: addFormSchema.value,
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onCancel() {
|
|
||||||
modalApi.close();
|
|
||||||
},
|
|
||||||
async onConfirm() {
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
// 获取表单值
|
|
||||||
const values = await formApi.getValues();
|
|
||||||
// 编辑
|
|
||||||
// await postProjectsCreate({ body: { ...values } });
|
|
||||||
message.success($t('common.addSuccess'));
|
|
||||||
emit('reload');
|
|
||||||
modalApi.close();
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="$t('common.add')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
// import { postProjectsUpdate } from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
import { editFormSchema } from './schema';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const data = ref<any>({});
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
// 所有表单项共用,可单独在表单内覆盖
|
|
||||||
commonConfig: {
|
|
||||||
// 所有表单项
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showDefaultActions: false,
|
|
||||||
// 垂直布局,label和input在不同行,值为vertical
|
|
||||||
// 水平布局,label和input在同一行
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: editFormSchema.value,
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onCancel() {
|
|
||||||
modalApi.close();
|
|
||||||
},
|
|
||||||
async onConfirm() {
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
// 获取表单值
|
|
||||||
const values = await formApi.getValues();
|
|
||||||
// 编辑
|
|
||||||
// await postProjectsUpdate({ body: { ...values } });
|
|
||||||
message.success($t('common.editSuccess'));
|
|
||||||
emit('reload');
|
|
||||||
modalApi.close();
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onOpenChange(isOpen: boolean) {
|
|
||||||
if (isOpen) {
|
|
||||||
data.value = modalApi.getData<Record<string, any>>();
|
|
||||||
formApi.setValues(data.value.row);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="$t('common.edit')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import { postEntityModelsCreateAggregate } from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
projectId: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const emit = defineEmits(['getTreeData']);
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
commonConfig: {
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showDefaultActions: false,
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: $t('common.pleaseInput'),
|
|
||||||
},
|
|
||||||
fieldName: 'code',
|
|
||||||
label: $t('code.code'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Textarea',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: $t('common.pleaseInput'),
|
|
||||||
},
|
|
||||||
fieldName: 'description',
|
|
||||||
label: $t('common.description'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onConfirm: async () => {
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
const values = await formApi.getValues();
|
|
||||||
await postEntityModelsCreateAggregate({
|
|
||||||
body: {
|
|
||||||
code: values.code,
|
|
||||||
description: values.description,
|
|
||||||
projectId: props.projectId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
message.success($t('common.addSuccess'));
|
|
||||||
emit('getTreeData');
|
|
||||||
modalApi.close();
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="$t('common.add')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,153 +0,0 @@
|
|||||||
<!--新增编辑实体Modal-->
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import type {
|
|
||||||
CreateEntityModelInput,
|
|
||||||
UpdateEntityModelInput,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import {
|
|
||||||
postEntityModelsCreateEntityModel,
|
|
||||||
postEntityModelsUpdateEntityModel,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
const emit = defineEmits(['getTreeData']);
|
|
||||||
const data = ref<Record<string, any>>({});
|
|
||||||
const [AddForm, addFormApi] = useVbenForm({
|
|
||||||
commonConfig: {
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
// 组件需要在 #/adapter.ts内注册,并加上类型
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'code',
|
|
||||||
label: $t('code.code'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Textarea',
|
|
||||||
fieldName: 'description',
|
|
||||||
label: $t('code.desc'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
fieldName: 'relationalType',
|
|
||||||
label: $t('code.relational'),
|
|
||||||
rules: 'required',
|
|
||||||
componentProps: {
|
|
||||||
options: [
|
|
||||||
{ label: '一对一', value: '10' },
|
|
||||||
{ label: '一对多', value: '20' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
showDefaultActions: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [EditForm, editFormApi] = useVbenForm({
|
|
||||||
commonConfig: {
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'code',
|
|
||||||
label: $t('code.code'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Textarea',
|
|
||||||
fieldName: 'description',
|
|
||||||
label: $t('code.desc'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
fieldName: 'relationalType',
|
|
||||||
label: $t('code.relational'),
|
|
||||||
rules: 'required',
|
|
||||||
componentProps: {
|
|
||||||
options: [
|
|
||||||
{ label: '一对一', value: '10' },
|
|
||||||
{ label: '一对多', value: '20' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: ['relationalType'],
|
|
||||||
if: () => !data.value.isRoot,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
showDefaultActions: false,
|
|
||||||
});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onOpenChange: (isOpen: boolean) => {
|
|
||||||
if (isOpen) {
|
|
||||||
data.value = modalApi.getData<Record<string, any>>();
|
|
||||||
if (data.value.isEdit) {
|
|
||||||
const { row } = data.value;
|
|
||||||
editFormApi.setValues({
|
|
||||||
...row,
|
|
||||||
relationalType: String(row.relationalType),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onConfirm: async () => {
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
if (data.value.isEdit) {
|
|
||||||
const { valid } = await editFormApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
const editFormValues = await editFormApi.getValues();
|
|
||||||
const params = {
|
|
||||||
...editFormValues,
|
|
||||||
id: data.value.id,
|
|
||||||
} as UpdateEntityModelInput;
|
|
||||||
data.value.isRoot && delete params.relationalType;
|
|
||||||
await postEntityModelsUpdateEntityModel({
|
|
||||||
body: params,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const { valid } = await addFormApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
const addFormValues = await addFormApi.getValues();
|
|
||||||
await postEntityModelsCreateEntityModel({
|
|
||||||
body: {
|
|
||||||
...addFormValues,
|
|
||||||
id: data.value.id,
|
|
||||||
} as CreateEntityModelInput,
|
|
||||||
});
|
|
||||||
message.success($t('common.addSuccess'));
|
|
||||||
}
|
|
||||||
modalApi.close();
|
|
||||||
emit('getTreeData');
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="data.isEdit ? $t('common.edit') : $t('common.add')">
|
|
||||||
<component :is="data.isEdit ? EditForm : AddForm" />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,190 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type {
|
|
||||||
CreateEntityModelPropertyInput,
|
|
||||||
UpdateEntityModelPropertyInput,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import {
|
|
||||||
postDataTypesList,
|
|
||||||
postEntityModelsCreateEntityModelProperty,
|
|
||||||
postEntityModelsUpdateEntityModelProperty,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const data = ref<Record<string, any>>({});
|
|
||||||
const dataTypeList = ref<any[]>();
|
|
||||||
const currentDataType = ref<string>();
|
|
||||||
const specialTypeList = new Set(['decimal', 'float']);
|
|
||||||
|
|
||||||
// 获取数据类型列表
|
|
||||||
async function getOptions() {
|
|
||||||
const { data: List } = await postDataTypesList({
|
|
||||||
body: { entityModelId: data.value.entityModelId },
|
|
||||||
});
|
|
||||||
dataTypeList.value = List;
|
|
||||||
return List;
|
|
||||||
}
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
commonConfig: {
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'code',
|
|
||||||
label: $t('code.code'),
|
|
||||||
rules: 'required',
|
|
||||||
formItemClass: 'col-span-2',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Textarea',
|
|
||||||
fieldName: 'description',
|
|
||||||
label: $t('code.desc'),
|
|
||||||
rules: 'required',
|
|
||||||
formItemClass: 'col-span-2',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
fieldName: 'dataTypeId',
|
|
||||||
label: $t('code.dataType'),
|
|
||||||
formItemClass: 'col-span-2',
|
|
||||||
componentProps: () => ({
|
|
||||||
options: dataTypeList.value,
|
|
||||||
'field-names': { label: 'description', value: 'id' },
|
|
||||||
onChange: (_value: any, data: Record<string, any>) => {
|
|
||||||
currentDataType.value = data.code;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Switch',
|
|
||||||
fieldName: 'isRequired',
|
|
||||||
label: $t('code.isRequired'),
|
|
||||||
defaultValue: true,
|
|
||||||
formItemClass: 'col-span-1',
|
|
||||||
componentProps: {
|
|
||||||
class: 'max-w-xs',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'InputNumber',
|
|
||||||
fieldName: 'maxLength',
|
|
||||||
label: $t('code.maxLength'),
|
|
||||||
rules: 'required',
|
|
||||||
defaultValue: 128,
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: ['dataTypeId'],
|
|
||||||
if: () => currentDataType.value === 'string',
|
|
||||||
},
|
|
||||||
formItemClass: 'col-span-1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'InputNumber',
|
|
||||||
fieldName: 'minLength',
|
|
||||||
label: $t('code.minLength'),
|
|
||||||
defaultValue: 0,
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: ['dataTypeId'],
|
|
||||||
if: () => currentDataType.value === 'string',
|
|
||||||
},
|
|
||||||
componentProps: {
|
|
||||||
min: 0,
|
|
||||||
},
|
|
||||||
formItemClass: 'col-span-1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'InputNumber',
|
|
||||||
fieldName: 'decimalPrecision',
|
|
||||||
label: $t('code.decimalPrecision18'),
|
|
||||||
componentProps: {
|
|
||||||
max: 18,
|
|
||||||
},
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: ['dataTypeId'],
|
|
||||||
if: () => specialTypeList.has(currentDataType.value as string),
|
|
||||||
},
|
|
||||||
formItemClass: 'col-span-1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'InputNumber',
|
|
||||||
fieldName: 'decimalScale',
|
|
||||||
label: $t('code.decimalPrecision6'),
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: ['dataTypeId'],
|
|
||||||
if: () => specialTypeList.has(currentDataType.value as string),
|
|
||||||
},
|
|
||||||
componentProps: {
|
|
||||||
max: 18,
|
|
||||||
},
|
|
||||||
formItemClass: 'col-span-1',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
wrapperClass: 'grid-cols-2',
|
|
||||||
showDefaultActions: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onOpenChange: async (isOpen: boolean) => {
|
|
||||||
if (isOpen) {
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true });
|
|
||||||
data.value = modalApi.getData<Record<string, any>>();
|
|
||||||
await getOptions();
|
|
||||||
if (data.value.isEdit) {
|
|
||||||
formApi.setValues({ ...data.value.row });
|
|
||||||
currentDataType.value = data.value.row.dataTypeCode;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onConfirm: async () => {
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
const addFormValues = await formApi.getValues();
|
|
||||||
await (data.value.isEdit
|
|
||||||
? postEntityModelsUpdateEntityModelProperty({
|
|
||||||
body: {
|
|
||||||
...addFormValues,
|
|
||||||
id: data.value.entityModelId,
|
|
||||||
propertyId: data.value.row.id,
|
|
||||||
enumTypeId: addFormValues.dataTypeId,
|
|
||||||
} as UpdateEntityModelPropertyInput,
|
|
||||||
})
|
|
||||||
: postEntityModelsCreateEntityModelProperty({
|
|
||||||
body: {
|
|
||||||
...addFormValues,
|
|
||||||
id: data.value.entityModelId,
|
|
||||||
enumTypeId: addFormValues.dataTypeId,
|
|
||||||
} as CreateEntityModelPropertyInput,
|
|
||||||
}));
|
|
||||||
message.success(
|
|
||||||
data.value.isEdit ? $t('common.editSuccess') : $t('common.addSuccess'),
|
|
||||||
);
|
|
||||||
modalApi.close();
|
|
||||||
emit('reload');
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="data.isEdit ? $t('common.edit') : $t('common.add')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type {
|
|
||||||
CreateEnumTypeInput,
|
|
||||||
UpdateEnumTypeInput,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import {
|
|
||||||
postEnumTypesCreateEnumType,
|
|
||||||
postEnumTypesUpdateEnumType,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
commonConfig: {
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'code',
|
|
||||||
label: $t('code.code'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Textarea',
|
|
||||||
fieldName: 'description',
|
|
||||||
label: $t('code.desc'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
showDefaultActions: false,
|
|
||||||
});
|
|
||||||
const data = ref<Record<string, any>>({});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onOpenChange: (isOpen: boolean) => {
|
|
||||||
if (isOpen) {
|
|
||||||
data.value = modalApi.getData<Record<string, any>>();
|
|
||||||
if (data.value.isEdit) {
|
|
||||||
const { row } = data.value;
|
|
||||||
formApi.setValues({
|
|
||||||
...row,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onConfirm: async () => {
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
const formValues = await formApi.getValues();
|
|
||||||
if (data.value.isEdit) {
|
|
||||||
const params = {
|
|
||||||
...formValues,
|
|
||||||
id: data.value.row.id,
|
|
||||||
};
|
|
||||||
await postEnumTypesUpdateEnumType({
|
|
||||||
body: params as UpdateEnumTypeInput,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await postEnumTypesCreateEnumType({
|
|
||||||
body: {
|
|
||||||
...formValues,
|
|
||||||
...data.value,
|
|
||||||
} as CreateEnumTypeInput,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
message.success(
|
|
||||||
data.value.isEdit ? $t('common.editSuccess') : $t('common.addSuccess'),
|
|
||||||
);
|
|
||||||
modalApi.close();
|
|
||||||
emit('reload');
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Modal :title="data.isEdit ? $t('common.edit') : $t('common.add')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type {
|
|
||||||
CreateEnumTypePropertyInput,
|
|
||||||
UpdateEnumTypePropertyInput,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import {
|
|
||||||
postEnumTypesCreateEnumTypeProperty,
|
|
||||||
postEnumTypesUpdateEnumTypeProperty,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
commonConfig: {
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'id',
|
|
||||||
label: 'id',
|
|
||||||
dependencies: {
|
|
||||||
show: () => false,
|
|
||||||
triggerFields: ['id'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'enumTypeId',
|
|
||||||
label: 'enumTypeId',
|
|
||||||
dependencies: {
|
|
||||||
show: () => false,
|
|
||||||
triggerFields: ['enumTypeId'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'code',
|
|
||||||
label: $t('code.code'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'InputNumber',
|
|
||||||
fieldName: 'value',
|
|
||||||
label: $t('code.value'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Textarea',
|
|
||||||
fieldName: 'description',
|
|
||||||
label: $t('code.desc'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
showDefaultActions: false,
|
|
||||||
});
|
|
||||||
const data = ref<Record<string, any>>({});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onOpenChange: (isOpen: boolean) => {
|
|
||||||
if (isOpen) {
|
|
||||||
data.value = modalApi.getData<Record<string, any>>();
|
|
||||||
if (data.value.isEdit) {
|
|
||||||
const { row, enumTypeId } = data.value;
|
|
||||||
formApi.setValues({
|
|
||||||
...row,
|
|
||||||
enumTypeId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onConfirm: async () => {
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
const formValues = await formApi.getValues();
|
|
||||||
if (data.value.isEdit) {
|
|
||||||
const params = {
|
|
||||||
...formValues,
|
|
||||||
id: data.value.row.id,
|
|
||||||
};
|
|
||||||
await postEnumTypesUpdateEnumTypeProperty({
|
|
||||||
body: params as UpdateEnumTypePropertyInput,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await postEnumTypesCreateEnumTypeProperty({
|
|
||||||
body: {
|
|
||||||
...formValues,
|
|
||||||
...data.value,
|
|
||||||
} as CreateEnumTypePropertyInput,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
message.success(
|
|
||||||
data.value.isEdit ? $t('common.editSuccess') : $t('common.addSuccess'),
|
|
||||||
);
|
|
||||||
modalApi.close();
|
|
||||||
emit('reload');
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Modal :title="data.isEdit ? $t('common.edit') : $t('common.add')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,806 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { TreeProps } from 'ant-design-vue';
|
|
||||||
import type { DataNode } from 'ant-design-vue/es/tree';
|
|
||||||
|
|
||||||
import type { VbenFormProps } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
|
||||||
|
|
||||||
import { onMounted, ref, watch } from 'vue';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Dropdown,
|
|
||||||
Input,
|
|
||||||
Menu,
|
|
||||||
message as Message,
|
|
||||||
message,
|
|
||||||
Modal,
|
|
||||||
Spin,
|
|
||||||
Tabs,
|
|
||||||
Tree,
|
|
||||||
} from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
||||||
import {
|
|
||||||
postEntityModelsDeleteAggregate,
|
|
||||||
postEntityModelsDeleteEntityModel,
|
|
||||||
postEntityModelsDeleteEntityModelProperty,
|
|
||||||
postEntityModelsPageProperty,
|
|
||||||
postEntityModelsTree,
|
|
||||||
postEnumTypesDeleteEnumType,
|
|
||||||
postEnumTypesDeleteEnumTypeProperty,
|
|
||||||
postEnumTypesPage,
|
|
||||||
postEnumTypesPageProperty,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
import AddAggregateRoot from './AddAggregateRootModal.vue';
|
|
||||||
import AddEditEntity from './AddEditEntityModal.vue';
|
|
||||||
import AddEditEntityProperty from './AddEditEntityPropertyModal.vue';
|
|
||||||
import AddEditEnumComponent from './AddEditEnumModal.vue';
|
|
||||||
import AddEditEnumPropertyComponent from './AddEditEnumPropertyModal.vue';
|
|
||||||
|
|
||||||
// 定义一个响应式变量,用于存储展开的节点
|
|
||||||
const expandedKeys = ref<(number | string)[]>([]);
|
|
||||||
// 定义一个响应式变量,用于存储搜索框的值
|
|
||||||
const searchValue = ref<string>('');
|
|
||||||
// 定义一个响应式变量,用于控制是否自动展开父节点
|
|
||||||
const autoExpandParent = ref<boolean>(true);
|
|
||||||
// 定义一个响应式变量,用于存储树形数据
|
|
||||||
const gData = ref<Array<DataNode>>([]);
|
|
||||||
// 定义一个响应式变量,用于存储当前激活的tab
|
|
||||||
const activeKey = ref('1');
|
|
||||||
// 定义一个响应式的变量,用于存储当前选中的节点的key
|
|
||||||
const currentSelectedKey = ref('');
|
|
||||||
// 定义一个响应式的变量,用于存储当前选中的节点
|
|
||||||
const currentSelectedTreeNode = ref();
|
|
||||||
const route = useRoute();
|
|
||||||
|
|
||||||
const contextMenuOptions = [
|
|
||||||
{ label: $t('common.add'), key: 'add' },
|
|
||||||
{ label: $t('common.edit'), key: 'edit' },
|
|
||||||
{ label: $t('common.delete'), key: 'delete' },
|
|
||||||
];
|
|
||||||
const loading = ref<boolean>(true);
|
|
||||||
onMounted(() => {
|
|
||||||
getTreeData().then(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const [AddAggregateRootModal, addAggregateRootModalApi] = useVbenModal({
|
|
||||||
// 连接抽离的组件
|
|
||||||
connectedComponent: AddAggregateRoot,
|
|
||||||
});
|
|
||||||
const [AddEditEntityModal, addEditEntityModalApi] = useVbenModal({
|
|
||||||
// 连接抽离的组件
|
|
||||||
connectedComponent: AddEditEntity,
|
|
||||||
});
|
|
||||||
// 定义一个异步函数,用于处理右键菜单的选择
|
|
||||||
const onContextMenuSelect = async (key: string) => {
|
|
||||||
// 根据选择的key值,执行不同的操作
|
|
||||||
switch (key) {
|
|
||||||
// 如果选择的key值为add,则打开添加编辑实体模态框
|
|
||||||
case 'add': {
|
|
||||||
addEditEntityModalApi.setData({
|
|
||||||
isEdit: false,
|
|
||||||
id: currentSelectedKey.value,
|
|
||||||
});
|
|
||||||
addEditEntityModalApi.open();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 如果选择的key值为delete,则弹出确认框,确认后执行删除操作
|
|
||||||
case 'delete': {
|
|
||||||
Modal.confirm({
|
|
||||||
title: `${$t('common.confirmDelete')}?`,
|
|
||||||
onOk: async () => {
|
|
||||||
// 构造删除实体的参数
|
|
||||||
const params = {
|
|
||||||
id: currentSelectedTreeNode.value.key,
|
|
||||||
aggregateId: currentSelectedTreeNode.value?.parentId,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 如果没有父节点,则不传aggregateId
|
|
||||||
if (currentSelectedTreeNode.value?.parentId) {
|
|
||||||
await postEntityModelsDeleteEntityModel({
|
|
||||||
body: params,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
delete params.aggregateId;
|
|
||||||
await postEntityModelsDeleteAggregate({
|
|
||||||
body: params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Message.success($t('common.success'));
|
|
||||||
currentSelectedKey.value = '';
|
|
||||||
currentSelectedTreeNode.value = null;
|
|
||||||
getTreeData();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
// 设置编辑实体模态框的数据
|
|
||||||
addEditEntityModalApi.setData({
|
|
||||||
isEdit: true, // 设置为编辑状态
|
|
||||||
isRoot: !currentSelectedTreeNode.value?.parentId, // 判断是否为根节点
|
|
||||||
id: currentSelectedKey.value, // 设置实体id
|
|
||||||
row: currentSelectedTreeNode.value, // 设置实体数据
|
|
||||||
});
|
|
||||||
// 打开编辑实体模态框
|
|
||||||
addEditEntityModalApi.open();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 当右键菜单点击时,执行该函数
|
|
||||||
const onContextMenuClick = (treeKey: string, nodeData: any, menuKey: any) => {
|
|
||||||
// 将当前选中的树节点key赋值给currentSelectedKey
|
|
||||||
currentSelectedKey.value = treeKey;
|
|
||||||
// 将当前选中的树节点数据赋值给currentSelectedTreeNode
|
|
||||||
currentSelectedTreeNode.value = nodeData;
|
|
||||||
// 调用onContextMenuSelect函数,传入menuKey
|
|
||||||
onContextMenuSelect(menuKey);
|
|
||||||
};
|
|
||||||
|
|
||||||
const dataList = ref<DataNode[]>([]);
|
|
||||||
const generateList = (data: TreeProps['treeData']) => {
|
|
||||||
if (!data) return;
|
|
||||||
for (const node of data) {
|
|
||||||
const { key, title, children } = node;
|
|
||||||
dataList.value.push({ key, title });
|
|
||||||
if (children) {
|
|
||||||
generateList(children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getParentKey = (
|
|
||||||
key: number | string,
|
|
||||||
tree: TreeProps['treeData'],
|
|
||||||
): number | string | undefined => {
|
|
||||||
if (!tree) return undefined;
|
|
||||||
let parentKey;
|
|
||||||
for (const node of tree) {
|
|
||||||
if (node.children) {
|
|
||||||
if (node.children.some((item) => item.key === key)) {
|
|
||||||
parentKey = node.key;
|
|
||||||
} else if (getParentKey(key, node.children)) {
|
|
||||||
parentKey = getParentKey(key, node.children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parentKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取所有节点的key
|
|
||||||
const getAllKeys = (tree: TreeProps['treeData']): (number | string)[] => {
|
|
||||||
const keys: (number | string)[] = [];
|
|
||||||
const traverse = (nodes: TreeProps['treeData']) => {
|
|
||||||
if (!nodes) return;
|
|
||||||
nodes.forEach((node) => {
|
|
||||||
if (node.key) {
|
|
||||||
keys.push(node.key);
|
|
||||||
}
|
|
||||||
if (node.children) {
|
|
||||||
traverse(node.children);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
traverse(tree);
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 展开所有节点
|
|
||||||
const expandAll = () => {
|
|
||||||
expandedKeys.value = getAllKeys(gData.value as TreeProps['treeData']);
|
|
||||||
autoExpandParent.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 折叠所有节点
|
|
||||||
const collapseAll = () => {
|
|
||||||
expandedKeys.value = [];
|
|
||||||
autoExpandParent.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 添加 onExpand 方法处理节点展开/折叠
|
|
||||||
const onExpand = (keys: (number | string)[], info: any) => {
|
|
||||||
expandedKeys.value = keys;
|
|
||||||
autoExpandParent.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSelect = (keys: any[], event: any) => {
|
|
||||||
currentSelectedKey.value = keys[0] ?? '';
|
|
||||||
// parentDisplayName.value = event.node.title;
|
|
||||||
if (!keys[0]) return '';
|
|
||||||
};
|
|
||||||
|
|
||||||
async function getTreeData() {
|
|
||||||
const { data = [] } = await postEntityModelsTree({
|
|
||||||
body: { projectId: route.query.projectId as string },
|
|
||||||
});
|
|
||||||
gData.value = data as DataNode[];
|
|
||||||
dataList.value = [];
|
|
||||||
generateList(data as TreeProps['treeData']);
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(searchValue, (value) => {
|
|
||||||
if (!value) {
|
|
||||||
expandedKeys.value = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const expanded = dataList.value
|
|
||||||
.map((item) => {
|
|
||||||
if (
|
|
||||||
typeof item.title === 'string' &&
|
|
||||||
item.title.toLowerCase().includes(value.toLowerCase())
|
|
||||||
) {
|
|
||||||
return getParentKey(item.key, gData.value as TreeProps['treeData']);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
})
|
|
||||||
.filter(
|
|
||||||
(item, i, self): item is number | string =>
|
|
||||||
item !== null && item !== undefined && self.indexOf(item) === i,
|
|
||||||
);
|
|
||||||
|
|
||||||
expandedKeys.value = expanded;
|
|
||||||
autoExpandParent.value = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const propertyFormOptions: VbenFormProps = {
|
|
||||||
resetButtonOptions: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'filter',
|
|
||||||
label: $t('common.keyword'),
|
|
||||||
labelWidth: 50,
|
|
||||||
componentProps: {
|
|
||||||
allowClear: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
showDefaultActions: true,
|
|
||||||
submitOnEnter: true,
|
|
||||||
showCollapseButton: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const propertyGridOptions: VxeGridProps<any> = {
|
|
||||||
columns: [
|
|
||||||
{ type: 'seq', title: $t('common.seq'), width: '50' },
|
|
||||||
{
|
|
||||||
field: 'code',
|
|
||||||
title: $t('code.code'),
|
|
||||||
minWidth: '200',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'description',
|
|
||||||
title: $t('common.description'),
|
|
||||||
minWidth: '200',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'dataTypeDescription',
|
|
||||||
title: $t('code.type'),
|
|
||||||
minWidth: '150',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'isRequired',
|
|
||||||
title: $t('code.isRequired'),
|
|
||||||
minWidth: '150',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'maxLength',
|
|
||||||
title: $t('code.maxLength'),
|
|
||||||
minWidth: '150',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'minLength',
|
|
||||||
title: $t('code.minLength'),
|
|
||||||
minWidth: '150',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'decimalPrecision',
|
|
||||||
title: $t('code.decimalPrecision18'),
|
|
||||||
minWidth: '150',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'decimalScale',
|
|
||||||
title: $t('code.decimalPrecision6'),
|
|
||||||
minWidth: '150',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: $t('common.action'),
|
|
||||||
field: 'action',
|
|
||||||
fixed: 'right',
|
|
||||||
width: '150',
|
|
||||||
slots: { default: 'action' },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
minHeight: '800',
|
|
||||||
keepSource: true,
|
|
||||||
pagerConfig: {},
|
|
||||||
radioConfig: {
|
|
||||||
highlight: true,
|
|
||||||
},
|
|
||||||
proxyConfig: {
|
|
||||||
ajax: {
|
|
||||||
query: async ({ page }, formValues) => {
|
|
||||||
if (!currentSelectedKey.value) return;
|
|
||||||
const { data } = await postEntityModelsPageProperty({
|
|
||||||
body: {
|
|
||||||
pageIndex: page.currentPage,
|
|
||||||
pageSize: page.pageSize,
|
|
||||||
id: currentSelectedKey.value,
|
|
||||||
...formValues,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const [PropertyGrid, propertyGridApi] = useVbenVxeGrid({
|
|
||||||
gridOptions: propertyGridOptions,
|
|
||||||
formOptions: propertyFormOptions,
|
|
||||||
});
|
|
||||||
|
|
||||||
const enumFormOptions: VbenFormProps = {
|
|
||||||
resetButtonOptions: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'filter',
|
|
||||||
label: $t('common.keyword'),
|
|
||||||
labelWidth: 50,
|
|
||||||
componentProps: {
|
|
||||||
allowClear: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
showDefaultActions: true,
|
|
||||||
submitOnEnter: true,
|
|
||||||
showCollapseButton: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const enumGridOptions: VxeGridProps<any> = {
|
|
||||||
columns: [
|
|
||||||
{ type: 'radio', title: $t('common.seq'), width: '50' },
|
|
||||||
{
|
|
||||||
field: 'code',
|
|
||||||
title: $t('code.code'),
|
|
||||||
minWidth: '200',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'description',
|
|
||||||
title: $t('common.description'),
|
|
||||||
minWidth: '200',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: $t('common.action'),
|
|
||||||
field: 'action',
|
|
||||||
fixed: 'right',
|
|
||||||
width: '150',
|
|
||||||
slots: { default: 'action' },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
minHeight: '800',
|
|
||||||
keepSource: true,
|
|
||||||
pagerConfig: {},
|
|
||||||
radioConfig: {
|
|
||||||
highlight: true,
|
|
||||||
},
|
|
||||||
proxyConfig: {
|
|
||||||
ajax: {
|
|
||||||
query: async ({ page }, formValues) => {
|
|
||||||
if (!currentSelectedKey.value) return;
|
|
||||||
const { data } = await postEnumTypesPage({
|
|
||||||
body: {
|
|
||||||
pageIndex: page.currentPage,
|
|
||||||
pageSize: page.pageSize,
|
|
||||||
id: currentSelectedKey.value,
|
|
||||||
...formValues,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const currentEnumTypeId = ref<string>('');
|
|
||||||
const enumGridEvent = {
|
|
||||||
radioChange: (values: any) => {
|
|
||||||
currentEnumTypeId.value = values.row.id;
|
|
||||||
enumPropertyGridApi.reload({
|
|
||||||
id: values.row.id,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const [EnumGrid, enumGridApi] = useVbenVxeGrid({
|
|
||||||
gridOptions: enumGridOptions,
|
|
||||||
formOptions: enumFormOptions,
|
|
||||||
gridEvents: enumGridEvent,
|
|
||||||
});
|
|
||||||
|
|
||||||
const enumPropertyFormOptions: VbenFormProps = {
|
|
||||||
resetButtonOptions: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'filter',
|
|
||||||
label: $t('common.keyword'),
|
|
||||||
labelWidth: 50,
|
|
||||||
componentProps: {
|
|
||||||
allowClear: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
showDefaultActions: true,
|
|
||||||
submitOnEnter: true,
|
|
||||||
showCollapseButton: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const enumPropertyGridOptions: VxeGridProps<any> = {
|
|
||||||
columns: [
|
|
||||||
{ type: 'seq', title: $t('common.seq'), width: '50' },
|
|
||||||
{
|
|
||||||
field: 'code',
|
|
||||||
title: $t('code.code'),
|
|
||||||
minWidth: '100',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'value',
|
|
||||||
title: $t('code.value'),
|
|
||||||
minWidth: '100',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'description',
|
|
||||||
title: $t('common.description'),
|
|
||||||
minWidth: '150',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: $t('common.action'),
|
|
||||||
field: 'action',
|
|
||||||
fixed: 'right',
|
|
||||||
width: '150',
|
|
||||||
slots: { default: 'action' },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
minHeight: '800',
|
|
||||||
keepSource: true,
|
|
||||||
pagerConfig: {},
|
|
||||||
radioConfig: {
|
|
||||||
highlight: true,
|
|
||||||
},
|
|
||||||
proxyConfig: {
|
|
||||||
ajax: {
|
|
||||||
query: async ({ page }, formValues) => {
|
|
||||||
if (!currentEnumTypeId.value) return;
|
|
||||||
const { data } = await postEnumTypesPageProperty({
|
|
||||||
body: {
|
|
||||||
pageIndex: page.currentPage,
|
|
||||||
pageSize: page.pageSize,
|
|
||||||
id: currentEnumTypeId.value,
|
|
||||||
...formValues,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const [EnumPropertyGrid, enumPropertyGridApi] = useVbenVxeGrid({
|
|
||||||
gridOptions: enumPropertyGridOptions,
|
|
||||||
formOptions: enumPropertyFormOptions,
|
|
||||||
});
|
|
||||||
watch(currentSelectedKey, () => {
|
|
||||||
propertyGridApi.reload();
|
|
||||||
enumGridApi.reload();
|
|
||||||
enumPropertyGridApi.reload();
|
|
||||||
});
|
|
||||||
const [AddEditEntityPropertyModal, addEditEntityPropertyModalApi] =
|
|
||||||
useVbenModal({
|
|
||||||
connectedComponent: AddEditEntityProperty,
|
|
||||||
});
|
|
||||||
|
|
||||||
const openAddEntityPropertyModal = () => {
|
|
||||||
if (!currentSelectedKey.value) {
|
|
||||||
message.error('请先选择实体');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addEditEntityPropertyModalApi.setData({
|
|
||||||
entityModelId: currentSelectedKey.value,
|
|
||||||
isEdit: false,
|
|
||||||
});
|
|
||||||
addEditEntityPropertyModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDeleteEntityModelProperty = async (row: Record<string, any>) => {
|
|
||||||
Modal.confirm({
|
|
||||||
title: `${$t('common.confirmDelete')}?`,
|
|
||||||
onOk: async () => {
|
|
||||||
await postEntityModelsDeleteEntityModelProperty({
|
|
||||||
body: {
|
|
||||||
propertyId: row.id,
|
|
||||||
id: currentSelectedKey.value,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
message.success($t('common.deleteSuccess'));
|
|
||||||
propertyGridApi.reload();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEditEntityModelProperty = async (row: Record<string, any>) => {
|
|
||||||
addEditEntityPropertyModalApi.setData({
|
|
||||||
entityModelId: currentSelectedKey.value,
|
|
||||||
isEdit: true,
|
|
||||||
row,
|
|
||||||
});
|
|
||||||
addEditEntityPropertyModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const [AddEditEnumModal, addEditEnumModalApi] = useVbenModal({
|
|
||||||
connectedComponent: AddEditEnumComponent,
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleAddEnum = () => {
|
|
||||||
if (!currentSelectedKey.value) {
|
|
||||||
message.error($t('code.pleaseSelectEntity'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addEditEnumModalApi.setData({
|
|
||||||
entityModelId: currentSelectedKey.value,
|
|
||||||
projectId: route.query.projectId,
|
|
||||||
isEdit: false,
|
|
||||||
});
|
|
||||||
addEditEnumModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEditEnum = (row: Record<string, any>) => {
|
|
||||||
addEditEnumModalApi.setData({
|
|
||||||
isEdit: true,
|
|
||||||
row,
|
|
||||||
});
|
|
||||||
addEditEnumModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDeleteEnum = async (row: Record<string, any>) => {
|
|
||||||
Modal.confirm({
|
|
||||||
title: `${$t('common.confirmDelete')}?`,
|
|
||||||
onOk: async () => {
|
|
||||||
await postEnumTypesDeleteEnumType({
|
|
||||||
body: { id: row.id, entityModelId: currentSelectedKey.value },
|
|
||||||
});
|
|
||||||
message.success($t('common.deleteSuccess'));
|
|
||||||
enumGridApi.reload();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const [AddEditEnumPropertyModal, addEditEnumPropertyModalApi] = useVbenModal({
|
|
||||||
connectedComponent: AddEditEnumPropertyComponent,
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleAddEnumProperty = () => {
|
|
||||||
if (!currentEnumTypeId.value) {
|
|
||||||
message.error($t('code.pleaseSelectEnum'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addEditEnumPropertyModalApi.setData({
|
|
||||||
enumTypeId: currentEnumTypeId.value,
|
|
||||||
isEdit: false,
|
|
||||||
});
|
|
||||||
addEditEnumPropertyModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEditEnumProperty = (row: Record<string, any>) => {
|
|
||||||
addEditEnumPropertyModalApi.setData({
|
|
||||||
isEdit: true,
|
|
||||||
enumTypeId: currentEnumTypeId.value,
|
|
||||||
row,
|
|
||||||
});
|
|
||||||
addEditEnumPropertyModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDeleteEnumProperty = async (row: Record<string, any>) => {
|
|
||||||
Modal.confirm({
|
|
||||||
title: `${$t('common.confirmDelete')}?`,
|
|
||||||
onOk: async () => {
|
|
||||||
await postEnumTypesDeleteEnumTypeProperty({
|
|
||||||
body: { id: row.id, enumTypeId: currentEnumTypeId.value },
|
|
||||||
});
|
|
||||||
message.success($t('common.deleteSuccess'));
|
|
||||||
enumPropertyGridApi.reload();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Spin :spinning="loading" tip="loading...">
|
|
||||||
<Page :auto-content-height="true">
|
|
||||||
<div class="grid grid-cols-12 gap-4">
|
|
||||||
<div class="bg-card col-span-4 xl:col-span-3">
|
|
||||||
<div class="bg-card flex items-center justify-between p-3">
|
|
||||||
<Button
|
|
||||||
class="mx-3"
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
@click="addAggregateRootModalApi.open"
|
|
||||||
>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<span
|
|
||||||
class="icon-[material-symbols--add-circle-outline]"
|
|
||||||
></span>
|
|
||||||
<span class="ml-1"> {{ $t('common.add') }}</span>
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
<Input.Search v-model:value="searchValue" class="ml-1 flex-1" />
|
|
||||||
<Dropdown class="ml-1">
|
|
||||||
<Button class="font-bold">......</Button>
|
|
||||||
<template #overlay>
|
|
||||||
<Menu>
|
|
||||||
<Menu.Item @click="expandAll">
|
|
||||||
{{ $t('common.expandAll') }}
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item @click="collapseAll">
|
|
||||||
{{ $t('common.collapseAll') }}
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
</template>
|
|
||||||
</Dropdown>
|
|
||||||
</div>
|
|
||||||
<Tree
|
|
||||||
:auto-expand-parent="autoExpandParent"
|
|
||||||
:block-node="true"
|
|
||||||
:expanded-keys="expandedKeys"
|
|
||||||
:tree-data="gData"
|
|
||||||
class="mt-3"
|
|
||||||
@expand="onExpand"
|
|
||||||
@select="onSelect"
|
|
||||||
>
|
|
||||||
<template #title="{ title, key: treeKey, data: nodeData }">
|
|
||||||
<Dropdown :trigger="['contextmenu']">
|
|
||||||
<span v-if="title.includes(searchValue)" class="block w-full">
|
|
||||||
{{ title.substring(0, title.indexOf(searchValue)) }}
|
|
||||||
<span style="color: #f50">{{ searchValue }}</span>
|
|
||||||
{{
|
|
||||||
title.substring(
|
|
||||||
title.indexOf(searchValue) + searchValue.length,
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
<span v-else class="block w-full">{{ title }}</span>
|
|
||||||
<template #overlay>
|
|
||||||
<Menu
|
|
||||||
@click="
|
|
||||||
({ key: menuKey }) =>
|
|
||||||
onContextMenuClick(treeKey, nodeData, menuKey)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<Menu.Item
|
|
||||||
v-for="item in contextMenuOptions"
|
|
||||||
:key="item.key"
|
|
||||||
>
|
|
||||||
{{ item.label }}
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
</template>
|
|
||||||
</Dropdown>
|
|
||||||
</template>
|
|
||||||
</Tree>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-span-8 xl:col-span-9">
|
|
||||||
<div class="bg-card">
|
|
||||||
<Tabs v-model:active-key="activeKey" class="px-3">
|
|
||||||
<Tabs.TabPane key="1" :tab="$t('code.property')">
|
|
||||||
<PropertyGrid>
|
|
||||||
<template #toolbar-tools>
|
|
||||||
<Button
|
|
||||||
:disabled="!currentSelectedKey"
|
|
||||||
type="primary"
|
|
||||||
@click="openAddEntityPropertyModal"
|
|
||||||
>
|
|
||||||
{{ $t('common.add') }}
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
<template #action="{ row }">
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
@click="handleEditEntityModelProperty(row)"
|
|
||||||
>
|
|
||||||
{{ $t('common.edit') }}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
danger
|
|
||||||
type="link"
|
|
||||||
@click="handleDeleteEntityModelProperty(row)"
|
|
||||||
>
|
|
||||||
{{ $t('common.delete') }}
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
</PropertyGrid>
|
|
||||||
</Tabs.TabPane>
|
|
||||||
<Tabs.TabPane key="2" :tab="$t('code.enum')">
|
|
||||||
<div class="grid grid-cols-12 gap-4">
|
|
||||||
<div class="bg-card col-span-6">
|
|
||||||
<EnumGrid>
|
|
||||||
<template #toolbar-tools>
|
|
||||||
<Button type="primary" @click="handleAddEnum">
|
|
||||||
{{ $t('common.add') }}
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #action="{ row }">
|
|
||||||
<Button type="link" @click="handleEditEnum(row)">
|
|
||||||
{{ $t('common.edit') }}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
danger
|
|
||||||
type="link"
|
|
||||||
@click="handleDeleteEnum(row)"
|
|
||||||
>
|
|
||||||
{{ $t('common.delete') }}
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
</EnumGrid>
|
|
||||||
</div>
|
|
||||||
<div class="bg-card col-span-6">
|
|
||||||
<EnumPropertyGrid>
|
|
||||||
<template #toolbar-tools>
|
|
||||||
<Button type="primary" @click="handleAddEnumProperty">
|
|
||||||
{{ $t('common.add') }}
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #action="{ row }">
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
@click="handleEditEnumProperty(row)"
|
|
||||||
>
|
|
||||||
{{ $t('common.edit') }}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
danger
|
|
||||||
type="link"
|
|
||||||
@click="handleDeleteEnumProperty(row)"
|
|
||||||
>
|
|
||||||
{{ $t('common.delete') }}
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
</EnumPropertyGrid>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Tabs.TabPane>
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<AddAggregateRootModal
|
|
||||||
:project-id="route.query.projectId"
|
|
||||||
@get-tree-data="getTreeData"
|
|
||||||
/>
|
|
||||||
<AddEditEntityModal @get-tree-data="getTreeData" />
|
|
||||||
<AddEditEntityPropertyModal @reload="propertyGridApi.reload" />
|
|
||||||
<AddEditEnumModal @reload="enumGridApi.reload" />
|
|
||||||
<AddEditEnumPropertyModal @reload="enumPropertyGridApi.reload" />
|
|
||||||
</Page>
|
|
||||||
</Spin>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@ -1,174 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type { VbenFormProps } from '#/adapter/form';
|
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
|
||||||
|
|
||||||
import { h } from 'vue';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { Modal, Tag } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
||||||
// import { postProjectsDelete, postProjectsPage } from '#/api-client/index';
|
|
||||||
import { TableAction } from '#/components/table-action';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
// 新增modal
|
|
||||||
import AddModal from './AddModal.vue';
|
|
||||||
// 编辑modal
|
|
||||||
import EditModal from './EditModal.vue';
|
|
||||||
import { querySchema, tableSchema } from './schema';
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const formOptions: VbenFormProps = {
|
|
||||||
// 默认展开
|
|
||||||
collapsed: false,
|
|
||||||
schema: querySchema.value,
|
|
||||||
// 控制表单是否显示折叠按钮
|
|
||||||
showCollapseButton: true,
|
|
||||||
// 按下回车时是否提交表单
|
|
||||||
submitOnEnter: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const gridOptions: VxeGridProps<any> = {
|
|
||||||
checkboxConfig: {
|
|
||||||
highlight: true,
|
|
||||||
labelField: 'name',
|
|
||||||
},
|
|
||||||
columns: tableSchema.value,
|
|
||||||
keepSource: true,
|
|
||||||
height: 'auto',
|
|
||||||
pagerConfig: {},
|
|
||||||
toolbarConfig: {
|
|
||||||
custom: true,
|
|
||||||
},
|
|
||||||
customConfig: {
|
|
||||||
storage: true,
|
|
||||||
},
|
|
||||||
proxyConfig: {
|
|
||||||
ajax: {
|
|
||||||
query: async ({ page }, formValues) => {
|
|
||||||
// const { data } = await postProjectsPage({
|
|
||||||
// body: {
|
|
||||||
// pageIndex: page.currentPage,
|
|
||||||
// pageSize: page.pageSize,
|
|
||||||
// ...formValues,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// return data;
|
|
||||||
return { items: [], totalCount: 0 };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
|
|
||||||
|
|
||||||
const [AddVbenModal, addModalApi] = useVbenModal({
|
|
||||||
// 连接抽离的组件
|
|
||||||
connectedComponent: AddModal,
|
|
||||||
});
|
|
||||||
const [EditVbenModal, editModalApi] = useVbenModal({
|
|
||||||
// 连接抽离的组件
|
|
||||||
connectedComponent: EditModal,
|
|
||||||
});
|
|
||||||
const handleAdd = () => {
|
|
||||||
addModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEdit = (row: Record<string, any>) => {
|
|
||||||
editModalApi.setData({
|
|
||||||
row,
|
|
||||||
});
|
|
||||||
editModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDelete = (row: any) => {
|
|
||||||
Modal.confirm({
|
|
||||||
title: `${$t('common.confirmDelete')}?`,
|
|
||||||
onOk: async () => {
|
|
||||||
// await postProjectsDelete({
|
|
||||||
// body: {
|
|
||||||
// id: row.id,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
gridApi.reload();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleViewModel = (row: Record<string, any>) => {
|
|
||||||
router.push({
|
|
||||||
name: 'EntityModel',
|
|
||||||
query: {
|
|
||||||
projectId: row.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Page auto-content-height>
|
|
||||||
<Grid>
|
|
||||||
<template #toolbar-actions>
|
|
||||||
<TableAction
|
|
||||||
:actions="[
|
|
||||||
{
|
|
||||||
label: $t('common.add'),
|
|
||||||
type: 'primary',
|
|
||||||
icon: 'ant-design:plus-outlined',
|
|
||||||
onClick: handleAdd.bind(null),
|
|
||||||
auth: ['AbpCodeManagement.Project.Create'],
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #supportTenant="{ row }">
|
|
||||||
<component
|
|
||||||
:is="
|
|
||||||
h(
|
|
||||||
Tag,
|
|
||||||
{ color: row.supportTenant ? 'green' : 'red' },
|
|
||||||
row.supportTenant ? $t('common.yes') : $t('common.no'),
|
|
||||||
)
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #action="{ row }">
|
|
||||||
<TableAction
|
|
||||||
:actions="[
|
|
||||||
{
|
|
||||||
label: $t('code.model'),
|
|
||||||
type: 'link',
|
|
||||||
size: 'small',
|
|
||||||
auth: ['AbpCodeManagement.Project.Model'],
|
|
||||||
onClick: handleViewModel.bind(null, row),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('common.edit'),
|
|
||||||
type: 'link',
|
|
||||||
size: 'small',
|
|
||||||
auth: ['AbpCodeManagement.Project.Update'],
|
|
||||||
onClick: handleEdit.bind(null, row),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('common.delete'),
|
|
||||||
type: 'link',
|
|
||||||
size: 'small',
|
|
||||||
auth: ['AbpCodeManagement.Project.Delete'],
|
|
||||||
popConfirm: {
|
|
||||||
title: $t('common.askConfirmDelete'),
|
|
||||||
confirm: handleDelete.bind(null, row),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</Grid>
|
|
||||||
<AddVbenModal @reload="gridApi.reload" />
|
|
||||||
<EditVbenModal @reload="gridApi.reload" />
|
|
||||||
</Page>
|
|
||||||
</template>
|
|
||||||
<style scoped></style>
|
|
||||||
@ -1,169 +0,0 @@
|
|||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
|
||||||
|
|
||||||
import { computed } from 'vue';
|
|
||||||
|
|
||||||
import { z } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
export const querySchema = computed(() => [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'filter',
|
|
||||||
label: $t('code.projectName'),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const tableSchema: any = computed((): VxeGridProps['columns'] => [
|
|
||||||
{ title: $t('common.seq'), type: 'seq', width: 50 },
|
|
||||||
{ field: 'companyName', title: $t('code.companyName'), minWidth: '150' },
|
|
||||||
{
|
|
||||||
field: 'projectName',
|
|
||||||
title: $t('code.projectName'),
|
|
||||||
minWidth: '150',
|
|
||||||
},
|
|
||||||
|
|
||||||
{ field: 'nameSpace', title: $t('code.namespace'), minWidth: '150' },
|
|
||||||
{
|
|
||||||
field: 'supportTenant',
|
|
||||||
title: $t('code.supportTenant'),
|
|
||||||
minWidth: '150',
|
|
||||||
slots: { default: 'supportTenant' },
|
|
||||||
},
|
|
||||||
{ field: 'remark', title: $t('code.remark'), minWidth: '150' },
|
|
||||||
{
|
|
||||||
field: 'creationTime',
|
|
||||||
title: $t('common.createTime'),
|
|
||||||
minWidth: '150',
|
|
||||||
formatter: ({ cellValue }) => {
|
|
||||||
return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: $t('common.action'),
|
|
||||||
field: 'action',
|
|
||||||
fixed: 'right',
|
|
||||||
width: '250',
|
|
||||||
slots: { default: 'action' },
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const addFormSchema = computed(() => [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
fieldName: 'companyName',
|
|
||||||
label: $t('code.companyName'),
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.companyName'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
fieldName: 'projectName',
|
|
||||||
label: $t('code.projectName'),
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.projectEnglishName'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// component: 'Input',
|
|
||||||
// componentProps: {},
|
|
||||||
// fieldName: 'nameSpace',
|
|
||||||
// label: $t('code.namespace'),
|
|
||||||
// rules: z
|
|
||||||
// .string()
|
|
||||||
// .min(1, { message: $t('common.pleaseInput') + $t('code.namespace') }),
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
component: 'RadioGroup',
|
|
||||||
componentProps: {
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: $t('common.yes'),
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('common.no'),
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
defaultValue: 0,
|
|
||||||
fieldName: 'supportTenant',
|
|
||||||
label: $t('code.supportTenant'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
fieldName: 'remark',
|
|
||||||
label: $t('code.remark'),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const editFormSchema = computed(() => [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
fieldName: 'id',
|
|
||||||
label: 'id',
|
|
||||||
dependencies: {
|
|
||||||
show: () => false,
|
|
||||||
triggerFields: ['id'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
fieldName: 'companyName',
|
|
||||||
label: $t('code.companyName'),
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.companyName'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
fieldName: 'projectName',
|
|
||||||
label: $t('code.projectName'),
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.projectEnglishName'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// component: 'Input',
|
|
||||||
// componentProps: {},
|
|
||||||
// fieldName: 'nameSpace',
|
|
||||||
// label: $t('code.namespace'),
|
|
||||||
// rules: z
|
|
||||||
// .string()
|
|
||||||
// .min(1, { message: $t('common.pleaseInput') + $t('code.namespace') }),
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
component: 'RadioGroup',
|
|
||||||
componentProps: {
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: $t('common.yes'),
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('common.no'),
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
defaultValue: 0,
|
|
||||||
fieldName: 'supportTenant',
|
|
||||||
label: $t('code.supportTenant'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
fieldName: 'remark',
|
|
||||||
label: $t('code.remark'),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import {
|
|
||||||
postTemplatesControlType,
|
|
||||||
postTemplatesCreateDetail,
|
|
||||||
postTemplatesUpdateDetail,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
const emit = defineEmits(['getTreeData']);
|
|
||||||
|
|
||||||
const data = ref<Record<string, any>>({});
|
|
||||||
const controlTypeList = ref<any[]>();
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
commonConfig: {
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
fieldName: 'templateType',
|
|
||||||
label: '类型',
|
|
||||||
componentProps: () => {
|
|
||||||
return {
|
|
||||||
options: [
|
|
||||||
{ label: '文件夹', value: 10 },
|
|
||||||
{ label: '文件', value: 20 },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
fieldName: 'controlType',
|
|
||||||
label: $t('code.templateType'),
|
|
||||||
componentProps: () => {
|
|
||||||
return {
|
|
||||||
options: controlTypeList.value,
|
|
||||||
fieldNames: { label: 'key', value: 'value' },
|
|
||||||
};
|
|
||||||
},
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: ['templateType'],
|
|
||||||
if: (values) => {
|
|
||||||
return values.templateType === 20;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'name',
|
|
||||||
label: $t('code.name'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Textarea',
|
|
||||||
fieldName: 'description',
|
|
||||||
label: $t('code.desc'),
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
showDefaultActions: false,
|
|
||||||
});
|
|
||||||
const getControlTypeList = async () => {
|
|
||||||
const { data = [] } = await postTemplatesControlType();
|
|
||||||
controlTypeList.value = data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onOpenChange: (isOpen: boolean) => {
|
|
||||||
if (isOpen) {
|
|
||||||
data.value = modalApi.getData<Record<string, any>>();
|
|
||||||
getControlTypeList();
|
|
||||||
if (data.value.isEdit) {
|
|
||||||
const { row } = data.value;
|
|
||||||
formApi.setValues({
|
|
||||||
...row,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onConfirm: async () => {
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
const formValues = await formApi.getValues();
|
|
||||||
if (data.value.isEdit) {
|
|
||||||
await postTemplatesUpdateDetail({
|
|
||||||
body: {
|
|
||||||
...formValues,
|
|
||||||
templateId: data.value.templateId,
|
|
||||||
templateDetailId: data.value.templateDetailId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
message.success($t('common.editSuccess'));
|
|
||||||
} else {
|
|
||||||
await postTemplatesCreateDetail({
|
|
||||||
body: {
|
|
||||||
...formValues,
|
|
||||||
templateId: data.value.templateId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
message.success($t('common.addSuccess'));
|
|
||||||
}
|
|
||||||
modalApi.close();
|
|
||||||
emit('getTreeData');
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="data.isEdit ? $t('common.edit') : $t('common.add')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import { postTemplatesCreate } from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
import { addFormSchema } from './schema';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
// 所有表单项共用,可单独在表单内覆盖
|
|
||||||
commonConfig: {
|
|
||||||
// 所有表单项
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showDefaultActions: false,
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: addFormSchema.value,
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onCancel() {
|
|
||||||
modalApi.close();
|
|
||||||
},
|
|
||||||
async onConfirm() {
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
// 获取表单值
|
|
||||||
const values = await formApi.getValues();
|
|
||||||
// 编辑
|
|
||||||
await postTemplatesCreate({ body: { ...values } });
|
|
||||||
message.success($t('common.addSuccess'));
|
|
||||||
emit('reload');
|
|
||||||
modalApi.close();
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="$t('common.add')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal, z } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import { postTemplatesCopy } from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
commonConfig: {
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showDefaultActions: false,
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
fieldName: 'name',
|
|
||||||
label: $t('code.templateName'),
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.templateName'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'remark',
|
|
||||||
label: $t('code.remark'),
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.remark'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = ref<any>();
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onOpenChange: (isOpen: boolean) => {
|
|
||||||
if (isOpen) {
|
|
||||||
data.value = modalApi.getData<Record<string, any>>();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onCancel() {
|
|
||||||
modalApi.close();
|
|
||||||
},
|
|
||||||
async onConfirm() {
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
const values = await formApi.getValues();
|
|
||||||
await postTemplatesCopy({ body: { ...values, id: data.value.id } });
|
|
||||||
message.success($t('common.copySuccess'));
|
|
||||||
emit('reload');
|
|
||||||
modalApi.close();
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal title="复制模板组">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import { postTemplatesUpdate } from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
import { editFormSchema } from './schema';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const data = ref<any>({});
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
// 所有表单项共用,可单独在表单内覆盖
|
|
||||||
commonConfig: {
|
|
||||||
// 所有表单项
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showDefaultActions: false,
|
|
||||||
// 垂直布局,label和input在不同行,值为vertical
|
|
||||||
// 水平布局,label和input在同一行
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: editFormSchema.value,
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onCancel() {
|
|
||||||
modalApi.close();
|
|
||||||
},
|
|
||||||
async onConfirm() {
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
// 获取表单值
|
|
||||||
const values = await formApi.getValues();
|
|
||||||
// 编辑
|
|
||||||
await postTemplatesUpdate({ body: { ...values } });
|
|
||||||
message.success($t('common.editSuccess'));
|
|
||||||
emit('reload');
|
|
||||||
modalApi.close();
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onOpenChange(isOpen: boolean) {
|
|
||||||
if (isOpen) {
|
|
||||||
data.value = modalApi.getData<Record<string, any>>();
|
|
||||||
formApi.setValues(data.value.row);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="$t('common.edit')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,432 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { DataNode, TreeProps } from 'ant-design-vue/es/tree';
|
|
||||||
|
|
||||||
import type { CreateTemplateDetailInput } from '#/api-client/index';
|
|
||||||
|
|
||||||
import { onMounted, ref, watch } from 'vue';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
|
|
||||||
import { useVbenForm, useVbenModal } from '@vben/common-ui';
|
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Dropdown,
|
|
||||||
Input,
|
|
||||||
Menu,
|
|
||||||
message as Message,
|
|
||||||
message,
|
|
||||||
Modal,
|
|
||||||
Spin,
|
|
||||||
Tree,
|
|
||||||
} from 'ant-design-vue';
|
|
||||||
|
|
||||||
import {
|
|
||||||
postTemplatesControlType,
|
|
||||||
postTemplatesCreateDetail,
|
|
||||||
postTemplatesDeleteDetail,
|
|
||||||
postTemplatesTree,
|
|
||||||
postTemplatesUpdateDetailContent,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
|
|
||||||
import AddEditTemplateModal from './AddEditTemplateModal.vue';
|
|
||||||
|
|
||||||
// 定义一个响应式变量,用于存储展开的节点
|
|
||||||
const expandedKeys = ref<(number | string)[]>([]);
|
|
||||||
// 定义一个响应式变量,用于存储搜索框的值
|
|
||||||
const searchValue = ref<string>('');
|
|
||||||
// 定义一个响应式变量,用于控制是否自动展开父节点
|
|
||||||
const autoExpandParent = ref<boolean>(true);
|
|
||||||
// 定义一个响应式变量,用于存储树形数据
|
|
||||||
const gData = ref<Array<DataNode>>([]);
|
|
||||||
// 定义一个响应式的变量,用于存储当前选中的节点的key
|
|
||||||
const currentSelectedKey = ref('');
|
|
||||||
// 定义一个响应式的变量,用于存储当前选中的节点
|
|
||||||
const currentSelectedTreeNode = ref();
|
|
||||||
const codeText = ref();
|
|
||||||
const route = useRoute();
|
|
||||||
|
|
||||||
const contextMenuOptions = [
|
|
||||||
{ label: $t('code.addFolder'), key: 'addFolder' },
|
|
||||||
{ label: $t('code.addFile'), key: 'addfile' },
|
|
||||||
{ label: $t('common.edit'), key: 'edit' },
|
|
||||||
{ label: $t('common.delete'), key: 'delete' },
|
|
||||||
];
|
|
||||||
const loading = ref<boolean>(true);
|
|
||||||
onMounted(() => {
|
|
||||||
getTreeData().then(() => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 定义一个异步函数,用于处理右键菜单的选择
|
|
||||||
const onContextMenuSelect = async (key: string) => {
|
|
||||||
// 根据选择的key值,执行不同的操作
|
|
||||||
switch (key) {
|
|
||||||
case 'addfile': {
|
|
||||||
openCreateDetailModal(key);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 如果选择的key值为add,则打开添加编辑实体模态框
|
|
||||||
case 'addFolder': {
|
|
||||||
openCreateDetailModal(key);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'delete': {
|
|
||||||
Modal.confirm({
|
|
||||||
title: `${$t('common.confirmDelete')}?`,
|
|
||||||
onOk: async () => {
|
|
||||||
const params = {
|
|
||||||
templateId: route.query.templateId as string,
|
|
||||||
templateDetailId: currentSelectedKey.value,
|
|
||||||
};
|
|
||||||
await postTemplatesDeleteDetail({
|
|
||||||
body: params,
|
|
||||||
});
|
|
||||||
Message.success($t('common.success'));
|
|
||||||
currentSelectedKey.value = '';
|
|
||||||
currentSelectedTreeNode.value = null;
|
|
||||||
getTreeData();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
addEditModalApi.setData({
|
|
||||||
isEdit: true,
|
|
||||||
templateId: route.query.templateId as string,
|
|
||||||
templateDetailId: currentSelectedKey.value,
|
|
||||||
row: currentSelectedTreeNode.value,
|
|
||||||
});
|
|
||||||
addEditModalApi.open();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 当右键菜单点击时,执行该函数
|
|
||||||
const onContextMenuClick = (treeKey: string, nodeData: any, menuKey: any) => {
|
|
||||||
// 将当前选中的树节点key赋值给currentSelectedKey
|
|
||||||
currentSelectedKey.value = treeKey;
|
|
||||||
// 将当前选中的树节点数据赋值给currentSelectedTreeNode
|
|
||||||
currentSelectedTreeNode.value = nodeData;
|
|
||||||
// 调用onContextMenuSelect函数,传入menuKey
|
|
||||||
onContextMenuSelect(menuKey);
|
|
||||||
};
|
|
||||||
|
|
||||||
const dataList = ref<DataNode[]>([]);
|
|
||||||
const generateList = (data: TreeProps['treeData']) => {
|
|
||||||
if (!data) return;
|
|
||||||
for (const node of data) {
|
|
||||||
const { key, title, children } = node;
|
|
||||||
dataList.value.push({ key, title });
|
|
||||||
if (children) {
|
|
||||||
generateList(children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getParentKey = (
|
|
||||||
key: number | string,
|
|
||||||
tree: TreeProps['treeData'],
|
|
||||||
): number | string | undefined => {
|
|
||||||
if (!tree) return undefined;
|
|
||||||
let parentKey;
|
|
||||||
for (const node of tree) {
|
|
||||||
if (node.children) {
|
|
||||||
if (node.children.some((item) => item.key === key)) {
|
|
||||||
parentKey = node.key;
|
|
||||||
} else if (getParentKey(key, node.children)) {
|
|
||||||
parentKey = getParentKey(key, node.children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parentKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取所有节点的key
|
|
||||||
const getAllKeys = (tree: TreeProps['treeData']): (number | string)[] => {
|
|
||||||
const keys: (number | string)[] = [];
|
|
||||||
const traverse = (nodes: TreeProps['treeData']) => {
|
|
||||||
if (!nodes) return;
|
|
||||||
nodes.forEach((node) => {
|
|
||||||
if (node.key) {
|
|
||||||
keys.push(node.key);
|
|
||||||
}
|
|
||||||
if (node.children) {
|
|
||||||
traverse(node.children);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
traverse(tree);
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 展开所有节点
|
|
||||||
const expandAll = () => {
|
|
||||||
expandedKeys.value = getAllKeys(gData.value as TreeProps['treeData']);
|
|
||||||
autoExpandParent.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 折叠所有节点
|
|
||||||
const collapseAll = () => {
|
|
||||||
expandedKeys.value = [];
|
|
||||||
autoExpandParent.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 添加 onExpand 方法处理节点展开/折叠
|
|
||||||
const onExpand = (keys: (number | string)[], info: any) => {
|
|
||||||
expandedKeys.value = keys;
|
|
||||||
autoExpandParent.value = false;
|
|
||||||
};
|
|
||||||
// 定义一个响应式变量,用于控制是否是否显示保存按钮
|
|
||||||
const showSaveContentBtn = ref<boolean>(false);
|
|
||||||
const onSelect = (keys: any[], event: any) => {
|
|
||||||
codeText.value = '';
|
|
||||||
showSaveContentBtn.value = false;
|
|
||||||
if (event.node.templateType === 10) return;
|
|
||||||
showSaveContentBtn.value = true;
|
|
||||||
currentSelectedKey.value = keys[0] ?? '';
|
|
||||||
codeText.value = event.node.content || '';
|
|
||||||
if (!keys[0]) return '';
|
|
||||||
};
|
|
||||||
const saveContent = async () => {
|
|
||||||
if (!currentSelectedKey.value) {
|
|
||||||
message.error('请选择节点');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const params = {
|
|
||||||
templateId: route.query.templateId as string,
|
|
||||||
templateDetailId: currentSelectedKey.value,
|
|
||||||
content: codeText.value,
|
|
||||||
};
|
|
||||||
await postTemplatesUpdateDetailContent({ body: params });
|
|
||||||
message.success($t('common.editSuccess'));
|
|
||||||
};
|
|
||||||
async function getTreeData() {
|
|
||||||
const { data = [] } = await postTemplatesTree({
|
|
||||||
body: { templateId: route.query.templateId as string },
|
|
||||||
});
|
|
||||||
gData.value = data as DataNode[];
|
|
||||||
dataList.value = [];
|
|
||||||
generateList(data as TreeProps['treeData']);
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(searchValue, (value) => {
|
|
||||||
if (!value) {
|
|
||||||
expandedKeys.value = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const expanded = dataList.value
|
|
||||||
.map((item) => {
|
|
||||||
if (
|
|
||||||
typeof item.title === 'string' &&
|
|
||||||
item.title.toLowerCase().includes(value.toLowerCase())
|
|
||||||
) {
|
|
||||||
return getParentKey(item.key, gData.value as TreeProps['treeData']);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
})
|
|
||||||
.filter(
|
|
||||||
(item, i, self): item is number | string =>
|
|
||||||
item !== null && item !== undefined && self.indexOf(item) === i,
|
|
||||||
);
|
|
||||||
|
|
||||||
expandedKeys.value = expanded;
|
|
||||||
autoExpandParent.value = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const [AddEditModal, addEditModalApi] = useVbenModal({
|
|
||||||
connectedComponent: AddEditTemplateModal,
|
|
||||||
});
|
|
||||||
|
|
||||||
const openTemplateModal = () => {
|
|
||||||
addEditModalApi.setData({
|
|
||||||
isEdit: false,
|
|
||||||
templateId: route.query.templateId as string,
|
|
||||||
});
|
|
||||||
addEditModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const [CreateDetailModal, createDetailModalApi] = useVbenModal({
|
|
||||||
onOpenChange: (isOpen: boolean) => {
|
|
||||||
if (isOpen) {
|
|
||||||
getControlTypeList();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onConfirm: async () => {
|
|
||||||
try {
|
|
||||||
createDetailModalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
const { valid } = await createDetailFormApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
const formValues = await createDetailFormApi.getValues();
|
|
||||||
let params: CreateTemplateDetailInput = {};
|
|
||||||
if (isFloder.value) {
|
|
||||||
// 创建文件夹
|
|
||||||
params = {
|
|
||||||
...formValues,
|
|
||||||
templateId: route.query.templateId as string,
|
|
||||||
parentId: currentSelectedKey.value,
|
|
||||||
templateType: 10,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// 创建文件
|
|
||||||
params = {
|
|
||||||
...formValues,
|
|
||||||
templateId: route.query.templateId as string,
|
|
||||||
parentId: currentSelectedKey.value,
|
|
||||||
templateType: 20,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
await postTemplatesCreateDetail({ body: params });
|
|
||||||
message.success($t('common.addSuccess'));
|
|
||||||
createDetailModalApi.close();
|
|
||||||
getTreeData();
|
|
||||||
} finally {
|
|
||||||
createDetailModalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const controlTypeList = ref<any[]>();
|
|
||||||
const isFloder = ref<boolean>(false);
|
|
||||||
const getControlTypeList = async () => {
|
|
||||||
const { data = [] } = await postTemplatesControlType();
|
|
||||||
controlTypeList.value = data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const [CreateDetailForm, createDetailFormApi] = useVbenForm({
|
|
||||||
commonConfig: {
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: [
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
fieldName: 'controlType',
|
|
||||||
label: '模板策略',
|
|
||||||
componentProps: () => {
|
|
||||||
return {
|
|
||||||
options: controlTypeList.value,
|
|
||||||
fieldNames: { label: 'key', value: 'value' },
|
|
||||||
};
|
|
||||||
},
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: ['templateType'],
|
|
||||||
if: () => {
|
|
||||||
return !isFloder.value;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'name',
|
|
||||||
label: '名称',
|
|
||||||
rules: 'required',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Textarea',
|
|
||||||
fieldName: 'description',
|
|
||||||
label: '描述',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
showDefaultActions: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const openCreateDetailModal = (key: string) => {
|
|
||||||
isFloder.value = key === 'addFolder';
|
|
||||||
createDetailModalApi.open();
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Spin :spinning="loading" tip="loading...">
|
|
||||||
<div class="m-4 grid min-h-[calc(100vh-120px)] grid-cols-12 gap-4">
|
|
||||||
<div class="bg-card col-span-4 xl:col-span-3">
|
|
||||||
<div class="bg-card flex items-center justify-between p-3">
|
|
||||||
<Button class="mx-3" size="small" type="primary">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<span class="icon-[material-symbols--add-circle-outline]"></span>
|
|
||||||
<span class="ml-1" @click="openTemplateModal">{{
|
|
||||||
$t('common.add')
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
<Input.Search v-model:value="searchValue" class="ml-1 flex-1" />
|
|
||||||
<Dropdown class="ml-1">
|
|
||||||
<Button class="font-bold">......</Button>
|
|
||||||
<template #overlay>
|
|
||||||
<Menu>
|
|
||||||
<Menu.Item @click="expandAll">
|
|
||||||
{{ $t('common.expandAll') }}
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item @click="collapseAll">
|
|
||||||
{{ $t('common.collapseAll') }}
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
</template>
|
|
||||||
</Dropdown>
|
|
||||||
</div>
|
|
||||||
<Tree
|
|
||||||
:auto-expand-parent="autoExpandParent"
|
|
||||||
:block-node="true"
|
|
||||||
:expanded-keys="expandedKeys"
|
|
||||||
:tree-data="gData"
|
|
||||||
class="mt-3"
|
|
||||||
@expand="onExpand"
|
|
||||||
@select="onSelect"
|
|
||||||
>
|
|
||||||
<template #title="{ title, key: treeKey, data: nodeData }">
|
|
||||||
<Dropdown :trigger="['contextmenu']">
|
|
||||||
<span v-if="title.includes(searchValue)" class="block w-full">
|
|
||||||
{{ title.substring(0, title.indexOf(searchValue)) }}
|
|
||||||
<span style="color: #f50">{{ searchValue }}</span>
|
|
||||||
{{
|
|
||||||
title.substring(
|
|
||||||
title.indexOf(searchValue) + searchValue.length,
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
<span v-else class="block w-full">{{ title }}</span>
|
|
||||||
<template #overlay>
|
|
||||||
<Menu
|
|
||||||
@click="
|
|
||||||
({ key: menuKey }) =>
|
|
||||||
onContextMenuClick(treeKey, nodeData, menuKey)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<Menu.Item v-for="item in contextMenuOptions" :key="item.key">
|
|
||||||
{{ item.label }}
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
</template>
|
|
||||||
</Dropdown>
|
|
||||||
</template>
|
|
||||||
</Tree>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-card col-span-8 xl:col-span-9">
|
|
||||||
<div class="bg-card">
|
|
||||||
<Button
|
|
||||||
v-show="showSaveContentBtn"
|
|
||||||
style="margin-left: 96%"
|
|
||||||
type="primary"
|
|
||||||
@click="saveContent"
|
|
||||||
>
|
|
||||||
{{ $t('common.save') }}
|
|
||||||
</Button>
|
|
||||||
<Codemirror v-model:value="codeText" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<AddEditModal @get-tree-data="getTreeData" />
|
|
||||||
<CreateDetailModal :title="$t('common.add')">
|
|
||||||
<CreateDetailForm />
|
|
||||||
</CreateDetailModal>
|
|
||||||
</div>
|
|
||||||
</Spin>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@ -1,212 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type { VbenFormProps } from '#/adapter/form';
|
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
|
||||||
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { Modal } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
||||||
import { postTemplatesDelete, postTemplatesPage } from '#/api-client/index';
|
|
||||||
import { TableAction } from '#/components/table-action';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
// 新增modal
|
|
||||||
import AddModal from './AddModal.vue';
|
|
||||||
import CopyModaComponent from './CopyModal.vue';
|
|
||||||
// 编辑modal
|
|
||||||
import EditModal from './EditModal.vue';
|
|
||||||
import { querySchema, tableSchema } from './schema';
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const formOptions: VbenFormProps = {
|
|
||||||
// 默认展开
|
|
||||||
collapsed: false,
|
|
||||||
schema: querySchema.value,
|
|
||||||
// 控制表单是否显示折叠按钮
|
|
||||||
showCollapseButton: true,
|
|
||||||
// 按下回车时是否提交表单
|
|
||||||
submitOnEnter: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const gridOptions: VxeGridProps<any> = {
|
|
||||||
checkboxConfig: {
|
|
||||||
highlight: true,
|
|
||||||
labelField: 'name',
|
|
||||||
},
|
|
||||||
columns: tableSchema.value,
|
|
||||||
keepSource: true,
|
|
||||||
height: 'auto',
|
|
||||||
pagerConfig: {},
|
|
||||||
toolbarConfig: {
|
|
||||||
custom: true,
|
|
||||||
},
|
|
||||||
customConfig: {
|
|
||||||
storage: true,
|
|
||||||
},
|
|
||||||
proxyConfig: {
|
|
||||||
ajax: {
|
|
||||||
query: async ({ page }, formValues) => {
|
|
||||||
const { data } = await postTemplatesPage({
|
|
||||||
body: {
|
|
||||||
pageIndex: page.currentPage,
|
|
||||||
pageSize: page.pageSize,
|
|
||||||
...formValues,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
|
|
||||||
|
|
||||||
const [AddVbenModal, addModalApi] = useVbenModal({
|
|
||||||
// 连接抽离的组件
|
|
||||||
connectedComponent: AddModal,
|
|
||||||
});
|
|
||||||
const [EditVbenModal, editModalApi] = useVbenModal({
|
|
||||||
// 连接抽离的组件
|
|
||||||
connectedComponent: EditModal,
|
|
||||||
});
|
|
||||||
const handleAdd = () => {
|
|
||||||
addModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEdit = (row: Record<string, any>) => {
|
|
||||||
editModalApi.setData({
|
|
||||||
row,
|
|
||||||
});
|
|
||||||
editModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDelete = (row: any) => {
|
|
||||||
Modal.confirm({
|
|
||||||
title: `${$t('common.confirmDelete')}?`,
|
|
||||||
onOk: async () => {
|
|
||||||
await postTemplatesDelete({
|
|
||||||
body: {
|
|
||||||
id: row.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
gridApi.reload();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const [CopyModal, copyModalApi] = useVbenModal({
|
|
||||||
connectedComponent: CopyModaComponent,
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleCopy = (row: Record<string, any>) => {
|
|
||||||
copyModalApi.setData({
|
|
||||||
id: row.id,
|
|
||||||
});
|
|
||||||
copyModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleViewDetail = (row: Record<string, any>) => {
|
|
||||||
router.push({
|
|
||||||
name: 'TemplateDetail',
|
|
||||||
query: {
|
|
||||||
templateId: row.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Page auto-content-height>
|
|
||||||
<Grid>
|
|
||||||
<template #toolbar-actions>
|
|
||||||
<TableAction
|
|
||||||
:actions="[
|
|
||||||
{
|
|
||||||
label: $t('common.add'),
|
|
||||||
type: 'primary',
|
|
||||||
icon: 'ant-design:plus-outlined',
|
|
||||||
onClick: handleAdd.bind(null),
|
|
||||||
auth: ['AbpCodeManagement.Template.Create'],
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #action="{ row }">
|
|
||||||
<TableAction
|
|
||||||
:actions="[
|
|
||||||
{
|
|
||||||
label: $t('code.detail'),
|
|
||||||
type: 'link',
|
|
||||||
size: 'small',
|
|
||||||
auth: ['AbpCodeManagement.Template.Update'],
|
|
||||||
onClick: handleViewDetail.bind(null, row),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('code.copy'),
|
|
||||||
type: 'link',
|
|
||||||
size: 'small',
|
|
||||||
auth: ['AbpCodeManagement.Template.Copy'],
|
|
||||||
onClick: handleCopy.bind(null, row),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('common.edit'),
|
|
||||||
type: 'link',
|
|
||||||
size: 'small',
|
|
||||||
auth: ['AbpCodeManagement.Template.Copy'],
|
|
||||||
onClick: handleEdit.bind(null, row),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('common.delete'),
|
|
||||||
type: 'link',
|
|
||||||
size: 'small',
|
|
||||||
auth: ['AbpCodeManagement.Template.Delete'],
|
|
||||||
popConfirm: {
|
|
||||||
title: $t('common.askConfirmDelete'),
|
|
||||||
confirm: handleDelete.bind(null, row),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- <Button
|
|
||||||
type="link"
|
|
||||||
v-access:code="'AbpCodeManagement.Template.Update'"
|
|
||||||
@click="handleViewDetail(row)"
|
|
||||||
>
|
|
||||||
{{ $t('code.detail') }}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
v-access:code="'AbpCodeManagement.Template.Copy'"
|
|
||||||
@click="handleCopy(row)"
|
|
||||||
>
|
|
||||||
{{ $t('code.copy') }}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
v-access:code="'AbpCodeManagement.Template.Update'"
|
|
||||||
@click="handleEdit(row)"
|
|
||||||
>
|
|
||||||
{{ $t('common.edit') }}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
danger
|
|
||||||
type="link"
|
|
||||||
v-access:code="'AbpCodeManagement.Template.Delete'"
|
|
||||||
@click="handleDelete(row)"
|
|
||||||
>
|
|
||||||
{{ $t('common.delete') }}
|
|
||||||
</Button> -->
|
|
||||||
</template>
|
|
||||||
</Grid>
|
|
||||||
<AddVbenModal @reload="gridApi.reload" />
|
|
||||||
<EditVbenModal @reload="gridApi.reload" />
|
|
||||||
<CopyModal @reload="gridApi.reload" />
|
|
||||||
</Page>
|
|
||||||
</template>
|
|
||||||
<style scoped></style>
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
|
||||||
|
|
||||||
import { computed } from 'vue';
|
|
||||||
|
|
||||||
import { z } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
export const querySchema = computed(() => [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'filter',
|
|
||||||
label: $t('code.templateName'),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const tableSchema: any = computed((): VxeGridProps['columns'] => [
|
|
||||||
{ title: $t('common.seq'), type: 'seq', width: 50 },
|
|
||||||
{ title: $t('code.templateName'), field: 'name', minWidth: '150' },
|
|
||||||
{ title: $t('code.remark'), field: 'remark', minWidth: '150' },
|
|
||||||
{
|
|
||||||
title: $t('common.action'),
|
|
||||||
field: 'action',
|
|
||||||
fixed: 'right',
|
|
||||||
width: '300',
|
|
||||||
slots: { default: 'action' },
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const addFormSchema = computed(() => [
|
|
||||||
{
|
|
||||||
fieldName: 'name',
|
|
||||||
label: $t('code.templateName'),
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.templateName'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'remark',
|
|
||||||
label: $t('code.remark'),
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.remark'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const editFormSchema = computed(() => [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
fieldName: 'id',
|
|
||||||
label: 'id',
|
|
||||||
dependencies: {
|
|
||||||
show: () => false,
|
|
||||||
triggerFields: ['id'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'name',
|
|
||||||
label: $t('code.templateName'),
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.templateName'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'remark',
|
|
||||||
label: $t('code.remark'),
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
rules: z.string().min(1, {
|
|
||||||
message: $t('common.pleaseInput') + $t('code.remark'),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type { CreateTextTemplateInput } from '#/api-client/index';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import { postTextTemplatesCreate } from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
import { addFormSchema } from './schema';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
// 所有表单项共用,可单独在表单内覆盖
|
|
||||||
commonConfig: {
|
|
||||||
// 所有表单项
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showDefaultActions: false,
|
|
||||||
// 垂直布局,label和input在不同行,值为vertical
|
|
||||||
// 水平布局,label和input在同一行
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: addFormSchema.value,
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onCancel() {
|
|
||||||
modalApi.close();
|
|
||||||
},
|
|
||||||
async onConfirm() {
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
// 获取表单值
|
|
||||||
const values = await formApi.getValues();
|
|
||||||
// 编辑
|
|
||||||
await postTextTemplatesCreate({
|
|
||||||
body: { ...values } as CreateTextTemplateInput,
|
|
||||||
});
|
|
||||||
message.success($t('common.addSuccess'));
|
|
||||||
emit('reload');
|
|
||||||
modalApi.close();
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="$t('common.add')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type { UpdateTextTemplateInput } from '#/api-client/index';
|
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import { postTextTemplatesUpdate } from '#/api-client/index';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
import { editFormSchema } from './schema';
|
|
||||||
|
|
||||||
const emit = defineEmits(['reload']);
|
|
||||||
const data = ref<any>({});
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
// 所有表单项共用,可单独在表单内覆盖
|
|
||||||
commonConfig: {
|
|
||||||
// 所有表单项
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-full',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showDefaultActions: false,
|
|
||||||
// 垂直布局,label和input在不同行,值为vertical
|
|
||||||
// 水平布局,label和input在同一行
|
|
||||||
layout: 'horizontal',
|
|
||||||
schema: editFormSchema.value,
|
|
||||||
wrapperClass: 'grid-cols-1',
|
|
||||||
});
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
onCancel() {
|
|
||||||
modalApi.close();
|
|
||||||
},
|
|
||||||
async onConfirm() {
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
try {
|
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
|
||||||
// 获取表单值
|
|
||||||
const values = await formApi.getValues();
|
|
||||||
// 编辑
|
|
||||||
await postTextTemplatesUpdate({
|
|
||||||
body: { ...values } as UpdateTextTemplateInput,
|
|
||||||
});
|
|
||||||
message.success($t('common.editSuccess'));
|
|
||||||
emit('reload');
|
|
||||||
modalApi.close();
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false, confirmLoading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onOpenChange(isOpen: boolean) {
|
|
||||||
if (isOpen) {
|
|
||||||
data.value = modalApi.getData<Record<string, any>>();
|
|
||||||
formApi.setValues(data.value.row);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Modal :title="$t('common.edit')">
|
|
||||||
<Form />
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
@ -1,176 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type { VbenFormProps } from '#/adapter/form';
|
|
||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
||||||
import {
|
|
||||||
postTextTemplatesDelete,
|
|
||||||
postTextTemplatesExport,
|
|
||||||
postTextTemplatesPage,
|
|
||||||
} from '#/api-client/index';
|
|
||||||
import { TableAction } from '#/components/table-action';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
// 新增modal
|
|
||||||
import AddModal from './AddModal.vue';
|
|
||||||
// 编辑modal
|
|
||||||
import EditModal from './EditModal.vue';
|
|
||||||
import { querySchema, tableSchema } from './schema';
|
|
||||||
|
|
||||||
const formOptions: VbenFormProps = {
|
|
||||||
// 默认展开
|
|
||||||
collapsed: false,
|
|
||||||
schema: querySchema.value,
|
|
||||||
// 控制表单是否显示折叠按钮
|
|
||||||
showCollapseButton: true,
|
|
||||||
// 按下回车时是否提交表单
|
|
||||||
submitOnEnter: false,
|
|
||||||
wrapperClass: 'grid-cols-4',
|
|
||||||
};
|
|
||||||
|
|
||||||
const gridOptions: VxeGridProps<any> = {
|
|
||||||
checkboxConfig: {
|
|
||||||
highlight: true,
|
|
||||||
labelField: 'name',
|
|
||||||
},
|
|
||||||
columns: tableSchema,
|
|
||||||
keepSource: true,
|
|
||||||
height: 'auto',
|
|
||||||
pagerConfig: {},
|
|
||||||
toolbarConfig: {
|
|
||||||
custom: true,
|
|
||||||
},
|
|
||||||
customConfig: {
|
|
||||||
storage: true,
|
|
||||||
},
|
|
||||||
proxyConfig: {
|
|
||||||
ajax: {
|
|
||||||
query: async ({ page }, formValues) => {
|
|
||||||
if (formValues?.time?.length === 2) {
|
|
||||||
formValues = {
|
|
||||||
...formValues,
|
|
||||||
startCreationTime: formValues.time[0],
|
|
||||||
endCreationTime: formValues.time[1],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const { data } = await postTextTemplatesPage({
|
|
||||||
body: {
|
|
||||||
pageIndex: page.currentPage,
|
|
||||||
pageSize: page.pageSize,
|
|
||||||
...formValues,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
|
|
||||||
|
|
||||||
const [AddVbenModal, addModalApi] = useVbenModal({
|
|
||||||
// 连接抽离的组件
|
|
||||||
connectedComponent: AddModal,
|
|
||||||
});
|
|
||||||
const [EditVbenModal, editModalApi] = useVbenModal({
|
|
||||||
// 连接抽离的组件
|
|
||||||
connectedComponent: EditModal,
|
|
||||||
});
|
|
||||||
const handleAdd = () => {
|
|
||||||
addModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEdit = (row: Record<string, any>) => {
|
|
||||||
editModalApi.setData({
|
|
||||||
row,
|
|
||||||
});
|
|
||||||
editModalApi.open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDelete = async (row: any) => {
|
|
||||||
await postTextTemplatesDelete({
|
|
||||||
body: {
|
|
||||||
id: row.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
gridApi.reload();
|
|
||||||
};
|
|
||||||
|
|
||||||
const exportData = async () => {
|
|
||||||
gridApi.setLoading(true);
|
|
||||||
try {
|
|
||||||
const formValues = await gridApi.formApi.getValues();
|
|
||||||
const {
|
|
||||||
pager: { currentPage, pageSize },
|
|
||||||
} = await gridApi.grid.getProxyInfo();
|
|
||||||
const pagination = { pageIndex: currentPage, pageSize };
|
|
||||||
|
|
||||||
const { data } = await postTextTemplatesExport({
|
|
||||||
body: { ...formValues, ...pagination },
|
|
||||||
responseType: 'blob',
|
|
||||||
});
|
|
||||||
|
|
||||||
const url = window.URL.createObjectURL(new Blob([data as Blob]));
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.setAttribute('download', '模板导出.xlsx');
|
|
||||||
document.body.append(link);
|
|
||||||
link.click();
|
|
||||||
link.remove();
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
} finally {
|
|
||||||
gridApi.setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Page auto-content-height>
|
|
||||||
<Grid>
|
|
||||||
<template #toolbar-actions>
|
|
||||||
<TableAction
|
|
||||||
:actions="[
|
|
||||||
{
|
|
||||||
label: $t('common.add'),
|
|
||||||
type: 'primary',
|
|
||||||
icon: 'ant-design:plus-outlined',
|
|
||||||
onClick: handleAdd.bind(null),
|
|
||||||
auth: ['AbpTemplateManagement.Template.Create'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('common.export'),
|
|
||||||
type: 'primary',
|
|
||||||
icon: 'ant-design:download-outlined',
|
|
||||||
onClick: exportData.bind(null),
|
|
||||||
auth: ['AbpTemplateManagement.Template.Export'],
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #action="{ row }">
|
|
||||||
<TableAction
|
|
||||||
:actions="[
|
|
||||||
{
|
|
||||||
label: $t('common.edit'),
|
|
||||||
auth: ['AbpTemplateManagement.Template.Update'],
|
|
||||||
onClick: handleEdit.bind(null, row),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('common.delete'),
|
|
||||||
auth: ['AbpTemplateManagement.Template.Delete'],
|
|
||||||
popConfirm: {
|
|
||||||
title: $t('common.askConfirmDelete'),
|
|
||||||
confirm: handleDelete.bind(null, row),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</Grid>
|
|
||||||
<AddVbenModal @reload="gridApi.reload" />
|
|
||||||
<EditVbenModal @reload="gridApi.reload" />
|
|
||||||
</Page>
|
|
||||||
</template>
|
|
||||||
<style scoped></style>
|
|
||||||
@ -1,155 +0,0 @@
|
|||||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
|
||||||
|
|
||||||
import { computed } from 'vue';
|
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
export const querySchema = computed(() => [
|
|
||||||
// {
|
|
||||||
// component: 'RangePicker',
|
|
||||||
// fieldName: 'time',
|
|
||||||
// label: $t('common.createTime'),
|
|
||||||
// componentProps: {
|
|
||||||
// 'value-format': 'YYYY-MM-DD',
|
|
||||||
// },
|
|
||||||
// defaultValue: [
|
|
||||||
// // 最近7天
|
|
||||||
// dayjs().subtract(7, 'day').format('YYYY-MM-DD'),
|
|
||||||
// dayjs().subtract(-1, 'day').format('YYYY-MM-DD'),
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'name',
|
|
||||||
label: $t('textTemplate.name'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'code',
|
|
||||||
label: $t('textTemplate.code'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'content',
|
|
||||||
label: $t('textTemplate.content'),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const tableSchema: any = computed((): VxeGridProps['columns'] => [
|
|
||||||
{ title: $t('common.seq'), type: 'seq', width: 50 },
|
|
||||||
{
|
|
||||||
title: $t('textTemplate.name'),
|
|
||||||
minWidth: '150',
|
|
||||||
field: 'name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: $t('textTemplate.code'),
|
|
||||||
minWidth: '150',
|
|
||||||
field: 'code',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: $t('textTemplate.content'),
|
|
||||||
minWidth: '150',
|
|
||||||
field: 'content',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: $t('textTemplate.cultureName'),
|
|
||||||
minWidth: '150',
|
|
||||||
field: 'cultureName',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: $t('common.action'),
|
|
||||||
field: 'action',
|
|
||||||
fixed: 'right',
|
|
||||||
width: '150',
|
|
||||||
slots: { default: 'action' },
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const addFormSchema = computed(() => [
|
|
||||||
{
|
|
||||||
fieldName: 'name',
|
|
||||||
label: $t('textTemplate.name'),
|
|
||||||
rules: 'required',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'code',
|
|
||||||
label: $t('textTemplate.code'),
|
|
||||||
rules: 'required',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'content',
|
|
||||||
label: $t('textTemplate.content'),
|
|
||||||
rules: 'required',
|
|
||||||
component: 'Textarea',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'cultureName',
|
|
||||||
label: $t('textTemplate.cultureName'),
|
|
||||||
rules: 'required',
|
|
||||||
component: 'Select',
|
|
||||||
componentProps: {
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: 'en',
|
|
||||||
value: 'en',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '简体中文',
|
|
||||||
value: 'zh-Hans',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const editFormSchema = computed(() => [
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {},
|
|
||||||
fieldName: 'id',
|
|
||||||
label: 'id',
|
|
||||||
dependencies: {
|
|
||||||
show: () => false,
|
|
||||||
triggerFields: ['id'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'name',
|
|
||||||
label: $t('textTemplate.name'),
|
|
||||||
rules: 'required',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'code',
|
|
||||||
label: $t('textTemplate.code'),
|
|
||||||
rules: 'required',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'content',
|
|
||||||
label: $t('textTemplate.content'),
|
|
||||||
rules: 'required',
|
|
||||||
component: 'Textarea',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'cultureName',
|
|
||||||
label: $t('textTemplate.cultureName'),
|
|
||||||
rules: 'required',
|
|
||||||
component: 'Select',
|
|
||||||
componentProps: {
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: 'en',
|
|
||||||
value: 'en',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '简体中文',
|
|
||||||
value: 'zh-Hans',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
Loading…
x
Reference in New Issue
Block a user