uview-plus 3.8.18 → 3.8.37

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 (39) hide show
  1. package/changelog.md +122 -0
  2. package/components/u-button/u-button.vue +60 -16
  3. package/components/u-calendar/calendar.js +4 -3
  4. package/components/u-calendar/header.vue +74 -32
  5. package/components/u-calendar/month.vue +9 -0
  6. package/components/u-calendar/props.js +5 -0
  7. package/components/u-calendar/u-calendar.vue +46 -0
  8. package/components/u-cropper/u-cropper.vue +409 -387
  9. package/components/u-input/u-input.vue +3 -1
  10. package/components/u-parse/node/node.vue +50 -20
  11. package/components/u-parse/u-parse.vue +38 -8
  12. package/components/u-poster/u-poster.vue +12 -10
  13. package/components/u-qrcode/qrcode.js +35 -29
  14. package/components/u-qrcode/u-qrcode.vue +17 -12
  15. package/components/u-toast/u-toast.vue +5 -1
  16. package/components/u-tooltip/u-tooltip.vue +1 -0
  17. package/index.scss +1 -0
  18. package/libs/config/config.js +2 -0
  19. package/libs/css/theme-legacy-bridge.scss +6 -0
  20. package/libs/css/theme-vars-core.scss +4 -0
  21. package/libs/i18n/locales/de.json +1 -0
  22. package/libs/i18n/locales/en.json +1 -0
  23. package/libs/i18n/locales/es.json +1 -0
  24. package/libs/i18n/locales/fr.json +1 -0
  25. package/libs/i18n/locales/ja.json +1 -0
  26. package/libs/i18n/locales/ko.json +1 -0
  27. package/libs/i18n/locales/ru.json +1 -0
  28. package/libs/i18n/locales/th.json +1 -0
  29. package/libs/i18n/locales/zh-Hans.json +1 -0
  30. package/libs/i18n/locales/zh-Hant.json +1 -0
  31. package/libs/root/index.js +5 -29
  32. package/libs/root/root.js +6 -2
  33. package/libs/theme/runtime.js +52 -3
  34. package/libs/theme/theme.js +13 -16
  35. package/package.json +1 -1
  36. package/theme.scss +0 -5
  37. package/types/comps/calendar.d.ts +5 -0
  38. package/types/comps/qrcode.d.ts +6 -0
  39. package/types/index.d.ts +6 -0
