iov-pro-components 0.0.3

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 (133) hide show
  1. package/.eslintignore +5 -0
  2. package/.eslintrc.js +192 -0
  3. package/.gitignore +3 -0
  4. package/README.md +4 -0
  5. package/babel.config.js +5 -0
  6. package/docs/.vuepress/config.js +169 -0
  7. package/docs/.vuepress/styles/index.styl +62 -0
  8. package/docs/.vuepress/styles/palette.styl +20 -0
  9. package/docs/.vuepress/theme/enhanceApp.js +100 -0
  10. package/docs/.vuepress/theme/index.js +3 -0
  11. package/docs/README.md +13 -0
  12. package/docs/components/description.md +519 -0
  13. package/docs/components/dialog-select.md +91 -0
  14. package/docs/components/display.md +36 -0
  15. package/docs/components/enums.md +33 -0
  16. package/docs/components/icon.md +406 -0
  17. package/docs/components/link-group.md +39 -0
  18. package/docs/components/page-detail.md +48 -0
  19. package/docs/components/page-module.md +51 -0
  20. package/docs/components/pro-form.md +958 -0
  21. package/docs/components/pro-table.md +683 -0
  22. package/docs/components/request.md +44 -0
  23. package/docs/components/search-table.md +963 -0
  24. package/docs/components/space.md +35 -0
  25. package/docs/components/sub-title.md +24 -0
  26. package/docs/components/submit-module.md +24 -0
  27. package/docs/template/add.md +124 -0
  28. package/docs/template/confirm.md +28 -0
  29. package/docs/template/detail.md +240 -0
  30. package/docs/template/dialog.md +339 -0
  31. package/docs/template/list.md +464 -0
  32. package/docs/template/tabs-mini.md +32 -0
  33. package/docs/template/tabs.md +32 -0
  34. package/jsconfig.json +19 -0
  35. package/lib/iov-pro-components.css +1 -0
  36. package/lib/iov-pro-components.min.js +7 -0
  37. package/lib/postcss.config.js +8 -0
  38. package/package.json +75 -0
  39. package/patches/vue-server-renderer+2.7.16.patch +13 -0
  40. package/rollup.config.mjs +79 -0
  41. package/src/App.vue +103 -0
  42. package/src/main.js +33 -0
  43. package/src/packages/column-tooltip/index.js +7 -0
  44. package/src/packages/column-tooltip/src/main.vue +127 -0
  45. package/src/packages/description/index.js +7 -0
  46. package/src/packages/description/src/main.vue +375 -0
  47. package/src/packages/description/src/text.vue +103 -0
  48. package/src/packages/dialog-select/index.js +7 -0
  49. package/src/packages/dialog-select/src/main.vue +308 -0
  50. package/src/packages/display/index.js +7 -0
  51. package/src/packages/display/src/main.vue +44 -0
  52. package/src/packages/enums/index.js +7 -0
  53. package/src/packages/enums/src/main.vue +23 -0
  54. package/src/packages/export/index.js +7 -0
  55. package/src/packages/export/src/main.vue +316 -0
  56. package/src/packages/fixed-button-group/index.js +7 -0
  57. package/src/packages/fixed-button-group/src/main.vue +104 -0
  58. package/src/packages/form/index.js +7 -0
  59. package/src/packages/form/src/collapse.vue +149 -0
  60. package/src/packages/form/src/main.vue +1190 -0
  61. package/src/packages/form-collapse/index.js +7 -0
  62. package/src/packages/index.js +86 -0
  63. package/src/packages/link-group/index.js +7 -0
  64. package/src/packages/link-group/src/main.vue +52 -0
  65. package/src/packages/page-detail/index.js +7 -0
  66. package/src/packages/page-detail/src/main.vue +123 -0
  67. package/src/packages/page-module/index.js +7 -0
  68. package/src/packages/page-module/src/main.vue +56 -0
  69. package/src/packages/preview/index.js +7 -0
  70. package/src/packages/preview/src/eval-image-viewer.js +50 -0
  71. package/src/packages/preview/src/image-viewer.vue +366 -0
  72. package/src/packages/preview/src/main.vue +97 -0
  73. package/src/packages/request/index.js +7 -0
  74. package/src/packages/request/src/main.vue +125 -0
  75. package/src/packages/search-table/index.js +7 -0
  76. package/src/packages/search-table/src/inner-tabs.vue +237 -0
  77. package/src/packages/search-table/src/main.vue +472 -0
  78. package/src/packages/search-table/src/outer-tabs.vue +45 -0
  79. package/src/packages/search-table-inner-tabs/index.js +7 -0
  80. package/src/packages/search-table-outer-tabs/index.js +7 -0
  81. package/src/packages/space/index.js +7 -0
  82. package/src/packages/space/src/main.vue +74 -0
  83. package/src/packages/sub-title/index.js +7 -0
  84. package/src/packages/sub-title/src/main.vue +70 -0
  85. package/src/packages/submit-module/index.js +7 -0
  86. package/src/packages/submit-module/src/main.vue +67 -0
  87. package/src/packages/table/index.js +7 -0
  88. package/src/packages/table/src/filter.vue +89 -0
  89. package/src/packages/table/src/main.vue +668 -0
  90. package/src/packages/table/src/search.vue +90 -0
  91. package/src/packages/table/src/sort.vue +118 -0
  92. package/src/packages/theme/index.scss +15 -0
  93. package/src/packages/theme/src/column-tooltip.scss +23 -0
  94. package/src/packages/theme/src/common/color.scss +134 -0
  95. package/src/packages/theme/src/description.scss +56 -0
  96. package/src/packages/theme/src/dialog-select.scss +32 -0
  97. package/src/packages/theme/src/fixed-button-group.scss +25 -0
  98. package/src/packages/theme/src/form.scss +11 -0
  99. package/src/packages/theme/src/link-group.scss +43 -0
  100. package/src/packages/theme/src/page-detail.scss +61 -0
  101. package/src/packages/theme/src/page-module.scss +46 -0
  102. package/src/packages/theme/src/preview.scss +67 -0
  103. package/src/packages/theme/src/search-table.scss +185 -0
  104. package/src/packages/theme/src/space.scss +12 -0
  105. package/src/packages/theme/src/sub-title.scss +47 -0
  106. package/src/packages/theme/src/submit-module.scss +13 -0
  107. package/src/packages/theme/src/table.scss +129 -0
  108. package/src/packages/theme/src/toolbar.scss +109 -0
  109. package/src/packages/toolbar/index.js +7 -0
  110. package/src/packages/toolbar/src/main.vue +126 -0
  111. package/src/packages/toolbar/src/setting.vue +217 -0
  112. package/src/packages/toolbar/src/style.vue +68 -0
  113. package/src/packages/toolbar/src/zoom.vue +65 -0
  114. package/src/router.js +83 -0
  115. package/src/utils/config-center.js +218 -0
  116. package/src/utils/function-eval.js +84 -0
  117. package/src/utils/index.js +104 -0
  118. package/src/views/column-tooltip.vue +37 -0
  119. package/src/views/components/OtherSelect.vue +18 -0
  120. package/src/views/description.vue +60 -0
  121. package/src/views/detail.vue +146 -0
  122. package/src/views/directive/number.js +82 -0
  123. package/src/views/enums.vue +22 -0
  124. package/src/views/export.vue +9 -0
  125. package/src/views/form-collapse.vue +185 -0
  126. package/src/views/form.vue +402 -0
  127. package/src/views/link-group.vue +16 -0
  128. package/src/views/preview.vue +33 -0
  129. package/src/views/request.vue +56 -0
  130. package/src/views/search-table.vue +297 -0
  131. package/src/views/table.vue +145 -0
  132. package/src/views/toolbar.vue +30 -0
  133. package/vue.config.js +22 -0
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 执行函数
3
+ * @param {Object | Function} inject 需要注入的属性
4
+ * @time 2024-10-31 15:52:08
5
+ */
6
+ function functionEval(inject = {}) {
7
+ /**
8
+ * 将注入的key转换成value
9
+ * @param {Object} map 映射的数据
10
+ * @param {String} key 当前key
11
+ * @time 2024-11-01 14:52:01
12
+ */
13
+ const injectKeyToValue = map => key => {
14
+ // 如果当前是字符串,则取出原始值
15
+ if (typeof key === 'string') {
16
+ return map[key]
17
+ }
18
+ // 如果当前是对象
19
+ if (key instanceof Object) {
20
+ return '__value' in key ? key.__value : key
21
+ }
22
+ return null
23
+ }
24
+
25
+ /**
26
+ * 返回需要可执行的方法
27
+ * @param {Function} fn 可执行的方法
28
+ * @param {Array} injectKeys 需要注入的属性
29
+ * @time 2024-10-31 15:54:11
30
+ */
31
+ return function(fn) {
32
+ // 转换后的方法
33
+ let evalFn = null
34
+ // 需要注入的属性集合
35
+ let injectValues = []
36
+ // 获取需要注入的属性值
37
+ const injectMaps = inject instanceof Function ? inject() : inject
38
+ // 如果当前是函数
39
+ if (fn instanceof Function) {
40
+ // 重新指向this
41
+ evalFn = fn.bind(null)
42
+ } else if (fn instanceof Object) {
43
+ // 方法需要注入的keys
44
+ const handlerInjectKeys = [...(fn.inject || [])]
45
+ // 如果是可执行的方法
46
+ if (fn.handler instanceof Function) {
47
+ evalFn = fn.handler.bind(null)
48
+ } else if (typeof fn.handler === 'string') {
49
+ evalFn = new Function(
50
+ ...handlerInjectKeys,
51
+ fn.handler
52
+ )
53
+ }
54
+ // 获取需要注入的属性值
55
+ injectValues = handlerInjectKeys.map(injectKeyToValue(injectMaps))
56
+ }
57
+ // 如果有回调方法,则直接执行
58
+ return (...args) => evalFn ? evalFn(...args, ...injectValues) : null
59
+ }
60
+ }
61
+
62
+ /**
63
+ * 是否是可转换的函数
64
+ * @param {Object|Function} 参数说明
65
+ * @param {参数类型} data 参数说明
66
+ * @return {返回类型} data 返回说明
67
+ * @time 2024-11-11 18:04:00
68
+ */
69
+ export const isEvalFunction = fn => {
70
+ // 如果当前不是对象或者函数
71
+ if (!(fn instanceof Object)) {
72
+ return false
73
+ }
74
+ // 如果当前是方法,则认为是可eval的方法
75
+ if (fn instanceof Function) {
76
+ return true
77
+ }
78
+ if (fn.handler instanceof Function && Array.isArray(fn.inject)) {
79
+ return true
80
+ }
81
+ return false
82
+ }
83
+
84
+ export default functionEval
@@ -0,0 +1,104 @@
1
+ import lodashGet from 'lodash/get'
2
+
3
+ /**
4
+ * 转换成大驼峰
5
+ * @param {String} tagName 参数说明
6
+ * @time 2024-10-29 10:33:46
7
+ */
8
+ export const toUpperCamelCase = tagName => {
9
+ // 如果当前是字符串
10
+ if (typeof tagName === 'string') {
11
+ // 首字母大写,并且去掉中划线的格式
12
+ return tagName
13
+ // 首字母大写
14
+ .replace(/\b(\w)/, match => match.toUpperCase())
15
+ // 去掉中划线,并将中划线后的首字母大写
16
+ .replace(/-\w/g, match => match.slice(1).toUpperCase())
17
+ }
18
+ return tagName
19
+ }
20
+
21
+ /**
22
+ * 从子元素中获取组件
23
+ * @param {Array} children 当前孩子节点
24
+ * @param {String} tagName 组件名
25
+ * @time 2024-11-14 14:46:45
26
+ */
27
+ export const getComponentFromChildren = (children, tagName) => {
28
+ // 当前组件
29
+ let component = null
30
+ // 遍历所有子节点
31
+ children.forEach(child => {
32
+ // 如果没找到子节点
33
+ if (!component) {
34
+ // 如果子节点能匹配上
35
+ if (child.$options.name === tagName) {
36
+ component = child
37
+ } else {
38
+ component = getComponentFromChildren(child.$children, tagName)
39
+ }
40
+ }
41
+ })
42
+ return component
43
+ }
44
+
45
+ /**
46
+ * 是否是url链接
47
+ * @param {String} target 需要判断的字符
48
+ * @time 2024-11-19 11:08:26
49
+ */
50
+ export const isUrl = target => {
51
+ // 如果非字符串类型
52
+ if (typeof target !== 'string') {
53
+ return false
54
+ }
55
+ return /^(https?:\/\/)?(www\.)?[a-z0-9.-]+\.[a-z]{2,}(\/[^\s]*)?$/i.test(target.toLowerCase()) || /^(\/[a-zA-Z]:|[a-zA-Z]:\\|\.\/|\.\.\/|\/)[a-zA-Z0-9\-_./\\]*$/.test(target.toLowerCase())
56
+ }
57
+
58
+ /**
59
+ * 是否是base64格式的图片字符串
60
+ * @param {String} target 需要判断的字符
61
+ * @time 2024-12-20 15:55:53
62
+ */
63
+ export const isBase64Image = target => {
64
+ return /^data:image\/.*;base64,/.test(target)
65
+ }
66
+
67
+ /**
68
+ * 生成随机字符串
69
+ * @param {Number} length 随机字符串的长度
70
+ * @time 2024-11-19 11:33:07
71
+ */
72
+ export const randomString = (length = 10) => {
73
+ // 所有字符串
74
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
75
+ // 当前结果
76
+ let result = ''
77
+ // 开始生成
78
+ for (let i = 0; i < length; i++) {
79
+ result += characters.charAt(Math.floor(Math.random() * characters.length))
80
+ }
81
+ return result
82
+ }
83
+
84
+ /**
85
+ * 将列的数据转换到行中
86
+ * @param {Array} cols 当前总数
87
+ * @time 2024-11-21 09:06:39
88
+ */
89
+ export const splitColsToRow = (cols, key = 'span') => {
90
+ // 当前所在的索引
91
+ let index = 0
92
+ // 开始处理数据
93
+ return cols.reduce((memo, col) => {
94
+ // 当前栅格
95
+ const totalSpan = memo[index].reduce((memo, c) => (memo + lodashGet(c, key)), 0)
96
+ // 如果当前栅格大于24,则另起一行
97
+ if (totalSpan + lodashGet(col, key) > 24) {
98
+ memo[++index] = [col]
99
+ } else {
100
+ memo[index].push(col)
101
+ }
102
+ return memo
103
+ }, [[]])
104
+ }
@@ -0,0 +1,37 @@
1
+ <template>
2
+ <div style="width: 50%">
3
+ <iov-pro-column-tooltip
4
+ :data="DATA"
5
+ effect="light"
6
+ placement="top-start"
7
+ overflow="auto"
8
+ />
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ const DATA = [
14
+ 'key1: value1',
15
+ 'key2: value2',
16
+ 'key3: value3',
17
+ 'key4: value4',
18
+ 'key5: value5',
19
+ 'key6: value6',
20
+ 'key7: value7',
21
+ 'key8: value8',
22
+ 'key9: value9',
23
+ 'key10: value10',
24
+ 'key11: value11',
25
+ 'key12: value12',
26
+ 'key13: value13'
27
+ ]
28
+
29
+ export default {
30
+ name: 'ColumnTooltipDemo',
31
+ data() {
32
+ return {
33
+ DATA
34
+ }
35
+ }
36
+ }
37
+ </script>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <el-select :value="value" placeholder="请选择值" @input="val => $emit('input', val)">
3
+ <el-option label="值1" value="1" />
4
+ <el-option label="值2" value="2" />
5
+ </el-select>
6
+ </template>
7
+
8
+ <script>
9
+ export default {
10
+ name: 'OtherSelect',
11
+ props: {
12
+ value: {
13
+ type: String,
14
+ default: ''
15
+ }
16
+ }
17
+ }
18
+ </script>
@@ -0,0 +1,60 @@
1
+ <template>
2
+ <iov-pro-preview>
3
+ <iov-pro-description
4
+ :data-source="dataSource"
5
+ :items="ITEMS"
6
+ >
7
+ <template #instro>
8
+ <div style="color: red;">{{ dataSource.instro }}</div>
9
+ </template>
10
+ </iov-pro-description>
11
+ </iov-pro-preview>
12
+ </template>
13
+
14
+ <script>
15
+ const SEX = [
16
+ { label: '男', value: 1 },
17
+ { label: '女', value: 2 }
18
+ ]
19
+
20
+ const TAGS = [
21
+ { label: '性格好', value: 1, type: 'success' },
22
+ { label: '是个好人', value: 2, type: 'success' },
23
+ { label: '渣男', value: 3, type: 'danger' }
24
+ ]
25
+
26
+ const ITEMS = [
27
+ { label: '姓名', prop: 'name' },
28
+ { label: '性别', prop: 'sex', type: 'enum', enums: SEX },
29
+ { label: '年龄', prop: 'age' },
30
+ { label: '标签', prop: 'tag', type: 'tag', enums: TAGS },
31
+ { label: '简介', value: '查看详情', type: 'link', onClick: { handler: console.log, inject: ['$router'] }},
32
+ { label: '文件', type: 'file', prop: 'file' },
33
+ { label: '附件', type: 'link', prop: 'attachment' },
34
+ { label: '自我介绍', prop: 'instro', type: 'slot', span: 24 }
35
+ ]
36
+
37
+ export default {
38
+ name: 'DescriptionDemo',
39
+ data() {
40
+ return {
41
+ dataSource: {
42
+ name: '张三',
43
+ sex: 1,
44
+ age: 18,
45
+ tag: 1,
46
+ instro: '1111111',
47
+ file: [
48
+ { name: '附件1.jpg', uuid: '1', isPrivate: true, url: 'https://prod-common-public.obs-helf.cucloud.cn/mall/goods/893f1000000000114669556' },
49
+ { name: '附件2.JPG', uuid: '2', isPrivate: false, url: 'https://prod-common-public.obs-helf.cucloud.cn/mall/goods/bcaa1000000000114669571' }
50
+ ],
51
+ attachment: [
52
+ { name: '附件1', icon: 'el-icon-video-camera-solid' },
53
+ { name: '附件2', icon: 'https://pic.rmb.bdstatic.com/bjh/news/8b97506ad15a7a495cefe17a0f7f9abf.gif' }
54
+ ]
55
+ },
56
+ ITEMS
57
+ }
58
+ }
59
+ }
60
+ </script>
@@ -0,0 +1,146 @@
1
+ <template>
2
+ <div class="detail-page-demo">
3
+ <iov-pro-request
4
+ :api="queryPageData"
5
+ :params="params"
6
+ >
7
+ <template #default="{ data, loading }">
8
+ <iov-pro-space
9
+ v-loading.fullscreen.lock="loading"
10
+ element-loading-spinner="page-loading"
11
+ space="10"
12
+ >
13
+ <iov-pro-page-detail
14
+ name="应用详情 - 单点登录"
15
+ icon="1"
16
+ desc="租户ID"
17
+ >
18
+ <iov-pro-description
19
+ :data-source="data"
20
+ :items="DETAIL_ITEMS"
21
+ label-width="180px"
22
+ />
23
+ <el-divider />
24
+ <iov-pro-sub-title
25
+ name="应用列表"
26
+ icon="1"
27
+ />
28
+ <iov-pro-table
29
+ :data-source="data ? data.tableData : []"
30
+ :columns="TABLE_COLUMNS"
31
+ />
32
+ </iov-pro-page-detail>
33
+ <iov-pro-page-module name="基本信息">
34
+ <iov-pro-description
35
+ :data-source="data"
36
+ :items="BASIC_LOGIN_ITEMS"
37
+ label-width="180px"
38
+ />
39
+ </iov-pro-page-module>
40
+ <iov-pro-page-module name="登录信息">
41
+ <iov-pro-description
42
+ :data-source="data"
43
+ :items="SSO_LOGIN_ITEMS"
44
+ label-width="180px"
45
+ />
46
+ </iov-pro-page-module>
47
+ </iov-pro-space>
48
+ </template>
49
+ </iov-pro-request>
50
+ <iov-pro-fixed-button-group height="88">
51
+ <el-button
52
+ size="small"
53
+ round
54
+ >取消</el-button>
55
+ <el-button
56
+ type="primary"
57
+ size="small"
58
+ round
59
+ >确定</el-button>
60
+ </iov-pro-fixed-button-group>
61
+ </div>
62
+ </template>
63
+
64
+ <script>
65
+ const DETAIL_ITEMS = [
66
+ { label: 'clientID', prop: 'clientId' },
67
+ { label: '是否接入单点登录', prop: 'isSso' }
68
+ ]
69
+
70
+ const BASIC_LOGIN_ITEMS = [
71
+ { label: '应用首页地址', prop: 'indexPageUrl' },
72
+ { label: '外部appid', prop: 'openAppKey' },
73
+ { label: '访问令牌有效期(秒)', prop: 'accessTokenTerm' }
74
+ ]
75
+
76
+ // SSO登录配置
77
+ const SSO_LOGIN_ITEMS = [
78
+ { label: '客户端id', prop: 'clientId' },
79
+ { label: '客户端密钥', prop: 'clientSecret' }
80
+ ]
81
+
82
+ const TABLE_COLUMNS = [
83
+ { label: '应用ID', prop: 'appId' },
84
+ { label: '应用名称', prop: 'appName' },
85
+ { label: '是否接入单点登录', prop: 'isSso' },
86
+ { label: '应用首页地址', prop: 'indexPageUrl' }
87
+ ]
88
+
89
+ export default {
90
+ name: 'DetailPageDemo',
91
+ data() {
92
+ return {
93
+ DETAIL_ITEMS,
94
+ BASIC_LOGIN_ITEMS,
95
+ SSO_LOGIN_ITEMS,
96
+ TABLE_COLUMNS,
97
+ params: {
98
+ id: 111111
99
+ }
100
+ }
101
+ },
102
+ methods: {
103
+ queryPageData(params) {
104
+ return new Promise((resolve) => {
105
+ setTimeout(() => {
106
+ console.log('接口请求参数:', params)
107
+ resolve({
108
+ isSso: '是',
109
+ indexPageUrl: 'https://www.baidu.com/',
110
+ openAppKey: 'alll1091899sjj18981',
111
+ accessTokenTerm: '1800',
112
+ clientId: 'i129jk91289837372',
113
+ clientSecret: 'o19276734jdhey78',
114
+ tableData: [
115
+ { appId: 1, appName: '小明', isSso: '是', indexPageUrl: 'https://www.baidu.com/' },
116
+ { appId: 2, appName: '小红', isSso: '否', indexPageUrl: 'https://www.google.com/' },
117
+ { appId: 3, appName: '小明', isSso: '是', indexPageUrl: 'https://www.baidu.com/' },
118
+ { appId: 4, appName: '小红', isSso: '否', indexPageUrl: 'https://www.google.com/' },
119
+ { appId: 5, appName: '小明', isSso: '是', indexPageUrl: 'https://www.baidu.com/' },
120
+ { appId: 6, appName: '小红', isSso: '否', indexPageUrl: 'https://www.google.com/' },
121
+ { appId: 7, appName: '小明', isSso: '是', indexPageUrl: 'https://www.baidu.com/' },
122
+ { appId: 8, appName: '小红', isSso: '否', indexPageUrl: 'https://www.google.com/' },
123
+ { appId: 9, appName: '小明', isSso: '是', indexPageUrl: 'https://www.baidu.com/' },
124
+ { appId: 10, appName: '小红', isSso: '否', indexPageUrl: 'https://www.google.com/' },
125
+ { appId: 11, appName: '小明', isSso: '是', indexPageUrl: 'https://www.baidu.com/' },
126
+ { appId: 12, appName: '小红', isSso: '否', indexPageUrl: 'https://www.google.com/' },
127
+ { appId: 13, appName: '小明', isSso: '是', indexPageUrl: 'https://www.baidu.com/' },
128
+ { appId: 14, appName: '小红', isSso: '否', indexPageUrl: 'https://www.google.com/' },
129
+ { appId: 15, appName: '小明', isSso: '是', indexPageUrl: 'https://www.baidu.com/' },
130
+ { appId: 26, appName: '小红', isSso: '否', indexPageUrl: 'https://www.google.com/' }
131
+ ]
132
+ })
133
+ }, 1000)
134
+ })
135
+ }
136
+ }
137
+ }
138
+ </script>
139
+
140
+ <style lang="scss">
141
+ .detail-page-demo {
142
+ background-color: lightgrey;
143
+ padding: 20px;
144
+ min-height: 600px;
145
+ }
146
+ </style>
@@ -0,0 +1,82 @@
1
+ import Vue from 'vue'
2
+ import lodashGet from 'lodash/get'
3
+
4
+ function checkNumber(el, binding, vnode) {
5
+ const decimals = !isNaN(binding.value) ? binding.value : 2 // 默认小数位数为 2
6
+
7
+ // 构建正则表达式,支持 0 和空值,不允许以 '.' 开头,也不允许多个零开头
8
+ const regex = new RegExp(`^(?!\\.)[0-9]*(\\.\\d{0,${decimals}})?$|^$`)
9
+
10
+ // 获取 el-input 内部的 input 元素
11
+ const input = el.tagName === 'INPUT' ? el : el.querySelector('input')
12
+ if (input) {
13
+ let previousValue = '' // 记录上次合法的值
14
+
15
+ input.addEventListener('input', (event) => {
16
+ let currentValue = input.value
17
+
18
+ // 使用 slice 去除多余的零
19
+ if (/^0[0-9]/.test(currentValue)) {
20
+ currentValue = currentValue.slice(0, 1) // 保留一个零,移除其他零
21
+ }
22
+
23
+ // 防止以小数点开头,例如 ".123" -> "0.123"
24
+ if (/^\./.test(currentValue)) {
25
+ currentValue = '0' + currentValue // 补全为 "0.123"
26
+ }
27
+
28
+ if (+decimals === 0 && /^\d+\.$/.test(currentValue)) {
29
+ currentValue = currentValue.slice(0, -1)
30
+ }
31
+
32
+ // 如果当前值合法,保存为上次合法值
33
+ if (regex.test(currentValue)) {
34
+ previousValue = currentValue
35
+ input.value = previousValue
36
+ } else {
37
+ // 如果不合法,恢复到上次合法值
38
+ const cursorPosition = input.selectionStart - 1 // 获取光标位置
39
+ input.value = previousValue // 恢复到合法值
40
+
41
+ // 修复光标位置
42
+ input.setSelectionRange(cursorPosition, cursorPosition)
43
+
44
+ // 手动触发 input 事件以更新 v-model
45
+ const event = new Event('input', { bubbles: true })
46
+ input.dispatchEvent(event)
47
+ }
48
+ // 如果当前正在合成,则关闭合成方法
49
+ if (lodashGet(vnode, 'componentInstance.isComposing')) {
50
+ // 设置当前未在合成
51
+ vnode.componentInstance.isComposing = false
52
+ vnode.componentInstance.handleInput(event)
53
+ }
54
+ })
55
+ input.addEventListener('blur', () => {
56
+ // 当前输入的值
57
+ const currentValue = input.value
58
+ // 如果当前输入的值以.结尾
59
+ if (/\.$/.test(currentValue)) {
60
+ previousValue = currentValue.slice(0, currentValue.length - 1)
61
+ input.value = previousValue
62
+ // 手动触发 input 事件以更新 v-model
63
+ const event = new Event('input', { bubbles: true })
64
+ input.dispatchEvent(event)
65
+ }
66
+ })
67
+ }
68
+ }
69
+
70
+ // 注册自定义指令
71
+ Vue.directive('number', {
72
+ bind(el, binding, vnode) {
73
+ checkNumber(el, binding, vnode)
74
+ },
75
+ unbind(el) {
76
+ const input = el.tagName === 'INPUT' ? el : el.querySelector('input')
77
+ if (input) {
78
+ input.removeEventListener('input', () => {})
79
+ input.removeEventListener('blur', () => {})
80
+ }
81
+ }
82
+ })
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <iov-pro-enums
3
+ :value="1"
4
+ :enums="ENUMS"
5
+ />
6
+ </template>
7
+
8
+ <script>
9
+ const ENUMS = [
10
+ { label: '男', value: 1 },
11
+ { label: '女', value: 2 }
12
+ ]
13
+
14
+ export default {
15
+ name: 'EnumsDemo',
16
+ data() {
17
+ return {
18
+ ENUMS
19
+ }
20
+ }
21
+ }
22
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <iov-pro-export />
3
+ </template>
4
+
5
+ <script>
6
+ export default {
7
+ name: 'ExportDemo'
8
+ }
9
+ </script>