oxy-uni-ui 1.1.0 → 1.2.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 (123) hide show
  1. package/attributes.json +1 -1
  2. package/components/common/abstracts/variable.scss +59 -1
  3. package/components/common/path.ts +9 -0
  4. package/components/common/util.ts +42 -0
  5. package/components/composables/index.ts +1 -0
  6. package/components/composables/useGlobalLoading.ts +42 -0
  7. package/components/composables/useGlobalMessage.ts +48 -0
  8. package/components/composables/useGlobalToast.ts +84 -0
  9. package/components/composables/useVirtualScroll.ts +173 -0
  10. package/components/oxy-cell/oxy-cell.vue +15 -2
  11. package/components/oxy-cell/types.ts +4 -0
  12. package/components/oxy-checkbox/index.scss +1 -1
  13. package/components/oxy-checkbox/oxy-checkbox.vue +2 -2
  14. package/components/oxy-col-picker/oxy-col-picker.vue +3 -0
  15. package/components/oxy-col-picker/types.ts +5 -1
  16. package/components/oxy-corner/index.scss +121 -1
  17. package/components/oxy-corner/oxy-corner.vue +18 -5
  18. package/components/oxy-corner/types.ts +24 -3
  19. package/components/oxy-date-strip/index.scss +10 -0
  20. package/components/oxy-date-strip/oxy-date-strip.vue +198 -0
  21. package/components/oxy-date-strip/types.ts +98 -0
  22. package/components/oxy-date-strip/utils.ts +67 -0
  23. package/components/oxy-date-strip-item/index.scss +94 -0
  24. package/components/oxy-date-strip-item/oxy-date-strip-item.vue +102 -0
  25. package/components/oxy-date-strip-item/types.ts +53 -0
  26. package/components/oxy-datetime-picker/oxy-datetime-picker.vue +3 -1
  27. package/components/oxy-datetime-picker/types.ts +5 -1
  28. package/components/oxy-echarts/index.scss +17 -0
  29. package/components/oxy-echarts/index.ts +1 -0
  30. package/components/oxy-echarts/oxy-echarts.vue +32 -0
  31. package/components/oxy-echarts/types.ts +12 -0
  32. package/components/oxy-file-list/index.scss +26 -0
  33. package/components/oxy-file-list/oxy-file-list.vue +208 -34
  34. package/components/oxy-file-list/types.ts +58 -2
  35. package/components/oxy-global-loading/oxy-global-loading.vue +53 -0
  36. package/components/oxy-global-message/oxy-global-message.vue +64 -0
  37. package/components/oxy-global-toast/oxy-global-toast.vue +53 -0
  38. package/components/oxy-img-lazy/index.scss +17 -0
  39. package/components/oxy-img-lazy/oxy-img-lazy.vue +332 -0
  40. package/components/oxy-img-lazy/types.ts +69 -0
  41. package/components/oxy-link/index.scss +57 -0
  42. package/components/oxy-link/oxy-link.vue +130 -0
  43. package/components/oxy-link/types.ts +81 -0
  44. package/components/oxy-list/index.scss +8 -1
  45. package/components/oxy-list/oxy-list.vue +121 -40
  46. package/components/oxy-list/types.ts +3 -15
  47. package/components/oxy-picker/oxy-picker.vue +3 -0
  48. package/components/oxy-picker/types.ts +5 -1
  49. package/components/oxy-radio/index.scss +3 -3
  50. package/components/oxy-radio/oxy-radio.vue +1 -1
  51. package/components/oxy-rich-text/icon/emjio.svg +1 -0
  52. package/components/oxy-rich-text/icon/quote.svg +1 -0
  53. package/components/oxy-rich-text/icon/text.svg +1 -0
  54. package/components/oxy-rich-text/icon/title.svg +1 -0
  55. package/components/oxy-rich-text/index.scss +159 -0
  56. package/components/oxy-rich-text/mp-html/card/card.vue +122 -0
  57. package/components/oxy-rich-text/mp-html/card/index.js +7 -0
  58. package/components/oxy-rich-text/mp-html/editable/config.js +15 -0
  59. package/components/oxy-rich-text/mp-html/editable/index.js +553 -0
  60. package/components/oxy-rich-text/mp-html/emoji/index.js +203 -0
  61. package/components/oxy-rich-text/mp-html/highlight/config.js +5 -0
  62. package/components/oxy-rich-text/mp-html/highlight/index.js +96 -0
  63. package/components/oxy-rich-text/mp-html/highlight/prism.css +1 -0
  64. package/components/oxy-rich-text/mp-html/highlight/prism.min.js +7 -0
  65. package/components/oxy-rich-text/mp-html/img-cache/index.js +138 -0
  66. package/components/oxy-rich-text/mp-html/latex/index.js +80 -0
  67. package/components/oxy-rich-text/mp-html/latex/katex.css +1 -0
  68. package/components/oxy-rich-text/mp-html/latex/katex.min.js +1 -0
  69. package/components/oxy-rich-text/mp-html/markdown/index.js +50 -0
  70. package/components/oxy-rich-text/mp-html/markdown/marked.min.js +71 -0
  71. package/components/oxy-rich-text/mp-html/mp-html.d.ts +184 -0
  72. package/components/oxy-rich-text/mp-html/mp-html.vue +675 -0
  73. package/components/oxy-rich-text/mp-html/node/node.vue +1161 -0
  74. package/components/oxy-rich-text/mp-html/parser.js +1428 -0
  75. package/components/oxy-rich-text/mp-html/search/index.js +132 -0
  76. package/components/oxy-rich-text/mp-html/style/index.js +129 -0
  77. package/components/oxy-rich-text/mp-html/style/parser.js +175 -0
  78. package/components/oxy-rich-text/mp-html/template/index.js +67 -0
  79. package/components/oxy-rich-text/mp-html/txv-video/index.js +46 -0
  80. package/components/oxy-rich-text/oxy-rich-text.vue +642 -0
  81. package/components/oxy-rich-text/types.ts +71 -0
  82. package/components/oxy-select/index.scss +255 -0
  83. package/components/oxy-select/oxy-select.vue +421 -0
  84. package/components/oxy-select/types.ts +71 -0
  85. package/components/oxy-select-picker/oxy-select-picker.vue +3 -0
  86. package/components/oxy-select-picker/types.ts +5 -1
  87. package/components/oxy-stream-render/index.scss +6 -0
  88. package/components/oxy-stream-render/oxy-stream-render.vue +204 -0
  89. package/components/oxy-stream-render/types.ts +5 -0
  90. package/components/oxy-tree/index.scss +43 -5
  91. package/components/oxy-tree/oxy-tree.vue +233 -35
  92. package/components/oxy-tree/types.ts +54 -7
  93. package/components/oxy-tree/utils.ts +51 -0
  94. package/components/oxy-virtual-scroll/index.scss +1 -1
  95. package/components/oxy-virtual-scroll/oxy-virtual-scroll.vue +69 -110
  96. package/components/oxy-virtual-scroll/types.ts +95 -5
  97. package/components/oxy-waterfall/index.scss +18 -0
  98. package/components/oxy-waterfall/oxy-waterfall.vue +218 -0
  99. package/components/oxy-waterfall/types.ts +90 -0
  100. package/components/oxy-waterfall-item/index.scss +8 -0
  101. package/components/oxy-waterfall-item/oxy-waterfall-item.vue +89 -0
  102. package/components/oxy-waterfall-item/types.ts +16 -0
  103. package/global.d.ts +7 -0
  104. package/index.ts +3 -0
  105. package/locale/lang/en-US.ts +35 -9
  106. package/locale/lang/zh-CN.ts +31 -5
  107. package/oxy-uni-ui.zip +0 -0
  108. package/package.json +1 -1
  109. package/tags.json +1 -1
  110. package/uni-echarts/changelog.md +2 -0
  111. package/uni-echarts/components/index.js +1 -0
  112. package/uni-echarts/components/uni-echarts/events.js +95 -0
  113. package/uni-echarts/components/uni-echarts/types.d.ts +183 -0
  114. package/uni-echarts/components/uni-echarts/types.js +1 -0
  115. package/uni-echarts/components/uni-echarts/uni-echarts.vue +530 -0
  116. package/uni-echarts/components/uni-echarts/uni-echarts.vue.d.ts +19 -0
  117. package/uni-echarts/global.d.ts +7 -0
  118. package/uni-echarts/index.d.ts +440 -0
  119. package/uni-echarts/index.js +2 -0
  120. package/uni-echarts/package.json +105 -0
  121. package/uni-echarts/shared-core.d.ts +269 -0
  122. package/uni-echarts/shared-core.js +900 -0
  123. package/web-types.json +1 -1
