@yukihong/schema-admin-x 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 (80) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc +55 -0
  3. package/README.md +208 -0
  4. package/app/controller/base.js +39 -0
  5. package/app/controller/project.js +80 -0
  6. package/app/controller/view.js +20 -0
  7. package/app/extend/logger.js +39 -0
  8. package/app/middleware/api-params-verify.js +79 -0
  9. package/app/middleware/api-sign-verify.js +34 -0
  10. package/app/middleware/error-handler.js +34 -0
  11. package/app/middleware/project-handler.js +27 -0
  12. package/app/middleware.js +40 -0
  13. package/app/pages/asserts/custom.css +13 -0
  14. package/app/pages/boot.js +53 -0
  15. package/app/pages/common/curl.js +91 -0
  16. package/app/pages/common/utils.js +3 -0
  17. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +21 -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 +131 -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 +100 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +106 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +131 -0
  26. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +126 -0
  27. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +102 -0
  28. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +26 -0
  29. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +128 -0
  30. package/app/pages/dashboard/dashboard.vue +99 -0
  31. package/app/pages/dashboard/entry.dashboard.js +44 -0
  32. package/app/pages/store/index.js +4 -0
  33. package/app/pages/store/menu.js +61 -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 +109 -0
  38. package/app/pages/widgets/schema-form/complex-view/input/input.vue +146 -0
  39. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +140 -0
  40. package/app/pages/widgets/schema-form/complex-view/select/select.vue +121 -0
  41. package/app/pages/widgets/schema-form/form-item-config.js +23 -0
  42. package/app/pages/widgets/schema-form/schema-form.vue +131 -0
  43. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +50 -0
  44. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +65 -0
  45. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +44 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +51 -0
  47. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +127 -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 +248 -0
  50. package/app/pages/widgets/sider-container/sider-container.vue +28 -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 +7 -0
  54. package/app/router/view.js +10 -0
  55. package/app/router-schema/project.js +30 -0
  56. package/app/service/base.js +13 -0
  57. package/app/service/project.js +50 -0
  58. package/app/view/entry.tpl +25 -0
  59. package/app/webpack/config/webpack.base.js +213 -0
  60. package/app/webpack/config/webpack.dev.js +61 -0
  61. package/app/webpack/config/webpack.prod.js +124 -0
  62. package/app/webpack/dev.js +63 -0
  63. package/app/webpack/libs/blank.js +1 -0
  64. package/app/webpack/prod.js +19 -0
  65. package/config/config.beta.js +3 -0
  66. package/config/config.default.js +3 -0
  67. package/config/config.prod.js +3 -0
  68. package/elpis-core/env.js +20 -0
  69. package/elpis-core/index.js +99 -0
  70. package/elpis-core/loader/config.js +52 -0
  71. package/elpis-core/loader/controller.js +75 -0
  72. package/elpis-core/loader/extend.js +55 -0
  73. package/elpis-core/loader/middleware.js +64 -0
  74. package/elpis-core/loader/router-schema.js +47 -0
  75. package/elpis-core/loader/router.js +59 -0
  76. package/elpis-core/loader/service.js +75 -0
  77. package/index.js +40 -0
  78. package/model/index.js +102 -0
  79. package/package.json +93 -0
  80. package/test/controller/project.test.js +217 -0
