@xujingquan/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 (90) hide show
  1. package/.browserslistrc +3 -0
  2. package/.eslintignore +4 -0
  3. package/.eslintrc +63 -0
  4. package/.husky/commit-msg +1 -0
  5. package/.husky/pre-commit +1 -0
  6. package/.prettierignore +16 -0
  7. package/.prettierrc +10 -0
  8. package/README.md +248 -0
  9. package/app/controller/base.js +41 -0
  10. package/app/controller/project.js +75 -0
  11. package/app/controller/view.js +28 -0
  12. package/app/extend/logger.js +39 -0
  13. package/app/middleware/api-params-verify.js +90 -0
  14. package/app/middleware/api-sign-veriyf.js +47 -0
  15. package/app/middleware/error-handler.js +33 -0
  16. package/app/middleware/project-handler.js +30 -0
  17. package/app/middleware.js +45 -0
  18. package/app/pages/asserts/custom.css +13 -0
  19. package/app/pages/boot.js +56 -0
  20. package/app/pages/common/api/business-api.js +19 -0
  21. package/app/pages/common/api/project-api.js +27 -0
  22. package/app/pages/common/request.js +119 -0
  23. package/app/pages/common/utils.js +2 -0
  24. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +20 -0
  25. package/app/pages/dashboard/complex-view/header-view/header-view.vue +116 -0
  26. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +44 -0
  27. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +37 -0
  28. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +122 -0
  29. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
  30. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +86 -0
  31. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +82 -0
  32. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +115 -0
  33. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +135 -0
  34. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +93 -0
  35. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
  36. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +115 -0
  37. package/app/pages/dashboard/dashboard.vue +93 -0
  38. package/app/pages/dashboard/entry.dashboard.js +45 -0
  39. package/app/pages/store/index.js +4 -0
  40. package/app/pages/store/menu.js +61 -0
  41. package/app/pages/store/project.js +17 -0
  42. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  43. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  44. package/app/pages/widgets/header-container/header-container.vue +111 -0
  45. package/app/pages/widgets/schema-form/complex-view/input/input.vue +141 -0
  46. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +142 -0
  47. package/app/pages/widgets/schema-form/complex-view/select/select.vue +119 -0
  48. package/app/pages/widgets/schema-form/form-item-config.js +23 -0
  49. package/app/pages/widgets/schema-form/schema-form.vue +130 -0
  50. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +50 -0
  51. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +62 -0
  52. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +40 -0
  53. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +48 -0
  54. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +121 -0
  55. package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
  56. package/app/pages/widgets/schema-table/schema-table.vue +243 -0
  57. package/app/pages/widgets/sider-container/sider-container.vue +26 -0
  58. package/app/public/static/logo.png +0 -0
  59. package/app/public/static/md5.js +950 -0
  60. package/app/public/static/normalize.css +267 -0
  61. package/app/router/project.js +11 -0
  62. package/app/router/view.js +13 -0
  63. package/app/router-schema/project.js +33 -0
  64. package/app/service/base.js +14 -0
  65. package/app/service/project.js +43 -0
  66. package/app/view/entry.tpl +27 -0
  67. package/app/webpack/config/utils.js +49 -0
  68. package/app/webpack/config/webpack-dev.js +55 -0
  69. package/app/webpack/config/webpack-prod.js +192 -0
  70. package/app/webpack/config/webpack.base.js +273 -0
  71. package/app/webpack/dev.js +60 -0
  72. package/app/webpack/libs/blank.js +1 -0
  73. package/app/webpack/prod.js +27 -0
  74. package/babel.config.js +15 -0
  75. package/commitlint.config.js +3 -0
  76. package/config/config.default.js +4 -0
  77. package/elpis-core/env.js +20 -0
  78. package/elpis-core/index.js +86 -0
  79. package/elpis-core/loader/config.js +54 -0
  80. package/elpis-core/loader/controller.js +69 -0
  81. package/elpis-core/loader/extend.js +57 -0
  82. package/elpis-core/loader/middleware.js +66 -0
  83. package/elpis-core/loader/router-schema.js +49 -0
  84. package/elpis-core/loader/router.js +50 -0
  85. package/elpis-core/loader/service.js +69 -0
  86. package/index.js +47 -0
  87. package/jsconfig.json +19 -0
  88. package/model/index.js +103 -0
  89. package/package.json +105 -0
  90. package/test/controller/project.test.js +200 -0
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <header-view :proj-name="projName" @menu-select="onMenuSelect">
3
+ <template #main-content>
4
+ <!-- 路由展示 -->
5
+ <router-view />
6
+ </template>
7
+ </header-view>
8
+ </template>
9
+
10
+ <script setup>
11
+ import HeaderView from './complex-view/header-view/header-view.vue';
12
+
13
+ import { ref, onMounted } from 'vue';
14
+ import { useRoute, useRouter } from 'vue-router';
15
+ import { useMenuStore } from '$elpisStore/menu';
16
+ import { useProjectStore } from '$elpisStore/project';
17
+ import { projectList, project } from '$elpisCommon/api/project-api';
18
+
19
+ const route = useRoute();
20
+ const router = useRouter();
21
+ const menuStore = useMenuStore();
22
+ const projectStore = useProjectStore();
23
+
24
+ const projName = ref('');
25
+
26
+ // 请求 project/list 接口,并记录到 project-store 中
27
+ async function getProjectList() {
28
+ try {
29
+ const params = { proj_key: route.query.proj_key };
30
+ const res = await projectList(params);
31
+ if (!res || !res.success || !res.data) {
32
+ return;
33
+ }
34
+
35
+ projectStore.setProjectList(res.data);
36
+ } finally {
37
+ }
38
+ }
39
+
40
+ // 请求 project 接口,并缓存到 menu-store 中
41
+ async function getProject() {
42
+ try {
43
+ const params = { proj_key: route.query.proj_key };
44
+ const res = await project(params);
45
+ if (!res || !res.success || !res.data) {
46
+ return;
47
+ }
48
+
49
+ const { name, menu } = res.data;
50
+ projName.value = name;
51
+ menuStore.setMenuList(menu);
52
+ } finally {
53
+ }
54
+ }
55
+
56
+ // 点击菜单回调
57
+ const onMenuSelect = function (menuItem) {
58
+ const { moduleType, key, customConfig } = menuItem;
59
+
60
+ // 如果是当前页面,不处理
61
+ if (key === route.query.key) return;
62
+
63
+ const pathMap = {
64
+ sider: '/sider',
65
+ iframe: '/iframe',
66
+ schema: '/schema',
67
+ custom: customConfig?.path,
68
+ };
69
+
70
+ router.push({
71
+ path: `/view/dashboard${pathMap[moduleType]}`,
72
+ query: {
73
+ key,
74
+ proj_key: route.query.proj_key,
75
+ },
76
+ });
77
+ };
78
+
79
+ onMounted(() => {
80
+ getProjectList();
81
+ getProject();
82
+ });
83
+ </script>
84
+
85
+ <style lang="less" scoped>
86
+ :deep(.el-main) {
87
+ padding: 0;
88
+ }
89
+
90
+ :deep(.el-container) {
91
+ height: 100%;
92
+ }
93
+ </style>
@@ -0,0 +1,45 @@
1
+ /**
2
+ * 这个 webpack 打包的入口之一
3
+ * 创建vue实例
4
+ */
5
+
6
+ import boot from '$elpisPages/boot.js';
7
+ import dashboard from './dashboard.vue';
8
+ import businessDashboardRoutreConfig from '$businessDashboardRoutreConfig';
9
+
10
+ const routes = [];
11
+
12
+ // 头部菜单路由
13
+ routes.push({
14
+ path: '/view/dashboard/iframe',
15
+ component: () => import('./complex-view/iframe-view/iframe-view.vue'),
16
+ });
17
+ routes.push({
18
+ path: '/view/dashboard/schema',
19
+ component: () => import('./complex-view/schema-view/schema-view.vue'),
20
+ });
21
+
22
+ const siderRouters = [
23
+ { path: 'iframe', component: () => import('./complex-view/iframe-view/iframe-view.vue') },
24
+ { path: 'schema', component: () => import('./complex-view/schema-view/schema-view.vue') },
25
+ ];
26
+
27
+ // 侧边栏菜单路由
28
+ routes.push({
29
+ path: '/view/dashboard/sider',
30
+ component: () => import('./complex-view/sider-view/sider-view.vue'),
31
+ children: siderRouters,
32
+ });
33
+
34
+ // 支持业务拓展路由
35
+ if (typeof businessDashboardRoutreConfig === 'function') {
36
+ businessDashboardRoutreConfig({ routes, siderRouters });
37
+ }
38
+
39
+ // 侧边栏兜底策略
40
+ routes.push({
41
+ path: '/view/dashboard/sider/:chapters+',
42
+ component: () => import('./complex-view/sider-view/sider-view.vue'),
43
+ });
44
+
45
+ boot(dashboard, { routes });
@@ -0,0 +1,4 @@
1
+ import { createPinia } from 'pinia';
2
+ const pinia = createPinia();
3
+
4
+ export default pinia;
@@ -0,0 +1,61 @@
1
+ import { defineStore } from 'pinia';
2
+ import { ref } from 'vue';
3
+
4
+ export const useMenuStore = defineStore('menu', () => {
5
+ // 菜单列表
6
+ const menuList = ref([]);
7
+
8
+ // 设置菜单列表
9
+ const setMenuList = function (list) {
10
+ menuList.value = list;
11
+ };
12
+
13
+ /**
14
+ * 找出菜单目录
15
+ * @param key 搜索字段
16
+ * @param value 搜索值
17
+ * @param mList 要搜索的菜单列表
18
+ */
19
+ const findMenuItem = function ({ key, value } = {}, mList = menuList.value) {
20
+ for (let i = 0; i < mList.length; i++) {
21
+ const menuItem = mList[i];
22
+ if (!menuItem) continue;
23
+
24
+ const { menuType, moduleType } = menuItem;
25
+
26
+ if (menuItem[key] === value) return menuItem;
27
+
28
+ if (menuType === 'group' && menuItem.subMenu) {
29
+ const mItem = findMenuItem({ key, value }, menuItem.subMenu);
30
+ if (mItem) return mItem;
31
+ }
32
+
33
+ if (moduleType === 'sider' && menuItem.siderConfig?.menu) {
34
+ const mItem = findMenuItem({ key, value }, menuItem.siderConfig.menu);
35
+ if (mItem) return mItem;
36
+ }
37
+ }
38
+ };
39
+
40
+ /**
41
+ * 找出第一个菜单目录
42
+ * @param mList 菜单列表
43
+ * */
44
+ const findFirstMenuItem = function (mList = menuList.value) {
45
+ if (!mList || !mList[0]) return;
46
+
47
+ let firstMenuItem = mList[0];
48
+ if (firstMenuItem.subMenu) {
49
+ firstMenuItem = findFirstMenuItem(firstMenuItem.subMenu);
50
+ }
51
+
52
+ return firstMenuItem;
53
+ };
54
+
55
+ return {
56
+ menuList,
57
+ setMenuList,
58
+ findMenuItem,
59
+ findFirstMenuItem,
60
+ };
61
+ });
@@ -0,0 +1,17 @@
1
+ import { defineStore } from 'pinia';
2
+ import { ref } from 'vue';
3
+
4
+ export const useProjectStore = defineStore('project', () => {
5
+ // 项目列表
6
+ const projectList = ref([]);
7
+
8
+ // 设置项目列表
9
+ const setProjectList = function (list) {
10
+ projectList.value = list;
11
+ };
12
+
13
+ return {
14
+ projectList,
15
+ setProjectList,
16
+ };
17
+ });
@@ -0,0 +1,111 @@
1
+ <template>
2
+ <el-container class="header-container">
3
+ <el-header class="header">
4
+ <el-row type="flex" align="middle" class="header-row">
5
+ <!-- 左上方 title -->
6
+ <el-row type="flex" align="middle" class="title-panel">
7
+ <img src="./asserts/logo.png" class="logo" />
8
+ <el-row class="text">{{ title }}</el-row>
9
+ </el-row>
10
+ <!-- 插槽:菜单区域 -->
11
+ <slot name="menu-content"></slot>
12
+ <!-- 右上方区域 -->
13
+ <el-row type="flex" align="middle" justify="end" class="setting-panel">
14
+ <!-- 插槽:设置区域 -->
15
+ <slot name="setting-content"></slot>
16
+ <img src="./asserts/avatar.png" class="avatar" />
17
+ <el-dropdown @command="handleUserCommand">
18
+ <span class="username">
19
+ {{ userName }}<i class="el-icon-arrow-down el-icon--right"></i>
20
+ </span>
21
+ <template #dropdown>
22
+ <el-dropdown-item command="logout">退出登录</el-dropdown-item>
23
+ </template>
24
+ </el-dropdown>
25
+ </el-row>
26
+ </el-row>
27
+ </el-header>
28
+ <el-main class="main-container">
29
+ <!-- 插槽:核心填充区域 -->
30
+ <slot name="main-content"></slot>
31
+ </el-main>
32
+ </el-container>
33
+ </template>
34
+
35
+ <script setup>
36
+ import { ref } from 'vue';
37
+
38
+ defineProps({
39
+ title: String,
40
+ });
41
+
42
+ const userName = ref('管理员');
43
+
44
+ const handleUserCommand = () => {
45
+ console.log('handleUserCommand');
46
+ };
47
+ </script>
48
+
49
+ <style lang="less" scoped>
50
+ .header-container {
51
+ min-width: 1000px;
52
+ height: 100%;
53
+ overflow: hidden;
54
+
55
+ .header {
56
+ max-height: 120px;
57
+ border-bottom: 1px solid #e8e8e8;
58
+
59
+ &-row {
60
+ height: 60px;
61
+ padding: 0 20px;
62
+
63
+ .title-panel {
64
+ width: 180px;
65
+ min-width: 180px;
66
+
67
+ .logo {
68
+ width: 25px;
69
+ height: 25px;
70
+ margin-right: 10px;
71
+ border-radius: 50%;
72
+ }
73
+
74
+ .text {
75
+ font-weight: 500;
76
+ font-size: 15px;
77
+ }
78
+ }
79
+
80
+ .setting-panel {
81
+ min-width: 180px;
82
+ margin-left: auto;
83
+
84
+ .avatar {
85
+ width: 30px;
86
+ height: 30px;
87
+ margin-right: 12px;
88
+ border-radius: 50%;
89
+ }
90
+
91
+ .username {
92
+ height: 60px;
93
+ font-weight: 500;
94
+ font-size: 16px;
95
+ line-height: 60px;
96
+ outline: none;
97
+ cursor: pointer;
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ .main-container {
104
+ height: 100%;
105
+ }
106
+ }
107
+
108
+ :deep(.el-header) {
109
+ padding: 0;
110
+ }
111
+ </style>
@@ -0,0 +1,141 @@
1
+ <template>
2
+ <el-row type="flex" align="middle" class="form-item">
3
+ <!-- label -->
4
+ <el-row class="item-label" justify="end">
5
+ <el-row v-if="schema?.option?.required" type="flex" class="required">*</el-row>
6
+ {{ schema.label ?? '' }}
7
+ </el-row>
8
+ <!-- value -->
9
+ <el-row class="item-value">
10
+ <el-input
11
+ v-model="dtoValue"
12
+ v-bind="schema.option"
13
+ :placeholder="placeholder"
14
+ class="component"
15
+ :class="validTips ? 'valid-border' : ''"
16
+ @focus="onFocus"
17
+ @blur="onBlur"
18
+ />
19
+ </el-row>
20
+ <!-- 错误信息 -->
21
+ <el-row v-if="validTips" class="valid-tips">{{ validTips }}</el-row>
22
+ </el-row>
23
+ </template>
24
+
25
+ <script setup>
26
+ import { ref, toRefs, watch, inject, onMounted } from 'vue';
27
+
28
+ const ajv = inject('ajv');
29
+
30
+ const props = defineProps({
31
+ schemaKey: String,
32
+ schema: Object,
33
+ model: [Number, String],
34
+ });
35
+
36
+ const { schemaKey, schema } = props;
37
+ const { model } = toRefs(props);
38
+
39
+ const name = ref('input');
40
+ const dtoValue = ref(undefined);
41
+ const placeholder = ref('');
42
+ const validTips = ref(null);
43
+
44
+ const initData = () => {
45
+ dtoValue.value = model.value ?? schema?.option?.default;
46
+ validTips.value = null;
47
+
48
+ const { minLength, maxLength, pattern } = schema;
49
+ const ruleList = [];
50
+ if (schema.option?.placeholder) {
51
+ ruleList.push(schema.option.placeholder);
52
+ }
53
+ if (minLength) {
54
+ ruleList.push(`最小长度: ${minLength}`);
55
+ }
56
+ if (maxLength) {
57
+ ruleList.push(`最大长度: ${maxLength}`);
58
+ }
59
+ if (pattern) {
60
+ ruleList.push(`格式: ${pattern}`);
61
+ }
62
+ placeholder.value = ruleList.join(' | ');
63
+ };
64
+
65
+ onMounted(() => {
66
+ initData();
67
+ });
68
+
69
+ watch(
70
+ [model, schema],
71
+ () => {
72
+ initData();
73
+ },
74
+ { deep: true }
75
+ );
76
+
77
+ const validate = () => {
78
+ validTips.value = null;
79
+ const { type } = schema;
80
+
81
+ // 校验是否必填
82
+ if (schema.option?.required && !dtoValue.value) {
83
+ validTips.value = '不能为空';
84
+ return false;
85
+ }
86
+
87
+ // ajv 校验 schema
88
+ if (dtoValue.value) {
89
+ const validate = ajv.compile(schema);
90
+ const valid = validate(dtoValue.value);
91
+ if (!valid && validate.errors?.[0]) {
92
+ const { keyword, params } = validate.errors[0];
93
+ switch (keyword) {
94
+ case 'type':
95
+ validTips.value = `类型必须为 ${type}`;
96
+ break;
97
+ case 'maxLength':
98
+ validTips.value = `最大长度应为 ${params.limit}`;
99
+ break;
100
+ case 'minLength':
101
+ validTips.value = `最小长度应为 ${params.limit}`;
102
+ break;
103
+ case 'pattern':
104
+ validTips.value = '格式不正确';
105
+ break;
106
+ default:
107
+ console.error(validate.errors[0]);
108
+ validTips.value = '不符合要求';
109
+ break;
110
+ }
111
+ return false;
112
+ }
113
+ }
114
+
115
+ return true;
116
+ };
117
+
118
+ const getValue = () => {
119
+ return dtoValue.value !== undefined
120
+ ? {
121
+ [schemaKey]: dtoValue.value,
122
+ }
123
+ : {};
124
+ };
125
+
126
+ const onFocus = () => {
127
+ validTips.value = null;
128
+ };
129
+
130
+ const onBlur = () => {
131
+ validate();
132
+ };
133
+
134
+ defineExpose({
135
+ name,
136
+ validate,
137
+ getValue,
138
+ });
139
+ </script>
140
+
141
+ <style lang="less" scoped></style>
@@ -0,0 +1,142 @@
1
+ <template>
2
+ <el-row type="flex" align="middle" class="form-item">
3
+ <!-- label -->
4
+ <el-row class="item-label" justify="end">
5
+ <el-row v-if="schema?.option?.required" type="flex" class="required">*</el-row>
6
+ {{ schema.label ?? '' }}
7
+ </el-row>
8
+ <!-- value -->
9
+ <el-row class="item-value">
10
+ <el-input-number
11
+ v-model="dtoValue"
12
+ v-bind="schema.option"
13
+ :controls="false"
14
+ :placeholder="placeholder"
15
+ class="component"
16
+ :class="validTips ? 'valid-border' : ''"
17
+ @focus="onFocus"
18
+ @blur="onBlur"
19
+ />
20
+ </el-row>
21
+ <!-- 错误信息 -->
22
+ <el-row v-if="validTips" class="valid-tips">{{ validTips }}</el-row>
23
+ </el-row>
24
+ </template>
25
+
26
+ <script setup>
27
+ import { ref, toRefs, watch, inject, onMounted } from 'vue';
28
+
29
+ const ajv = inject('ajv');
30
+
31
+ const props = defineProps({
32
+ schemaKey: String,
33
+ schema: Object,
34
+ model: Number,
35
+ });
36
+
37
+ const { schemaKey, schema } = props;
38
+ const { model } = toRefs(props);
39
+
40
+ const name = ref('inputNumber');
41
+ const dtoValue = ref(undefined);
42
+ const placeholder = ref('');
43
+ const validTips = ref(null);
44
+
45
+ const initData = () => {
46
+ dtoValue.value = model.value ?? schema?.option?.default;
47
+ validTips.value = null;
48
+
49
+ const { minium, maximum } = schema;
50
+
51
+ const ruleList = [];
52
+ if (schema.option?.placeholder) {
53
+ ruleList.push(schema.option.placeholder);
54
+ }
55
+ if (minium !== undefined) {
56
+ ruleList.push(`最小值: ${minium}`);
57
+ }
58
+ if (maximum !== undefined) {
59
+ ruleList.push(`最大值: ${maximum}`);
60
+ }
61
+
62
+ placeholder.value = ruleList.join(' | ');
63
+ };
64
+
65
+ onMounted(() => {
66
+ initData();
67
+ });
68
+
69
+ watch(
70
+ [model, schema],
71
+ () => {
72
+ initData();
73
+ },
74
+ { deep: true }
75
+ );
76
+
77
+ const validate = () => {
78
+ validTips.value = null;
79
+ const { type } = schema;
80
+
81
+ // 校验是否必填
82
+ if (schema.option?.required && !dtoValue.value) {
83
+ validTips.value = '不能为空';
84
+ return false;
85
+ }
86
+
87
+ // ajv 校验 schema
88
+ if (dtoValue.value) {
89
+ const validate = ajv.compile(schema);
90
+ const valid = validate(dtoValue.value);
91
+ if (!valid && validate.errors?.[0]) {
92
+ const { keyword, params } = validate.errors[0];
93
+ switch (keyword) {
94
+ case 'type':
95
+ validTips.value = `类型必须为 ${type}`;
96
+ break;
97
+ case 'minium':
98
+ validTips.value = `最小值为 ${params.limit}`;
99
+ break;
100
+ case 'maximum':
101
+ validTips.value = `最大值为 ${params.limit}`;
102
+ break;
103
+ default:
104
+ console.error(validate.errors[0]);
105
+ validTips.value = '不符合要求';
106
+ break;
107
+ }
108
+ return false;
109
+ }
110
+ }
111
+
112
+ return true;
113
+ };
114
+
115
+ const getValue = () => {
116
+ return dtoValue.value !== undefined
117
+ ? {
118
+ [schemaKey]: dtoValue.value,
119
+ }
120
+ : {};
121
+ };
122
+
123
+ const onFocus = () => {
124
+ validTips.value = null;
125
+ };
126
+
127
+ const onBlur = () => {
128
+ validate();
129
+ };
130
+
131
+ defineExpose({
132
+ name,
133
+ validate,
134
+ getValue,
135
+ });
136
+ </script>
137
+
138
+ <style lang="less" scoped>
139
+ :deep(.el-input-number .el-input__inner) {
140
+ text-align: left;
141
+ }
142
+ </style>