@@ -642,6 +642,7 @@ $-tag-close-color: var(--oxy-tag-close-color, $-tag-info-color) !default; // 关
642
642
  $-tag-close-active-color: var(--oxy-tag-close-active-color, rgba(0, 0, 0, 0.45)) !default; // 关闭按钮 active 颜色
643
643
 
644
644
  /* corner */
645
+ $-corner-radius: var(--oxy-corner-radius, 12px) !default; // 圆角大小
645
646
  $-corner-font-size: var(--oxy-corner-fs, $-fs-secondary) !default; // 字号
646
647
  $-corner-font-weight: var(--oxy-corner-fs, 400) !default; // 字号
647
648
  $-corner-color: var(--oxy-corner-color, $-color-white) !default; // 字体颜色
@@ -662,6 +663,13 @@ $-corner-horizontal-info-bg: var(--oxy-corner-info-bg, resultColor(90deg, $-colo
662
663
  $-corner-horizontal-success-bg: var(--oxy-corner-success-bg, resultColor(90deg, $-color-success, 'light' 'dark', #ffffff #b2ebcf, 0% 100%)) !default; // success 背景颜色
663
664
  $-corner-horizontal-warning-bg: var(--oxy-corner-warning-bg, resultColor(90deg, $-color-warning, 'light' 'dark', #ffffff #fcedd6, 0% 100%)) !default; // warning 背景颜色
664
665
  $-corner-horizontal-danger-bg: var(--oxy-corner-danger-bg, resultColor(90deg, $-color-danger, 'light' 'dark', #ffffff #ffd5d8, 0% 100%)) !default; // danger 背景颜色
666
+ $-corner-embedded-font-size: var(--oxy-corner-fs, $-fs-content) !default; // 字号
667
+ $-corner-embedded-font-weight: var(--oxy-corner-fs, 400) !default; // 字号
668
+ $-corner-embedded-primary-bg: var(--oxy-corner-primary-bg, #cceaff) !default; // 主背景颜色
669
+ $-corner-embedded-info-bg: var(--oxy-corner-info-bg, #eef4fc) !default; // info 背景颜色
670
+ $-corner-embedded-success-bg: var(--oxy-corner-success-bg, #b2ebcf) !default; // success 背景颜色
671
+ $-corner-embedded-warning-bg: var(--oxy-corner-warning-bg, #fcedd6) !default; // warning 背景颜色
672
+ $-corner-embedded-danger-bg: var(--oxy-corner-danger-bg, #ffd5d8) !default; // danger 背景颜色
665
673
 
666
674
  /* toast */
667
675
  $-toast-color: var(--oxy-toast-color, $-color-white) !default; // 文字颜色
@@ -968,6 +976,16 @@ $-text-error-color: var(--oxy-text-error-color, $-color-danger) !default;
968
976
  $-text-warning-color: var(--oxy-text-warning-color, $-color-warning) !default;
969
977
  $-text-success-color: var(--oxy-text-success-color, $-color-success) !default;
970
978
 
979
+ /* link */
980
+ $-link-info-color: var(--oxy-link-info-color, $-color-content) !default;
981
+ $-link-primary-color: var(--oxy-link-primary-color, $-color-theme) !default;
982
+ $-link-error-color: var(--oxy-link-error-color, $-color-danger) !default;
983
+ $-link-warning-color: var(--oxy-link-warning-color, $-color-warning) !default;
984
+ $-link-success-color: var(--oxy-link-success-color, $-color-success) !default;
985
+ $-link-font-size-small: var(--oxy-link-font-size-small, $-fs-content) !default;
986
+ $-link-font-size-medium: var(--oxy-link-font-size-medium, $-fs-title) !default;
987
+ $-link-font-size-large: var(--oxy-link-font-size-large, $-fs-important) !default;
988
+
971
989
  /* video-preview */
972
990
  $-video-preview-bg: var(--oxy-video-preview-bg, rgba(0, 0, 0, 0.8)) !default; // 背景色
973
991
  $-video-preview-close-color: var(--oxy-video-preview-close-color, #fff) !default; // 图标颜色
@@ -997,6 +1015,46 @@ $-signature-button-margin-left: var(--oxy-signature-button-margin-left, 8px) !de
997
1015
 
998
1016
 
999
1017
  /* tree */
1000
- $-tree-node-current-bg:var(--oxy-tree-node-current-bg, var(--oxy-color-theme, #4d80ef1a));
1018
+ $-tree-node-current-bg:var(--oxy-tree-node-current-bg, #4d80ef1a);
1001
1019
  $-tree-node-current-color:var(--oxy-tree-node-current-color, $-text-primary-color);
1002
1020
  $-tree-node-disabled-color:var(--oxy-tree-node-disabled-color, $-color-icon-disabled);
1021
+ $-tree-search-input-color:var(--oxy-tree-search-input-color, #f6f6f6);
1022
+
1023
+ /* rich-text */
1024
+ $-rich-text-primary-color: var(--oxy-rich-text-primary-color, $-color-content);
1025
+ $-rich-text-title-color: var(--oxy-rich-text-title-color, $-color-title);
1026
+ $-rich-text-blockquote-border-color: var(--oxy-rich-text-blockquote-border-color, $-color-theme);
1027
+ $-rich-text-blockquote-color: var(--oxy-rich-text-blockquote-color, #555);
1028
+ $-rich-text-blockquote-bg: var(--oxy-rich-text-blockquote-bg, #f7f8fa);
1029
+ $-rich-text-list-color: var(--oxy-rich-text-list-color, #444);
1030
+ $-rich-text-a-color: var(--oxy-rich-text-a-color, $-color-theme);
1031
+ $-rich-text-strong-color: var(--oxy-rich-text-strong-color, #222);
1032
+ $-rich-text-em-color: var(--oxy-rich-text-em-color, #222);
1033
+ $-rich-text-hr-color: var(--oxy-rich-text-hr-color, #e5e6eb);
1034
+ $-rich-text-table-border-color: var(--oxy-rich-text-table-border-color, #e5e6eb);
1035
+ $-rich-text-table-head-bg: var(--oxy-rich-text-table-head-bg, #f7f8fa);
1036
+ $-rich-text-table-head-color: var(--oxy-rich-text-table-head-color, #333);
1037
+ $-rich-text-table-text-color: var(--oxy-rich-text-table-text-color, #444);
1038
+ $-rich-text-code-bg: var(--oxy-rich-text-code-bg, #2d2d2d);
1039
+ $-rich-text-code-color: var(--oxy-rich-text-code-color, #f8f8f2);
1040
+ $-rich-text-editable-border-color: var(--oxy-rich-text-editable-border-color, #e9e9e9);
1041
+ $-rich-text-toolbox-bg: var(--oxy-rich-text-toolbox-bg, #ededed);
1042
+ $-rich-text-popup-divider-color: var(--oxy-rich-text-popup-divider-color, gray);
1043
+
1044
+ /* date-strip */
1045
+ $-date-strip-bg-color: var(--oxy-date-strip-bg-color, $-color-white);
1046
+ $-date-strip-height: var(--oxy-date-strip-height, 86px);
1047
+ $-date-strip-padding-x: var(--oxy-date-strip-padding-x, 0);
1048
+ $-date-strip-padding-y: var(--oxy-date-strip-padding-y, 8px);
1049
+ $-date-strip-font-size: var(--oxy-date-strip-font-size, 16px);
1050
+ $-date-strip-color: var(--oxy-date-strip-color, $-color-content);
1051
+ $-date-strip-prefix-color: var(--oxy-date-strip-prefix-color, $-font-gray-2);
1052
+ $-date-strip-prefix-font-size: var(--oxy-date-strip-prefix-font-size, 14px);
1053
+ $-date-strip-suffix-color: var(--oxy-date-strip-color, $-font-gray-2);
1054
+ $-date-strip-suffix-font-size: var(--oxy-date-strip-suffix-font-size, 14px);
1055
+ $-date-strip-active-color: var(--oxy-date-strip-active-color, $-color-theme);
1056
+ $-date-strip-square-radius: var(--oxy-date-strip-square-radius, 4px);
1057
+ $-date-strip-grid-width: var(--oxy-date-strip-grid-width, 50px);
1058
+ $-date-strip-grid-square-padding-x: var(--oxy-date-strip-grid-square-padding-x, 0);
1059
+ $-date-strip-grid-square-padding-y: var(--oxy-date-strip-grid-square-padding-y, 6px);
1060
+ $-date-strip-grid-circle-radius: var(--oxy-date-strip-grid-circle-radius, 50%);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 获取当前页面路径
3
+ * @returns 当前页面路径
4
+ */
5
+ export function getCurrentPath() {
6
+ const pages = getCurrentPages()
7
+ const currentPage = pages[pages.length - 1]
8
+ return currentPage?.route || ''
9
+ }
@@ -25,6 +25,39 @@ export function addUnit(num: number | string) {
25
25
  return Number.isNaN(Number(num)) ? `${num}` : `${num}px`
26
26
  }
27
27
 
28
+ /**
29
+ * 单位转换函数,将字符串数字或带有单位的字符串转换为数字
30
+ * @param value 要转换的值,可以是字符串数字或带有单位的字符串
31
+ * @returns 转换后的数字,如果无法转换则返回0
32
+ */
33
+ export function unitConvert(value: string | number | null | undefined, base: number = 0): number {
34
+ // 如果是字符串数字
35
+ if (isNumeric(value)) {
36
+ return Number(value)
37
+ }
38
+ // 如果有单位
39
+ if (isString(value)) {
40
+ const reg = /^-?([0-9]+)?([.]{1}[0-9]+){0,1}(em|rpx|px|%)$/g
41
+ const results = reg.exec(value)
42
+ if (!value || !results) {
43
+ return 0
44
+ }
45
+ const unit = results[3]
46
+ const _value = parseFloat(value)
47
+ if (unit === 'rpx') {
48
+ return uni.upx2px(_value)
49
+ }
50
+ if (unit === 'px') {
51
+ return _value * 1
52
+ }
53
+ if (unit == '%') {
54
+ return (_value / 100) * base
55
+ }
56
+ // 如果是其他单位,可以继续添加对应的转换逻辑
57
+ }
58
+ return 0
59
+ }
60
+
28
61
  /**
29
62
  * @description 判断target是否对象
30
63
  * @param value
@@ -335,6 +368,15 @@ export function isNumber(value: any): value is number {
335
368
  return getType(value) === 'number'
336
369
  }
337
370
 
371
+ /**
372
+ * 检查一个值是否为数字类型或表示数字的字符串
373
+ * @param value 要检查的值,可以是 string 类型或 number 类型
374
+ * @returns 如果值是数字类型或表示数字的字符串,则返回 true;否则返回 false
375
+ */
376
+ export function isNumeric(value: any): boolean {
377
+ return /^(-)?\d+(\.\d+)?$/.test(value)
378
+ }
379
+
338
380
  /**
339
381
  * 检查给定值是否为 Promise 对象。
340
382
  * @param {unknown} value 要检查的值
@@ -9,3 +9,4 @@ export { useRaf } from './useRaf'
9
9
  export { useTouch } from './useTouch'
10
10
  export { useTranslate } from './useTranslate'
11
11
  export { useUpload } from './useUpload'
12
+ export { useVirtualScroll } from './useVirtualScroll'
@@ -0,0 +1,42 @@
1
+ import type { ToastOptions } from '../oxy-toast/types'
2
+ import { deepMerge } from '../common/util'
3
+ import { getCurrentPath } from '../common/path'
4
+
5
+ import { defineStore } from 'pinia'
6
+
7
+ interface GlobalLoading {
8
+ loadingOptions: ToastOptions
9
+ currentPage: string
10
+ }
11
+
12
+ const defaultOptions: ToastOptions = {
13
+ show: false
14
+ }
15
+ export const useGlobalLoading = defineStore('global-loading', {
16
+ state: (): GlobalLoading => ({
17
+ loadingOptions: defaultOptions,
18
+ currentPage: ''
19
+ }),
20
+ getters: {},
21
+ actions: {
22
+ // 加载提示
23
+ loading(option: ToastOptions | string) {
24
+ this.currentPage = getCurrentPath()
25
+ this.loadingOptions = deepMerge(
26
+ {
27
+ iconName: 'loading',
28
+ duration: 0,
29
+ cover: true,
30
+ position: 'middle',
31
+ show: true
32
+ },
33
+ typeof option === 'string' ? { msg: option } : option
34
+ ) as ToastOptions
35
+ },
36
+ // 关闭Toast
37
+ close() {
38
+ this.loadingOptions = defaultOptions
39
+ this.currentPage = ''
40
+ }
41
+ }
42
+ })
@@ -0,0 +1,48 @@
1
+ import type { MessageOptions, MessageResult } from '../oxy-message-box/types'
2
+ import { deepMerge, isString } from '../common/util'
3
+ import { defineStore } from 'pinia'
4
+ import { getCurrentPath } from '../common/path'
5
+
6
+ export type GlobalMessageOptions = MessageOptions & {
7
+ success?: (res: MessageResult) => void
8
+ fail?: (res: MessageResult) => void
9
+ }
10
+
11
+ interface GlobalMessage {
12
+ messageOptions: GlobalMessageOptions | null
13
+ currentPage: string
14
+ }
15
+
16
+ export const useGlobalMessage = defineStore('global-message', {
17
+ state: (): GlobalMessage => ({
18
+ messageOptions: null,
19
+ currentPage: ''
20
+ }),
21
+ actions: {
22
+ show(option: GlobalMessageOptions | string) {
23
+ this.currentPage = getCurrentPath()
24
+ this.messageOptions = {
25
+ ...(isString(option) ? { title: option } : option)
26
+ }
27
+ },
28
+ alert(option: GlobalMessageOptions | string) {
29
+ const messageOptions = deepMerge({ type: 'alert' }, isString(option) ? { title: option } : option) as MessageOptions
30
+ messageOptions.showCancelButton = false
31
+ this.show(messageOptions)
32
+ },
33
+ confirm(option: GlobalMessageOptions | string) {
34
+ const messageOptions = deepMerge({ type: 'confirm' }, isString(option) ? { title: option } : option) as MessageOptions
35
+ messageOptions.showCancelButton = true
36
+ this.show(messageOptions)
37
+ },
38
+ prompt(option: GlobalMessageOptions | string) {
39
+ const messageOptions = deepMerge({ type: 'prompt' }, isString(option) ? { title: option } : option) as MessageOptions
40
+ messageOptions.showCancelButton = true
41
+ this.show(messageOptions)
42
+ },
43
+ close() {
44
+ this.messageOptions = null
45
+ this.currentPage = ''
46
+ }
47
+ }
48
+ })
@@ -0,0 +1,84 @@
1
+ import type { ToastOptions } from '../oxy-toast/types'
2
+ import { deepMerge } from '../common/util'
3
+ import { defineStore } from 'pinia'
4
+
5
+ import { getCurrentPath } from '../common/path'
6
+
7
+ interface GlobalToast {
8
+ toastOptions: ToastOptions
9
+ currentPage: string
10
+ }
11
+
12
+ const defaultOptions: ToastOptions = {
13
+ duration: 2000,
14
+ show: false
15
+ }
16
+ export const useGlobalToast = defineStore('global-toast', {
17
+ state: (): GlobalToast => ({
18
+ toastOptions: defaultOptions,
19
+ currentPage: ''
20
+ }),
21
+ getters: {},
22
+ actions: {
23
+ // 打开Toast
24
+ show(option: ToastOptions | string) {
25
+ this.currentPage = getCurrentPath()
26
+ const options = deepMerge(defaultOptions, typeof option === 'string' ? { msg: option } : option) as ToastOptions
27
+ this.toastOptions = deepMerge(options, {
28
+ show: true,
29
+ position: options.position || 'middle'
30
+ }) as ToastOptions
31
+ },
32
+ // 成功提示
33
+ success(option: ToastOptions | string) {
34
+ this.show(
35
+ deepMerge(
36
+ {
37
+ iconName: 'success',
38
+ duration: 1500
39
+ },
40
+ typeof option === 'string' ? { msg: option } : option
41
+ ) as ToastOptions
42
+ )
43
+ },
44
+ // 关闭提示
45
+ error(option: ToastOptions | string) {
46
+ this.show(
47
+ deepMerge(
48
+ {
49
+ iconName: 'error',
50
+ direction: 'vertical'
51
+ },
52
+ typeof option === 'string' ? { msg: option } : option
53
+ ) as ToastOptions
54
+ )
55
+ },
56
+ // 常规提示
57
+ info(option: ToastOptions | string) {
58
+ this.show(
59
+ deepMerge(
60
+ {
61
+ iconName: 'info'
62
+ },
63
+ typeof option === 'string' ? { msg: option } : option
64
+ ) as ToastOptions
65
+ )
66
+ },
67
+ // 警告提示
68
+ warning(option: ToastOptions | string) {
69
+ this.show(
70
+ deepMerge(
71
+ {
72
+ iconName: 'warning'
73
+ },
74
+ typeof option === 'string' ? { msg: option } : option
75
+ ) as ToastOptions
76
+ )
77
+ },
78
+ // 关闭Toast
79
+ close() {
80
+ this.toastOptions = defaultOptions
81
+ this.currentPage = ''
82
+ }
83
+ }
84
+ })
@@ -0,0 +1,173 @@
1
+ /**
2
+ * 虚拟滚动组合式函数 - 用于复用虚拟滚动逻辑
3
+ */
4
+
5
+ import { ref, computed, watch, nextTick, type Ref } from 'vue'
6
+ import { VirtualScrollEngine } from '../oxy-virtual-scroll/virtual-scroll'
7
+
8
+ export interface UseVirtualScrollOptions {
9
+ data: Ref<any[]>
10
+ virtual: Ref<boolean>
11
+ height: Ref<string>
12
+ itemHeight: Ref<string>
13
+ idKey: Ref<string>
14
+ backToTopThreshold: Ref<string>
15
+ }
16
+
17
+ export interface UseVirtualScrollReturn {
18
+ // 响应式数据
19
+ scrollTop: Ref<number>
20
+ showBackTopBtn: Ref<boolean>
21
+ virtualData: Ref<any[]>
22
+ startIndex: Ref<number>
23
+ virtualOffsetY: Ref<number>
24
+ totalHeight: Ref<number>
25
+ displayData: Ref<any[]>
26
+
27
+ // 方法
28
+ initScrollData: () => void
29
+ initScrollEngine: () => void
30
+ updateVisibleData: () => void
31
+ scrollToTop: () => void
32
+ scrollToBottom: () => void
33
+ scrollToPosition: (position: number | string) => void
34
+ scrollToElement: (item: any) => void
35
+ scrollToElementById: (id: string | number) => void
36
+ onScroll: (scrollTopValue: number) => void
37
+ }
38
+
39
+ export function useVirtualScroll(options: UseVirtualScrollOptions): UseVirtualScrollReturn {
40
+ const { data, virtual, height, itemHeight, idKey, backToTopThreshold } = options
41
+
42
+ // 响应式数据
43
+ const scrollTop = ref<number>(0)
44
+ const _scrollTop = ref<number>(0)
45
+ const showBackTopBtn = ref<boolean>(false)
46
+ const virtualData = ref<any[]>([])
47
+ const startIndex = ref<number>(0)
48
+ const virtualOffsetY = ref<number>(0)
49
+ const virtualEngine = ref<any>(null)
50
+
51
+ // 计算属性
52
+ const displayData = computed<any[]>(() => data.value)
53
+
54
+ const totalHeight = computed(() => {
55
+ return displayData.value.length * parseFloat(itemHeight.value)
56
+ })
57
+
58
+ // 监听数据变化
59
+ watch(
60
+ () => data.value,
61
+ () => {
62
+ nextTick(initScrollData)
63
+ },
64
+ {
65
+ immediate: true,
66
+ deep: true
67
+ }
68
+ )
69
+
70
+ // 初始化滚动数据
71
+ function initScrollData() {
72
+ if (!virtual.value) {
73
+ // 非虚拟滚动模式:直接使用全部数据
74
+ virtualData.value = displayData.value
75
+ virtualOffsetY.value = 0
76
+ return
77
+ }
78
+
79
+ virtualEngine.value = new VirtualScrollEngine({
80
+ containerHeight: parseFloat(height.value),
81
+ itemHeight: parseFloat(itemHeight.value),
82
+ data: displayData.value
83
+ })
84
+ updateVisibleData()
85
+ }
86
+
87
+ // 初始化滚动引擎
88
+ function initScrollEngine() {
89
+ if (!virtual.value) return
90
+
91
+ virtualEngine.value = new VirtualScrollEngine({
92
+ containerHeight: parseFloat(height.value),
93
+ itemHeight: parseFloat(itemHeight.value),
94
+ data: displayData.value
95
+ })
96
+ }
97
+
98
+ // 更新可见数据
99
+ function updateVisibleData() {
100
+ if (!virtual.value) return // 非虚拟模式不处理
101
+
102
+ if (virtualEngine.value) {
103
+ const { visibleData, offsetY } = virtualEngine.value.updateVisibleData(_scrollTop.value || 0)
104
+ virtualData.value = visibleData
105
+ virtualOffsetY.value = offsetY
106
+ }
107
+ }
108
+
109
+ // 滚动事件处理
110
+ function onScroll(scrollTopValue: number) {
111
+ _scrollTop.value = scrollTopValue
112
+ showBackTopBtn.value = scrollTopValue > parseFloat(backToTopThreshold.value)
113
+ updateVisibleData()
114
+ }
115
+
116
+ // 滚动到顶部
117
+ function scrollToTop() {
118
+ scrollTop.value = 0
119
+ nextTick(() => {
120
+ scrollTop.value = 0
121
+ })
122
+ }
123
+
124
+ // 滚动到底部
125
+ function scrollToBottom() {
126
+ scrollToPosition(totalHeight.value)
127
+ }
128
+
129
+ // 滚动到指定位置
130
+ function scrollToPosition(position: number | string) {
131
+ scrollTop.value = typeof position === 'number' ? position : parseFloat(position)
132
+ }
133
+
134
+ // 滚动到指定元素
135
+ function scrollToElement(item: any) {
136
+ const index = data.value.findIndex((o) => item[idKey.value] && o[idKey.value] && o[idKey.value] === item[idKey.value])
137
+ if (index > 0) {
138
+ const scrollDistance = parseFloat(itemHeight.value) * index
139
+ scrollToPosition(scrollDistance)
140
+ }
141
+ }
142
+
143
+ // 根据ID滚动到指定元素
144
+ function scrollToElementById(id: string | number) {
145
+ const index = data.value.findIndex((o) => id && o[idKey.value] && o[idKey.value] === id)
146
+ if (index > 0) {
147
+ const scrollDistance = parseFloat(itemHeight.value) * index
148
+ scrollToPosition(scrollDistance)
149
+ }
150
+ }
151
+
152
+ return {
153
+ // 响应式数据
154
+ scrollTop,
155
+ showBackTopBtn,
156
+ virtualData,
157
+ startIndex,
158
+ virtualOffsetY,
159
+ totalHeight,
160
+ displayData,
161
+
162
+ // 方法
163
+ initScrollData,
164
+ initScrollEngine,
165
+ updateVisibleData,
166
+ scrollToTop,
167
+ scrollToBottom,
168
+ scrollToPosition,
169
+ scrollToElement,
170
+ scrollToElementById,
171
+ onScroll
172
+ }
173
+ }
@@ -7,7 +7,7 @@
7
7
  @click="onClick"
8
8
  >
9
9
  <view :class="['oxy-cell__wrapper', vertical ? 'is-vertical' : '']">
10
- <view v-if="showLeft" class="oxy-cell__left" :style="titleWidth ? 'min-width:' + titleWidth + ';max-width:' + titleWidth + ';' : ''">
10
+ <view v-if="showLeft" class="oxy-cell__left" :style="leftStyle">
11
11
  <text v-if="isRequired && markerSide === 'before'" class="oxy-cell__required oxy-cell__required--left">*</text>
12
12
  <!--左侧icon部位-->
13
13
  <slot name="icon">
@@ -65,7 +65,7 @@ import { useCell } from '../composables/useCell'
65
65
  import { useParent } from '../composables/useParent'
66
66
  import { FORM_KEY } from '../oxy-form/types'
67
67
  import { cellProps } from './types'
68
- import { isDef } from '../common/util'
68
+ import { isDef, objToStyle } from '../common/util'
69
69
 
70
70
  const props = defineProps(cellProps)
71
71
  const emit = defineEmits(['click'])
@@ -116,6 +116,19 @@ const showLeft = computed(() => {
116
116
  return hasIcon || hasTitle || hasLabel
117
117
  })
118
118
 
119
+ const leftStyle = computed(() => {
120
+ const leftStyle: Record<string, any> = {}
121
+ if (props.titleWidth) {
122
+ leftStyle['min-width'] = props.titleWidth
123
+ leftStyle['max-width'] = props.titleWidth
124
+ }
125
+ if (props.titlePercent) {
126
+ leftStyle['flex'] = 'none'
127
+ leftStyle['width'] = props.titlePercent
128
+ }
129
+ return objToStyle(leftStyle)
130
+ })
131
+
119
132
  /**
120
133
  * @description 点击cell的handle
121
134
  */
@@ -53,6 +53,10 @@ export const cellProps = {
53
53
  * 设置左侧标题宽度
54
54
  */
55
55
  titleWidth: String,
56
+ /**
57
+ * 设置左侧标题占比
58
+ */
59
+ titlePercent: String,
56
60
  /**
57
61
  * 是否垂直居中,默认顶部居中
58
62
  */
@@ -73,7 +73,7 @@
73
73
  margin-bottom: $-checkbox-margin;
74
74
  font-size: 0;
75
75
  -webkit-tap-highlight-color: transparent;
76
- line-height: 1.2;
76
+ // line-height: 1.2;
77
77
 
78
78
  @include when(last-child) {
79
79
  margin-bottom: 0;
@@ -14,8 +14,8 @@
14
14
  :class="`oxy-checkbox__shape ${innerShape === 'square' ? 'is-square' : ''} ${customShapeClass}`"
15
15
  :style="isChecked && !innerDisabled && innerCheckedColor ? 'color :' + innerCheckedColor : ''"
16
16
  >
17
- <oxy-icon custom-class="oxy-checkbox__indeterminate" name="decrease" />
18
- <oxy-icon custom-class="oxy-checkbox__check" name="check-bold" />
17
+ <oxy-icon v-if="indeterminate" custom-class="oxy-checkbox__indeterminate" name="decrease" />
18
+ <oxy-icon v-else custom-class="oxy-checkbox__check" name="check-bold" />
19
19
  </view>
20
20
  <!--shape为button时只保留oxy-checkbox__label-->
21
21
  <view
@@ -294,6 +294,9 @@ function showPicker() {
294
294
  const { disabled, readonly } = props
295
295
 
296
296
  if (disabled || readonly) return
297
+ if (isFunction(props.beforeOpen) && !props.beforeOpen()) {
298
+ return
299
+ }
297
300
  pickerShow.value = true
298
301
  lastPickerColSelected.value = pickerColSelected.value.slice(0)
299
302
  lastSelectList.value = selectList.value.slice(0)
@@ -152,7 +152,11 @@ export const colPickerProps = {
152
152
  /**
153
153
  * 必填标记位置,可选值:before、after
154
154
  */
155
- markerSide: makeStringProp<'before' | 'after'>('before')
155
+ markerSide: makeStringProp<'before' | 'after'>('before'),
156
+ /**
157
+ * 打开pop之前的校验
158
+ */
159
+ beforeOpen: Function as PropType<() => boolean>
156
160
  }
157
161
 
158
162
  export type ColPickerProps = ExtractPropTypes<typeof colPickerProps>