@@ -0,0 +1,53 @@
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
+ * @param pageComponent vue 入口组件
17
+ * @param routes 路由列表
18
+ * @param libs 页面依赖的第三方包
19
+ */
20
+ export default (pageComponent, { routes, libs } = {}) => {
21
+
22
+ const app = createApp(pageComponent);
23
+
24
+ // 应用
25
+ app.use(ElementUI);
26
+
27
+ // 引入 pinia
28
+ app.use(pinia);
29
+
30
+ // 引入第三方包
31
+ if(libs && libs.length) {
32
+ for(let i = 0; i < libs.length; ++i) {
33
+ app.use(libs[i]);
34
+ }
35
+ }
36
+
37
+ // 页面路由
38
+ if( routes && routes.length) {
39
+ const router = createRouter({
40
+ history: createWebHistory(), // 采用 history 模式
41
+ routes
42
+ });
43
+
44
+ app.use(router);
45
+ router.isReady().then(() => {
46
+ app.mount('#root');
47
+ });
48
+ } else {
49
+ app.mount('#root');
50
+ }
51
+
52
+
53
+ }
@@ -0,0 +1,91 @@
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 = 6000, // timeout
16
+ errorMessage = '网络异常'
17
+ }) => {
18
+ // 接口签名处理(让接口变动态)
19
+ const signKey = 'asd23fhakjs25dhaksdh5kjashcjk';
20
+ const st = Date.now();
21
+
22
+ const dtoHeaders = {
23
+ ...headers,
24
+ s_t: st,
25
+ s_sign: md5(`${signKey}_${st}`)
26
+ }
27
+
28
+ if(!url) {
29
+ throw new Error(`$curl 方法缺少参数:url`);
30
+ }
31
+
32
+ if(url.indexOf('/api/proj/') > -1 && window.projKey) {
33
+ dtoHeaders.proj_key = window.projKey;
34
+ }
35
+
36
+ // 构造请求参数(把参数转换为 axios 参数)
37
+ const ajaxStting = {
38
+ url,
39
+ method ,
40
+ params: query,
41
+ data,
42
+ responseType,
43
+ timeout,
44
+ headers: dtoHeaders
45
+ }
46
+
47
+ return axios.request(ajaxStting).then((response) => {
48
+ const resData = response.data || {};
49
+
50
+ // 后端 API 返回格式
51
+ const { success } = resData;
52
+
53
+ // 失败
54
+ if(!success) {
55
+ const { message, code } = resData;
56
+
57
+ if(code === 442) {
58
+ ElMessage.error('请求参数异常');
59
+ } else if(code === 445) {
60
+ ElMessage.error('请求不合法');
61
+ } else if(code === 446) {
62
+ ElMessage.error('缺少项目必要参数');
63
+ }else if(code === 50000) {
64
+ ElMessage.error(message);
65
+ } else{
66
+ ElMessage.error(errorMessage);
67
+ }
68
+
69
+ console.error(message);
70
+
71
+ return Promise.resolve({ success, message, code })
72
+ }
73
+
74
+ // 成功
75
+ const { data, metadata } = resData;
76
+ return Promise.resolve({success, data, metadata});
77
+ }).catch((error) => {
78
+ const {message} = error;
79
+
80
+ if(message.match(/timeout/)) {
81
+ return Promise.resolve({
82
+ message: 'Request Timeout',
83
+ code: 504
84
+ })
85
+ }
86
+
87
+ return Promise.resolve(error);
88
+ });
89
+ }
90
+
91
+ export default curl;
@@ -0,0 +1,3 @@
1
+ const utils = {};
2
+
3
+ export default utils;
@@ -0,0 +1,21 @@
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
+ :menuItem="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>
21
+ </style>
@@ -0,0 +1,127 @@
1
+ <template>
2
+
3
+ <header-container :title="projName">
4
+ <template #menu-content>
5
+ <!-- 根据 menuStore.menuList 渲染 -->
6
+ <el-menu
7
+ :default-active="activeKey"
8
+ :ellipsis="false"
9
+ mode="horizontal"
10
+ @select="onMenuSelect"
11
+ >
12
+ <template v-for="item in menuStore.menuList">
13
+ <sub-menu
14
+ v-if="item.subMenu && item.subMenu.length > 0"
15
+ :menu-item="item"
16
+ ></sub-menu>
17
+ <el-menu-item v-else :index="item.key">
18
+ {{ item.name }}
19
+ </el-menu-item>
20
+ </template>
21
+ </el-menu>
22
+
23
+ </template>
24
+ <template #setting-content>
25
+ <!-- 根据 projectStore.projectList 渲染 -->
26
+ <el-dropdown @command="handleProjectCommand">
27
+ <span class="project-list">
28
+ {{projName}}
29
+ <el-icon v-if="projectStore.projectList.length > 1" class="el-icon--right">
30
+ <ArrowDown></ArrowDown>
31
+ </el-icon>
32
+ </span>
33
+ <template v-if="projectStore.projectList.length > 1" #dropdown>
34
+ <el-dropdown-menu>
35
+ <el-dropdown-item
36
+ v-for="item in projectStore.projectList"
37
+ :key="item.key"
38
+ :command="item.key"
39
+ :disabled="item.name === projName"
40
+ >
41
+ {{ item.name}}
42
+ </el-dropdown-item>
43
+ </el-dropdown-menu>
44
+ </template>
45
+ </el-dropdown>
46
+ </template>
47
+ <template #main-content>
48
+ <slot name="main-content"></slot>
49
+ </template>
50
+ </header-container>
51
+
52
+ </template>
53
+
54
+ <script setup>
55
+ import { ref, watch, onMounted } from 'vue';
56
+ import { useRoute } from 'vue-router';
57
+ import { ArrowDown } from '@element-plus/icons-vue';
58
+ import HeaderContainer from '$elpisWidgets/header-container/header-container.vue'
59
+ import SubMenu from './complex-view/sub-menu/sub-menu.vue'
60
+ import { useMenuStore } from '$elpisStore/menu';
61
+ import { useProjectStore } from '$elpisStore/project';
62
+
63
+ const route = useRoute();
64
+ const menuStore = useMenuStore();
65
+ const projectStore = useProjectStore();
66
+
67
+ defineProps({
68
+ projName: String
69
+ });
70
+
71
+ const emit = defineEmits(['menu-select']);
72
+
73
+ const activeKey = ref('');
74
+
75
+ const setActiveKey = function() {
76
+ const menuItem = menuStore.findMenuItem({
77
+ key: 'key',
78
+ value: route.query.key
79
+ });
80
+ activeKey.value = menuItem?.key;
81
+ }
82
+
83
+ watch(() => route.query.key, () => {
84
+ setActiveKey();
85
+ })
86
+
87
+ watch(() => menuStore.menuList, () => {
88
+ setActiveKey();
89
+ }, { deep: true})
90
+
91
+ onMounted(() => {
92
+ setActiveKey();
93
+ });
94
+
95
+ const onMenuSelect = function (menuKey) {
96
+ const menuItem = menuStore.findMenuItem({
97
+ key: 'key',
98
+ value: menuKey
99
+ });
100
+ emit('menu-select', menuItem);
101
+ }
102
+
103
+ const handleProjectCommand = function (event) {
104
+ const projectItem = projectStore.projectList.find(item => item.key === event);
105
+ if(!projectItem || !projectItem.homePage) { return; }
106
+ const { host } = window.location;
107
+ console.log(`http://${host}/view/ddashboard${projectItem.homePage}`)
108
+ window.location.replace(`http://${host}/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-item) {
124
+ // border-bottom: 0;
125
+ // border-color: #fff;
126
+ }
127
+ </style>
@@ -0,0 +1,44 @@
1
+ <template>
2
+
3
+ <iframe :src="path" class="iframe"></iframe>
4
+ </template>
5
+
6
+ <script setup>
7
+ import { ref, watch, onMounted } from 'vue';
8
+ import { useRoute } from 'vue-router';
9
+ import { useMenuStore } from '$elpisStore/menu.js';
10
+
11
+ const route = useRoute();
12
+ const menuStore = useMenuStore();
13
+
14
+ const path = ref('');
15
+ const setPath = function () {
16
+ const { key, sider_key: siderKey } = route.query;
17
+ const menuItem = menuStore.findMenuItem({
18
+ key: 'key',
19
+ value: siderKey ?? key
20
+ });
21
+ path.value = menuItem?.iframeConfig?.path ?? '';
22
+ }
23
+
24
+ watch([
25
+ () => route.query.key,
26
+ () => route.query.sider_key,
27
+ () => menuStore.menuList
28
+ ], () => {
29
+ setPath();
30
+ }, { deep: true});
31
+
32
+ onMounted(() => {
33
+ setPath();
34
+ });
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
+ ></schema-search-bar>
9
+ </el-card>
10
+ </template>
11
+
12
+ <script setup>
13
+ import { inject } from 'vue';
14
+ import SchemaSearchBar from '$elpisWidgets/schema-search-bar/schema-search-bar.vue';
15
+ const { searchSchema } = inject('schemaViewData');
16
+
17
+ const emit = defineEmits(['search']);
18
+
19
+ const onLoad = (searchValObj) => {
20
+ emit('search', searchValObj);
21
+ }
22
+ const onSearch = (searchValObj) => {
23
+ emit('search', searchValObj);
24
+
25
+ }
26
+ const onReset = () => {
27
+ emit('search', {});
28
+
29
+ }
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,131 @@
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 (组件 widdget) -->
16
+ <schema-table
17
+ ref="schemaTableRef"
18
+ :schema="tableSchema"
19
+ :api="api"
20
+ :apiParams="apiParams"
21
+ :buttons="tableConfig?.rowButtons ?? []"
22
+ @operate="operationHandler"
23
+ ></schema-table>
24
+
25
+ </el-card>
26
+ </template>
27
+
28
+ <script setup>
29
+ import { ref, inject } from 'vue';
30
+ import { ElMessageBox, ElNotification } from 'element-plus';
31
+ import $curl from '$elpisCommon/curl.js';
32
+ import SchemaTable from '$elpisWidgets/schema-table/schema-table.vue';
33
+
34
+ const emit = defineEmits(['operate']);
35
+
36
+ const {
37
+ api,
38
+ apiParams,
39
+ tableSchema,
40
+ tableConfig
41
+ } = inject('schemaViewData');
42
+
43
+ const schemaTableRef = ref(null);
44
+
45
+ const EventHandlerMap = {
46
+ remove: removeData
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
+ function removeData({ btnConfig, rowData }) {
57
+ const { eventOption } = btnConfig;
58
+ if(!eventOption?.params) { return; }
59
+
60
+ const { params } = eventOption;
61
+
62
+ const removeKey = Object.keys(params)[0];
63
+ let removeValue;
64
+ const removeValueList = params[removeKey].split('::');
65
+ console.log('removeValueList',removeValueList)
66
+ if(removeValueList[0] === 'schema' && removeValueList[1]) {
67
+ removeValue = rowData[removeValueList[1]];
68
+ }
69
+ ElMessageBox.confirm(
70
+ `确认删除${removeKey}为:${removeValue}的数据?`,
71
+ 'Warning',
72
+ {
73
+ confirmButtonText: '确认',
74
+ cancelButtonText: '取消',
75
+ type: 'warning'
76
+ }
77
+ ).then(async () => {
78
+ schemaTableRef.value.showLoading();
79
+ const res = await $curl({
80
+ method: 'delete',
81
+ url: api.value,
82
+ data: {
83
+ [removeKey]: removeValue
84
+ },
85
+ errorMessage: '删除失败'
86
+ });
87
+ schemaTableRef.value.hideLoading();
88
+
89
+ if(!res || !res.success || !res.data) {
90
+ return;
91
+ }
92
+ ElNotification({
93
+ title: '删除成功',
94
+ message: '删除成功',
95
+ type: 'success'
96
+ });
97
+
98
+ await initTableData();
99
+ });
100
+ }
101
+
102
+ const initTableData = async () => {
103
+ await schemaTableRef.value.initData();
104
+ }
105
+
106
+ const loadTableData = async () => {
107
+ await schemaTableRef.value.loadTableData();
108
+ }
109
+
110
+ defineExpose({
111
+ loadTableData
112
+ })
113
+
114
+ </script>
115
+
116
+ <style lang="less" scoped>
117
+ .table-panel {
118
+ flex: 1;
119
+ margin: 10px;
120
+
121
+ .operation-panel {
122
+ margin-bottom: 10px;
123
+ }
124
+ }
125
+
126
+ :deep(.el-card__body) {
127
+ height: 98%;
128
+ display: flex;
129
+ flex-direction: column;
130
+ }
131
+ </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,100 @@
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
+ <h4>{{title}}</h4>
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
+ title.value = config.title;
51
+ saveBtnText.value = config.saveBtnText;
52
+ isShow.value = true;
53
+ }
54
+
55
+ const close = () => {
56
+ isShow.value = false;
57
+ }
58
+
59
+ const save = async () => {
60
+ if(loading.value) { return; }
61
+
62
+ if(!schemaFormRef.value.validate()) { return ; }
63
+
64
+ loading.value = true;
65
+
66
+ const res = await $curl({
67
+ method: 'post',
68
+ url: api.value,
69
+ data: {
70
+ ...schemaFormRef.value.getValue()
71
+ }
72
+ });
73
+
74
+ loading.value = false;
75
+
76
+ if(!res || !res.success) {
77
+ return;
78
+ }
79
+ ElNotification({
80
+ title: '创建成功',
81
+ message: '创建成功',
82
+ type: 'success'
83
+ });
84
+
85
+ close();
86
+
87
+ emit('command', {
88
+ event: 'loadTableData'
89
+ });
90
+ }
91
+
92
+ defineExpose({
93
+ name,
94
+ show
95
+ });
96
+
97
+ </script>
98
+
99
+ <style lang="less" scoped>
100
+ </style>