package/changelog.md CHANGED
@@ -1,3 +1,125 @@
1
+ ## 3.8.37(2026-05-22)
2
+ feat: 日历组件新增今天按钮并支持快速回到当月
3
+
4
+ 在日历头部增加今天按钮与禁用态,点击后可跳转到今天所在月份;为今天日期增加独立高亮样式且不覆盖用户当前已选日期。同时补充 showToday 配置、类型声明与多语言文案键,保证不同语言和模式下行为一致。
5
+
6
+ ## 3.8.36(2026-05-20)
7
+ fix: 修复 u-parse 链接点击在 iOS 端可能闪退的问题
8
+
9
+ - 在 u-parse 的两个链接点击入口统一增加 href 规范化与外链判断,避免空值或非法值传入 plus.runtime.openWeb/openURL。
10
+ - 同时将原生外链打开封装为受保护调用并添加异常兜底,降低 APP-PLUS 与 APP-HARMONY 下点击链接导致崩溃的风险。
11
+
12
+ ## 3.8.35(2026-05-19)
13
+ fix: 修复up-input在confirm阶段可能丢失扫码内容
14
+
15
+ - 问题背景:issue #1011 反馈外接扫码枪场景下,up-input 的 confirm 回调偶发丢码,连续0更明显。
16
+ - 原因分析:组件 onConfirm 直接返回 innerValue,当扫码输入与回车触发节奏接近时,confirm 可能早于最后一次 input 同步,导致取到旧值。
17
+ - 改动说明:onConfirm 优先使用 event.detail.value,若平台未提供该字段再回退到 innerValue,兼容原有行为并降低扫码场景丢码风险。
18
+ ## 3.8.34(2026-05-18)
19
+ fix: 仅在 TabBar 页面同步 TabBar 样式
20
+
21
+ - 在 libs/theme/runtime.js 新增 isTabBarPage 与 trySetTabBarStyle,统一封装 TabBar 页面判断与安全调用。
22
+ - 在 runtime/theme/common mixin 的原生主题同步路径中,全部改为调用 trySetTabBarStyle,不再直接调用 uni.setTabBarStyle。
23
+
24
+ ## 3.8.33(2026-05-17)
25
+ fix: 修复主题变量桥接与 nvue 按钮取色问题
26
+
27
+ - 调整主题 bridge 的导出位置,避免 legacy light 变量在样式注入后覆盖用户自定义 CSS 变量。
28
+ - 修复 up-button 在 nvue 下的主题取色与 info/plain 样式问题,补充运行时取色兜底,避免按钮颜色错误或主题方法缺失时报错。
29
+ - 同步更新示例接入、版本号与变更记录,保持主题改造后的行为与文档一致。
30
+
31
+ ## 3.8.32(2026-05-14)
32
+ feat: 新增二维码静区配置
33
+
34
+ - 为 up-qrcode 增加 quietZone 属性,默认值调整为 0。
35
+ - 同步更新二维码绘制逻辑与类型声明,支持按静区宽度控制外层留白。
36
+
37
+ ## 3.8.31(2026-05-14)
38
+ fix: 修复toast组件overlay设置为false时不显示toast的问题 (#1016)
39
+
40
+
41
+ ## 3.8.30(2026-05-14)
42
+ fix(tooltip): 修复tooltip组件字体大小(size)属性未生效的问题
43
+
44
+ ## 3.8.29(2026-05-13)
45
+ style: 将 Toast 组件硬编码颜色替换为主题变量
46
+
47
+ - 替换 primary、success、error、warning 类型的背景与边框硬编码颜色
48
+ - 统一接入 $u-{type}-light 与 $u-{type}-disabled 主题变量
49
+ - 增强组件在不同主题下的样式一致性与可维护性
50
+
51
+ ## 3.8.28(2026-05-12)
52
+ style: 优化 up-textarea 组件主题变量与边框样式
53
+
54
+ - 字数统计区域新增文本颜色主题变量支持
55
+ - 输入框区域重构样式计算,补充背景色、文本色与光标色主题变量
56
+ - 移除原有边框 CSS 类名依赖,改为通过计算属性动态注入边框样式
57
+ - 新增边框颜色计算逻辑,根据亮暗色模式自动适配主题色
58
+ - 修复 H5 端 uni-app 默认包装器样式冲突,统一背景、边框与占位符颜色
59
+
60
+ ## 3.8.27(2026-05-11)
61
+ feat: 新增 nativeThemeSync 配置控制原生UI主题同步
62
+
63
+ - 在 config 中新增 nativeThemeSync 选项,默认值为 false
64
+ - 在 theme.js 与 runtime.js 的 applyNativeThemeUI 中增加配置拦截,未开启时跳过原生导航栏、页面背景及 tabBar 的样式同步
65
+ - 补充 TypeScript 类型定义,明确默认关闭以避免升级覆盖项目已有的 pages.json 或 theme.json 全局样式
66
+ - 更新验证脚本,增加对该配置开关行为的断言测试
67
+ ## 3.8.26(2026-05-11)
68
+ fix: 修复海报组件多行文本截断与省略号渲染问题
69
+
70
+ - 提取省略号宽度计算与截断逻辑为独立辅助函数,提升代码可维护性
71
+ - 修正达到最大行数时的截断流程,确保末行正确计算宽度并添加省略号
72
+ - 调整换行后当前行字符的赋值时机,避免首字符丢失或渲染状态错乱
73
+ - 补充文件末尾缺失的换行符以符合代码规范
74
+
75
+ ## 3.8.25(2026-05-10)
76
+ fix: 修复H5安装时写入页面背景
77
+
78
+ - 移除主题初始化时对html、body和#app背景色的内联写入,避免use(uviewPlus)覆盖业务页面背景。
79
+ - 补充运行时主题回归断言,确保H5仍同步data-up-theme但不再改写宿主页面背景样式。
80
+
81
+ ## 3.8.24(2026-05-09)
82
+ fix: 合并 up-slider 组件重复的 mounted 生命周期钩子
83
+
84
+ - 将原本分散的两个 mounted 钩子合并为单个 async mounted
85
+ - 确保高度/尺寸赋值与滑块 DOM 尺寸获取逻辑在同一钩子内顺序执行
86
+ - 移除底部重复的生命周期代码块,修复因 Vue 钩子执行顺序不确定导致的 init 初始化异常
87
+
88
+ ## 3.8.23(2026-05-09)
89
+ style: 弹窗组件支持主题变量动态设置指示器与关闭图标颜色
90
+
91
+ - 将底部横条指示器背景色替换为 --up-light-color 主题变量
92
+ - 将关闭图标颜色替换为 --up-content-color 主题变量
93
+ - 新增 indicatorStyle 与 closeIconColor 计算属性实现动态绑定
94
+ - 同步更新 CSS 与内联样式,移除硬编码颜色值以提升多主题适配能力
95
+
96
+ ## 3.8.22(2026-05-08)
97
+ style: 优化 up-input 组件边框样式与主题变量适配
98
+
99
+ - 移除原有的 u-border 和 u-border-bottom 工具类,改为通过内联样式动态控制边框
100
+ - 新增 inputBorderColor 计算属性,支持通过 --up-input-border-color 主题变量自定义边框颜色
101
+ - 适配深色模式,默认边框颜色根据主题状态自动切换为半透明白色或浅色边框
102
+ - 统一将边框宽度设置为 0.5px,提升多端显示的一致性
103
+
104
+ ## 3.8.21(2026-05-07)
105
+ fix: 修正索引锚点默认背景色识别逻辑
106
+
107
+ - 扩展默认背景色判断条件,兼容 #f1f1f1 与 #dedede
108
+ - 更新主题变量回退默认值为 #f1f1f1 以匹配新版设计
109
+
110
+ ## 3.8.20(2026-05-06)
111
+ feat: 表单标签颜色支持主题变量动态适配
112
+
113
+ - 新增 labelDynamicStyle 计算属性,动态读取 --up-main-color 主题变量
114
+ - 将动态样式注入标签元素,实现表单标签颜色随主题配置自动切换
115
+
116
+ ## 3.8.19(2026-04-30)
117
+ feat: 为日期时间选择器遮罩层添加暗色模式自适应样式
118
+
119
+ - 新增 resolvedMaskStyle 计算属性,优先返回外部传入的 maskStyle
120
+ - 未传入自定义样式且处于暗色主题时,自动注入渐变背景以适配深色模式
121
+ - 替换模板中的遮罩样式绑定,避免硬编码并提升主题切换兼容性
122
+
1
123
  ## 3.8.18(2026-04-29)
2
124
  fix: 规避 H5 主题切换时的导航栏 page not found 报错
3
125
 
@@ -117,6 +117,7 @@ import { mixin } from '../../libs/mixin/mixin';
117
117
  import { props } from "./props";
118
118
  import { addStyle } from '../../libs/function/index';
119
119
  import { throttle } from '../../libs/function/throttle';
120
+ import { getThemeVar } from '../../libs/theme/runtime.js';
120
121
  /**
121
122
  * button 按钮
122
123
  * @description Button 按钮
@@ -194,8 +195,43 @@ export default {
194
195
  isDarkTheme() {
195
196
  return this.$u.theme && this.$u.theme.mode === 'dark';
196
197
  },
198
+ nvueMainColor() {
199
+ return this.resolveNvueColor(this.$u.color.mainColor, this.isDarkTheme ? '#f5f5f5' : '#303133');
200
+ },
201
+ nvueBorderColor() {
202
+ return this.resolveNvueColor(this.$u.color.borderColor, this.isDarkTheme ? '#3a3a3c' : '#dadbde');
203
+ },
197
204
  themeTypeColor() {
198
- return this.$u.color[this.type] || this.$u.color.info;
205
+ const fallbackMap = {
206
+ primary: '#3c9cff',
207
+ success: '#5ac725',
208
+ warning: '#f9ae3d',
209
+ error: '#f56c6c',
210
+ info: '#909399',
211
+ };
212
+ const type = fallbackMap[this.type] ? this.type : 'info';
213
+ return this.resolveNvueColor(
214
+ this.upThemeVar(`--up-${type}`, fallbackMap[type]),
215
+ fallbackMap[type]
216
+ );
217
+ },
218
+ nvueInfoBackgroundColor() {
219
+ return this.upThemeVar(
220
+ '--up-button-info-background-color',
221
+ this.upThemeVar(
222
+ '--up-card-bg-color',
223
+ this.isDarkTheme ? '#1c1c1e' : '#ffffff'
224
+ )
225
+ );
226
+ },
227
+ nvuePlainBackgroundColor() {
228
+ return this.upThemeVar(
229
+ '--up-button-plain-background-color',
230
+ this.upThemeVar(
231
+ '--up-card-bg-color',
232
+ this.isDarkTheme ? '#1c1c1e' : '#ffffff'
233
+ )
234
+ );
199
235
  },
200
236
  loadingColor() {
201
237
  if (this.plain) {
@@ -212,13 +248,11 @@ export default {
212
248
  iconColorCom() {
213
249
  // 如果是镂空状态,设置了color就用color值,否则使用主题颜色,
214
250
  // up-icon的color能接受一个主题颜色的值
215
- if (this.iconColor) return this.iconColor;
251
+ if (this.iconColor) return this.iconColor;
216
252
  if (this.plain) {
217
253
  return this.color ? this.color : this.type;
218
254
  } else {
219
- return this.type === "info"
220
- ? (this.isDarkTheme ? "#f3f4f6" : "#000000")
221
- : "#ffffff";
255
+ return this.type === "info" ? this.nvueMainColor : "#ffffff";
222
256
  }
223
257
  },
224
258
  baseColor() {
@@ -249,26 +283,28 @@ export default {
249
283
  }
250
284
  return style;
251
285
  }
286
+ // #ifdef APP-NVUE
252
287
  const typeColor = this.themeTypeColor;
253
288
  if (this.plain) {
254
- style.color = this.type === 'info' ? this.$u.color.mainColor : typeColor;
255
- style.backgroundColor = this.isDarkTheme ? '#1c1c1e' : '#ffffff';
256
- style.borderColor = this.type === 'info' ? this.$u.color.borderColor : typeColor;
289
+ style.color = this.type === 'info' ? this.nvueMainColor : typeColor;
290
+ style.backgroundColor = this.nvuePlainBackgroundColor;
291
+ style.borderColor = this.type === 'info' ? this.nvueBorderColor : typeColor;
257
292
  style.borderWidth = this.hairline ? '0.5px' : '1px';
258
293
  style.borderStyle = 'solid';
259
294
  } else {
260
295
  style.borderWidth = this.hairline ? '0.5px' : '1px';
261
296
  style.borderStyle = 'solid';
262
297
  if (this.type === 'info') {
263
- style.color = this.$u.color.mainColor;
264
- style.backgroundColor = this.isDarkTheme ? '#2c2c2e' : '#ffffff';
265
- style.borderColor = this.$u.color.borderColor;
298
+ style.color = this.nvueMainColor;
299
+ style.backgroundColor = this.nvueInfoBackgroundColor;
300
+ style.borderColor = this.nvueBorderColor;
266
301
  } else {
267
302
  style.color = '#ffffff';
268
303
  style.backgroundColor = typeColor;
269
304
  style.borderColor = typeColor;
270
305
  }
271
306
  }
307
+ // #endif
272
308
  return style;
273
309
  },
274
310
  // nvue版本按钮的字体不会继承父组件的颜色,需要对每一个text组件进行单独的设置
@@ -276,7 +312,7 @@ export default {
276
312
  let style = {};
277
313
  // 针对自定义了color颜色的情况,镂空状态下,就是用自定义的颜色
278
314
  if (this.type === "info") {
279
- style.color = this.$u.color.mainColor;
315
+ style.color = this.nvueMainColor;
280
316
  }
281
317
  if (this.color) {
282
318
  style.color = this.plain ? this.color : "white";
@@ -301,6 +337,14 @@ export default {
301
337
  'error', 'opensetting', 'launchapp', 'agreeprivacyauthorization'],
302
338
  methods: {
303
339
  addStyle,
340
+ resolveNvueColor(colorValue, fallbackColor) {
341
+ if (typeof colorValue !== 'string') return fallbackColor;
342
+ if (colorValue.indexOf('var(') > -1) return fallbackColor;
343
+ return colorValue;
344
+ },
345
+ upThemeVar(varName, fallbackColor) {
346
+ return getThemeVar(varName, fallbackColor, this.$u);
347
+ },
304
348
  clickHandler(e: any) {
305
349
  // 非禁止并且非加载中,才能点击
306
350
  if (!this.disabled && !this.loading) {
@@ -362,9 +406,9 @@ $u-button-mini-height: 22px !default;
362
406
  $u-button-mini-font-size: 10px !default;
363
407
  $u-button-mini-min-width: 50px !default;
364
408
  $u-button-disabled-opacity: 0.5 !default;
365
- $u-button-info-color: #323233 !default;
366
- $u-button-info-background-color: #fff !default;
367
- $u-button-info-border-color: #ebedf0 !default;
409
+ $u-button-info-color: $u-main-color !default;
410
+ $u-button-info-background-color: var(--up-button-info-background-color, var(--up-card-bg-color, #fff)) !default;
411
+ $u-button-info-border-color: $u-border-color !default;
368
412
  $u-button-info-border-width: 1px !default;
369
413
  $u-button-info-border-style: solid !default;
370
414
  $u-button-success-color: #fff !default;
@@ -397,7 +441,7 @@ $u-button-square-border-top-left-radius: 3px !default;
397
441
  $u-button-square-border-bottom-left-radius: 3px !default;
398
442
  $u-button-square-border-bottom-right-radius: 3px !default;
399
443
  $u-button-icon-min-width: 1em !default;
400
- $u-button-plain-background-color: #fff !default;
444
+ $u-button-plain-background-color: var(--up-button-plain-background-color, var(--up-card-bg-color, #fff)) !default;
401
445
  $u-button-hairline-border-width: 0.5px !default;
402
446
 
403
447
  .u-button {
@@ -38,9 +38,10 @@ export default {
38
38
  showRangePrompt: true,
39
39
  allowSameDay: false,
40
40
  round: 0,
41
- monthNum: 3,
42
- monthSwitch: false,
43
- weekText: [t("up.week.one"), t("up.week.two"), t("up.week.three"), t("up.week.four"), t("up.week.five"), t("up.week.six"), t("up.week.seven")],
41
+ monthNum: 3,
42
+ monthSwitch: false,
43
+ showToday: true,
44
+ weekText: [t("up.week.one"), t("up.week.two"), t("up.week.three"), t("up.week.four"), t("up.week.five"), t("up.week.six"), t("up.week.seven")],
44
45
  forbidDays: [],
45
46
  forbidDaysToast: t("up.calendar.disabled"),
46
47
  monthFormat: '',
@@ -4,10 +4,10 @@
4
4
  class="u-calendar-header__title"
5
5
  v-if="showTitle"
6
6
  >{{ title }}</text>
7
- <view
8
- class="u-calendar-header__subtitle-wrap"
9
- v-if="showSubtitle"
10
- >
7
+ <view
8
+ class="u-calendar-header__subtitle-wrap"
9
+ v-if="showSubtitle"
10
+ >
11
11
  <text
12
12
  v-if="showSwitch"
13
13
  class="u-calendar-header__switch"
@@ -27,13 +27,19 @@
27
27
  :class="{ 'u-calendar-header__switch--disabled': nextDisabled }"
28
28
  @click="next"
29
29
  >›</text>
30
- <text
31
- v-if="showSwitch"
32
- class="u-calendar-header__switch"
33
- :class="{ 'u-calendar-header__switch--disabled': nextYearDisabled }"
34
- @click="nextYear"
35
- >»</text>
36
- </view>
30
+ <text
31
+ v-if="showSwitch"
32
+ class="u-calendar-header__switch"
33
+ :class="{ 'u-calendar-header__switch--disabled': nextYearDisabled }"
34
+ @click="nextYear"
35
+ >»</text>
36
+ <text
37
+ v-if="showToday"
38
+ class="u-calendar-header__today"
39
+ :class="{ 'u-calendar-header__today--disabled': todayDisabled }"
40
+ @click="today"
41
+ >{{ todayText }}</text>
42
+ </view>
37
43
  <view class="u-calendar-header__weekdays">
38
44
  <text class="u-calendar-header__weekdays__weekday">{{ weekText[0] }}</text>
39
45
  <text class="u-calendar-header__weekdays__weekday">{{ weekText[1] }}</text>
@@ -100,12 +106,27 @@
100
106
  type: Boolean,
101
107
  default: false
102
108
  },
103
- // 下一年按钮是否禁用
104
- nextYearDisabled: {
105
- type: Boolean,
106
- default: false
107
- }
108
- },
109
+ // 下一年按钮是否禁用
110
+ nextYearDisabled: {
111
+ type: Boolean,
112
+ default: false
113
+ },
114
+ // 是否显示今天按钮
115
+ showToday: {
116
+ type: Boolean,
117
+ default: true
118
+ },
119
+ // 今天按钮文案
120
+ todayText: {
121
+ type: String,
122
+ default: ''
123
+ },
124
+ // 今天按钮是否禁用
125
+ todayDisabled: {
126
+ type: Boolean,
127
+ default: false
128
+ }
129
+ },
109
130
  data() {
110
131
  return {
111
132
 
@@ -127,13 +148,18 @@
127
148
  this.$emit('prevYear')
128
149
  }
129
150
  },
130
- nextYear() {
131
- if (!this.nextYearDisabled) {
132
- this.$emit('nextYear')
133
- }
134
- }
135
- },
136
- }
151
+ nextYear() {
152
+ if (!this.nextYearDisabled) {
153
+ this.$emit('nextYear')
154
+ }
155
+ },
156
+ today() {
157
+ if (!this.todayDisabled) {
158
+ this.$emit('today')
159
+ }
160
+ }
161
+ },
162
+ }
137
163
  </script>
138
164
 
139
165
  <style lang="scss" scoped>
@@ -182,17 +208,33 @@
182
208
  }
183
209
  }
184
210
 
185
- &__weekdays {
186
- @include flex;
187
- justify-content: space-between;
211
+ &__weekdays {
212
+ @include flex;
213
+ justify-content: space-between;
188
214
 
189
215
  &__weekday {
190
216
  font-size: 13px;
191
217
  color: var(--up-main-color, $u-main-color);
192
218
  line-height: 30px;
193
219
  flex: 1;
194
- text-align: center;
195
- }
196
- }
197
- }
198
- </style>
220
+ text-align: center;
221
+ }
222
+ }
223
+
224
+ &__today {
225
+ margin-left: 4px;
226
+ height: 28px;
227
+ line-height: 28px;
228
+ padding: 0 10px;
229
+ border-radius: 14px;
230
+ font-size: 13px;
231
+ color: var(--up-primary, $u-primary);
232
+ border: 1px solid var(--up-primary, $u-primary);
233
+ flex-shrink: 0;
234
+
235
+ &--disabled {
236
+ opacity: 0.35;
237
+ }
238
+ }
239
+ }
240
+ </style>
@@ -135,6 +135,11 @@
135
135
  forbidDaysToast: {
136
136
  type: String,
137
137
  default: ''
138
+ },
139
+ // 今天日期,用于独立高亮
140
+ todayDate: {
141
+ type: String,
142
+ default: ''
138
143
  }
139
144
  },
140
145
  data() {
@@ -193,6 +198,10 @@
193
198
  if (this.selected.some(item => this.dateSame(item, date))) {
194
199
  style.backgroundColor = this.color
195
200
  }
201
+ if (this.todayDate && this.dateSame(date, this.todayDate) && !this.selected.some(item => this.dateSame(item, date))) {
202
+ style.border = `1px solid ${this.color}`
203
+ style.boxSizing = 'border-box'
204
+ }
196
205
  if (this.mode === 'single') {
197
206
  if (date === this.selected[0]) {
198
207
  // 因为需要对nvue的兼容,只能这么写,无法缩写,也无法通过类名控制等等
@@ -148,6 +148,11 @@ export const props = defineMixin({
148
148
  type: Boolean,
149
149
  default: () => defProps.calendar.monthSwitch
150
150
  },
151
+ // 是否显示今天按钮
152
+ showToday: {
153
+ type: Boolean,
154
+ default: () => defProps.calendar.showToday
155
+ },
151
156
  // 星期文案
152
157
  weekText: {
153
158
  type: Array,
@@ -16,6 +16,9 @@
16
16
  :showTitle="showTitle"
17
17
  :weekText="weekText"
18
18
  :showSwitch="monthSwitch"
19
+ :showToday="showToday"
20
+ :todayText="todayText"
21
+ :todayDisabled="todayDisabled"
19
22
  :prevDisabled="switchPrevDisabled"
20
23
  :nextDisabled="switchNextDisabled"
21
24
  :prevYearDisabled="switchPrevYearDisabled"
@@ -24,6 +27,7 @@
24
27
  @next="nextMonth"
25
28
  @prevYear="prevYear"
26
29
  @nextYear="nextYear"
30
+ @today="jumpToToday"
27
31
  ></uHeader>
28
32
  <scroll-view
29
33
  v-if="!monthSwitch"
@@ -56,6 +60,7 @@
56
60
  :forbidDays="forbidDays"
57
61
  :forbidDaysToast="forbidDaysToast"
58
62
  :monthFormat="monthFormat"
63
+ :todayDate="todayDate"
59
64
  ref="month"
60
65
  @monthSelected="monthSelected"
61
66
  @updateMonthTop="onUpdateMonthTop"
@@ -88,6 +93,7 @@
88
93
  :forbidDays="forbidDays"
89
94
  :forbidDaysToast="forbidDaysToast"
90
95
  :monthFormat="monthFormat"
96
+ :todayDate="todayDate"
91
97
  ref="month"
92
98
  @monthSelected="monthSelected"
93
99
  @updateMonthTop="onUpdateMonthTop"
@@ -121,6 +127,7 @@ import { mpMixin } from '../../libs/mixin/mpMixin.js'
121
127
  import { mixin } from '../../libs/mixin/mixin.js'
122
128
  import { addUnit, getPx, range, error, padZero } from '../../libs/function/index';
123
129
  import test from '../../libs/function/test';
130
+ import { t } from '../../libs/i18n'
124
131
  /**
125
132
  * Calendar 日历
126
133
  * @description 此组件用于单个选择日期,范围选择日期等,日历被包裹在底部弹起的容器中.
@@ -224,6 +231,28 @@ export default {
224
231
  ? Number(this.minDate)
225
232
  : this.minDate
226
233
  },
234
+ todayDate() {
235
+ return dayjs().format('YYYY-MM-DD')
236
+ },
237
+ todayText() {
238
+ return t('up.calendar.today')
239
+ },
240
+ todayDisabled() {
241
+ const today = dayjs(this.todayDate)
242
+ const minDate = this.innerMinDate
243
+ ? dayjs(this.innerMinDate)
244
+ : null
245
+ const maxDate = this.innerMaxDate
246
+ ? dayjs(this.innerMaxDate)
247
+ : null
248
+ if (minDate && today.isBefore(minDate, 'day')) {
249
+ return true
250
+ }
251
+ if (maxDate && today.isAfter(maxDate, 'day')) {
252
+ return true
253
+ }
254
+ return false
255
+ },
227
256
  // 多个条件的变化,会引起选中日期的变化,这里统一管理监听
228
257
  selectedChange() {
229
258
  return [this.innerMinDate, this.innerMaxDate, this.defaultDate]
@@ -449,6 +478,22 @@ export default {
449
478
  this.monthIndex += 12
450
479
  }
451
480
  },
481
+ jumpToToday() {
482
+ if (this.todayDisabled) {
483
+ return
484
+ }
485
+ const targetMonth = dayjs(this.todayDate).format('YYYY-MM')
486
+ if (this.monthSwitch) {
487
+ const todayMonthIndex = this.months.findIndex(({ year, month }) => {
488
+ return `${year}-${padZero(month)}` === targetMonth
489
+ })
490
+ if (todayMonthIndex !== -1) {
491
+ this.monthIndex = todayMonthIndex
492
+ }
493
+ return
494
+ }
495
+ this.scrollIntoDefaultMonth(targetMonth)
496
+ },
452
497
  // 滚动到默认设置的月份
453
498
  scrollIntoDefaultMonth(selected) {
454
499
  // 查询默认日期在可选列表的下标
@@ -462,6 +507,7 @@ export default {
462
507
  if (_index !== -1) {
463
508
  // #ifndef MP-WEIXIN
464
509
  this.$nextTick(() => {
510
+ this.scrollIntoView = ''
465
511
  this.scrollIntoView = `month-${_index}`
466
512
  this.scrollIntoViewScroll = this.scrollIntoView
467
513
  })