@shhhwm/elpis 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc +55 -0
  3. package/README.md +214 -0
  4. package/app/controller/base.js +43 -0
  5. package/app/controller/project.js +72 -0
  6. package/app/controller/view.js +22 -0
  7. package/app/extend/logger.js +43 -0
  8. package/app/middleware/api-params-verify.js +90 -0
  9. package/app/middleware/api-sign-verify.js +33 -0
  10. package/app/middleware/error-handler.js +34 -0
  11. package/app/middleware/project-handler.js +29 -0
  12. package/app/middleware.js +38 -0
  13. package/app/pages/asserts/custom.css +12 -0
  14. package/app/pages/boot.js +50 -0
  15. package/app/pages/common/curl.js +88 -0
  16. package/app/pages/common/utils.js +2 -0
  17. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +20 -0
  18. package/app/pages/dashboard/complex-view/header-view/header-view.vue +127 -0
  19. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +44 -0
  20. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +41 -0
  21. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +137 -0
  22. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
  23. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +102 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +110 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +130 -0
  26. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +129 -0
  27. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +100 -0
  28. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +25 -0
  29. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +124 -0
  30. package/app/pages/dashboard/dashboard.vue +98 -0
  31. package/app/pages/dashboard/entry.dashboard.js +46 -0
  32. package/app/pages/store/index.js +3 -0
  33. package/app/pages/store/menu.js +73 -0
  34. package/app/pages/store/project.js +17 -0
  35. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  36. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  37. package/app/pages/widgets/header-container/header-container.vue +110 -0
  38. package/app/pages/widgets/schema-form/complex-view/input/input.vue +137 -0
  39. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +137 -0
  40. package/app/pages/widgets/schema-form/complex-view/select/select.vue +115 -0
  41. package/app/pages/widgets/schema-form/form-item-config.js +23 -0
  42. package/app/pages/widgets/schema-form/schema-form.vue +132 -0
  43. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +47 -0
  44. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +64 -0
  45. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +41 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +48 -0
  47. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +131 -0
  48. package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
  49. package/app/pages/widgets/schema-table/schema-table.vue +245 -0
  50. package/app/pages/widgets/sider-container/sider-container.vue +30 -0
  51. package/app/public/static/logo.png +0 -0
  52. package/app/public/static/normalize.css +239 -0
  53. package/app/router/project.js +18 -0
  54. package/app/router/view.js +8 -0
  55. package/app/router-schema/project.js +30 -0
  56. package/app/service/base.js +13 -0
  57. package/app/service/project.js +47 -0
  58. package/app/view/entry.tpl +29 -0
  59. package/app/webpack/config/webpack.base.js +266 -0
  60. package/app/webpack/config/webpack.dev.js +62 -0
  61. package/app/webpack/config/webpack.prod.js +112 -0
  62. package/app/webpack/dev.js +54 -0
  63. package/app/webpack/libs/blank.js +1 -0
  64. package/app/webpack/prod.js +23 -0
  65. package/config/config.default.js +3 -0
  66. package/elpis-core/env.js +23 -0
  67. package/elpis-core/index.js +98 -0
  68. package/elpis-core/loader/config.js +83 -0
  69. package/elpis-core/loader/controller.js +75 -0
  70. package/elpis-core/loader/extend.js +63 -0
  71. package/elpis-core/loader/middleware.js +73 -0
  72. package/elpis-core/loader/router-schema.js +54 -0
  73. package/elpis-core/loader/router.js +42 -0
  74. package/elpis-core/loader/service.js +75 -0
  75. package/index.js +38 -0
  76. package/model/index.js +110 -0
  77. package/package.json +104 -0
  78. package/test/controller/project.test.js +216 -0
@@ -0,0 +1,12 @@
1
+ html, body {
2
+ height: 100%;
3
+ }
4
+
5
+ #root {
6
+ height: 100%;
7
+ }
8
+
9
+ input:-webkit-autofill {
10
+ /* 覆盖自动填充背景颜色 */
11
+ -webkit-box-shadow: 0 0 0px 1000px #121212 inset;
12
+ }
@@ -0,0 +1,50 @@
1
+ import { createApp } from "vue";
2
+
3
+ // 引入 elementUI
4
+ import ElementUI from "element-plus";
5
+ import "element-plus/theme-chalk/index.css";
6
+ import "element-plus/theme-chalk/dark/css-vars.css";
7
+
8
+ import "./asserts/custom.css";
9
+
10
+ import pinia from "$elpisStore";
11
+
12
+ import { createRouter, createWebHistory } from "vue-router";
13
+
14
+ /**
15
+ * vue 页面主入口, 用于启动 vue
16
+ * @params pageComponent vue 入口组件
17
+ * @param routes 路由列表
18
+ * @param libs 页面依赖的第三方包
19
+ */
20
+ export default (pageComponent, { routes, libs } = {}) => {
21
+ const app = createApp(pageComponent);
22
+
23
+ // 应用 ElementUI
24
+ app.use(ElementUI);
25
+
26
+ // 引入 pinia
27
+ app.use(pinia);
28
+
29
+ // 引入第三方包
30
+ if (libs && libs.length) {
31
+ for (let i = 0; i < libs.length; ++i) {
32
+ app.use(libs[i]);
33
+ }
34
+ }
35
+
36
+ // 页面路由
37
+ if (routes && routes.length) {
38
+ const router = createRouter({
39
+ history: createWebHistory(), // 采用 history 模式
40
+ routes,
41
+ });
42
+
43
+ app.use(router);
44
+ router.isReady().then(() => {
45
+ app.mount("#root");
46
+ });
47
+ } else {
48
+ app.mount("#root");
49
+ }
50
+ };
@@ -0,0 +1,88 @@
1
+ const md5 = require("md5");
2
+ import { ElMessage } from "element-plus";
3
+
4
+ /**
5
+ * 前端封装的 curl 方法
6
+ * @param options 请求参数
7
+ */
8
+ const curl = ({
9
+ url, // 请求地址
10
+ method = "post", // 请求方法
11
+ headers = {}, // 请求头
12
+ query = {}, // url query
13
+ data = {}, // post body
14
+ responseType = "json", // response data type
15
+ timeout = 60000, // timeout
16
+ errorMessage = "网络异常",
17
+ }) => {
18
+ // 接口签名处理(让接口变动态)
19
+ const signKey = "95da0407-a7e2-2852-715e-2bbf48d89e99";
20
+ const st = Date.now();
21
+
22
+ const dtoHeaders = {
23
+ ...headers,
24
+ s_t: st,
25
+ s_sign: md5(`${signKey}_${st}`),
26
+ };
27
+ if (url.indexOf('/api/proj/') > -1 && window.projKey) {
28
+ dtoHeaders.proj_Key = window.projKey
29
+ }
30
+
31
+ // 构造请求参数(把参数转换为 axios 参数)
32
+ const ajaxStting = {
33
+ url,
34
+ method,
35
+ params: query,
36
+ data,
37
+ responseType,
38
+ timeout,
39
+ headers: dtoHeaders,
40
+ };
41
+
42
+ return axios
43
+ .request(ajaxStting)
44
+ .then((response) => {
45
+ const resData = response.data || {};
46
+
47
+ // 后端API返回格式
48
+ const { success } = resData;
49
+
50
+ // 失败
51
+ if (!success) {
52
+ const { message, code } = resData;
53
+ if (code === 442) {
54
+ ElMessage.error("请求参数异常");
55
+ } else if (code === 445) {
56
+ ElMessage.error("请求不合法");
57
+ } else if (code === 446) {
58
+ ElMessage.error("缺少项目必要参数");
59
+ } else if (code === 50000) {
60
+ ElMessage.error(message);
61
+ } else {
62
+ ElMessage.error(errorMessage);
63
+ }
64
+
65
+ console.error(message);
66
+
67
+ return Promise.resolve({ success, code, message });
68
+ }
69
+
70
+ // 成功
71
+ const { data, metadata } = resData;
72
+ return Promise.resolve({ success, data, metadata });
73
+ })
74
+ .catch((error) => {
75
+ const { message } = error;
76
+
77
+ if (message.match(/timeout/)) {
78
+ return Promise.resolve({
79
+ message: "Request Timeout",
80
+ code: 504,
81
+ });
82
+ }
83
+
84
+ return Promise.resolve(error);
85
+ });
86
+ };
87
+
88
+ export default curl;
@@ -0,0 +1,2 @@
1
+ const utils = {};
2
+ export default utils;
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <el-sub-menu :index="menuItem.key">
3
+ <template #title>{{ menuItem.name }}</template>
4
+ <div :key="item.key" v-for="item in menuItem.subMenu">
5
+ <sub-menu
6
+ v-if="item.subMenu && item.subMenu.length > 0"
7
+ :menu-item="item"
8
+ ></sub-menu>
9
+ <el-menu-item v-else :index="item.key">
10
+ {{ item.name }}
11
+ </el-menu-item>
12
+ </div>
13
+ </el-sub-menu>
14
+ </template>
15
+
16
+ <script setup>
17
+ const { menuItem } = defineProps(['menuItem'])
18
+ </script>
19
+
20
+ <style lang="less" scoped></style>
@@ -0,0 +1,127 @@
1
+ <template>
2
+ <header-container :title="projName">
3
+ <template #menu-content>
4
+ <!-- 根据 menuStore.menuList 渲染 -->
5
+ <el-menu
6
+ :default-active="activeKey"
7
+ :ellipsis="false"
8
+ mode="horizontal"
9
+ @select="onMenuSelect"
10
+ >
11
+ <template v-for="item in menuStore.menuList">
12
+ <sub-menu
13
+ v-if="item.subMenu && item.subMenu.length > 0"
14
+ :menu-item="item"
15
+ ></sub-menu>
16
+ <el-menu-item v-else :index="item.key">
17
+ {{ item.name }}
18
+ </el-menu-item>
19
+ </template>
20
+ </el-menu>
21
+ </template>
22
+ <template #setting-content>
23
+ <!-- 根据 projectStore.projectList 渲染 -->
24
+ <el-dropdown @command="handleProjectCommand">
25
+ <span class="project-list">
26
+ {{ projName }}
27
+ <el-icon v-if="projectStore.projectList.length > 1" class="el-icon--right">
28
+ <ArrowDown />
29
+ </el-icon>
30
+ </span>
31
+ <template v-if="projectStore.projectList.length > 1" #dropdown>
32
+ <el-dropdown-menu>
33
+ <el-dropdown-item
34
+ v-for="item in projectStore.projectList"
35
+ :key="item.key"
36
+ :command="item.key"
37
+ :disabled="item.name === projName"
38
+ >
39
+ {{ item.name }}
40
+ </el-dropdown-item>
41
+ </el-dropdown-menu>
42
+ </template>
43
+ </el-dropdown>
44
+ </template>
45
+ <template #main-content>
46
+ <slot name="main-content"></slot>
47
+ </template>
48
+ </header-container>
49
+ </template>
50
+
51
+ <script setup>
52
+ import { ref, watch, onMounted } from 'vue';
53
+ import { useRoute } from 'vue-router';
54
+ import { ArrowDown} from '@element-plus/icons-vue'
55
+ import HeaderContainer from '$elpisWidgets/header-container/header-container.vue'
56
+ import SubMenu from './complex-view/sub-menu/sub-menu.vue'
57
+ import { useMenuStore } from '$elpisStore/menu.js';
58
+ import { useProjectStore } from '$elpisStore/project.js';
59
+
60
+ const route = useRoute()
61
+ const menuStore = useMenuStore();
62
+ const projectStore = useProjectStore();
63
+
64
+ defineProps({
65
+ projName: String
66
+ })
67
+
68
+ const emit = defineEmits(['menu-select'])
69
+
70
+ const activeKey = ref('');
71
+
72
+ const setActiveKey = function () {
73
+ const menuItem = menuStore.findMenuItem({
74
+ key: 'key',
75
+ value: route.query.key
76
+ })
77
+
78
+ activeKey.value = menuItem?.key;
79
+ }
80
+
81
+ watch(() => route.query.key, () => {
82
+ setActiveKey()
83
+ })
84
+
85
+ watch(() => menuStore.menuList, () => {
86
+ setActiveKey()
87
+ }, { deep: true })
88
+
89
+ onMounted(() => {
90
+ setActiveKey()
91
+ })
92
+
93
+ const onMenuSelect = function (menuKey) {
94
+ const menuItem = menuStore.findMenuItem({
95
+ key: 'key',
96
+ value: menuKey
97
+ })
98
+ emit('menu-select', menuItem)
99
+ }
100
+
101
+ const handleProjectCommand = function (event) {
102
+ const projectItem = projectStore.projectList.find(item => item.key === event)
103
+ if (!projectItem || !projectItem.homePage) {
104
+ return
105
+ }
106
+
107
+ const { origin } = window.location;
108
+ window.location.replace(`${origin}/view/dashboard${projectItem.homePage}`)
109
+ }
110
+
111
+ </script>
112
+
113
+ <style lang="less" scoped>
114
+ .project-list {
115
+ margin-right: 20px;
116
+ cursor: pointer;
117
+ color: var(--el-color-primary);
118
+ display: flex;
119
+ align-items: center;
120
+ outline: none;
121
+ }
122
+
123
+ :deep(.el-menu--horizontal.el-menu) {
124
+ // border-bottom:0
125
+ border-color: #e8e8e8
126
+ }
127
+ </style>
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <iframe :src="path" class="iframe"></iframe>
3
+ </template>
4
+
5
+ <script setup>
6
+ import { ref, watch, onMounted } from 'vue';
7
+ import { useRoute } from 'vue-router';
8
+ import { useMenuStore } from '$elpisStore/menu.js'
9
+
10
+ const route = useRoute();
11
+ const menuStore = useMenuStore();
12
+
13
+ watch([
14
+ () => route.query.key,
15
+ () => route.query.sider_key,
16
+ () => menuStore.menuList,
17
+ ], () => {
18
+ setPath()
19
+ }, { deep: true });
20
+
21
+ onMounted(() => {
22
+ setPath()
23
+ })
24
+
25
+ const path = ref('');
26
+ const setPath = function () {
27
+ const { key, sider_key: siderKey } = route.query;
28
+
29
+ const menuItem = menuStore.findMenuItem({
30
+ key: 'key',
31
+ value: siderKey ?? key
32
+ })
33
+
34
+ path.value = menuItem?.iframeConfig?.path ?? '';
35
+ }
36
+ </script>
37
+
38
+ <style lang="less" scoped>
39
+ .iframe {
40
+ border: 0;
41
+ width: 100%;
42
+ height: 100%;
43
+ }
44
+ </style>
@@ -0,0 +1,41 @@
1
+ <template>
2
+ <el-card class="search-panel">
3
+ <schema-search-bar
4
+ :schema="searchSchema"
5
+ @load="onLoad"
6
+ @search="onSearch"
7
+ @reset="onReset"
8
+ >
9
+ </schema-search-bar>
10
+ </el-card>
11
+ </template>
12
+
13
+ <script setup>
14
+ import { inject } from 'vue';
15
+ import SchemaSearchBar from '$elpisWidgets/schema-search-bar/schema-search-bar.vue';
16
+ const { searchSchema } = inject('schemaViewData');
17
+
18
+ const emit = defineEmits(['search']);
19
+
20
+ const onLoad = (searchValObj) => {
21
+ emit('search', searchValObj);
22
+ }
23
+
24
+ const onSearch = (searchValObj) => {
25
+ emit('search', searchValObj);
26
+ }
27
+
28
+ const onReset = () => {
29
+ emit('search', {});
30
+ }
31
+ </script>
32
+
33
+ <style lang="less" scoped>
34
+ .search-panel {
35
+ margin: 10px 10px 0 10px;
36
+ }
37
+
38
+ :deep(.el-card__body) {
39
+ padding-bottom: 2px;
40
+ }
41
+ </style>
@@ -0,0 +1,137 @@
1
+ <template>
2
+ <el-card class="table-panel">
3
+ <!-- operation-panel -->
4
+ <el-row
5
+ v-if="tableConfig?.headerButtons?.length > 0"
6
+ justify="end"
7
+ class="operation-panel"
8
+ >
9
+ <el-button
10
+ v-for="item in tableConfig.headerButtons"
11
+ v-bind="item"
12
+ @click="operationHandler({ btnConfig: item })"
13
+ > {{ item.label }}</el-button>
14
+ </el-row>
15
+ <!-- schema-table (组件 widget)-->
16
+ <schema-table
17
+ ref="schemaTableRef"
18
+ :schema="tableSchema"
19
+ :api="api"
20
+ :apiParmas="apiParmas"
21
+ :buttons="tableConfig?.rowButtons ?? []"
22
+ @operate="operationHandler"
23
+ ></schema-table>
24
+ </el-card>
25
+ </template>
26
+
27
+ <script setup>
28
+ import { ref, inject } from 'vue';
29
+ import { ElMessageBox, ElNotification } from 'element-plus';
30
+ import $curl from '$elpisCommon/curl.js'
31
+ import SchemaTable from '$elpisWidgets/schema-table/schema-table.vue'
32
+
33
+ const emit = defineEmits(['operate'])
34
+
35
+ const {
36
+ api,
37
+ apiParmas,
38
+ tableSchema,
39
+ tableConfig
40
+ } = inject('schemaViewData');
41
+
42
+ const schemaTableRef = ref(null);
43
+
44
+ const EventHandlerMap = {
45
+ remove: removeData
46
+ }
47
+
48
+ const operationHandler = ({ btnConfig, rowData }) => {
49
+ const { eventKey } = btnConfig;
50
+ if (EventHandlerMap[eventKey]) {
51
+ EventHandlerMap[eventKey]({ btnConfig, rowData })
52
+ } else {
53
+ emit('operate', { btnConfig, rowData })
54
+ }
55
+ }
56
+
57
+ function removeData({ btnConfig, rowData }) {
58
+ const { eventOption } = btnConfig;
59
+
60
+ if (!eventOption?.params) {
61
+ return
62
+ }
63
+
64
+ const { params } = eventOption;
65
+
66
+ const removeKey = Object.keys(params)[0]
67
+
68
+ let removeValue;
69
+ const removeValueList = params[removeKey].split('::');
70
+ if (removeValueList[0] === 'schema' && removeValueList[1]) {
71
+ removeValue = rowData[removeValueList[1]]
72
+ }
73
+
74
+ ElMessageBox.confirm(
75
+ `确认删除 ${removeKey} 为: ${removeValue} 数据?`,
76
+ 'Warning',
77
+ {
78
+ confirmButtonText: '确认',
79
+ cancelButtonText: '取消',
80
+ type: 'warning'
81
+ }
82
+ ).then(async () => {
83
+ schemaTableRef.value.showLoading();
84
+ const res = await $curl({
85
+ method: 'delete',
86
+ url: api.value,
87
+ data: {
88
+ [removeKey]: removeValue
89
+ },
90
+ errorMessage: '删除失败'
91
+ });
92
+ schemaTableRef.value.hideLoading();
93
+
94
+ if (!res || !res.success || !res.data) {
95
+ return
96
+ }
97
+
98
+ ElNotification({
99
+ title: '删除成功',
100
+ message: '删除成功',
101
+ type: 'success'
102
+ })
103
+
104
+ await initTableData();
105
+ })
106
+ }
107
+
108
+ const initTableData = async () => {
109
+ await schemaTableRef.value.initData()
110
+ }
111
+
112
+ const loadTableData = async () => {
113
+ await schemaTableRef.value.loadTableData();
114
+ }
115
+
116
+ defineExpose({
117
+ loadTableData
118
+ })
119
+
120
+ </script>
121
+
122
+ <style lang="less" scoped>
123
+ .table-panel {
124
+ flex: 1;
125
+ margin: 10px;
126
+
127
+ .operation-panel {
128
+ margin-bottom: 10px;
129
+ }
130
+ }
131
+
132
+ :deep(.el-card__body) {
133
+ height: 98%;
134
+ display: flex;
135
+ flex-direction: column;
136
+ }
137
+ </style>
@@ -0,0 +1,23 @@
1
+ import createForm from "./create-form/create-form.vue";
2
+ import editForm from "./edit-form/edit-form.vue";
3
+ import detailPanel from "./detail-panel/detail-panel.vue";
4
+
5
+ // 业务扩展 component 配置
6
+ import BusinessComponentConfig from "$businessComponentConfig";
7
+
8
+ const ComponentConfig = {
9
+ createForm: {
10
+ component: createForm,
11
+ },
12
+ editForm: {
13
+ component: editForm,
14
+ },
15
+ detailPanel: {
16
+ component: detailPanel,
17
+ },
18
+ };
19
+
20
+ export default {
21
+ ...ComponentConfig,
22
+ ...BusinessComponentConfig
23
+ };
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <el-drawer
3
+ v-model="isShow"
4
+ direction="rtl"
5
+ :destroy-on-close="true"
6
+ :size="550"
7
+ >
8
+ <template #header>
9
+ <h3>{{ title }}</h3>
10
+ </template>
11
+ <template #default>
12
+ <schema-form
13
+ ref="schemaFormRef"
14
+ v-loading="loading"
15
+ :schema="components[name]?.schema"
16
+ ></schema-form>
17
+ </template>
18
+ <template #footer>
19
+ <el-button
20
+ type="primary"
21
+ @click="save"
22
+ >{{ saveBtnText }}</el-button>
23
+ </template>
24
+ </el-drawer>
25
+ </template>
26
+
27
+ <script setup>
28
+ import { ref, inject } from 'vue';
29
+ import { ElNotification } from 'element-plus';
30
+ import $curl from '$elpisCommon/curl.js'
31
+ import SchemaForm from '$elpisWidgets/schema-form/schema-form.vue'
32
+
33
+ const {
34
+ api,
35
+ components
36
+ } = inject('schemaViewData');
37
+
38
+ const emit = defineEmits(['command'])
39
+
40
+ const name = ref('createForm');
41
+
42
+ const schemaFormRef = ref(null);
43
+ const isShow = ref(false);
44
+ const loading = ref(false);
45
+ const title = ref('');
46
+ const saveBtnText = ref('');
47
+
48
+ const show = () => {
49
+ const { config } = components.value[name.value]
50
+
51
+ title.value = config.title
52
+ saveBtnText.value = config.saveBtnText
53
+
54
+ isShow.value = true;
55
+ }
56
+
57
+ const close = () => {
58
+ isShow.value = false;
59
+ }
60
+
61
+ const save = async () => {
62
+ if (loading.value) { return };
63
+
64
+ if (!schemaFormRef.value.validate()) { return };
65
+
66
+ loading.value = true;
67
+
68
+ const res = await $curl({
69
+ method: 'post',
70
+ url: api.value,
71
+ data: {
72
+ ...schemaFormRef.value.getValue()
73
+ }
74
+ });
75
+
76
+ loading.value = false;
77
+
78
+ if (!res || !res.success) {
79
+ return
80
+ }
81
+
82
+ ElNotification({
83
+ title: '创建成功',
84
+ message: '创建成功',
85
+ type: 'success'
86
+ });
87
+
88
+ close();
89
+
90
+ emit('command', {
91
+ event: 'loadTableData'
92
+ })
93
+ }
94
+
95
+ defineExpose({
96
+ name,
97
+ show
98
+ });
99
+
100
+ </script>
101
+
102
+ <style lang="less" scoped></style>