Browse Source

迭代更新依赖包

fanghuisheng 1 year ago
parent
commit
abdf802055
100 changed files with 6036 additions and 1474 deletions
  1. 43 0
      src/uni_modules/lime-echart/changelog.md
  2. 30 17
      src/uni_modules/lime-echart/components/l-echart/canvas.js
  3. 141 0
      src/uni_modules/lime-echart/components/l-echart/l-echart.uvue
  4. 145 155
      src/uni_modules/lime-echart/components/l-echart/l-echart.vue
  5. 51 0
      src/uni_modules/lime-echart/components/l-echart/nvue.js
  6. 83 12
      src/uni_modules/lime-echart/components/l-echart/utils.js
  7. 105 0
      src/uni_modules/lime-echart/components/l-echart/uvue.uts
  8. 95 0
      src/uni_modules/lime-echart/components/lime-echart/lime-echart.nvue
  9. 96 0
      src/uni_modules/lime-echart/components/lime-echart/lime-echart.uvue
  10. 163 0
      src/uni_modules/lime-echart/components/lime-echart/lime-echart.vue
  11. 16 11
      src/uni_modules/lime-echart/package.json
  12. 220 52
      src/uni_modules/lime-echart/readme.md
  13. 16 1
      src/uni_modules/lime-echart/static/echarts.min.js
  14. 177 0
      src/uni_modules/lime-echart/static/nvue.html
  15. 0 0
      src/uni_modules/lime-echart/static/uni.webview.1.5.5.js
  16. 173 0
      src/uni_modules/lime-echart/static/uvue.html
  17. 2 0
      src/uni_modules/uni-badge/changelog.md
  18. 3 3
      src/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
  19. 1 1
      src/uni_modules/uni-badge/package.json
  20. 15 7
      src/uni_modules/uni-calendar/changelog.md
  21. 4 5
      src/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
  22. 25 20
      src/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
  23. 12 2
      src/uni_modules/uni-calendar/components/uni-calendar/util.js
  24. 1 1
      src/uni_modules/uni-calendar/package.json
  25. 3 3
      src/uni_modules/uni-calendar/readme.md
  26. 2 0
      src/uni_modules/uni-data-checkbox/changelog.md
  27. 3 3
      src/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
  28. 1 1
      src/uni_modules/uni-data-checkbox/package.json
  29. 11 0
      src/uni_modules/uni-data-picker/changelog.md
  30. 380 0
      src/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.uvue
  31. 10 6
      src/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
  32. 0 0
      src/uni_modules/uni-data-picker/components/uni-data-pickerview/loading.uts
  33. 693 0
      src/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.uts
  34. 76 0
      src/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.css
  35. 69 0
      src/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.uvue
  36. 17 15
      src/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
  37. 4 3
      src/uni_modules/uni-data-picker/package.json
  38. 1 1
      src/uni_modules/uni-data-picker/readme.md
  39. 15 0
      src/uni_modules/uni-data-select/changelog.md
  40. 144 57
      src/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue
  41. 1 1
      src/uni_modules/uni-data-select/package.json
  42. 82 33
      src/uni_modules/uni-datetime-picker/changelog.md
  43. 3 13
      src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
  44. 129 125
      src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
  45. 1 1
      src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json
  46. 16 36
      src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue
  47. 336 287
      src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
  48. 203 192
      src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
  49. 1 1
      src/uni_modules/uni-datetime-picker/package.json
  50. 18 1
      src/uni_modules/uni-easyinput/changelog.md
  51. 122 137
      src/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
  52. 1 1
      src/uni_modules/uni-easyinput/package.json
  53. 2 0
      src/uni_modules/uni-fab/changelog.md
  54. 3 2
      src/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
  55. 1 1
      src/uni_modules/uni-fab/package.json
  56. 8 0
      src/uni_modules/uni-file-picker/changelog.md
  57. 25 2
      src/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
  58. 23 2
      src/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
  59. 4 7
      src/uni_modules/uni-file-picker/package.json
  60. 4 0
      src/uni_modules/uni-forms/changelog.md
  61. 7 11
      src/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
  62. 1 1
      src/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
  63. 1 1
      src/uni_modules/uni-forms/package.json
  64. 18 0
      src/uni_modules/uni-icons/changelog.md
  65. 91 0
      src/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
  66. 31 17
      src/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
  67. 32 31
      src/uni_modules/uni-icons/components/uni-icons/uniicons.css
  68. BIN
      src/uni_modules/uni-icons/components/uni-icons/uniicons.ttf
  69. 664 0
      src/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts
  70. 649 0
      src/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js
  71. 14 12
      src/uni_modules/uni-icons/package.json
  72. 26 0
      src/uni_modules/uni-list/changelog.md
  73. 62 7
      src/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
  74. 94 14
      src/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
  75. 100 85
      src/uni_modules/uni-list/components/uni-list/uni-list.vue
  76. 4 7
      src/uni_modules/uni-list/package.json
  77. 4 0
      src/uni_modules/uni-nav-bar/changelog.md
  78. 1 1
      src/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
  79. 1 4
      src/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
  80. 1 1
      src/uni_modules/uni-nav-bar/package.json
  81. 2 0
      src/uni_modules/uni-notice-bar/changelog.md
  82. 5 0
      src/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
  83. 1 1
      src/uni_modules/uni-notice-bar/package.json
  84. 6 0
      src/uni_modules/uni-number-box/changelog.md
  85. 3 3
      src/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue
  86. 4 7
      src/uni_modules/uni-number-box/package.json
  87. 16 0
      src/uni_modules/uni-popup/changelog.md
  88. 41 18
      src/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
  89. 1 1
      src/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
  90. 90 0
      src/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue
  91. 4 10
      src/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
  92. 5 8
      src/uni_modules/uni-popup/package.json
  93. 4 0
      src/uni_modules/uni-search-bar/changelog.md
  94. 1 1
      src/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json
  95. 1 1
      src/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json
  96. 6 3
      src/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue
  97. 4 7
      src/uni_modules/uni-search-bar/package.json
  98. 6 0
      src/uni_modules/uni-swipe-action/changelog.md
  99. 2 2
      src/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
  100. 4 2
      src/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js

+ 43 - 0
src/uni_modules/lime-echart/changelog.md

@@ -1,3 +1,46 @@
+## 0.8.4(2024-01-27)
+- chore: 更新文档
+## 0.8.3(2024-01-21)
+- chore: 更新文档
+## 0.8.2(2024-01-21)
+- feat: 支持 `uvue`
+## 0.8.1(2023-08-24)
+- fix: app 的`touch`事件为`object` 导致无法显示 `tooltip`
+## 0.8.0(2023-08-22)
+- fix: 离屏 报错问题
+- fix: 微信小程序PC无法使用事件
+- chore: 更新文档
+## 0.7.9(2023-07-29)
+- chore: 更新文档
+## 0.7.8(2023-07-29)
+- fix: 离屏 报错问题
+## 0.7.7(2023-07-27)
+- chore: 更新文档
+- chore: lime-echart 里的示例使用自定tooltips
+- feat: 对支持离屏的使用离屏创建(微信、字节、支付宝)
+## 0.7.6(2023-06-30)
+- fix: vue3 报`width`的错
+## 0.7.5(2023-05-25)
+- chore: 更新文档 和 demo, 使用`lime-echart`这个标签即可查看示例
+## 0.7.4(2023-05-22)
+- chore: 增加关于钉钉小程序上传时提示安全问题的说明及修改建议
+## 0.7.3(2023-05-16)
+- chore: 更新 vue3 非微信小程序平台可能缺少`wx`的说明
+## 0.7.2(2023-05-16)
+- chore: 更新 vue3 非微信小程序平台的可以缺少`wx`的说明
+## 0.7.1(2023-04-26)
+- chore: 更新demo,使用`lime-echart`这个标签即可查看示例
+- chore:微信小程序的`tooltip`文字有阴影,怀疑是微信的锅,临时解决方法是`tooltip.shadowBlur = 0`
+## 0.7.0(2023-04-24)
+- fix: 修复`setAttribute is not a function`
+## 0.6.9(2023-04-15)
+- chore: 更新文档,vue3请使用echarts esm的包
+## 0.6.8(2023-03-22)
+- feat: mac pc无法使用canvas 2d
+## 0.6.7(2023-03-17)
+- feat: 更新文档
+## 0.6.6(2023-03-17)
+- feat: 微信小程序PC已经支持canvas 2d,故去掉判断PC
 ## 0.6.5(2022-11-03)
 - fix: 某些手机touches为对象,导致无法交互。
 ## 0.6.4(2022-10-28)

+ 30 - 17
src/uni_modules/lime-echart/components/l-echart/canvas.js

@@ -124,7 +124,9 @@ export class Canvas {
 		this.tagName = 'canvas'
 		this.canvasNode = canvasNode;
 		this.com = com;
-		if (!isNew) {this._initStyle(ctx)}
+		if (!isNew) {
+			this._initStyle(ctx)
+		}
 		this._initEvent();
 		this._ee = new EventEmit()
 	}
@@ -133,6 +135,11 @@ export class Canvas {
 			return this.ctx;
 		}
 	}
+	setAttribute(key, value) {
+		if(key === 'aria-label') {
+			this.com['ariaLabel'] = value
+		}
+	}
 	setChart(chart) {
 		this.chart = chart;
 	}
@@ -171,13 +178,13 @@ export class Canvas {
 		this._ee.off(type, listener)
 	}
 	_initCanvas(zrender, ctx) {
-		zrender.util.getContext = function() {
-			return ctx;
-		};
-		zrender.util.$override('measureText', function(text, font) {
-			ctx.font = font || '12px sans-serif';
-			return ctx.measureText(text, font);
-		});
+		// zrender.util.getContext = function() {
+		// 	return ctx;
+		// };
+		// zrender.util.$override('measureText', function(text, font) {
+		// 	ctx.font = font || '12px sans-serif';
+		// 	return ctx.measureText(text, font);
+		// });
 	}
 	_initStyle(ctx, child) {
 		const styles = [
@@ -194,17 +201,17 @@ export class Canvas {
 			'lineJoin',
 			'lineDash',
 			'miterLimit',
-			'font'
+			// 'font'
 		];
 		const colorReg = /#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])\b/g;
 		styles.forEach(style => {
 			Object.defineProperty(ctx, style, {
 				set: value => {
-					if (style === 'font' && fontSizeReg.test(value)) {
-						const match = fontSizeReg.exec(value);
-						ctx.setFontSize(match[1]);
-						return;
-					}
+					// if (style === 'font' && fontSizeReg.test(value)) {
+					// 	const match = fontSizeReg.exec(value);
+					// 	ctx.setFontSize(match[1]);
+					// 	return;
+					// }
 					if (style === 'opacity') {
 						ctx.setGlobalAlpha(value)
 						return;
@@ -260,13 +267,15 @@ export class Canvas {
 				return len;
 			}
 			ctx.measureText = (text, font) => {
-				let fontSize = 12;
+				let fontSize = ctx?.state?.fontSize || 12;
 				if (font) {
 					fontSize = parseInt(font.match(/([\d\.]+)px/)[1])
 				}
 				fontSize /= 2;
+				let isBold = fontSize >= 16;
+				const widthFactor = isBold ? 1.3 : 1;
 				return {
-					width: strLen(text) * fontSize
+					width: strLen(text) * fontSize * widthFactor
 				};
 			}
 		}
@@ -334,6 +343,9 @@ export function dispatch(name, {x,y, wheelDelta}) {
 }
 export function setCanvasCreator(echarts, {canvas, node}) {
 	// echarts.setCanvasCreator(() => canvas);
+	if(echarts && !echarts.registerPreprocessor) {
+		return console.warn('echarts 版本不对或未传入echarts,vue3请使用esm格式')
+	}
 	echarts.registerPreprocessor(option => {
 		if (option && option.series) {
 			if (option.series.length > 0) {
@@ -365,7 +377,8 @@ export function setCanvasCreator(echarts, {canvas, node}) {
 		echarts.setPlatformAPI({
 			loadImage: canvas.setChart ? loadImage : null,
 			createCanvas(){
-				return canvas
+				const key = 'createOffscreenCanvas'
+				return uni.canIUse(key) && uni[key] ? uni[key]({type: '2d'}) : canvas
 			}
 		})
 	}

+ 141 - 0
src/uni_modules/lime-echart/components/l-echart/l-echart.uvue

@@ -0,0 +1,141 @@
+<template>
+	<web-view class="lime-echart" ref="limeEchart" :style="[customStyle]" :webview-styles="[webviewStyles]"
+		src="/uni_modules/lime-echart/static/uvue.html?v=1011">
+	</web-view>
+</template>
+
+<script lang="uts">
+	import { Echarts } from './uvue';
+	type EchartsResolve = (value : Echarts) => void
+	export default {
+		name: 'l-echart',
+		props: {
+			webviewStyles: {
+				type: Object
+			},
+			customStyle: {
+				type: Object
+			},
+			isDisableScroll: {
+				type: Boolean,
+				default: false
+			},
+			isClickable: {
+				type: Boolean,
+				default: true
+			},
+			enableHover: {
+				type: Boolean,
+				default: false
+			},
+			beforeDelay: {
+				type: Number,
+				default: 30
+			}
+		},
+		data() {
+			return {
+				finished: false,
+				map: [] as EchartsResolve[],
+				context: null as UniWebViewElement | null,
+				// el: null as  UniWebViewElement | null,
+				chart: null as Echarts | null
+			};
+		},
+		computed: {
+
+		},
+		unmounted() {
+
+		},
+		created() {
+
+		},
+		mounted() {
+			this.createSelectorQuery().select('.lime-echart').boundingClientRect(_ => {
+				const context = this.$el as UniWebViewElement
+				this.context = context
+				// context.addEventListener('error', (_ : WebViewErrorEvent) => { })
+				// context.addEventListener('loading', (_ : WebViewLoadingEvent) => { })
+				context.addEventListener('loaded', (event : WebViewLoadedEvent) => {
+					this.finished = true
+					event.stopPropagation()
+					event.preventDefault()
+					this.trigger()
+					this.$emit('finished')
+				})
+				
+			}).exec()
+
+		},
+		methods: {
+			_next() {
+				if (this.chart == null) {
+					console.warn(`组件还未初始化,请先使用 init`)
+					return
+				}
+			},
+			setOption(option : UTSJSONObject) {
+				this._next()
+				this.chart?.setOption(option);
+			},
+			showLoading() {
+				this._next()
+				this.chart?.showLoading();
+			},
+			hideLoading() {
+				this._next()
+				this.chart?.hideLoading();
+			},
+			clear() { 
+				this._next()
+				this.chart?.clear();
+			},
+			dispose() {
+				this._next()
+				this.chart?.dispose();
+			},
+			resize(size:UTSJSONObject) { 
+				this._next()
+				this.chart?.resize(size);
+			},
+			canvasToTempFilePath(opt: UTSJSONObject) {
+				this._next()
+				this.chart?.canvasToTempFilePath(opt)
+			},
+			trigger() {
+				if (this.finished) {
+					if (this.chart == null) {
+						this.chart = new Echarts(this.context!)
+					}
+					while (this.map.length > 0) {
+						const resolve = this.map.pop() as EchartsResolve
+						resolve(this.chart!)
+					}
+				}
+			},
+			init() : Promise<Echarts> {
+				return new Promise((resolve) => {
+					this.map.push(resolve)
+					this.trigger()
+				})
+			},
+			init(callback : (chart : Echarts) => void) : Promise<Echarts> {
+				if (this.chart !== null) {
+					callback(this.chart!)
+				} else {
+					console.warn('echarts 未加载完成,您可以延时一下')
+				}
+				return new Promise((resolve) => {
+					this.map.push(resolve)
+					this.trigger()
+				})
+			}
+		}
+	};
+</script>
+<style lang="scss">
+	.lime-echart {
+		flex: 1;
+	}
+</style>

+ 145 - 155
src/uni_modules/lime-echart/components/l-echart/l-echart.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="lime-echart" :style="customStyle" v-if="canvasId" ref="limeEchart">
+	<view class="lime-echart" :style="customStyle" v-if="canvasId" ref="limeEchart" :aria-label="ariaLabel">
 		<!-- #ifndef APP-NVUE -->
 		<canvas
 			class="lime-echart__canvas"
@@ -12,9 +12,9 @@
 			@touchmove="touchMove"
 			@touchend="touchEnd"
 		/>
-		<canvas
+		<!-- <canvas
 			class="lime-echart__canvas"
-			v-else-if="isPc"
+			v-else-if="isPC"
 			:style="canvasStyle"
 			:id="canvasId"
 			:canvas-id="canvasId"
@@ -22,7 +22,7 @@
 			@mousedown="touchStart"
 			@mousemove="touchMove"
 			@mouseup="touchEnd"
-		/>
+		/> -->
 		<canvas
 			class="lime-echart__canvas"
 			v-else
@@ -36,6 +36,15 @@
 			@touchmove="touchMove"
 			@touchend="touchEnd"
 		/>
+		<view class="lime-echart__mask"
+			v-if="isPC"
+			@mousedown="touchStart"
+			@mousemove="touchMove"
+			@mouseup="touchEnd"
+			@touchstart="touchStart"
+			@touchmove="touchMove"
+			@touchend="touchEnd">
+		</view>
 		<canvas v-if="isOffscreenCanvas" :style="offscreenStyle" :canvas-id="offscreenCanvasId"></canvas>
 		<!-- #endif -->
 		<!-- #ifdef APP-NVUE -->
@@ -45,7 +54,7 @@
 			:style="canvasStyle"
 			:webview-styles="webviewStyles"
 			ref="webview"
-			src="/uni_modules/lime-echart/static/index.html"
+			src="/uni_modules/lime-echart/static/nvue.html?v=1"
 			@pagefinish="finished = true"
 			@onPostMessage="onMessage"
 		></web-view>
@@ -61,10 +70,11 @@ global = {}
 // #endif
 // #ifndef APP-NVUE
 import {Canvas, setCanvasCreator, dispatch} from './canvas';
-import { compareVersion, wrapTouch, devicePixelRatio ,sleep} from './utils';
+import {wrapTouch, convertTouchesToArray, devicePixelRatio ,sleep, canIUseCanvas2d, getRect} from './utils';
 // #endif
 // #ifdef APP-NVUE
 import { base64ToPath, sleep } from './utils';
+import {Echarts} from './nvue'
 // #endif
 const charts = {}
 const echartsObj = {}
@@ -101,17 +111,18 @@ export default {
 			// #ifndef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY
 			use2dCanvas: false,
 			// #endif
+			ariaLabel: '图表',
 			width: null,
 			height: null,
 			nodeWidth: null,
 			nodeHeight: null,
-			canvasNode: null,
+			// canvasNode: null,
 			config: {},
 			inited: false,
 			finished: false,
 			file: '',
 			platform: '',
-			isPc: false,
+			isPC: false,
 			isDown: false,
 			isOffscreenCanvas: false,
 			offscreenWidth: 0,
@@ -132,42 +143,40 @@ export default {
 			return  this.width && this.height ? ('width:' + this.width + 'px;height:' + this.height + 'px') : ''
 		}
 	},
+	// #ifndef VUE3
 	beforeDestroy() {
 		this.clear()
 		this.dispose()
 		// #ifdef H5
-		if(this.isPc) {
-			document.removeEventListener('mousewheel')
+		if(this.isPC) {
+			document.removeEventListener('mousewheel', this.mousewheel)
+		}
+		// #endif
+	},
+	// #endif
+	// #ifdef VUE3
+	beforeUnmount() {
+		this.clear()
+		this.dispose()
+		// #ifdef H5
+		if(this.isPC) {
+			document.removeEventListener('mousewheel', this.mousewheel)
 		}
 		// #endif
 	},
+	// #endif
 	created() {
 		// #ifdef H5
 		if(!('ontouchstart' in window)) {
-			this.isPc = true
-			document.addEventListener('mousewheel', (e) => {
-				if(this.chart) {
-					const touch = this.getTouch(e)
-					const handler = this.chart.getZr().handler;
-					dispatch.call(handler, 'mousewheel', touch)
-				}
-			})
+			this.isPC = true
+			document.addEventListener('mousewheel', this.mousewheel)
 		}
 		// #endif
 		// #ifdef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY
-		const { SDKVersion, version, platform, environment } = uni.getSystemInfoSync();
-		// #endif
-		// #ifdef MP-WEIXIN
+		const { platform } = uni.getSystemInfoSync();
 		this.isPC = /windows/i.test(platform)
-		this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '2.9.2') >= 0 && !((/ios/i.test(platform) && /7.0.20/.test(version)) || /wxwork/i.test(environment)) && !this.isPC;
-		// #endif
-		// #ifdef MP-TOUTIAO
-		this.isPC = /devtools/i.test(platform)
-		this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '1.78.0') >= 0;
-		// #endif
-		// #ifdef MP-ALIPAY
-		this.use2dCanvas = this.type === '2d' && compareVersion(my.SDKVersion, '2.7.0') >= 0;
 		// #endif
+		this.use2dCanvas = this.type === '2d' && canIUseCanvas2d()
 	},
 	mounted() {
 		this.$nextTick(() => {
@@ -178,11 +187,15 @@ export default {
 		// #ifdef APP-NVUE
 		onMessage(e) {
 			const res = e?.detail?.data[0] || null;
-			if (res?.event) {
+			 if (res?.event) {
+				 const data = JSON.parse(res.data)
 				if(res.event === 'inited') {
 					this.inited = true
+				} else if(res.event.startsWith('@')){
+					this.chart.dispatchAction(res.event.split('@')[1], data.options)
 				}
-				this.$emit(res.event, JSON.parse(res.data));
+				
+				this.$emit(res.event, data);
 			} else if(res?.file){
 				this.file = res.data
 			} else if(!res[0] && JSON.stringify(res[0]) != '{}'){
@@ -202,7 +215,7 @@ export default {
 			}
 			// #ifdef APP-NVUE
 			if(typeof callback === 'function') {
-				this.$refs.webview.evalJs(`setChart(${JSON.stringify(callback.toString())}, ${JSON.stringify(this.roptions)})`);
+				this.$refs.webview.evalJs(`setChart(${JSON.stringify(callback.toString())}, ${JSON.stringify(this.chart.options)})`);
 			}
 			// #endif
 		},
@@ -211,51 +224,26 @@ export default {
 				console.warn(`组件还未初始化,请先使用 init`)
 				return
 			}
-			// #ifndef APP-NVUE
 			this.chart.setOption(...arguments);
-			// #endif
-			// #ifdef APP-NVUE
-			this.$refs.webview.evalJs(`setOption(${JSON.stringify(arguments)})`);
-			// #endif
 		},
 		showLoading() {
 			if(this.chart) {
-				// #ifndef APP-NVUE
 				this.chart.showLoading(...arguments)
-				// #endif
-				// #ifdef APP-NVUE
-				this.$refs.webview.evalJs(`showLoading(${JSON.stringify(arguments)})`);
-				// #endif
 			}
 		},
 		hideLoading() {
 			if(this.chart) {
-				// #ifndef APP-NVUE
 				this.chart.hideLoading()
-				// #endif
-				// #ifdef APP-NVUE
-				this.$refs.webview.evalJs(`hideLoading()`);
-				// #endif
 			}
 		},
 		clear() {
 			if(this.chart) {
-				// #ifndef APP-NVUE
 				this.chart.clear()
-				// #endif
-				// #ifdef APP-NVUE
-				this.$refs.webview.evalJs(`clear()`);
-				// #endif
 			}
 		},
 		dispose() {
 			if(this.chart) {
-				// #ifndef APP-NVUE
 				this.chart.dispose()
-				// #endif
-				// #ifdef APP-NVUE
-				this.$refs.webview.evalJs(`dispose()`);
-				// #endif
 			}
 		},
 		resize(size) {
@@ -263,12 +251,8 @@ export default {
 				this.height = size.height
 				this.width = size.width
 				if(this.chart) {this.chart.resize(size)}
-				// #ifdef APP-NVUE
-				this.$refs.webview.evalJs(`resize(${size})`);
-				// #endif
 			} else {
 				this.$nextTick(() => {
-					// #ifndef APP-NVUE
 					uni.createSelectorQuery()
 						.in(this)
 						.select(`.lime-echart`)
@@ -281,10 +265,6 @@ export default {
 								this.chart.resize({width, height})
 							}
 						});
-					// #endif
-					// #ifdef APP-NVUE
-					this.$refs.webview.evalJs(`resize()`);
-					// #endif
 				})
 				
 			}
@@ -292,7 +272,7 @@ export default {
 		},
 		canvasToTempFilePath(args = {}) {
 			// #ifndef APP-NVUE
-			const { use2dCanvas, canvasId, canvasNode } = this;
+			const { use2dCanvas, canvasId } = this;
 			return new Promise((resolve, reject) => {
 				const copyArgs = Object.assign({
 					canvasId,
@@ -301,7 +281,7 @@ export default {
 				}, args);
 				if (use2dCanvas) {
 					delete copyArgs.canvasId;
-					copyArgs.canvas = canvasNode;
+					copyArgs.canvas = this.canvasNode;
 				}
 				uni.canvasToTempFilePath(copyArgs, this);
 			});
@@ -322,15 +302,9 @@ export default {
 			// #endif
 		},
 		async init(echarts, ...args) {
-			// #ifdef APP-NVUE
-			if(arguments && !arguments.length) {
-				console.error('缺少参数:init(theme?:string, opts?: object, callback: function)')
-				return
-			}
-			// #endif
 			// #ifndef APP-NVUE
-			if(arguments && arguments.length < 2) {
-				console.error('缺少参数:init(echarts, theme?:string, opts?: object, callback: function)')
+			if(arguments && arguments.length < 1) {
+				console.error('缺少参数:init(echarts, theme?:string, opts?: object, callback?: function)')
 				return
 			}
 			// #endif
@@ -353,25 +327,21 @@ export default {
 			}
 			let config = await this.getContext();
 			// #ifndef APP-NVUE
+			setCanvasCreator(echarts, config)
+			this.chart = echarts.init(config.canvas, theme, Object.assign({}, config, opts))
 			if(typeof callback === 'function') {
-				setCanvasCreator(echarts, config)
-				this.chart = echarts.init(config.canvas, theme, Object.assign({}, config, opts))
 				callback(this.chart)
 			} else {
-				console.error('callback 非 function')
+				return this.chart
 			}
 			// #endif
 			// #ifdef APP-NVUE
+			this.chart = new Echarts(this.$refs.webview)
+			this.$refs.webview.evalJs(`init(null, null, ${JSON.stringify(opts)}, ${theme})`)
 			if(callback) {
-				this.chart = {
-					setOption: (options) => {
-						this.roptions = options
-					}
-				}
 				callback(this.chart)
-				this.$refs.webview.evalJs(`init(${JSON.stringify(callback.toString())}, ${JSON.stringify(this.roptions)}, ${JSON.stringify(opts)}, ${theme})`)
 			} else {
-				console.error('callback 非 function')
+				return this.chart
 			}
 			// #endif
 		},
@@ -389,92 +359,95 @@ export default {
 			})
 			// #endif
 			// #ifndef APP-NVUE
-			const { use2dCanvas} = this;
-			let dpr = devicePixelRatio
-			if (use2dCanvas) {
-				return new Promise(resolve => {
-					uni.createSelectorQuery()
-						.in(this)
-						.select(`#${this.canvasId}`)
-						.fields({
-							node: true,
-							size: true
-						})
-						.exec(res => {
-							let { node, width, height } = res[0];
-							this.width = width = width || 300;
-							this.height = height = height || 300;
-							const ctx = node.getContext('2d');
-							const canvas = new Canvas(ctx, this, true, node);
-							this.canvasNode = node
-							resolve({ canvas, width, height, devicePixelRatio: dpr, node });
-						});
-				});
-			}
-			return new Promise(resolve => {
-				uni.createSelectorQuery()
-					.in(this)
-					.select(`#${this.canvasId}`)
-					.boundingClientRect()
-					.exec(res => {
-						if (res) {
-							let { width, height } = res[0];
-							this.width = width = width || 300;
-							this.height = height = height || 300;
-							// #ifdef MP-TOUTIAO
-							dpr = !this.isPC ? devicePixelRatio : 1// 1.25
-							// #endif
-							// #ifndef MP-ALIPAY || MP-TOUTIAO
-							dpr = this.isPC ? devicePixelRatio : 1
-							// #endif
-							// #ifdef MP-ALIPAY || MP-LARK
-							dpr = devicePixelRatio
-							// #endif
-							this.rect = res[0]
-							this.nodeWidth = width * dpr;
-							this.nodeHeight = height * dpr;
-							const ctx = uni.createCanvasContext(this.canvasId, this);
-							const canvas =  new Canvas(ctx, this, false);
-							resolve({ canvas, width, height, devicePixelRatio: dpr });
-						}
-					});
-			});
+			return getRect(`#${this.canvasId}`, {context: this, type: this.use2dCanvas ? 'fields': 'boundingClientRect'}).then(res => {
+				if(res) {
+					let dpr = devicePixelRatio
+					let {width, height, node} = res
+					let canvas;
+					this.width = width = width || 300;
+					this.height = height = height || 300;
+					if(node) {
+						const ctx = node.getContext('2d');
+						canvas = new Canvas(ctx, this, true, node);
+						this.canvasNode = node
+					} else {
+						// #ifdef MP-TOUTIAO
+						dpr = !this.isPC ? devicePixelRatio : 1// 1.25
+						// #endif
+						// #ifndef MP-ALIPAY || MP-TOUTIAO
+						dpr = this.isPC ? devicePixelRatio : 1
+						// #endif
+						// #ifdef MP-ALIPAY || MP-LARK
+						dpr = devicePixelRatio
+						// #endif
+						this.rect = res
+						this.nodeWidth = width * dpr;
+						this.nodeHeight = height * dpr;
+						const ctx = uni.createCanvasContext(this.canvasId, this);
+						canvas =  new Canvas(ctx, this, false);
+					}
+					return { canvas, width, height, devicePixelRatio: dpr, node };
+				} else {
+					return {}
+				}
+			})
 			// #endif
 		},
 		// #ifndef APP-NVUE
-		getRelative(e) {
-			return {x: e.pageX - this.rect.left, y: e.pageY - this.rect.top, wheelDelta: e.wheelDelta}
+		getRelative(e, touches) {
+			let { clientX, clientY } = e
+			if(!(clientX && clientY) && touches && touches[0]) {
+				clientX = touches[0].clientX
+				clientY = touches[0].clientY
+			}
+			return {x: clientX - this.rect.left, y: clientY - this.rect.top, wheelDelta: e.wheelDelta || 0}
 		},
-		getTouch(e) {
-			return e.touches && e.touches[0] && e.touches[0].x ? e.touches[0] : this.getRelative(e);
+		getTouch(e, touches) {
+			const {x} = touches && touches[0] || {}
+			return x ? touches[0] : this.getRelative(e, touches);
 		},
 		touchStart(e) {
 			this.isDown = true
-			if (this.chart && ((e.touches.length > 0 || e.touches['0'])  && e.type != 'mousemove' || e.type == 'mousedown')) {
-				const touch = this.getTouch(e)
-				this.startX = touch.x
-				this.startY = touch.y
-				this.startT = new Date()
-				const handler = this.chart.getZr().handler;
-				dispatch.call(handler, 'mousedown', touch)
-				dispatch.call(handler, 'mousemove', touch)
-				handler.processGesture(wrapTouch(e), 'start');
-				clearTimeout(this.endTimer);
+			const next = () => {
+				const touches = convertTouchesToArray(e.touches)
+				if(this.chart) {
+					const touch = this.getTouch(e, touches)
+					this.startX = touch.x
+					this.startY = touch.y
+					this.startT = new Date()
+					const handler = this.chart.getZr().handler;
+					dispatch.call(handler, 'mousedown', touch)
+					dispatch.call(handler, 'mousemove', touch)
+					handler.processGesture(wrapTouch(e), 'start');
+					clearTimeout(this.endTimer);
+				}
+				
+			}
+			if(this.isPC) {
+				getRect(`#${this.canvasId}`, {context: this}).then(res => {
+					this.rect = res
+					next()
+				})
+				return
 			}
+			next()
 		},
 		touchMove(e) {
-			if(this.isPc && this.enableHover && !this.isDown) {this.isDown = true}
-			if (this.chart && ((e.touches.length > 0 || e.touches['0']) && e.type != 'mousemove' || e.type == 'mousemove' && this.isDown)) {
+			if(this.isPC && this.enableHover && !this.isDown) {this.isDown = true}
+			const touches = convertTouchesToArray(e.touches)
+			if (this.chart && this.isDown) {
 				const handler = this.chart.getZr().handler;
-				dispatch.call(handler, 'mousemove', this.getTouch(e))
+				dispatch.call(handler, 'mousemove', this.getTouch(e, touches))
 				handler.processGesture(wrapTouch(e), 'change');
 			}
+			
 		},
 		touchEnd(e) {
 			this.isDown = false
 			if (this.chart) {
-				const {x} = e.changedTouches && e.changedTouches[0] || {}
-				const touch = (x ? e.changedTouches[0] : this.getRelative(e)) || {};
+				const touches = convertTouchesToArray(e.changedTouches)
+				const {x} = touches && touches[0] || {}
+				const touch = (x ? touches[0] : this.getRelative(e, touches)) || {};
 				const handler = this.chart.getZr().handler;
 				const isClick = Math.abs(touch.x - this.startX) < 10 && new Date() - this.startT < 200;
 				dispatch.call(handler, 'mouseup', touch)
@@ -488,12 +461,19 @@ export default {
 					},50)
 				}
 			}
+		},
+		// #endif
+		// #ifdef H5
+		mousewheel(e){
+			if(this.chart) {
+				dispatch.call(this.chart.getZr().handler, 'mousewheel', this.getTouch(e))
+			}
 		}
 		// #endif
 	}
 };
 </script>
-<style scoped>
+<style>	
 .lime-echart {
 	position: relative;
 	/* #ifndef APP-NVUE */
@@ -513,4 +493,14 @@ export default {
 	flex: 1;
 	/* #endif */
 }
+/* #ifndef APP-NVUE */
+.lime-echart__mask {
+	position: absolute;
+	width: 100%;
+	height: 100%;
+	left: 0;
+	top: 0;
+	z-index: 1;
+}
+/* #endif */
 </style>

+ 51 - 0
src/uni_modules/lime-echart/components/l-echart/nvue.js

@@ -0,0 +1,51 @@
+export class Echarts {
+	eventMap = new Map()
+	constructor(webview) {
+		this.webview = webview
+		this.options = null
+	}
+	setOption() {
+		this.options = arguments
+		this.webview.evalJs(`setOption(${JSON.stringify(arguments)})`);
+	}
+	getOption() {
+		return this.options
+	}
+	showLoading() {
+		this.webview.evalJs(`showLoading(${JSON.stringify(arguments)})`);
+	}
+	hideLoading() {
+		this.webview.evalJs(`hideLoading()`);
+	}
+	clear() {
+		this.webview.evalJs(`clear()`);
+	}
+	dispose() {
+		this.webview.evalJs(`dispose()`);
+	}
+	resize(size) {
+		if(size) {
+			this.webview.evalJs(`resize(${size})`);
+		} else {
+			this.webview.evalJs(`resize()`);
+		}
+	}
+	on(type, ...args) {
+		const query = args[0]
+		const useQuery = query && typeof query != 'function'
+		const param = useQuery ? [type, query] : [type]
+		const key = `${type}${useQuery ? JSON.stringify(query): '' }`
+		const callback = useQuery ? args[1]: args[0]
+		if(typeof callback == 'function'){
+			this.eventMap.set(key, callback)
+		}
+		this.webview.evalJs(`on(${JSON.stringify(param)})`);
+		console.warn('nvue 暂不支持事件')
+	}
+	dispatchAction(type, options){
+		const handler = this.eventMap.get(type)
+		if(handler){
+			handler(options)
+		}
+	}
+}

+ 83 - 12
src/uni_modules/lime-echart/components/l-echart/utils.js

@@ -22,16 +22,59 @@ export function compareVersion(v1, v2) {
 	}
 	return 0
 }
+const systemInfo = uni.getSystemInfoSync();
+
+function gte(version) {
+	// 截止 2023-03-22 mac pc小程序不支持 canvas 2d
+	let {
+		SDKVersion,
+		platform
+	} = systemInfo;
+	// #ifdef MP-ALIPAY
+	SDKVersion = my.SDKVersion
+	// #endif
+	// #ifdef MP-WEIXIN
+	return platform !== 'mac' && compareVersion(SDKVersion, version) >= 0;
+	// #endif
+	return compareVersion(SDKVersion, version) >= 0;
+}
+
+
+export function canIUseCanvas2d() {
+	// #ifdef MP-WEIXIN
+	return gte('2.9.0');
+	// #endif
+	// #ifdef MP-ALIPAY
+	return gte('2.7.0');
+	// #endif
+	// #ifdef MP-TOUTIAO
+	return gte('1.78.0');
+	// #endif
+	return false
+}
+
+export function convertTouchesToArray(touches) {
+	// 如果 touches 是一个数组,则直接返回它
+	if (Array.isArray(touches)) {
+		return touches;
+	}
+	// 如果touches是一个对象,则转换为数组
+	if (typeof touches === 'object' && touches !== null) {
+		return Object.values(touches);
+	}
+	// 对于其他类型,直接返回它
+	return touches;
+}
 
 export function wrapTouch(event) {
-  for (let i = 0; i < event.touches.length; ++i) {
-    const touch = event.touches[i];
-    touch.offsetX = touch.x;
-    touch.offsetY = touch.y;
-  }
-  return event;
+	for (let i = 0; i < event.touches.length; ++i) {
+		const touch = event.touches[i];
+		touch.offsetX = touch.x;
+		touch.offsetY = touch.y;
+	}
+	return event;
 }
-export const devicePixelRatio = wx.getSystemInfoSync().pixelRatio
+export const devicePixelRatio = uni.getSystemInfoSync().pixelRatio
 // #endif
 // #ifdef APP-NVUE
 export function base64ToPath(base64) {
@@ -44,12 +87,12 @@ export function base64ToPath(base64) {
 			}
 			const time = new Date().getTime();
 			const filePath = `_doc/uniapp_temp/${time}.${format}`
-			
-			bitmap.save(filePath, {}, 
+
+			bitmap.save(filePath, {},
 				() => {
 					bitmap.clear()
 					resolve(filePath)
-				}, 
+				},
 				(error) => {
 					bitmap.clear()
 					console.error(`${JSON.stringify(error)}`)
@@ -69,6 +112,34 @@ export function sleep(time) {
 	return new Promise((resolve) => {
 		setTimeout(() => {
 			resolve(true)
-		},time)
+		}, time)
 	})
-}
+}
+
+
+export function getRect(selector, options = {}) {
+	const typeDefault = 'boundingClientRect'
+	const {
+		context,
+		type = typeDefault
+	} = options
+	return new Promise((resolve, reject) => {
+		const dom = uni.createSelectorQuery().in(context).select(selector);
+		const result = (rect) => {
+			if (rect) {
+				resolve(rect)
+			} else {
+				reject()
+			}
+		}
+		if (type == typeDefault) {
+			dom[type](result).exec()
+		} else {
+			dom[type]({
+				node: true,
+				size: true,
+				rect: true
+			}, result).exec()
+		}
+	});
+};

+ 105 - 0
src/uni_modules/lime-echart/components/l-echart/uvue.uts

@@ -0,0 +1,105 @@
+
+type EchartsEventHandler = (event: UTSJSONObject)=>void
+// type EchartsTempResolve = (obj : UTSJSONObject) => void
+// type EchartsTempOptions = UTSJSONObject
+export class Echarts {
+	options: UTSJSONObject = {} as UTSJSONObject
+	context: UniWebViewElement
+	eventMap: Map<string, EchartsEventHandler> = new Map()
+	private temp: UTSJSONObject[] = []
+	constructor(context: UniWebViewElement){
+		this.context = context
+		this.init()
+	}
+	init(){
+		this.context.evalJS(`init(null, null, ${JSON.stringify({})})`)
+		
+		this.context.addEventListener('message', (e : WebViewMessageEvent) => {
+			// event.stopPropagation()
+			// event.preventDefault()
+			const log = e.detail.data!.get('log')
+			const event = e.detail.data!.get('event')
+			const options = e.detail.data!.get('options')
+			const file = e.detail.data!.get('file')
+			if (log != null) {
+				console.log(log)
+			}
+			if (event != null && options != null) {
+				this.dispatchAction(event as string, options as UTSJSONObject)
+			}
+			if(file != null){
+				while (this.temp.length > 0) {
+					const opt = this.temp.pop()
+					const success = opt?.get('success')
+					if(typeof success == 'function'){
+						success as (res: UTSJSONObject) => void
+						success({tempFilePath: file})
+					}
+				}
+			}
+			
+		})
+	}
+	setOption(option: UTSJSONObject){
+		this.options = option;
+		this.context.evalJS(`setOption(${JSON.stringify([option])})`)
+	}
+	setOption(option: UTSJSONObject, notMerge: boolean = false, lazyUpdate: boolean = false){
+		this.options = option;
+		this.context.evalJS(`setOption(${JSON.stringify([option, notMerge, lazyUpdate])})`)
+	}
+	setOption(option: UTSJSONObject, notMerge: UTSJSONObject){
+		this.options = option;
+		this.context.evalJS(`setOption(${JSON.stringify([option, notMerge])})`)
+	}
+	getOption(): UTSJSONObject {
+		return this.options
+	}
+	showLoading(){
+		this.context.evalJS(`showLoading(${JSON.stringify([] as any[])})`);
+	}
+	showLoading(type: string, opts: UTSJSONObject){
+		this.context.evalJS(`showLoading(${JSON.stringify([type, opts])})`);
+	}
+	hideLoading(){
+		this.context.evalJS(`hideLoading()`);
+	}
+	clear(){
+		this.context.evalJS(`clear()`);
+	}
+	dispose(){
+		this.context.evalJS(`dispose()`);
+	}
+	resize(size:UTSJSONObject){
+		this.context.evalJS(`resize(${JSON.stringify(size)})`);
+	}
+	resize(){
+		this.context.evalJS(`resize()`);
+	}
+	on(type:string, query: any, callback: EchartsEventHandler) {
+		const key = `${type}${JSON.stringify(query)}`
+		if(typeof callback == 'function'){
+			this.eventMap.set(key, callback)
+		}
+		this.context.evalJS(`on(${JSON.stringify([type, query])})`);
+		console.warn('uvue 暂不支持事件')
+	}
+	on(type:string, callback: EchartsEventHandler) {
+		const key = `${type}`
+		if(typeof callback == 'function'){
+			this.eventMap.set(key, callback)
+		}
+		this.context.evalJS(`on(${JSON.stringify([type])})`);
+		console.warn('uvue 暂不支持事件')
+	}
+	dispatchAction(type:string, options: UTSJSONObject){
+		const handler = this.eventMap.get(type)
+		if(handler!=null){
+			handler(options)
+		}
+	}
+	canvasToTempFilePath(opt: UTSJSONObject){
+		this.context.evalJS(`on(${JSON.stringify(opt)})`);
+		this.temp.push(opt)
+	}
+}

+ 95 - 0
src/uni_modules/lime-echart/components/lime-echart/lime-echart.nvue

@@ -0,0 +1,95 @@
+<template>
+	<view style="width: 100%; height: 408px;">
+		<l-echart ref="chartRef" @finished="init"></l-echart>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				showTip: false,
+				option: {
+					tooltip: {
+						trigger: 'axis',
+						// shadowBlur: 0,
+						textStyle: {
+							textShadowBlur: 0
+						},
+						renderMode: 'richText',
+					},
+					legend: {
+						data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
+					},
+					grid: {
+						left: '3%',
+						right: '4%',
+						bottom: '3%',
+						containLabel: true
+					},
+					xAxis: {
+						type: 'category',
+						boundaryGap: false,
+						data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
+					},
+					yAxis: {
+						type: 'value'
+					},
+					series: [
+						{
+							name: '邮件营销',
+							type: 'line',
+							stack: '总量',
+							data: [120, 132, 101, 134, 90, 230, 210]
+						},
+						{
+							name: '联盟广告',
+							type: 'line',
+							stack: '总量',
+							data: [220, 182, 191, 234, 290, 330, 310]
+						},
+						{
+							name: '视频广告',
+							type: 'line',
+							stack: '总量',
+							data: [150, 232, 201, 154, 190, 330, 410]
+						},
+						{
+							name: '直接访问',
+							type: 'line',
+							stack: '总量',
+							data: [320, 332, 301, 334, 390, 330, 320]
+						},
+						{
+							name: '搜索引擎',
+							type: 'line',
+							stack: '总量',
+							data: [820, 932, 901, 934, 1290, 1330, 1320]
+						}
+					]
+				}
+			}
+		},
+		mounted() {
+			console.log('lime echarts nvue')
+		},
+		methods: {
+			init() {
+				const chartRef = this.$refs['chartRef']
+				chartRef.init(chart => {
+					chart.setOption(this.option);
+				})
+			},
+			save() {
+				// this.$refs.chart.canvasToTempFilePath({
+				// 	success(res) {
+				// 		console.log('res::::', res)
+				// 	}
+				// })
+			}
+		}
+	}
+</script>
+<style>
+
+</style>

+ 96 - 0
src/uni_modules/lime-echart/components/lime-echart/lime-echart.uvue

@@ -0,0 +1,96 @@
+<template>
+	<view style="width: 100%; height: 408px;">
+		<l-echart ref="chartRef" @finished="init"></l-echart>
+	</view>
+</template>
+
+<script lang="uts">
+	export default {
+		data() {
+			return {
+				showTip: false,
+				option: {
+					tooltip: {
+						trigger: 'axis',
+						// shadowBlur: 0,
+						textStyle: {
+							textShadowBlur: 0
+						},
+						renderMode: 'richText',
+					},
+					legend: {
+						data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
+					},
+					grid: {
+						left: '3%',
+						right: '4%',
+						bottom: '3%',
+						containLabel: true
+					},
+					xAxis: {
+						type: 'category',
+						boundaryGap: false,
+						data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
+					},
+					yAxis: {
+						type: 'value'
+					},
+					series: [
+						{
+							name: '邮件营销',
+							type: 'line',
+							stack: '总量',
+							data: [120, 132, 101, 134, 90, 230, 210]
+						},
+						{
+							name: '联盟广告',
+							type: 'line',
+							stack: '总量',
+							data: [220, 182, 191, 234, 290, 330, 310]
+						},
+						{
+							name: '视频广告',
+							type: 'line',
+							stack: '总量',
+							data: [150, 232, 201, 154, 190, 330, 410]
+						},
+						{
+							name: '直接访问',
+							type: 'line',
+							stack: '总量',
+							data: [320, 332, 301, 334, 390, 330, 320]
+						},
+						{
+							name: '搜索引擎',
+							type: 'line',
+							stack: '总量',
+							data: [820, 932, 901, 934, 1290, 1330, 1320]
+						}
+					]
+				}
+			}
+		},
+		mounted() {
+			console.log('lime echarts uvue')
+		},
+		methods: {
+			init() {
+				const chartRef = this.$refs['chartRef'] as LEchartComponentPublicInstance
+				chartRef.init(chart => {
+					chart.setOption(this.option);
+					
+				})
+			},
+			save() {
+				// this.$refs.chart.canvasToTempFilePath({
+				// 	success(res) {
+				// 		console.log('res::::', res)
+				// 	}
+				// })
+			}
+		}
+	}
+</script>
+<style>
+
+</style>

+ 163 - 0
src/uni_modules/lime-echart/components/lime-echart/lime-echart.vue

@@ -0,0 +1,163 @@
+<template>
+	<view >
+		<view style="height: 750rpx; position: relative">
+			<l-echart ref="chart" @finished="init"></l-echart>
+			<view class="customTooltips" :style="{left: position[0] + 'px',top: position[1] + 'px'}" v-if="params.length && position.length && showTip">
+				<view>这是个自定的tooltips</view>
+				<view>{{params[0]['axisValue']}}</view>
+				<view v-for="item in params">
+					<view>
+						<text>{{item.seriesName}}</text>
+						<text>{{item.value}}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>		
+</template>
+
+<script>
+	// nvue 不需要引入
+	// #ifdef VUE2
+	import * as echarts from '@/uni_modules/lime-echart/static/echarts.min';
+	// #endif
+	// #ifdef VUE3
+	// #ifdef MP
+	// 由于vue3 使用vite 不支持umd格式的包,小程序依然可以使用,但需要使用require
+	const echarts = require('../../static/echarts.min');
+	// #endif
+	// #ifndef MP
+	// 由于 vue3 使用vite 不支持umd格式的包,故引入npm的包
+	import * as echarts from 'echarts/dist/echarts.esm';
+	// #endif
+	// #endif
+	export default {
+		data() {
+			return {
+				showTip: false,
+				position: [],
+				params: [],
+				option:  {
+					tooltip: {
+						trigger: 'axis',
+						// shadowBlur: 0,
+						textStyle: {
+							textShadowBlur : 0
+						},
+						renderMode: 'richText',
+						position: (point, params, dom, rect, size) => {
+							// 假设自定义的tooltips尺寸
+							const box = [170, 170]
+							// 偏移
+							const offsetX = point[0] < size.viewSize[0] / 2 ? 20 : -box[0] - 20;
+							const offsetY = point[1] < size.viewSize[1] / 2 ? 20 : -box[1] - 20;
+							const x = point[0] + offsetX;
+							const y = point[1] + offsetY;
+							
+							this.position = [x, y]
+							this.params = params
+						},
+						formatter: (params, ticket, callback) => {
+							
+						}
+					},
+					legend: {
+						data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
+					},
+					grid: {
+						left: '3%',
+						right: '4%',
+						bottom: '3%',
+						containLabel: true
+					},
+					xAxis: {
+						type: 'category',
+						boundaryGap: false,
+						data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
+					},
+					yAxis: {
+						type: 'value'
+					},
+					series: [
+						{
+							name: '邮件营销',
+							type: 'line',
+							stack: '总量',
+							data: [120, 132, 101, 134, 90, 230, 210]
+						},
+						{
+							name: '联盟广告',
+							type: 'line',
+							stack: '总量',
+							data: [220, 182, 191, 234, 290, 330, 310]
+						},
+						{
+							name: '视频广告',
+							type: 'line',
+							stack: '总量',
+							data: [150, 232, 201, 154, 190, 330, 410]
+						},
+						{
+							name: '直接访问',
+							type: 'line',
+							stack: '总量',
+							data: [320, 332, 301, 334, 390, 330, 320]
+						},
+						{
+							name: '搜索引擎',
+							type: 'line',
+							stack: '总量',
+							data: [820, 932, 901, 934, 1290, 1330, 1320]
+						}
+					]
+				}
+			}
+		},
+		
+		methods: {
+			init() {
+				// init(echarts, theme?:string, opts?:{}, chart => {})
+				// echarts 必填, 非nvue必填,nvue不用填
+				// theme 可选,应用的主题,目前只支持名称,如:'dark'
+				// opts = { // 可选
+				//	locale?: string  // 从 `5.0.0` 开始支持
+				// }
+				// chart => {} , callback 返回图表实例
+				// setTimeout(()=>{
+				// 	this.$refs.chart.init(echarts, chart => {
+				// 		chart.setOption(this.option);
+				// 	});
+				// },300)
+				this.$refs.chart.init(echarts, chart => {
+					chart.setOption(this.option);
+					
+					// 监听tooltip显示事件
+					chart.on('showTip', (params) => {
+					  this.showTip = true
+					  console.log('showTip::')
+					});
+					chart.on('hideTip', (params) => {
+						setTimeout(() => {
+							 this.showTip = false
+						},300)
+					});
+					
+				});
+			},
+			save() {
+				this.$refs.chart.canvasToTempFilePath({
+					success(res) {
+						console.log('res::::', res)
+					}
+				})
+			}
+		}
+	}
+</script>
+<style>
+	.customTooltips {
+		position: absolute;
+		background-color: rgba(255, 255, 255, 0.8);
+		padding: 20rpx;
+	}
+</style>

+ 16 - 11
src/uni_modules/lime-echart/package.json

@@ -1,7 +1,7 @@
 {
   "id": "lime-echart",
-  "displayName": "百度图表 echarts",
-  "version": "0.6.5",
+  "displayName": "echarts",
+  "version": "0.8.4",
   "description": "echarts 全端兼容,一款使echarts图表能跑在uniapp各端中的插件",
   "keywords": [
     "echarts",
@@ -13,7 +13,7 @@
   "engines": {
     "HBuilderX": "^3.6.4"
   },
-"dcloudext": {
+  "dcloudext": {
     "sale": {
       "regular": {
         "price": "0.00"
@@ -44,7 +44,8 @@
       "client": {
         "App": {
           "app-vue": "y",
-          "app-nvue": "y"
+          "app-nvue": "y",
+          "app-uvue": "y"
         },
         "H5-mobile": {
           "Safari": "y",
@@ -64,21 +65,25 @@
           "阿里": "y",
           "百度": "y",
           "字节跳动": "y",
-        "QQ": "y",
-        "钉钉": "u",
-        "快手": "u",
-        "飞书": "u",
-        "京东": "u"
+          "QQ": "y",
+          "钉钉": "u",
+          "快手": "u",
+          "飞书": "u",
+          "京东": "u"
         },
         "快应用": {
           "华为": "u",
           "联盟": "u"
         },
         "Vue": {
-            "vue2": "y",
-            "vue3": "y"
+          "vue2": "y",
+          "vue3": "y"
         }
       }
     }
+  },
+  "dependencies": {
+    "echarts": "^5.4.1",
+    "zrender": "^5.4.3"
   }
 }

+ 220 - 52
src/uni_modules/lime-echart/readme.md

@@ -11,45 +11,47 @@
 
 
 ## 安装
-- 第一步、在uniapp 插件市场 找到 [百度图表](https://ext.dcloud.net.cn/plugin?id=4899) 导入
-- 第二步、安装 echarts 或者直接使用插件内的echarts.min文件
-```cmd
-pnpm add echarts
- -or-
-npm install echarts
-```
-
+- 第一步:在市场导入 [百度图表](https://ext.dcloud.net.cn/plugin?id=4899) 
+- 第二步:选择插件依赖:
+  1、可以选插件内的`echarts`包或自定义包,自定义包[下载地址](https://echarts.apache.org/zh/builder.html)<br>
+  2、或者使用`npm`安装`echarts`	
 
 **注意** 
-* 🔔 必须使用hbuilderx 3.4.8-alpha及以上
 * 🔔 echarts 5.3.0及以上
-* 🔔 如果是 `cli` 项目需要主动 `import` 插件
-```js
-import LEchart from '@/uni_modules/lime-echart/components/l-echart/l-echart.vue';
-export default {
-	components: {LEchart}
-}
-```
+* 🔔 如果是 `cli` 项目请下载插件到`src`目录下的`uni_modules`,没有这个目录就创建一个
+
 
 ## 代码演示
-### 基础用法
+
+### Vue2
 ```html
-<view><l-echart ref="chart" @finished="init"></l-echart></view>
+<view style="width:750rpx; height:750rpx"><l-echart ref="chartRef" @finished="init"></l-echart></view>
 ```
 
+####  插件依赖 方式一:引入插件内的或自定义包
+- 引入插件内提供或自己下载的[自定义包](https://echarts.apache.org/zh/builder.html)
 ```js
-// 如果你使用插件内提供的echarts.min
-// 也可以自行去官网下载自定义覆盖
-// 这种方式仅限于vue2
+// 插件内的 二选一
 import * as echarts from '@/uni_modules/lime-echart/static/echarts.min'
-//---or----------------------------------
+// 自定义的 二选一 下载后放入项目的路径
+import * as echarts from 'xxx/echarts.min'
+```
+
+####  插件依赖 方式二:npm包
+- 自行安装 `echarts`
+- 可根据自己的需要全量引入或按需引入
 
-// 如果你使用 npm 安装了 echarts --------- 使用以下方式
-// 引入全量包
+```cmd
+pnpm add echarts
+ -or-
+npm install echarts
+```
+
+```js
+// 全量包  二选一
 import * as echarts from 'echarts'
-//---or----------------------------------
 
-// 按需引入 开始
+// 按需引入 二选一
 import * as echarts from 'echarts/core';
 import {LineChart, BarChart} from 'echarts/charts';
 import {TitleComponent,TooltipComponent,GridComponent, DatasetComponent, TransformComponent, LegendComponent } from 'echarts/components';
@@ -58,7 +60,7 @@ import {LabelLayout,UniversalTransition} from 'echarts/features';
 // 引入 Canvas 渲染器,注意引入 CanvasRenderer 是必须的一步
 import {CanvasRenderer} from 'echarts/renderers';
 
-// 注册必须的组件
+// 按需引入 注册必须的组件
 echarts.use([
 	LegendComponent,
 	TitleComponent,
@@ -72,9 +74,9 @@ echarts.use([
 	UniversalTransition,
 	CanvasRenderer
 ]);
-//-------------按需引入结束------------------------
-
+```
 
+```js
 export default {
 	data() {
 		return {
@@ -164,35 +166,116 @@ export default {
 		};
 	},
 	// 组件能被调用必须是组件的节点已经被渲染到页面上
-	// 1、在页面mounted里调用,有时候mounted 组件也未必渲染完成
-	mounted() {
-		// init(echarts, theme?:string, opts?:{}, chart => {})
-		// echarts 必填, 非nvue必填,nvue不用填
-		// theme 可选,应用的主题,目前只支持名称,如:'dark'
-		// opts = { // 可选
-		//	locale?: string  // 从 `5.0.0` 开始支持
-		// }
-		// chart => {} , callback 必填,返回图表实例
-		this.$refs.chart.init(echarts, chart => {
-			chart.setOption(this.option);
-		});
-	},
-	// 2、或者使用组件的finished事件里调用
 	methods: {
-		init() {
-			this.$refs.chart.init(echarts, chart => {
-				chart.setOption(this.option);
-			});
+		async init() {
+			// chart 图表实例不能存在data里
+			const chart = await this.$refs.chartRef.init(echarts);
+			chart.setOption(this.option)
 		}
 	}
 }
 ```
 
+### Vue3
+
+```html
+<view style="width:750rpx; height:750rpx"><l-echart ref="chart" @finished="init"></l-echart></view>
+```
+
+####  插件依赖 小程序引入插件内的包或自定义包
+- 引入插件内提供或自己下载的[自定义包](https://echarts.apache.org/zh/builder.html)
+- `require`仅支持相对路径,不支持路径别名
+
+```js
+// 插件内的 二选一 
+const echarts = require('../../uni_modules/lime-echart/static/echarts.min');
+// 自定义的 二选一 下载后放入项目的路径
+const echarts = require('xxx/xxx/echarts');
+```
+
+#### 非小程序端不支持引入插件内的包
+- 由于vue3使用的是vite 不支持非`esm`格式,故不支持引入插件内的包
+- 可使用`npm`包
+
+#### 插件依赖 方式二:npm包
+- 可自行安装 `echarts`
+- 可根据自己的需要全量引入或按需引入
+
+```cmd
+pnpm add echarts
+ -or-
+npm install echarts
+```
+
+```js
+// 全量包  二选一
+import * as echarts from 'echarts'
+
+// 按需引入 二选一
+import * as echarts from 'echarts/core';
+import {LineChart, BarChart} from 'echarts/charts';
+import {TitleComponent,TooltipComponent,GridComponent, DatasetComponent, TransformComponent, LegendComponent } from 'echarts/components';
+// 标签自动布局,全局过渡动画等特性
+import {LabelLayout,UniversalTransition} from 'echarts/features';
+// 引入 Canvas 渲染器,注意引入 CanvasRenderer 是必须的一步
+import {CanvasRenderer} from 'echarts/renderers';
+
+// 按需引入 注册必须的组件
+echarts.use([
+	LegendComponent,
+	TitleComponent,
+	TooltipComponent,
+	GridComponent,
+	DatasetComponent,
+	TransformComponent,
+	LineChart,
+	BarChart,
+	LabelLayout,
+	UniversalTransition,
+	CanvasRenderer
+]);
+```
+
+```js
+
+const chartRef = ref(null)
+
+onMounted( ()=>{
+	// 组件能被调用必须是组件的节点已经被渲染到页面上
+	setTimeout(async()=>{
+		if(!chartRef.value) return
+		const myChart = await chartRef.value.init(echarts)
+		myChart.setOption(data)
+	},300)
+})
+
+```
+
+
+### Uvue
+- Uvue和Nvue不需要引入`echarts`,因为它们的实现方式是`webview`
+
+```js
+methods: {
+	async init() {
+		const chartRef = this.$refs['chartRef'] as LEchartComponentPublicInstance
+		const myChart = await chartRef.init()
+		myChart.setOption(this.option)
+	}
+}
+```
+
+
 ## 数据更新
-- 使用 `ref` 可获取`setOption`设置更新
+- 1、使用 `ref` 可获取`setOption`设置更新
+- 2、也可以拿到图表实例`chart`设置`myChart.setOption(data)`
 
 ```js
+// ref
 this.$refs.chart.setOption(data)
+
+// 图表实例
+myChart.setOption(data)
 ```
 
 ## 图表大小
@@ -205,13 +288,99 @@ this.$refs.chart.resize()
 this.$refs.chart.resize({width: 375, height: 375})
 ```
 
+## 自定义Tooltips
+- uvue\nvue 不支持
+由于除H5之外都不存在dom,但又有tooltips个性化的需求,代码就不贴了,看示例吧
+```
+代码位于/uni_modules/lime-echart/component/lime-echart
+```
+
+
+## 插件标签
+- 默认 l-echart 为 component
+- 默认 lime-echart 为 demo
+```html
+ // 在任意地方使用可查看domo, 代码位于/uni_modules/lime-echart/component/lime-echart
+<lime-echart></lime-echart>
+```
+
 
 ## 常见问题
+- 钉钉小程序 由于没有`measureText`,模拟的`measureText`又无法得到当前字体的`fontWeight`,故可能存在估计不精细的问题
 - 微信小程序 `2d` 只支持 真机调试2.0
-- 微信开发工具会出现canvas不跟随页面的情况,真机不影响
+- 微信开发工具会出现 `canvas` 不跟随页面的情况,真机不影响
+- 微信开发工具会出现 `canvas` 层级过高的问题,真机一般不受影响,可以先测只有两个元素的页面看是否会有层级问题。
 - toolbox 不支持 `saveImage`
 - echarts 5.3.0 的 lines 不支持 trailLength,故需设置为 `0`
 - dataZoom H5不要设置 `showDetail` 
+- 如果微信小程序的`tooltip`文字有阴影,可能是微信的锅,临时解决方法是`tooltip.shadowBlur = 0`
+- 如果钉钉小程序上传时报安全问题`Uint8Clamped`,可以向钉钉反馈是安全代码扫描把Uint8Clamped数组错误识别了,也可以在 echarts 文件修改`Uint8Clamped`
+```js
+// 找到这段代码把代码中`Uint8Clamped`改成`Uint8_Clamped`,再把下划线去掉,不过直接去掉`Uint8Clamped`也是可行的
+// ["Int8","Uint8","Uint8Clamped","Int16","Uint16","Int32","Uint32","Float32","Float64"],(function(t,e){return t["[object "+e+"Array]"]
+// 改成如下
+["Int8","Uint8","Uint8_Clamped","Int16","Uint16","Int32","Uint32","Float32","Float64"],(function(t,e){return t["[object "+e.replace('_','')+"Array]"]
+```
+
+### vue3
+如果您是使用 **vite + vue3** 非微信小程序可能会遇到`echarts`文件缺少`wx`判断导致无法使用或缺少`tooltip`<br>
+
+方式一:可以在`echarts.min.js`文件开头增加以下内容,参考插件内的echart.min.js的做法
+
+```js
+var prefix = () => {
+	var UNDEFINED = 'undefined'
+	if(typeof wx !== UNDEFINED) return wx // 微信
+	if(typeof tt !== UNDEFINED) return tt // 字节 飞书
+	if(typeof swan !== UNDEFINED) return swan // 百度
+	if(typeof my !== UNDEFINED) return my // 支付宝
+	if(typeof dd !== UNDEFINED) return dd // 钉钉
+	if(typeof ks !== UNDEFINED) return ks // 快手
+	if(typeof jd !== UNDEFINED) return jd // 京东
+	if(typeof qa !== UNDEFINED) return qa // 快应用
+	if(typeof qq !== UNDEFINED) return qq // qq
+	if(typeof qh !== UNDEFINED) return qh // 360
+	if(typeof uni !== UNDEFINED) return uni
+	return null
+}
+//在 !function(t,e){"object"==typeof 下面加入 可能是第36行
+var wx = prefix();
+/*! *****************************************************************************
+    Copyright (c) Microsoft Corporation.
+```
+
+方式二:在`vite.config.js`的`define`设置环境
+
+```js
+//  或者在`vite.config.js`的`define`设置环境
+import { defineConfig } from 'vite';
+import uni from '@dcloudio/vite-plugin-uni';
+
+const UNI_PLATFORM = {
+	"app": "uni",
+	"web": "uni",
+	"mp-weixin": "wx",
+	"mp-baidu": "swan",
+	"mp-alipay": "my",
+	"mp-toutiao": "tt",
+	"mp-lark": "tt",
+	"mp-qq": "qq",
+	"mp-kuaishou": "ks",
+	"mp-jd": "jd",
+	"mp-360": "qh",
+	"quickapp-webview-union": "qa",
+	"quickapp-webview-huawei": "qa",
+	"quickapp-webview": "qa",
+}
+
+export default defineConfig({
+	plugins: [uni()],
+	define: { 
+		global: UNI_PLATFORM[process.env.UNI_PLATFORM],
+		wx: UNI_PLATFORM[process.env.UNI_PLATFORM]
+	}
+});
+```
 
 
 ## Props
@@ -240,6 +409,5 @@ this.$refs.chart.resize({width: 375, height: 375})
 
 ## 打赏
 如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。  
-
-![输入图片说明](https://static-6d65bd90-8508-4d6c-abbc-a4ef5c8e49e7.bspapp.com/image/222521_bb543f96_518581.jpeg "微信图片编辑_20201122220352.jpg")
-![输入图片说明](https://static-6d65bd90-8508-4d6c-abbc-a4ef5c8e49e7.bspapp.com/image/wxplay.jpg "wxplay.jpg")
+![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png)
+![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png)

File diff suppressed because it is too large
+ 16 - 1
src/uni_modules/lime-echart/static/echarts.min.js


+ 177 - 0
src/uni_modules/lime-echart/static/nvue.html

@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<html lang="zh">
+	<head>
+		<meta charset="UTF-8">
+		<meta name="viewport"
+			content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
+		<meta http-equiv="X-UA-Compatible" content="ie=edge">
+		<title></title>
+		<style type="text/css">
+			html,
+			body,
+			.canvas {
+				padding: 0;
+				margin: 0;
+				overflow-y: hidden;
+				background-color: transparent;
+				width: 100%;
+				height: 100%;
+			}
+		</style>
+	</head>
+	<body>
+		<div class="canvas" id="limeChart"></div>
+		<script type="text/javascript" src="./uni.webview.1.5.3.js"></script>
+		<script type="text/javascript" src="./echarts.min.js"></script>
+		<script type="text/javascript" src="./ecStat.min.js"></script>
+		<!-- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-liquidfill@latest/dist/echarts-liquidfill.min.js"></script> -->
+		<script>
+			let chart = null;
+			let cache = [];
+			console.log = function(...agrs) {
+				postMessage(agrs)
+			}
+
+			function emit(event, data) {
+				let dataStr = JSON.stringify(data, stringify)
+				postMessage({
+					event,
+					data: dataStr
+				})
+				cache = []
+			}
+
+			function postMessage(data) {
+				uni.postMessage({
+					data
+				});
+			}
+
+			function stringify(key, value) {
+				if (typeof value === 'object' && value !== null) {
+					if (cache.indexOf(value) !== -1) {
+						return;
+					}
+					cache.push(value);
+				}
+				return value;
+			}
+
+			function parse(name, callback, options) {
+				const optionNameReg = /[\w]+\.setOption\(([\w]+\.)?([\w]+)\)/
+				if (optionNameReg.test(callback)) {
+					const optionNames = callback.match(optionNameReg)
+					if (optionNames[1]) {
+						const _this = optionNames[1].split('.')[0]
+						window[_this] = {}
+						window[_this][optionNames[2]] = options
+						return optionNames[2]
+					} else {
+						return null
+					}
+				}
+				return null
+			}
+
+			function init(callback, options, opts = {}, theme = null) {
+				if (!chart) {
+					chart = echarts.init(document.getElementById('limeChart'), theme, opts)
+					if (options) {
+						chart.setOption(options)
+					}
+					// const name = parse('a', callback, options)
+					// console.log('options::', callback)
+					// if(name) this[name] = options
+					// eval(`a = ${callback};`)
+					// if(a) {a(chart)}
+				}
+			}
+
+			function setChart(callback, options) {
+				if (!callback) return
+				if (chart && callback && options) {
+					var r = null
+					const name = parse('r', callback, options)
+					if (name) this[name] = options
+					eval(`r = ${callback};`)
+					if (r) {
+						r(chart)
+					}
+				}
+			}
+
+			function setOption(data) {
+				if (chart) chart.setOption(data[0], data[1])
+			}
+
+			function showLoading(data) {
+				if (chart) chart.showLoading(data[0], data[1])
+			}
+
+			function hideLoading() {
+				if (chart) chart.hideLoading()
+			}
+
+			function clear() {
+				if (chart) chart.clear()
+
+			}
+
+			function dispose() {
+				if (chart) chart.dispose()
+			}
+
+			function resize(size) {
+				if (chart) chart.resize(size)
+			}
+
+			function canvasToTempFilePath(opt = {}) {
+				if (chart) {
+					const src = chart.getDataURL(opt)
+					postMessage({
+						file: true,
+						data: src
+					})
+				}
+			}
+
+			function on(data) {
+				if (chart && data.length > 0) {
+					const [type, query] = data
+					const useQuery = query && typeof query != 'function'
+					const key = `${type}${useQuery ? JSON.stringify(query): '' }`
+					if (query) {
+						chart.on(type, query, (options) => {
+							const obj = {}
+							Object.keys(options).forEach(key => {
+								if (key != 'event') {
+									obj[key] = options[key]
+								}
+							})
+							emit(`@${key}`, {
+								event: key,
+								options: obj
+							})
+						})
+					} else {
+						chart.on(type, (options) => {
+							
+							const obj = {}
+							Object.keys(options).forEach(key => {
+								if (key != 'event') {
+									obj[key] = options[key]
+								}
+
+							})
+							emit(`@${key}`, {
+								event: key,
+								options: obj
+							})
+						})
+					}
+				}
+
+			}
+		</script>
+	</body>
+</html>

File diff suppressed because it is too large
+ 0 - 0
src/uni_modules/lime-echart/static/uni.webview.1.5.5.js


+ 173 - 0
src/uni_modules/lime-echart/static/uvue.html

@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+<html lang="zh">
+	<head>
+		<meta charset="UTF-8">
+		<meta name="viewport"
+			content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
+		<meta http-equiv="X-UA-Compatible" content="ie=edge">
+		<title></title>
+		<style type="text/css">
+			html,
+			body,
+			.canvas {
+				padding: 0;
+				margin: 0;
+				overflow-y: hidden;
+				background-color: transparent;
+				width: 100%;
+				height: 100%;
+			}
+		</style>
+	</head>
+	<body>
+		<div class="canvas" id="limeChart"></div>
+		<script type="text/javascript" src="./uni.webview.1.5.5.js"></script>
+		<script type="text/javascript" src="./echarts.min.js"></script>
+		<script type="text/javascript" src="./ecStat.min.js"></script>
+		<!-- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-liquidfill@latest/dist/echarts-liquidfill.min.js"></script> -->
+		<script>
+			let chart = null;
+			let cache = [];
+			console.log = function(...agrs) {
+				emit('log', {
+					log: agrs,
+				})
+			}
+
+			function emit(event, data) {
+				postMessage({
+					// event,
+					data
+				})
+				cache = []
+			}
+
+			function postMessage(data) {
+				window.__uniapp_x_.postMessage(JSON.stringify(data))
+			};
+
+			function stringify(key, value) {
+				if (typeof value === 'object' && value !== null) {
+					if (cache.indexOf(value) !== -1) {
+						return;
+					}
+					cache.push(value);
+				}
+				return value;
+			}
+
+			function parse(name, callback, options) {
+				const optionNameReg = /[\w]+\.setOption\(([\w]+\.)?([\w]+)\)/
+				if (optionNameReg.test(callback)) {
+					const optionNames = callback.match(optionNameReg)
+					if (optionNames[1]) {
+						const _this = optionNames[1].split('.')[0]
+						window[_this] = {}
+						window[_this][optionNames[2]] = options
+						return optionNames[2]
+					} else {
+						return null
+					}
+				}
+				return null
+			}
+
+			function init(callback, options, opts = {}, theme = null) {
+				if (!chart) {
+					chart = echarts.init(document.getElementById('limeChart'), theme, opts)
+
+					if (options) {
+						chart.setOption(options)
+					}
+				}
+			}
+
+			function on(data) {
+				if (chart && data.length > 0) {
+					const [type, query] = data
+					const key = `${type}${JSON.stringify(query??'')}`
+					if (query) {
+						chart.on(type, query, (options) => {
+							const obj = {}
+							Object.keys(options).forEach(key => {
+								if (key != 'event') {
+									obj[key] = options[key]
+								}
+
+							})
+							emit(key, {
+								event: key,
+								options: obj
+							})
+						})
+					} else {
+						chart.on(type, (options) => {
+							const obj = {}
+							Object.keys(options).forEach(key => {
+								if (key != 'event') {
+									obj[key] = options[key]
+								}
+
+							})
+							emit(key, {
+								event: key,
+								options: obj
+							})
+						})
+					}
+				}
+
+			}
+
+			function setChart(callback, options) {
+				if (!callback) return
+				if (chart && callback && options) {
+					var r = null
+					const name = parse('r', callback, options)
+					if (name) this[name] = options
+					eval(`r = ${callback};`)
+					if (r) {
+						r(chart)
+					}
+				}
+			}
+
+			function setOption(data) {
+				if (chart) chart.setOption(data[0], data[1])
+			}
+
+			function showLoading(data) {
+				if (chart) chart.showLoading(data[0], data[1])
+			}
+
+			function hideLoading() {
+				if (chart) chart.hideLoading()
+			}
+
+			function clear() {
+				if (chart) chart.clear()
+
+			}
+
+			function dispose() {
+				if (chart) chart.dispose()
+			}
+
+			function resize(size) {
+				if (chart) chart.resize(size)
+			}
+
+			function canvasToTempFilePath(opt = {}) {
+				if (chart) {
+					
+					delete opt.success
+					const src = chart.getDataURL(opt)
+					postMessage({
+						// event: 'file',
+						file: file
+					})
+				}
+			}
+		</script>
+	</body>
+</html>

+ 2 - 0
src/uni_modules/uni-badge/changelog.md

@@ -1,3 +1,5 @@
+## 1.2.2(2023-01-28)
+- 修复 运行/打包 控制台警告问题
 ## 1.2.1(2022-09-05)
 - 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473)
 ## 1.2.0(2021-11-19)

+ 3 - 3
src/uni_modules/uni-badge/components/uni-badge/uni-badge.vue

@@ -21,7 +21,7 @@
 	 * 	@value error 红色
 	 * @property {String} inverted = [true|false] 是否无需背景颜色
 	 * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
-	 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上		
+	 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
 	 * 	@value rightTop 右上
 	 * 	@value rightBottom 右下
 	 * 	@value leftTop 左上
@@ -192,11 +192,12 @@
 		display: flex;
 		overflow: hidden;
 		box-sizing: border-box;
+		font-feature-settings: "tnum";
+		min-width: 20px;
 		/* #endif */
 		justify-content: center;
 		flex-direction: row;
 		height: 20px;
-		min-width: 20px;
 		padding: 0 4px;
 		line-height: 18px;
 		color: #fff;
@@ -206,7 +207,6 @@
 		border: 1px solid #fff;
 		text-align: center;
 		font-family: 'Helvetica Neue', Helvetica, sans-serif;
-		font-feature-settings: "tnum";
 		font-size: $bage-size;
 		/* #ifdef H5 */
 		z-index: 999;

+ 1 - 1
src/uni_modules/uni-badge/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-badge",
   "displayName": "uni-badge 数字角标",
-  "version": "1.2.1",
+  "version": "1.2.2",
   "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
   "keywords": [
     "",

+ 15 - 7
src/uni_modules/uni-calendar/changelog.md

@@ -1,20 +1,28 @@
+## 1.4.11(2024-01-10)
+- 修复 回到今天时,月份显示不一致问题
+## 1.4.10(2023-04-10)
+- 修复 某些情况 monthSwitch 未触发的Bug
+## 1.4.9(2023-02-02)
+- 修复 某些情况切换月份错误的Bug
+## 1.4.8(2023-01-30)
+- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964)
 ## 1.4.7(2022-09-16)
-- 可以使用 uni-scss 控制主题色
+- 优化 支持使用 uni-scss 控制主题色
 ## 1.4.6(2022-09-08)
-- fix: 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件
+- 修复 表头年月切换,导致改变当前日期为选择月1号,且未触发change事件的Bug
 ## 1.4.5(2022-02-25)
-- 修复 条件编译 nvue 不支持的 css 样式
+- 修复 条件编译 nvue 不支持的 css 样式的Bug
 ## 1.4.4(2022-02-25)
-- 修复 条件编译 nvue 不支持的 css 样式
+- 修复 条件编译 nvue 不支持的 css 样式的Bug
 ## 1.4.3(2021-09-22)
-- 修复 startDate、 endDate 属性失效的 bug
+- 修复 startDate、 endDate 属性失效的Bug
 ## 1.4.2(2021-08-24)
 - 新增 支持国际化
 ## 1.4.1(2021-08-05)
-- 修复 弹出层被 tabbar 遮盖 bug
+- 修复 弹出层被 tabbar 遮盖的Bug
 ## 1.4.0(2021-07-30)
 - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
 ## 1.3.16(2021-05-12)
 - 新增 组件示例地址
 ## 1.3.15(2021-02-04)
-- 调整为uni_modules目录规范 
+- 调整为uni_modules目录规范

+ 4 - 5
src/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue

@@ -51,11 +51,10 @@
 </template>
 
 <script>
-	import {
-	initVueI18n
-	} from '@dcloudio/uni-i18n'
-	import messages from './i18n/index.js'
-	const {	t	} = initVueI18n(messages)
+	import { initVueI18n } from '@dcloudio/uni-i18n'
+	import i18nMessages from './i18n/index.js'
+	const {	t	} = initVueI18n(i18nMessages)
+
 	export default {
 		emits:['change'],
 		props: {

+ 25 - 20
src/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue

@@ -20,7 +20,7 @@
 				<view class="uni-calendar__header-btn-box" @click.stop="next">
 					<view class="uni-calendar__header-btn uni-calendar--right"></view>
 				</view>
-				<text class="uni-calendar__backtoday" @click="backtoday">{{todayText}}</text>
+				<text class="uni-calendar__backtoday" @click="backToday">{{todayText}}</text>
 
 			</view>
 			<view class="uni-calendar__box">
@@ -62,12 +62,12 @@
 
 <script>
 	import Calendar from './util.js';
-	import calendarItem from './uni-calendar-item.vue'
-	import {
-	initVueI18n
-	} from '@dcloudio/uni-i18n'
-	import messages from './i18n/index.js'
-	const {	t	} = initVueI18n(messages)
+	import CalendarItem from './uni-calendar-item.vue'
+
+	import { initVueI18n } from '@dcloudio/uni-i18n'
+	import i18nMessages from './i18n/index.js'
+	const {	t	} = initVueI18n(i18nMessages)
+
 	/**
 	 * Calendar 日历
 	 * @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
@@ -90,7 +90,7 @@
 	 */
 	export default {
 		components: {
-			calendarItem
+			CalendarItem
 		},
 		emits:['close','confirm','change','monthSwitch'],
 		props: {
@@ -199,26 +199,26 @@
 			}
 		},
 		created() {
-			// 获取日历方法实例
 			this.cale = new Calendar({
-				// date: new Date(),
 				selected: this.selected,
 				startDate: this.startDate,
 				endDate: this.endDate,
 				range: this.range,
 			})
-			// 选中某一天
-			// this.cale.setDate(this.date)
 			this.init(this.date)
-			// this.setDay
 		},
 		methods: {
 			// 取消穿透
 			clean() {},
 			bindDateChange(e) {
 				const value = e.detail.value + '-1'
-				console.log(this.cale.getDate(value));
 				this.setDate(value)
+
+				const { year,month } = this.cale.getDate(value)
+        this.$emit('monthSwitch', {
+            year,
+            month
+        })
 			},
 			/**
 			 * 初始化日期显示
@@ -323,11 +323,17 @@
 			/**
 			 * 回到今天
 			 */
-			backtoday() {
-				console.log(this.cale.getDate(new Date()).fullDate);
-				let date = this.cale.getDate(new Date()).fullDate
-				// this.cale.setDate(date)
-				this.init(date)
+			backToday() {
+				const nowYearMonth = `${this.nowDate.year}-${this.nowDate.month}`
+				const date = this.cale.getDate(new Date())
+        const todayYearMonth = `${date.year}-${date.month}`
+
+				this.init(date.fullDate)
+
+        if(nowYearMonth !== todayYearMonth) {
+          this.monthSwitch()
+        }
+
 				this.change()
 			},
 			/**
@@ -446,7 +452,6 @@
 
 	.uni-calendar--fixed-width {
 		width: 50px;
-		// padding: 0 15px;
 	}
 
 	.uni-calendar__backtoday {

+ 12 - 2
src/uni_modules/uni-calendar/components/uni-calendar/util.js

@@ -76,10 +76,20 @@ class Calendar {
 				dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
 				break
 			case 'month':
-				if (dd.getDate() === 31) {
+				if (dd.getDate() === 31 && AddDayCount>0) {
 					dd.setDate(dd.getDate() + AddDayCount)
 				} else {
-					dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
+					const preMonth = dd.getMonth()
+					dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期
+					const nextMonth = dd.getMonth()
+					// 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
+					if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){
+						dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount))
+					}
+					// 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
+					if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){
+						dd.setMonth(nextMonth-(nextMonth-preMonth-AddDayCount))
+					}
 				}
 				break
 			case 'year':

+ 1 - 1
src/uni_modules/uni-calendar/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-calendar",
   "displayName": "uni-calendar 日历",
-  "version": "1.4.7",
+  "version": "1.4.11",
   "description": "日历组件",
   "keywords": [
     "uni-ui",

+ 3 - 3
src/uni_modules/uni-calendar/readme.md

@@ -77,7 +77,7 @@ export default {
 ### Calendar Props
 
 |  属性名	|    类型	| 默认值| 说明																													|
-| 		| 																													|
+| -	| -	| - | - |
 | date		| String	|-		| 自定义当前时间,默认为今天																							|
 | lunar		| Boolean	| false	| 显示农历																												|
 | startDate	| String	|-		| 日期选择范围-开始日期																									|
@@ -91,7 +91,7 @@ export default {
 ### Calendar Events
 
 |  事件名		| 说明								|返回值|
-| 								|		| 									|
+| -	|	-	| -	|
 | open	| 弹出日历组件,`insert :false` 时生效|- 	|
 
 
@@ -100,4 +100,4 @@ export default {
 
 ## 组件示例
 
-点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar)
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar)

+ 2 - 0
src/uni_modules/uni-data-checkbox/changelog.md

@@ -1,3 +1,5 @@
+## 1.0.4(2024-01-27)
+- 修复 修复错别字chagne为change
 ## 1.0.3(2022-09-16)
 - 可以使用 uni-scss 控制主题色
 ## 1.0.2(2022-06-30)

+ 3 - 3
src/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue

@@ -7,7 +7,7 @@
 			</view>
 		</template>
 		<template v-else>
-			<checkbox-group v-if="multiple" class="checklist-group" :class="{'is-list':mode==='list' || wrap}" @change="chagne">
+			<checkbox-group v-if="multiple" class="checklist-group" :class="{'is-list':mode==='list' || wrap}" @change="change">
 				<label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']"
 				 :style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index">
 					<checkbox class="hidden" hidden :disabled="disabled || !!item.disabled" :value="item[map.value]+''" :checked="item.selected" />
@@ -20,7 +20,7 @@
 					</view>
 				</label>
 			</checkbox-group>
-			<radio-group v-else class="checklist-group" :class="{'is-list':mode==='list','is-wrap':wrap}" @change="chagne">
+			<radio-group v-else class="checklist-group" :class="{'is-list':mode==='list','is-wrap':wrap}" @change="change">
 				<!-- -->
 				<label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']"
 				 :style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index">
@@ -248,7 +248,7 @@
 				}
 				return parent;
 			},
-			chagne(e) {
+			change(e) {
 				const values = e.detail.value
 
 				let detail = {

+ 1 - 1
src/uni_modules/uni-data-checkbox/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-data-checkbox",
   "displayName": "uni-data-checkbox 数据选择器",
-  "version": "1.0.3",
+  "version": "1.0.4",
   "description": "通过数据驱动的单选框和复选框",
   "keywords": [
     "uni-ui",

+ 11 - 0
src/uni_modules/uni-data-picker/changelog.md

@@ -1,3 +1,14 @@
+## 2.0.0(2023-12-14)
+- 新增 支持 uni-app-x
+## 1.1.2(2023-04-11)
+- 修复 更改 modelValue 报错的 bug
+- 修复 v-for 未使用 key 值控制台 warning
+## 1.1.1(2023-02-21)
+- 修复代码合并时引发 value 属性为空时不渲染数据的问题
+## 1.1.0(2023-02-15)
+- 修复 localdata 不支持动态更新的bug
+## 1.0.9(2023-02-15)
+- 修复 localdata 不支持动态更新的bug
 ## 1.0.8(2022-09-16)
 - 可以使用 uni-scss 控制主题色
 ## 1.0.7(2022-07-06)

+ 380 - 0
src/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.uvue

@@ -0,0 +1,380 @@
+<template>
+  <view class="uni-data-tree">
+    <view class="uni-data-tree-input" @click="handleInput">
+      <slot :data="selectedPaths" :error="error">
+        <view class="input-value" :class="{'input-value-border': border}">
+          <text v-if="error!=null" class="error-text">{{error!.errMsg}}</text>
+          <scroll-view v-if="selectedPaths.length" class="selected-path" scroll-x="true">
+            <view class="selected-list">
+              <template v-for="(item, index) in selectedPaths">
+                <text class="text-color">{{item[mappingTextName]}}</text>
+                <text v-if="index<selectedPaths.length-1" class="input-split-line">{{split}}</text>
+              </template>
+            </view>
+          </scroll-view>
+          <text v-else-if="error==null&&!loading" class="placeholder">{{placeholder}}</text>
+          <view v-if="!readonly" class="arrow-area">
+            <view class="input-arrow"></view>
+          </view>
+        </view>
+      </slot>
+      <view v-if="loading && !isOpened" class="selected-loading">
+        <slot name="picker-loading" :loading="loading"></slot>
+      </view>
+    </view>
+    <view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view>
+    <view class="uni-data-tree-dialog" v-if="isOpened">
+      <view class="uni-popper__arrow"></view>
+      <view class="dialog-caption">
+        <view class="dialog-title-view">
+          <text class="dialog-title">{{popupTitle}}</text>
+        </view>
+        <view class="dialog-close" @click="handleClose">
+          <view class="dialog-close-plus" data-id="close"></view>
+          <view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
+        </view>
+      </view>
+      <view ref="pickerView" class="uni-data-pickerview">
+        <view v-if="error!=null" class="error">
+          <text class="error-text">{{error!.errMsg}}</text>
+        </view>
+        <scroll-view v-if="!isCloudDataList" :scroll-x="true">
+          <view class="selected-node-list">
+            <template v-for="(item, index) in selectedNodes">
+              <text class="selected-node-item" :class="{'selected-node-item-active':index==selectedIndex}"
+                @click="onTabSelect(index)">
+                {{item[mappingTextName]}}
+              </text>
+            </template>
+          </view>
+        </scroll-view>
+        <list-view class="list-view" :scroll-y="true">
+          <list-item class="list-item" v-for="(item, _) in currentDataList" @click="onNodeClick(item)">
+            <text class="item-text" :class="{'item-text-disabled': item['disable']}">{{item[mappingTextName]}}</text>
+            <text class="check" v-if="item[mappingValueName] == selectedNodes[selectedIndex][mappingValueName]"></text>
+          </list-item>
+        </list-view>
+        <view class="loading-cover" v-if="loading">
+          <slot name="pickerview-loading" :loading="loading"></slot>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+  import { dataPicker } from "../uni-data-pickerview/uni-data-picker.uts"
+
+  /**
+   * DataPicker 级联选择
+   * @description 支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+   * @property {String} popup-title 弹出窗口标题
+   * @property {Array} localdata 本地数据,参考
+   * @property {Boolean} border = [true|false] 是否有边框
+   * @property {Boolean} readonly = [true|false] 是否仅读
+   * @property {Boolean} preload = [true|false] 是否预加载数据
+   * @value true 开启预加载数据,点击弹出窗口后显示已加载数据
+   * @value false 关闭预加载数据,点击弹出窗口后开始加载数据
+   * @property {Boolean} step-searh = [true|false] 是否分布查询
+   * @value true 启用分布查询,仅查询当前选中节点
+   * @value false 关闭分布查询,一次查询出所有数据
+   * @property {String|DBFieldString} self-field 分布查询当前字段名称
+   * @property {String|DBFieldString} parent-field 分布查询父字段名称
+   * @property {String|DBCollectionString} collection 表名
+   * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
+   * @property {String} orderby 排序字段及正序倒叙设置
+   * @property {String|JQLString} where 查询条件
+   * @event {Function} popupshow 弹出的选择窗口打开时触发此事件
+   * @event {Function} popuphide 弹出的选择窗口关闭时触发此事件
+   */
+  export default {
+    name: 'UniDataPicker',
+    emits: ['popupopened', 'popupclosed', 'nodeclick', 'change', 'input', 'update:modelValue', 'inputclick'],
+    mixins: [dataPicker],
+    props: {
+      popupTitle: {
+        type: String,
+        default: '请选择'
+      },
+      placeholder: {
+        type: String,
+        default: '请选择'
+      },
+      heightMobile: {
+        type: String,
+        default: ''
+      },
+      readonly: {
+        type: Boolean,
+        default: false
+      },
+      clearIcon: {
+        type: Boolean,
+        default: true
+      },
+      border: {
+        type: Boolean,
+        default: true
+      },
+      split: {
+        type: String,
+        default: '/'
+      },
+      ellipsis: {
+        type: Boolean,
+        default: true
+      }
+    },
+    data() {
+      return {
+        isOpened: false
+      }
+    },
+    computed: {
+      isShowClearIcon() : boolean {
+        if (this.readonly) {
+          return false
+        }
+
+        if (this.clearIcon && this.selectedPaths.length > 0) {
+          return true
+        }
+
+        return false
+      }
+    },
+    created() {
+      this.load()
+    },
+    methods: {
+      clear() {
+      },
+      load() {
+        if (this.isLocalData) {
+          this.loadLocalData()
+        } else if (this.isCloudDataList || this.isCloudDataTree) {
+          this.loadCloudDataPath()
+        }
+      },
+      show() {
+        this.isOpened = true
+        this.$emit('popupopened')
+        if (!this.hasCloudTreeData) {
+          this.loadData()
+        }
+      },
+      hide() {
+        this.isOpened = false
+        this.$emit('popupclosed')
+      },
+      handleInput() {
+        if (this.readonly) {
+          this.$emit('inputclick')
+        } else {
+          this.show()
+        }
+      },
+      handleClose() {
+        this.hide()
+      },
+      onFinish() {
+        this.selectedPaths = this.getChangeNodes()
+        this.$emit('change', this.selectedPaths)
+        this.hide()
+      }
+    }
+  }
+</script>
+
+<style>
+  @import url("../uni-data-pickerview/uni-data-pickerview.css");
+
+  .uni-data-tree {
+    position: relative;
+  }
+
+  .uni-data-tree-input {
+    position: relative;
+  }
+
+  .selected-loading {
+    display: flex;
+    justify-content: center;
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+  }
+
+  .error-text {
+    flex: 1;
+    font-size: 12px;
+    color: #DD524D;
+  }
+
+  .input-value {
+    flex-direction: row;
+    align-items: center;
+    flex-wrap: nowrap;
+    padding: 5px 5px;
+    padding-right: 5px;
+    overflow: hidden;
+    min-height: 28px;
+  }
+
+  .input-value-border {
+    border: 1px solid #e5e5e5;
+    border-radius: 5px;
+  }
+
+  .selected-path {
+    flex: 1;
+    flex-direction: row;
+    overflow: hidden;
+  }
+
+  .load-more {
+    width: 40px;
+  }
+
+  .selected-list {
+    flex-direction: row;
+    flex-wrap: nowrap;
+  }
+
+  .selected-item {
+    flex-direction: row;
+    flex-wrap: nowrap;
+  }
+
+  .text-color {
+    font-size: 14px;
+    color: #333;
+  }
+
+  .placeholder {
+    color: grey;
+    font-size: 14px;
+  }
+
+  .input-split-line {
+    opacity: .5;
+    margin-left: 1px;
+    margin-right: 1px;
+  }
+
+  .arrow-area {
+    position: relative;
+    padding: 0 12px;
+    margin-left: auto;
+    justify-content: center;
+    transform: rotate(-45deg);
+    transform-origin: center;
+  }
+
+  .input-arrow {
+    width: 8px;
+    height: 8px;
+    border-left: 2px solid #999;
+    border-bottom: 2px solid #999;
+  }
+
+  .uni-data-tree-cover {
+    position: fixed;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, .4);
+    flex-direction: column;
+    z-index: 100;
+  }
+
+  .uni-data-tree-dialog {
+    position: fixed;
+    left: 0;
+    top: 20%;
+    right: 0;
+    bottom: 0;
+    background-color: #FFFFFF;
+    border-top-left-radius: 10px;
+    border-top-right-radius: 10px;
+    flex-direction: column;
+    z-index: 102;
+    overflow: hidden;
+  }
+
+  .dialog-caption {
+    position: relative;
+    flex-direction: row;
+  }
+
+  .dialog-title-view {
+    flex: 1;
+  }
+
+  .dialog-title {
+    align-self: center;
+    padding: 0 10px;
+    line-height: 44px;
+  }
+
+  .dialog-close {
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    flex-direction: row;
+    align-items: center;
+    padding: 0 15px;
+  }
+
+  .dialog-close-plus {
+    width: 16px;
+    height: 2px;
+    background-color: #666;
+    border-radius: 2px;
+    transform: rotate(45deg);
+  }
+
+  .dialog-close-rotate {
+    position: absolute;
+    transform: rotate(-45deg);
+  }
+
+  .uni-data-pickerview {
+    flex: 1;
+  }
+
+  .icon-clear {
+    display: flex;
+    align-items: center;
+  }
+
+  /* #ifdef H5 */
+  @media all and (min-width: 768px) {
+    .uni-data-tree-cover {
+      background-color: transparent;
+    }
+
+    .uni-data-tree-dialog {
+      position: absolute;
+      top: 55px;
+      height: auto;
+      min-height: 400px;
+      max-height: 50vh;
+      background-color: #fff;
+      border: 1px solid #EBEEF5;
+      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+      border-radius: 4px;
+      overflow: unset;
+    }
+
+    .dialog-caption {
+      display: none;
+    }
+  }
+  /* #endif */
+</style>

+ 10 - 6
src/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue

@@ -75,7 +75,7 @@
    */
   export default {
     name: 'UniDataPicker',
-    emits: ['popupopened', 'popupclosed', 'nodeclick', 'input', 'change', 'update:modelValue'],
+    emits: ['popupopened', 'popupclosed', 'nodeclick', 'input', 'change', 'update:modelValue','inputclick'],
     mixins: [dataPicker],
     components: {
       DataPickerView
@@ -131,9 +131,16 @@
         this.load();
       })
     },
+    watch: {
+			localdata: {
+				handler() {
+					this.load()
+				},
+        deep: true
+			},
+    },
     methods: {
       clear() {
-        this.modelValue = null;
         this._dispatchEvent([]);
       },
       onPropsChange() {
@@ -148,10 +155,6 @@
           return;
         }
 
-        if (!this.hasValue) {
-          return;
-        }
-
         // 回显本地数据
         if (this.isLocalData) {
           this.loadData();
@@ -184,6 +187,7 @@
       },
       handleInput() {
         if (this.readonly) {
+					this.$emit('inputclick')
           return
         }
         this.show()

File diff suppressed because it is too large
+ 0 - 0
src/uni_modules/uni-data-picker/components/uni-data-pickerview/loading.uts


+ 693 - 0
src/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.uts

@@ -0,0 +1,693 @@
+export type PaginationType = {
+  current : number,
+  size : number,
+  count : number
+}
+
+export type LoadMoreType = {
+  contentdown : string,
+  contentrefresh : string,
+  contentnomore : string
+}
+
+export type SelectedItemType = {
+  name : string,
+  value : string,
+}
+
+export type GetCommandOptions = {
+  collection ?: UTSJSONObject,
+  field ?: string,
+  orderby ?: string,
+  where ?: any,
+  pageData ?: string,
+  pageCurrent ?: number,
+  pageSize ?: number,
+  getCount ?: boolean,
+  getTree ?: any,
+  getTreePath ?: UTSJSONObject,
+  startwith ?: string,
+  limitlevel ?: number,
+  groupby ?: string,
+  groupField ?: string,
+  distinct ?: boolean,
+  pageIndistinct ?: boolean,
+  foreignKey ?: string,
+  loadtime ?: string,
+  manual ?: boolean
+}
+
+const DefaultSelectedNode = {
+  text: '请选择',
+  value: ''
+}
+
+export const dataPicker = defineMixin({
+  props: {
+    localdata: {
+      type: Array as PropType<Array<UTSJSONObject>>,
+      default: [] as Array<UTSJSONObject>
+    },
+    collection: {
+      type: Object,
+      default: ''
+    },
+    field: {
+      type: String,
+      default: ''
+    },
+    orderby: {
+      type: String,
+      default: ''
+    },
+    where: {
+      type: Object,
+      default: ''
+    },
+    pageData: {
+      type: String,
+      default: 'add'
+    },
+    pageCurrent: {
+      type: Number,
+      default: 1
+    },
+    pageSize: {
+      type: Number,
+      default: 20
+    },
+    getcount: {
+      type: Boolean,
+      default: false
+    },
+    gettree: {
+      type: Object,
+      default: ''
+    },
+    gettreepath: {
+      type: Object,
+      default: ''
+    },
+    startwith: {
+      type: String,
+      default: ''
+    },
+    limitlevel: {
+      type: Number,
+      default: 10
+    },
+    groupby: {
+      type: String,
+      default: ''
+    },
+    groupField: {
+      type: String,
+      default: ''
+    },
+    distinct: {
+      type: Boolean,
+      default: false
+    },
+    pageIndistinct: {
+      type: Boolean,
+      default: false
+    },
+    foreignKey: {
+      type: String,
+      default: ''
+    },
+    loadtime: {
+      type: String,
+      default: 'auto'
+    },
+    manual: {
+      type: Boolean,
+      default: false
+    },
+    preload: {
+      type: Boolean,
+      default: false
+    },
+    stepSearh: {
+      type: Boolean,
+      default: true
+    },
+    selfField: {
+      type: String,
+      default: ''
+    },
+    parentField: {
+      type: String,
+      default: ''
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    value: {
+      type: Object,
+      default: ''
+    },
+    modelValue: {
+      type: Object,
+      default: ''
+    },
+    defaultProps: {
+      type: Object as PropType<UTSJSONObject>,
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      error: null as UniCloudError | null,
+      treeData: [] as Array<UTSJSONObject>,
+      selectedIndex: 0,
+      selectedNodes: [] as Array<UTSJSONObject>,
+      selectedPages: [] as Array<UTSJSONObject>[],
+      selectedValue: '',
+      selectedPaths: [] as Array<UTSJSONObject>,
+      pagination: {
+        current: 1,
+        size: 20,
+        count: 0
+      } as PaginationType
+    }
+  },
+  computed: {
+    mappingTextName() : string {
+      // TODO
+      return (this.defaultProps != null) ? this.defaultProps!.getString('text', 'text') : 'text'
+    },
+    mappingValueName() : string {
+      // TODO
+      return (this.defaultProps != null) ? this.defaultProps!.getString('value', 'value') : 'value'
+    },
+    currentDataList() : Array<UTSJSONObject> {
+      if (this.selectedIndex > this.selectedPages.length - 1) {
+        return [] as Array<UTSJSONObject>
+      }
+      return this.selectedPages[this.selectedIndex]
+    },
+    isLocalData() : boolean {
+      return this.localdata.length > 0
+    },
+    isCloudData() : boolean {
+      return this._checkIsNotNull(this.collection)
+    },
+    isCloudDataList() : boolean {
+      return (this.isCloudData && (this.parentField.length == 0 && this.selfField.length == 0))
+    },
+    isCloudDataTree() : boolean {
+      return (this.isCloudData && this.parentField.length > 0 && this.selfField.length > 0)
+    },
+    dataValue() : any {
+      return this.hasModelValue ? this.modelValue : this.value
+    },
+    hasCloudTreeData() : boolean {
+      return this.treeData.length > 0
+    },
+    hasModelValue() : boolean {
+      if (typeof this.modelValue == 'string') {
+        const valueString = this.modelValue as string
+        return (valueString.length > 0)
+      } else if (Array.isArray(this.modelValue)) {
+        const valueArray = this.modelValue as Array<string>
+        return (valueArray.length > 0)
+      }
+      return false
+    },
+    hasCloudDataValue() : boolean {
+      if (typeof this.dataValue == 'string') {
+        const valueString = this.dataValue as string
+        return (valueString.length > 0)
+      }
+      return false
+    }
+  },
+  created() {
+    this.pagination.current = this.pageCurrent
+    this.pagination.size = this.pageSize
+
+    this.$watch(
+      () : any => [
+        this.pageCurrent,
+        this.pageSize,
+        this.localdata,
+        this.value,
+        this.collection,
+        this.field,
+        this.getcount,
+        this.orderby,
+        this.where,
+        this.groupby,
+        this.groupField,
+        this.distinct
+      ],
+      (newValue : Array<any>, oldValue : Array<any>) => {
+        this.pagination.size = this.pageSize
+        if (newValue[0] !== oldValue[0]) {
+          this.pagination.current = this.pageCurrent
+        }
+
+        this.onPropsChange()
+      }
+    )
+  },
+  methods: {
+    onPropsChange() {
+      this.selectedIndex = 0
+      this.treeData.length = 0
+      this.selectedNodes.length = 0
+      this.selectedPages.length = 0
+      this.selectedPaths.length = 0
+
+      // 加载数据
+      this.$nextTick(() => {
+        this.loadData()
+      })
+    },
+
+    onTabSelect(index : number) {
+      this.selectedIndex = index
+    },
+
+    onNodeClick(nodeData : UTSJSONObject) {
+      if (nodeData.getBoolean('disable', false)) {
+        return
+      }
+
+      const isLeaf = this._checkIsLeafNode(nodeData)
+
+      this._trimSelectedNodes(nodeData)
+
+      this.$emit('nodeclick', nodeData)
+
+      if (this.isLocalData) {
+        if (isLeaf || !this._checkHasChildren(nodeData)) {
+          this.onFinish()
+        }
+      } else if (this.isCloudDataList) {
+        this.onFinish()
+      } else if (this.isCloudDataTree) {
+        if (isLeaf) {
+          this.onFinish()
+        } else if (!this._checkHasChildren(nodeData)) {
+          // 尝试请求一次,如果没有返回数据标记为叶子节点
+          this.loadCloudDataNode(nodeData)
+        }
+      }
+    },
+
+    getChangeNodes(): Array<UTSJSONObject> {
+      const nodes: Array<UTSJSONObject> = []
+      this.selectedNodes.forEach((node : UTSJSONObject) => {
+        const newNode: UTSJSONObject = {}
+        newNode[this.mappingTextName] = node.getString(this.mappingTextName)
+        newNode[this.mappingValueName] = node.getString(this.mappingValueName)
+        nodes.push(newNode)
+      })
+      return nodes
+    },
+
+    onFinish() { },
+
+    // 加载数据(自动判定环境)
+    loadData() {
+      if (this.isLocalData) {
+        this.loadLocalData()
+      } else if (this.isCloudDataList) {
+        this.loadCloudDataList()
+      } else if (this.isCloudDataTree) {
+        this.loadCloudDataTree()
+      }
+    },
+
+    // 加载本地数据
+    loadLocalData() {
+      this.treeData = this.localdata
+      if (Array.isArray(this.dataValue)) {
+        const value = this.dataValue as Array<UTSJSONObject>
+        this.selectedPaths = value.slice(0)
+        this._pushSelectedTreeNodes(value, this.localdata)
+      } else {
+        this._pushSelectedNodes(this.localdata)
+      }
+    },
+
+    // 加载 Cloud 数据 (单列)
+    loadCloudDataList() {
+      this._loadCloudData(null, (data : Array<UTSJSONObject>) => {
+        this.treeData = data
+        this._pushSelectedNodes(data)
+      })
+    },
+
+    // 加载 Cloud 数据 (树形)
+    loadCloudDataTree() {
+      let commandOptions = {
+        field: this._cloudDataPostField(),
+        where: this._cloudDataTreeWhere(),
+        getTree: true
+      } as GetCommandOptions
+      if (this._checkIsNotNull(this.gettree)) {
+        commandOptions.startwith = `${this.selfField}=='${this.dataValue as string}'`
+      }
+      this._loadCloudData(commandOptions, (data : Array<UTSJSONObject>) => {
+        this.treeData = data
+        if (this.selectedPaths.length > 0) {
+          this._pushSelectedTreeNodes(this.selectedPaths, data)
+        } else {
+          this._pushSelectedNodes(data)
+        }
+      })
+    },
+
+    // 加载 Cloud 数据 (节点)
+    loadCloudDataNode(nodeData : UTSJSONObject) {
+      const commandOptions = {
+        field: this._cloudDataPostField(),
+        where: this._cloudDataNodeWhere()
+      } as GetCommandOptions
+      this._loadCloudData(commandOptions, (data : Array<UTSJSONObject>) => {
+        nodeData['children'] = data
+        if (data.length == 0) {
+          nodeData['isleaf'] = true
+          this.onFinish()
+        } else {
+          this._pushSelectedNodes(data)
+        }
+      })
+    },
+
+    // 回显 Cloud Tree Path
+    loadCloudDataPath() {
+      if (!this.hasCloudDataValue) {
+        return
+      }
+
+      const command : GetCommandOptions = {}
+
+      // 单列
+      if (this.isCloudDataList) {
+        // 根据 field's as value标识匹配 where 条件
+        let where : Array<string> = [];
+        let whereField = this._getForeignKeyByField();
+        if (whereField.length > 0) {
+          where.push(`${whereField} == '${this.dataValue as string}'`)
+        }
+
+        let whereString = where.join(' || ')
+        if (this._checkIsNotNull(this.where)) {
+          whereString = `(${this.where}) && (${whereString})`
+        }
+
+        command.field = this._cloudDataPostField()
+        command.where = whereString
+      }
+
+      // 树形
+      if (this.isCloudDataTree) {
+        command.field = this._cloudDataPostField()
+        command.getTreePath = {
+          startWith: `${this.selfField}=='${this.dataValue as string}'`
+        }
+      }
+
+      this._loadCloudData(command, (data : Array<UTSJSONObject>) => {
+        this._extractTreePath(data, this.selectedPaths)
+      })
+    },
+
+    _loadCloudData(options ?: GetCommandOptions, callback ?: ((data : Array<UTSJSONObject>) => void)) {
+      if (this.loading) {
+        return
+      }
+      this.loading = true
+
+      this.error = null
+
+      this._getCommand(options).then((response : UniCloudDBGetResult) => {
+        callback?.(response.data)
+      }).catch((err : any | null) => {
+        this.error = err as UniCloudError
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+
+    _cloudDataPostField() : string {
+      let fields = [this.field];
+      if (this.parentField.length > 0) {
+        fields.push(`${this.parentField} as parent_value`)
+      }
+      return fields.join(',')
+    },
+
+    _cloudDataTreeWhere() : string {
+      let result : Array<string> = []
+      let selectedNodes = this.selectedNodes.length > 0 ? this.selectedNodes : this.selectedPaths
+      let parentField = this.parentField
+      if (parentField.length > 0) {
+        result.push(`${parentField} == null || ${parentField} == ""`)
+      }
+      if (selectedNodes.length > 0) {
+        for (var i = 0; i < selectedNodes.length - 1; i++) {
+          const parentFieldValue = selectedNodes[i].getString('value', '')
+          result.push(`${parentField} == '${parentFieldValue}'`)
+        }
+      }
+
+      let where : Array<string> = []
+      if (this._checkIsNotNull(this.where)) {
+        where.push(`(${this.where as string})`)
+      }
+
+      if (result.length > 0) {
+        where.push(`(${result.join(' || ')})`)
+      }
+
+      return where.join(' && ')
+    },
+
+    _cloudDataNodeWhere() : string {
+      const where : Array<string> = []
+      if (this.selectedNodes.length > 0) {
+        const value = this.selectedNodes[this.selectedNodes.length - 1].getString('value', '')
+        where.push(`${this.parentField} == '${value}'`)
+      }
+
+      let whereString = where.join(' || ')
+      if (this._checkIsNotNull(this.where)) {
+        return `(${this.where as string}) && (${whereString})`
+      }
+
+      return whereString
+    },
+
+    _getWhereByForeignKey() : string {
+      let result : Array<string> = []
+      let whereField = this._getForeignKeyByField();
+      if (whereField.length > 0) {
+        result.push(`${whereField} == '${this.dataValue as string}'`)
+      }
+
+      if (this._checkIsNotNull(this.where)) {
+        return `(${this.where}) && (${result.join(' || ')})`
+      }
+
+      return result.join(' || ')
+    },
+
+    _getForeignKeyByField() : string {
+      const fields = this.field.split(',')
+      let whereField = ''
+      for (let i = 0; i < fields.length; i++) {
+        const items = fields[i].split('as')
+        if (items.length < 2) {
+          continue
+        }
+        if (items[1].trim() === 'value') {
+          whereField = items[0].trim()
+          break
+        }
+      }
+      return whereField
+    },
+
+    _getCommand(options ?: GetCommandOptions) : Promise<UniCloudDBGetResult> {
+      let db = uniCloud.databaseForJQL()
+
+      let collection = Array.isArray(this.collection) ? db.collection(...(this.collection as Array<any>)) : db.collection(this.collection)
+
+      let filter : UniCloudDBFilter | null = null
+      if (this.foreignKey.length > 0) {
+        filter = collection.foreignKey(this.foreignKey)
+      }
+
+      const where : any = options?.where ?? this.where
+      if (typeof where == 'string') {
+        const whereString = where as string
+        if (whereString.length > 0) {
+          filter = (filter != null) ? filter.where(where) : collection.where(where)
+        }
+      } else {
+        filter = (filter != null) ? filter.where(where) : collection.where(where)
+      }
+
+      let query : UniCloudDBQuery | null = null
+      if (this.field.length > 0) {
+        query = (filter != null) ? filter.field(this.field) : collection.field(this.field)
+      }
+      if (this.groupby.length > 0) {
+        if (query != null) {
+          query = query.groupBy(this.groupby)
+        } else if (filter != null) {
+          query = filter.groupBy(this.groupby)
+        }
+      }
+      if (this.groupField.length > 0) {
+        if (query != null) {
+          query = query.groupField(this.groupField)
+        } else if (filter != null) {
+          query = filter.groupField(this.groupField)
+        }
+      }
+      if (this.distinct == true) {
+        if (query != null) {
+          query = query.distinct(this.field)
+        } else if (filter != null) {
+          query = filter.distinct(this.field)
+        }
+      }
+      if (this.orderby.length > 0) {
+        if (query != null) {
+          query = query.orderBy(this.orderby)
+        } else if (filter != null) {
+          query = filter.orderBy(this.orderby)
+        }
+      }
+
+      const size = this.pagination.size
+      const current = this.pagination.current
+      if (query != null) {
+        query = query.skip(size * (current - 1)).limit(size)
+      } else if (filter != null) {
+        query = filter.skip(size * (current - 1)).limit(size)
+      } else {
+        query = collection.skip(size * (current - 1)).limit(size)
+      }
+
+      const getOptions = {}
+      const treeOptions = {
+        limitLevel: this.limitlevel,
+        startWith: this.startwith
+      }
+      if (this.getcount == true) {
+        getOptions['getCount'] = this.getcount
+      }
+
+      const getTree : any = options?.getTree ?? this.gettree
+      if (typeof getTree == 'string') {
+        const getTreeString = getTree as string
+        if (getTreeString.length > 0) {
+          getOptions['getTree'] = treeOptions
+        }
+      } else if (typeof getTree == 'object') {
+        getOptions['getTree'] = treeOptions
+      } else {
+        getOptions['getTree'] = getTree
+      }
+
+      const getTreePath = options?.getTreePath ?? this.gettreepath
+      if (typeof getTreePath == 'string') {
+        const getTreePathString = getTreePath as string
+        if (getTreePathString.length > 0) {
+          getOptions['getTreePath'] = getTreePath
+        }
+      } else {
+        getOptions['getTreePath'] = getTreePath
+      }
+
+      return query.get(getOptions)
+    },
+
+    _checkIsNotNull(value : any) : boolean {
+      if (typeof value == 'string') {
+        const valueString = value as string
+        return (valueString.length > 0)
+      } else if (value instanceof UTSJSONObject) {
+        return true
+      }
+      return false
+    },
+
+    _checkIsLeafNode(nodeData : UTSJSONObject) : boolean {
+      if (this.selectedIndex >= this.limitlevel) {
+        return true
+      }
+
+      if (nodeData.getBoolean('isleaf', false)) {
+        return true
+      }
+
+      return false
+    },
+
+    _checkHasChildren(nodeData : UTSJSONObject) : boolean {
+      const children = nodeData.getArray('children') ?? ([] as Array<any>)
+      return children.length > 0
+    },
+
+    _pushSelectedNodes(nodes : Array<UTSJSONObject>) {
+      this.selectedNodes.push(DefaultSelectedNode)
+      this.selectedPages.push(nodes)
+      this.selectedIndex = this.selectedPages.length - 1
+    },
+
+    _trimSelectedNodes(nodeData : UTSJSONObject) {
+      this.selectedNodes.splice(this.selectedIndex)
+      this.selectedNodes.push(nodeData)
+
+      if (this.selectedPages.length > 0) {
+        this.selectedPages.splice(this.selectedIndex + 1)
+      }
+
+      const children = nodeData.getArray<UTSJSONObject>('children') ?? ([] as Array<UTSJSONObject>)
+      if (children.length > 0) {
+        this.selectedNodes.push(DefaultSelectedNode)
+        this.selectedPages.push(children)
+      }
+
+      this.selectedIndex = this.selectedPages.length - 1
+    },
+
+    _pushSelectedTreeNodes(paths : Array<UTSJSONObject>, nodes : Array<UTSJSONObject>) {
+      let children : Array<UTSJSONObject> = nodes
+      paths.forEach((node : UTSJSONObject) => {
+        const findNode = children.find((item : UTSJSONObject) : boolean => {
+          return (item.getString(this.mappingValueName) == node.getString(this.mappingValueName))
+        })
+        if (findNode != null) {
+          this.selectedPages.push(children)
+          this.selectedNodes.push(node)
+          children = findNode.getArray<UTSJSONObject>('children') ?? ([] as Array<UTSJSONObject>)
+        }
+      })
+      this.selectedIndex = this.selectedPages.length - 1
+    },
+
+    _extractTreePath(nodes : Array<UTSJSONObject>, result : Array<UTSJSONObject>) {
+      if (nodes.length == 0) {
+        return
+      }
+
+      const node = nodes[0]
+      result.push(node)
+
+      const children = node.getArray<UTSJSONObject>('children')
+      if (Array.isArray(children) && children!.length > 0) {
+        this._extractTreePath(children, result)
+      }
+    }
+  }
+})

+ 76 - 0
src/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.css

@@ -0,0 +1,76 @@
+.uni-data-pickerview {
+  position: relative;
+  flex-direction: column;
+  overflow: hidden;
+}
+
+.loading-cover {
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  align-items: center;
+  justify-content: center;
+  background-color: rgba(150, 150, 150, .1);
+}
+
+.error {
+  background-color: #fff;
+  padding: 15px;
+}
+
+.error-text {
+  color: #DD524D;
+}
+
+.selected-node-list {
+  flex-direction: row;
+  flex-wrap: nowrap;
+}
+
+.selected-node-item {
+  margin-left: 10px;
+  margin-right: 10px;
+  padding: 8px 10px 8px 10px;
+  border-bottom: 2px solid transparent;
+}
+
+.selected-node-item-active {
+  color: #007aff;
+  border-bottom-color: #007aff;
+}
+
+.list-view {
+  flex: 1;
+}
+
+.list-item {
+  flex-direction: row;
+  justify-content: space-between;
+  padding: 12px 15px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.item-text {
+  color: #333333;
+}
+
+.item-text-disabled {
+  opacity: .5;
+}
+
+.item-text-overflow {
+  overflow: hidden;
+}
+
+.check {
+  margin-right: 5px;
+  border: 2px solid #007aff;
+  border-left: 0;
+  border-top: 0;
+  height: 12px;
+  width: 6px;
+  transform-origin: center;
+  transform: rotate(45deg);
+}

+ 69 - 0
src/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.uvue

@@ -0,0 +1,69 @@
+<template>
+  <view class="uni-data-pickerview">
+    <view v-if="error!=null" class="error">
+      <text class="error-text">{{error!.errMsg}}</text>
+    </view>
+    <scroll-view v-if="!isCloudDataList" :scroll-x="true">
+      <view class="selected-node-list">
+        <template v-for="(item, index) in selectedNodes">
+          <text class="selected-node-item" :class="{'selected-node-item-active':index==selectedIndex}"
+            @click="onTabSelect(index)">
+            {{item[mappingTextName]}}
+          </text>
+        </template>
+      </view>
+    </scroll-view>
+    <list-view class="list-view" :scroll-y="true">
+      <list-item class="list-item" v-for="(item, _) in currentDataList" @click="onNodeClick(item)">
+        <text class="item-text" :class="{'item-text-disabled': item['disable']}">{{item[mappingTextName]}}</text>
+        <text class="check" v-if="item[mappingValueName] == selectedNodes[selectedIndex][mappingValueName]"></text>
+      </list-item>
+    </list-view>
+    <view class="loading-cover" v-if="loading">
+      <slot name="pickerview-loading" :loading="loading"></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+  import { dataPicker } from "./uni-data-picker.uts"
+
+  /**
+   * DataPickerview
+   * @description uni-data-pickerview
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+   * @property {Array} localdata 本地数据,参考
+   * @property {Boolean} step-searh = [true|false] 是否分布查询
+   * @value true 启用分布查询,仅查询当前选中节点
+   * @value false 关闭分布查询,一次查询出所有数据
+   * @property {String|DBFieldString} self-field 分布查询当前字段名称
+   * @property {String|DBFieldString} parent-field 分布查询父字段名称
+   * @property {String|DBCollectionString} collection 表名
+   * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
+   * @property {String} orderby 排序字段及正序倒叙设置
+   * @property {String|JQLString} where 查询条件
+   */
+  export default {
+    name: 'UniDataPickerView',
+    emits: ['nodeclick', 'change', 'update:modelValue'],
+    mixins: [dataPicker],
+    props: {
+      ellipsis: {
+        type: Boolean,
+        default: true
+      }
+    },
+    created() {
+      this.loadData()
+    },
+    methods: {
+      onFinish() {
+        this.$emit('change', this.getChangeNodes())
+      }
+    }
+  }
+</script>
+
+<style>
+  @import url("uni-data-pickerview.css");
+</style>

+ 17 - 15
src/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue

@@ -2,25 +2,27 @@
   <view class="uni-data-pickerview">
     <scroll-view v-if="!isCloudDataList" class="selected-area" scroll-x="true">
       <view class="selected-list">
-        <template v-for="(item,index) in selected">
-          <view class="selected-item"
-            :class="{'selected-item-active':index==selectedIndex}"
-            v-if="item.text" @click="handleSelect(index)">
-            <text>{{item.text}}</text>
+          <view 
+            class="selected-item"
+            v-for="(item,index) in selected"
+            :key="index"
+            :class="{
+              'selected-item-active':index == selectedIndex
+            }"
+            @click="handleSelect(index)"
+          >
+            <text>{{item.text || ''}}</text>
           </view>
-        </template>
       </view>
     </scroll-view>
     <view class="tab-c">
-      <template v-for="(child, i) in dataList">
-        <scroll-view class="list" :key="i" v-if="i==selectedIndex" :scroll-y="true">
-          <view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in child"
-            @click="handleNodeClick(item, i, j)">
-            <text class="item-text">{{item[map.text]}}</text>
-            <view class="check" v-if="selected.length > i && item[map.value] == selected[i].value"></view>
-          </view>
-        </scroll-view>
-      </template>
+      <scroll-view class="list" :scroll-y="true">
+        <view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in dataList[selectedIndex]" :key="j"
+          @click="handleNodeClick(item, selectedIndex, j)">
+          <text class="item-text">{{item[map.text]}}</text>
+          <view class="check" v-if="selected.length > selectedIndex && item[map.value] == selected[selectedIndex].value"></view>
+        </view>
+      </scroll-view>
 
       <view class="loading-cover" v-if="loading">
         <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>

+ 4 - 3
src/uni_modules/uni-data-picker/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-data-picker",
   "displayName": "uni-data-picker 数据驱动的picker选择器",
-  "version": "1.0.8",
+  "version": "2.0.0",
   "description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景",
   "keywords": [
     "uni-ui",
@@ -53,7 +53,8 @@
       "client": {
         "App": {
           "app-vue": "y",
-          "app-nvue": "u"
+          "app-nvue": "y",
+          "app-uvue": "y"
         },
         "H5-mobile": {
           "Safari": "y",
@@ -87,4 +88,4 @@
       }
     }
   }
-}
+}

+ 1 - 1
src/uni_modules/uni-data-picker/readme.md

@@ -19,4 +19,4 @@
 在uniCloud数据表中新建表“uni-id-address”和“opendb-city-china”,这2个表的schema自带foreignKey关联。在“uni-id-address”表的表结构页面使用schema2code生成前端页面,会自动生成地址管理的维护页面,自动从“opendb-city-china”表包含的中国所有省市区信息里选择地址。
 
 ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-picker)
-#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839

+ 15 - 0
src/uni_modules/uni-data-select/changelog.md

@@ -1,3 +1,18 @@
+## 1.0.7(2024-01-20)
+- 修复 长文本回显超过容器的bug,超过容器部分显示省略号
+## 1.0.6(2023-04-12)
+- 修复 微信小程序点击时会改变背景颜色的 bug
+## 1.0.5(2023-02-03)
+- 修复 禁用时会显示清空按钮
+## 1.0.4(2023-02-02)
+- 优化 查询条件短期内多次变更只查询最后一次变更后的结果
+- 调整 内部缓存键名调整为 uni-data-select-lastSelectedValue
+## 1.0.3(2023-01-16)
+- 修复 不关联服务空间报错的问题
+## 1.0.2(2023-01-14)
+- 新增  属性 `format` 可用于格式化显示选项内容
+## 1.0.1(2022-12-06)
+- 修复  当where变化时,数据不会自动更新的问题
 ## 0.1.9(2022-09-05)
 - 修复 微信小程序下拉框出现后选择会点击到蒙板后面的输入框
 ## 0.1.8(2022-08-29)

+ 144 - 57
src/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue

@@ -2,12 +2,16 @@
 	<view class="uni-stat__select">
 		<span v-if="label" class="uni-label-text hide-on-phone">{{label + ':'}}</span>
 		<view class="uni-stat-box" :class="{'uni-stat__actived': current}">
-			<view class="uni-select"  :class="{'uni-select--disabled':disabled}">
+			<view class="uni-select" :class="{'uni-select--disabled':disabled}">
 				<view class="uni-select__input-box" @click="toggleSelector">
-					<view v-if="current" class="uni-select__input-text">{{current}}</view>
+					<view v-if="current" class="uni-select__input-text">{{textShow}}</view>
 					<view v-else class="uni-select__input-text uni-select__input-placeholder">{{typePlaceholder}}</view>
-					<uni-icons v-if="current && clear" type="clear" color="#c0c4cc" size="24" @click="clearVal" />
-					<uni-icons v-else :type="showSelector? 'top' : 'bottom'" size="14" color="#999" />
+					<view v-if="current && clear && !disabled" @click.stop="clearVal" >
+						<uni-icons type="clear" color="#c0c4cc" size="24"/>
+					</view>
+					<view v-else>
+						<uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" />
+					</view>
 				</view>
 				<view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" />
 				<view class="uni-select__selector" v-if="showSelector">
@@ -16,10 +20,9 @@
 						<view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0">
 							<text>{{emptyTips}}</text>
 						</view>
-						<view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData"
-							:key="index" @click="change(item)">
-							<text
-								:class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text>
+						<view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData" :key="index"
+							@click="change(item)">
+							<text :class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text>
 						</view>
 					</scroll-view>
 				</view>
@@ -44,17 +47,8 @@
 	 */
 
 	export default {
-		name: "uni-stat-select",
+		name: "uni-data-select",
 		mixins: [uniCloud.mixinDatacom || {}],
-		data() {
-			return {
-				showSelector: false,
-				current: '',
-				mixinDatacomResData: [],
-				apps: [],
-				channels: []
-			};
-		},
 		props: {
 			localdata: {
 				type: Array,
@@ -90,15 +84,32 @@
 				type: Number,
 				default: 0
 			},
-      disabled: {
+			disabled: {
 				type: Boolean,
 				default: false
-			}
+			},
+			// 格式化输出 用法 field="_id as value, version as text, uni_platform as label" format="{label} - {text}"
+			format: {
+				type: String,
+				default: ''
+			},
+		},
+		data() {
+			return {
+				showSelector: false,
+				current: '',
+				mixinDatacomResData: [],
+				apps: [],
+				channels: [],
+				cacheKey: "uni-data-select-lastSelectedValue",
+			};
 		},
 		created() {
-			this.last = `${this.collection}_last_selected_option_value`
+			this.debounceGet = this.debounce(() => {
+				this.query();
+			}, 300);
 			if (this.collection && !this.localdata.length) {
-				this.mixinDatacomEasyGet()
+				this.debounceGet();
 			}
 		},
 		computed: {
@@ -113,8 +124,25 @@
 				return placeholder ?
 					common + placeholder :
 					common
+			},
+			valueCom(){
+				// #ifdef VUE3
+				return this.modelValue;
+				// #endif
+				// #ifndef VUE3
+				return this.value;
+				// #endif
+			},
+			textShow(){
+				// 长文本显示
+				let text = this.current;
+				if (text.length > 10) {
+					return text.slice(0, 25) + '...';
+				}
+				return text;
 			}
 		},
+
 		watch: {
 			localdata: {
 				immediate: true,
@@ -124,16 +152,9 @@
 					}
 				}
 			},
-			// #ifndef VUE3
-			value() {
+			valueCom(val, old) {
 				this.initDefVal()
 			},
-			// #endif
-			// #ifdef VUE3
-			modelValue() {
-				this.initDefVal()
-			},
-			// #endif
 			mixinDatacomResData: {
 				immediate: true,
 				handler(val) {
@@ -141,30 +162,50 @@
 						this.initDefVal()
 					}
 				}
-			}
+			},
+
 		},
 		methods: {
+			debounce(fn, time = 100){
+				let timer = null
+				return function(...args) {
+					if (timer) clearTimeout(timer)
+					timer = setTimeout(() => {
+						fn.apply(this, args)
+					}, time)
+				}
+			},
+			// 执行数据库查询
+			query(){
+				this.mixinDatacomEasyGet();
+			},
+			// 监听查询条件变更事件
+			onMixinDatacomPropsChange(){
+				if (this.collection) {
+					this.debounceGet();
+				}
+			},
 			initDefVal() {
 				let defValue = ''
-				if ((this.value || this.value === 0) && !this.isDisabled(this.value)) {
-					defValue = this.value
-				} else if ((this.modelValue || this.modelValue === 0) && !this.isDisabled(this.modelValue)) {
-					defValue = this.modelValue
+				if ((this.valueCom || this.valueCom === 0) && !this.isDisabled(this.valueCom)) {
+					defValue = this.valueCom
 				} else {
 					let strogeValue
 					if (this.collection) {
-						strogeValue = uni.getStorageSync(this.last)
+						strogeValue = this.getCache()
 					}
 					if (strogeValue || strogeValue === 0) {
 						defValue = strogeValue
 					} else {
 						let defItem = ''
-						if (this.defItem > 0 && this.defItem < this.mixinDatacomResData.length) {
+						if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) {
 							defItem = this.mixinDatacomResData[this.defItem - 1].value
 						}
 						defValue = defItem
 					}
-					this.emit(defValue)
+          if (defValue || defValue === 0) {
+					  this.emit(defValue)
+          }
 				}
 				const def = this.mixinDatacomResData.find(item => item.value === defValue)
 				this.current = def ? this.formatItemName(def) : ''
@@ -189,7 +230,7 @@
 			clearVal() {
 				this.emit('')
 				if (this.collection) {
-					uni.removeStorageSync(this.last)
+					this.removeCache()
 				}
 			},
 			change(item) {
@@ -200,18 +241,17 @@
 				}
 			},
 			emit(val) {
-				this.$emit('change', val)
 				this.$emit('input', val)
 				this.$emit('update:modelValue', val)
+				this.$emit('change', val)
 				if (this.collection) {
-					uni.setStorageSync(this.last, val)
+					this.setCache(val);
 				}
 			},
-
 			toggleSelector() {
-        if(this.disabled){
-          return
-        }
+				if (this.disabled) {
+					return
+				}
 
 				this.showSelector = !this.showSelector
 			},
@@ -222,14 +262,50 @@
 					channel_code
 				} = item
 				channel_code = channel_code ? `(${channel_code})` : ''
-				return this.collection.indexOf('app-list') > 0 ?
-					`${text}(${value})` :
-					(
-						text ?
-						text :
-						`未命名${channel_code}`
-					)
-			}
+
+				if (this.format) {
+					// 格式化输出
+					let str = "";
+					str = this.format;
+					for (let key in item) {
+						str = str.replace(new RegExp(`{${key}}`,"g"),item[key]);
+					}
+					return str;
+				} else {
+					return this.collection.indexOf('app-list') > 0 ?
+						`${text}(${value})` :
+						(
+							text ?
+							text :
+							`未命名${channel_code}`
+						)
+				}
+			},
+			// 获取当前加载的数据
+			getLoadData(){
+				return this.mixinDatacomResData;
+			},
+			// 获取当前缓存key
+			getCurrentCacheKey(){
+				return this.collection;
+			},
+			// 获取缓存
+			getCache(name=this.getCurrentCacheKey()){
+				let cacheData = uni.getStorageSync(this.cacheKey) || {};
+				return cacheData[name];
+			},
+			// 设置缓存
+			setCache(value, name=this.getCurrentCacheKey()){
+				let cacheData = uni.getStorageSync(this.cacheKey) || {};
+				cacheData[name] = value;
+				uni.setStorageSync(this.cacheKey, cacheData);
+			},
+			// 删除缓存
+			removeCache(name=this.getCurrentCacheKey()){
+				let cacheData = uni.getStorageSync(this.cacheKey) || {};
+				delete cacheData[name];
+				uni.setStorageSync(this.cacheKey, cacheData);
+			},
 		}
 	}
 </script>
@@ -253,7 +329,9 @@
 		display: flex;
 		align-items: center;
 		// padding: 15px;
+		/* #ifdef H5 */
 		cursor: pointer;
+		/* #endif */
 		width: 100%;
 		flex: 1;
 		box-sizing: border-box;
@@ -297,10 +375,10 @@
 		flex: 1;
 		height: 35px;
 
-    &--disabled{
-      background-color: #f5f7fa;
-      cursor: not-allowed;
-    }
+		&--disabled {
+			background-color: #f5f7fa;
+			cursor: not-allowed;
+		}
 	}
 
 	.uni-select__label {
@@ -357,6 +435,14 @@
 		/* #endif */
 	}
 
+	/* #ifdef H5 */
+	@media (min-width: 768px) {
+		.uni-select__selector-scroll {
+			max-height: 600px;
+		}
+	}
+	/* #endif */
+
 	.uni-select__selector-empty,
 	.uni-select__selector-item {
 		/* #ifndef APP-NVUE */
@@ -436,5 +522,6 @@
 		bottom: 0;
 		right: 0;
 		left: 0;
+		z-index: 2;
 	}
 </style>

+ 1 - 1
src/uni_modules/uni-data-select/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-data-select",
   "displayName": "uni-data-select 下拉框选择器",
-  "version": "0.1.9",
+  "version": "1.0.7",
   "description": "通过数据驱动的下拉框选择器",
   "keywords": [
     "uni-ui",

+ 82 - 33
src/uni_modules/uni-datetime-picker/changelog.md

@@ -1,41 +1,90 @@
+## 2.2.30(2024-01-31)
+- 修复 隐藏“秒”时,在IOS15及以下版本时出现 结束时间在开始时间之前 的bug [详情](https://github.com/dcloudio/uni-ui/issues/788)
+## 2.2.29(2024-01-20)
+- 新增 show事件,弹窗弹出时触发该事件 [详情](https://github.com/dcloudio/uni-app/issues/4694)
+## 2.2.28(2024-01-18)
+- 去除 noChange事件,当进行日期范围选择时,若只选了一天,则开始结束日期都为同一天 [详情](https://github.com/dcloudio/uni-ui/issues/815)
+## 2.2.27(2024-01-10)
+- 优化 增加noChange事件,当进行日期范围选择时,若有空值,则触发该事件 [详情](https://github.com/dcloudio/uni-ui/issues/815)
+## 2.2.26(2024-01-08)
+- 修复 字节小程序时间选择范围器失效问题 [详情](https://github.com/dcloudio/uni-ui/issues/834)
+## 2.2.25(2023-10-18)
+- 修复 PC端初次修改时间,开始时间未更新的Bug [详情](https://github.com/dcloudio/uni-ui/issues/737)
+## 2.2.24(2023-06-02)
+- 修复 部分情况修改时间,开始、结束时间显示异常的Bug [详情](https://ask.dcloud.net.cn/question/171146)
+- 优化 当前月可以选择上月、下月的日期的Bug
+## 2.2.23(2023-05-02)
+- 修复 部分情况修改时间,开始时间未更新的Bug [详情](https://github.com/dcloudio/uni-ui/issues/737)
+- 修复 部分平台及设备第一次点击无法显示弹框的Bug
+- 修复 ios 日期格式未补零显示及使用异常的Bug [详情](https://ask.dcloud.net.cn/question/162979)
+## 2.2.22(2023-03-30)
+- 修复 日历 picker 修改年月后,自动选中当月1日的Bug [详情](https://ask.dcloud.net.cn/question/165937)
+- 修复 小程序端 低版本 ios NaN的Bug [详情](https://ask.dcloud.net.cn/question/162979)
+## 2.2.21(2023-02-20)
+- 修复 firefox 浏览器显示区域点击无法拉起日历弹框的Bug [详情](https://ask.dcloud.net.cn/question/163362)
+## 2.2.20(2023-02-17)
+- 优化 值为空依然选中当天问题
+- 优化 提供 default-value 属性支持配置选择器打开时默认显示的时间
+- 优化 非范围选择未选择日期时间,点击确认按钮选中当前日期时间
+- 优化 字节小程序日期时间范围选择,底部日期换行的Bug
+## 2.2.19(2023-02-09)
+- 修复 2.2.18 引起范围选择配置 end 选择无效的Bug [详情](https://github.com/dcloudio/uni-ui/issues/686)
+## 2.2.18(2023-02-08)
+- 修复 移动端范围选择change事件触发异常的Bug [详情](https://github.com/dcloudio/uni-ui/issues/684)
+- 优化 PC端输入日期格式错误时返回当前日期时间
+- 优化 PC端输入日期时间超出 start、end 限制的Bug
+- 优化 移动端日期时间范围用法时间展示不完整问题
+## 2.2.17(2023-02-04)
+- 修复 小程序端绑定 Date 类型报错的Bug [详情](https://github.com/dcloudio/uni-ui/issues/679)
+- 修复 vue3 time-picker 无法显示绑定时分秒的Bug
+## 2.2.16(2023-02-02)
+- 修复 字节小程序报错的Bug
+## 2.2.15(2023-02-02)
+- 修复 某些情况切换月份错误的Bug
+## 2.2.14(2023-01-30)
+- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/162033)
+## 2.2.13(2023-01-10)
+- 修复 多次加载组件造成内存占用的Bug
+## 2.2.12(2022-12-01)
+- 修复 vue3 下 i18n 国际化初始值不正确的Bug
 ## 2.2.11(2022-09-19)
-- 修复,支付宝小程序样式错乱,[详情](https://github.com/dcloudio/uni-app/issues/3861)
+- 修复 支付宝小程序样式错乱的Bug [详情](https://github.com/dcloudio/uni-app/issues/3861)
 ## 2.2.10(2022-09-19)
-- 修复,反向选择日期范围,日期显示异常,[详情](https://ask.dcloud.net.cn/question/153401?item_id=212892&rf=false)
+- 修复 反向选择日期范围,日期显示异常的Bug [详情](https://ask.dcloud.net.cn/question/153401?item_id=212892&rf=false)
 ## 2.2.9(2022-09-16)
 - 可以使用 uni-scss 控制主题色
 ## 2.2.8(2022-09-08)
-- 修复 close事件无效的 bug
+- 修复 close事件无效的Bug
 ## 2.2.7(2022-09-05)
-- 修复 移动端 maskClick 无效的 bug,详见:[https://ask.dcloud.net.cn/question/140824?item_id=209458&rf=false](https://ask.dcloud.net.cn/question/140824?item_id=209458&rf=false)
+- 修复 移动端 maskClick 无效的Bug [详情](https://ask.dcloud.net.cn/question/140824)
 ## 2.2.6(2022-06-30)
 - 优化 组件样式,调整了组件图标大小、高度、颜色等,与uni-ui风格保持一致
 ## 2.2.5(2022-06-24)
-- 修复 日历顶部年月及底部确认未国际化 bug
+- 修复 日历顶部年月及底部确认未国际化的Bug
 ## 2.2.4(2022-03-31)
-- 修复 Vue3 下动态赋值,单选类型未响应的 bug
+- 修复 Vue3 下动态赋值,单选类型未响应的Bug
 ## 2.2.3(2022-03-28)
-- 修复 Vue3 下动态赋值未响应的 bug
+- 修复 Vue3 下动态赋值未响应的Bug
 ## 2.2.2(2021-12-10)
-- 修复 clear-icon 属性在小程序平台不生效的 bug
+- 修复 clear-icon 属性在小程序平台不生效的Bug
 ## 2.2.1(2021-12-10)
-- 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的 bug
+- 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的Bug
 ## 2.2.0(2021-11-19)
-- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
-- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
-## 2.1.5(2021-11-09) 
+- 优化 组件UI,并提供设计资源 [详情](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移 [https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
+## 2.1.5(2021-11-09)
 - 新增 提供组件设计资源,组件样式调整
 ## 2.1.4(2021-09-10)
-- 修复 hide-second 在移动端的 bug
-- 修复 单选赋默认值时,赋值日期未高亮的 bug
-- 修复 赋默认值时,移动端未正确显示时间的 bug
+- 修复 hide-second 在移动端的Bug
+- 修复 单选赋默认值时,赋值日期未高亮的Bug
+- 修复 赋默认值时,移动端未正确显示时间的Bug
 ## 2.1.3(2021-09-09)
 - 新增 hide-second 属性,支持只使用时分,隐藏秒
 ## 2.1.2(2021-09-03)
 - 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次
 - 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法
 - 优化 调整字号大小,美化日历界面
-- 修复 因国际化导致的 placeholder 失效的 bug
+- 修复 因国际化导致的 placeholder 失效的Bug
 ## 2.1.1(2021-08-24)
 - 新增 支持国际化
 - 优化 范围选择器在 pc 端过宽的问题
@@ -43,50 +92,50 @@
 - 新增 适配 vue3
 ## 2.0.19(2021-08-09)
 - 新增 支持作为 uni-forms 子组件相关功能
-- 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的 bug
+- 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的Bug
 ## 2.0.18(2021-08-05)
-- 修复 type 属性动态赋值无效的 bug
+- 修复 type 属性动态赋值无效的Bug
 - 修复 ‘确认’按钮被 tabbar 遮盖 bug
-- 修复 组件未赋值时范围选左、右日历相同的 bug
+- 修复 组件未赋值时范围选左、右日历相同的Bug
 ## 2.0.17(2021-08-04)
-- 修复 范围选未正确显示当前值的 bug
-- 修复 h5 平台(移动端)报错 'cale' of undefined 的 bug
+- 修复 范围选未正确显示当前值的Bug
+- 修复 h5 平台(移动端)报错 'cale' of undefined 的Bug
 ## 2.0.16(2021-07-21)
 - 新增 return-type 属性支持返回 date 日期对象
 ## 2.0.15(2021-07-14)
-- 修复 单选日期类型,初始赋值后不在当前日历的 bug
+- 修复 单选日期类型,初始赋值后不在当前日历的Bug
 - 新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效)
 - 优化 移动端移除显示框的清空按钮,无实际用途
 ## 2.0.14(2021-07-14)
-- 修复 组件赋值为空,界面未更新的 bug
-- 修复 start 和 end 不能动态赋值的 bug
-- 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的 bug
+- 修复 组件赋值为空,界面未更新的Bug
+- 修复 start 和 end 不能动态赋值的Bug
+- 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的Bug
 ## 2.0.13(2021-07-08)
-- 修复 范围选择不能动态赋值的 bug
+- 修复 范围选择不能动态赋值的Bug
 ## 2.0.12(2021-07-08)
 - 修复 范围选择的初始时间在一个月内时,造成无法选择的bug
 ## 2.0.11(2021-07-08)
 - 优化 弹出层在超出视窗边缘定位不准确的问题
 ## 2.0.10(2021-07-08)
-- 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的 bug
+- 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的Bug
 - 优化 弹出层在超出视窗边缘被遮盖的问题
 ## 2.0.9(2021-07-07)
 - 新增 maskClick 事件
-- 修复 特殊情况日历 rpx 布局错误的 bug,rpx -> px
+- 修复 特殊情况日历 rpx 布局错误的Bug,rpx -> px
 - 修复 范围选择时清空返回值不合理的bug,['', ''] -> []
 ## 2.0.8(2021-07-07)
 - 新增 日期时间显示框支持插槽
 ## 2.0.7(2021-07-01)
 - 优化 添加 uni-icons 依赖
 ## 2.0.6(2021-05-22)
-- 修复 图标在小程序上不显示的 bug
+- 修复 图标在小程序上不显示的Bug
 - 优化 重命名引用组件,避免潜在组件命名冲突
 ## 2.0.5(2021-05-20)
 - 优化 代码目录扁平化
 ## 2.0.4(2021-05-12)
 - 新增 组件示例地址
 ## 2.0.3(2021-05-10)
-- 修复 ios 下不识别 '-' 日期格式的 bug
+- 修复 ios 下不识别 '-' 日期格式的Bug
 - 优化 pc 下弹出层添加边框和阴影
 ## 2.0.2(2021-05-08)
 - 修复 在 admin 中获取弹出层定位错误的bug
@@ -97,7 +146,7 @@
  > 注意:此版本不向后兼容,不再支持单独时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker)
 ## 1.0.6(2021-03-18)
 - 新增 hide-second 属性,时间支持仅选择时、分
-- 修复 选择跟显示的日期不一样的 bug
-- 修复 chang事件触发2次的 bug
-- 修复 分、秒 end 范围错误的 bug
+- 修复 选择跟显示的日期不一样的Bug
+- 修复 chang事件触发2次的Bug
+- 修复 分、秒 end 范围错误的Bug
 - 优化 更好的 nvue 适配

+ 3 - 13
src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue

@@ -13,10 +13,10 @@
 				'uni-calendar-item--after-checked':weeks.afterMultiple,
 				'uni-calendar-item--disable':weeks.disable,
 				}">
-			<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
+			<text v-if="selected && weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
 			<text class="uni-calendar-item__weeks-box-text uni-calendar-item__weeks-box-text-disable uni-calendar-item--checked-text">{{weeks.date}}</text>
 		</view>
-		<view :class="{'uni-calendar-item--isDay': weeks.isDay}"></view>
+		<view :class="{'uni-calendar-item--today': weeks.isToday}"></view>
 	</view>
 </template>
 
@@ -41,10 +41,6 @@
 					return []
 				}
 			},
-			lunar: {
-				type: Boolean,
-				default: false
-			},
 			checkHover: {
 				type: Boolean,
 				default: false
@@ -83,11 +79,6 @@
 		color: darken($color: $uni-primary, $amount: 40%);
 	}
 
-	.uni-calendar-item__weeks-lunar-text {
-		font-size: 12px;
-		color: #333;
-	}
-
 	.uni-calendar-item__weeks-box-item {
 		position: relative;
 		/* #ifndef APP-NVUE */
@@ -116,7 +107,6 @@
 	}
 
 	.uni-calendar-item__weeks-box .uni-calendar-item--disable {
-		// background-color: rgba(249, 249, 249, $uni-opacity-disabled);
 		cursor: default;
 	}
 
@@ -124,7 +114,7 @@
 		color: #D1D1D1;
 	}
 
-	.uni-calendar-item--isDay {
+	.uni-calendar-item--today {
 		position: absolute;
 		top: 10px;
 		right: 17%;

+ 129 - 125
src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue

@@ -1,31 +1,37 @@
 <template>
 	<view class="uni-calendar" @mouseleave="leaveCale">
-		<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}"
-			@click="clean();maskClick()"></view>
+
+		<view v-if="!insert && show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}"
+			@click="maskClick"></view>
+
 		<view v-if="insert || show" class="uni-calendar__content"
 			:class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow, 'uni-calendar__content-mobile': aniMaskShow}">
 			<view class="uni-calendar__header" :class="{'uni-calendar__header-mobile' :!insert}">
-				<view v-if="left" class="uni-calendar__header-btn-box" @click.stop="pre">
+
+				<view class="uni-calendar__header-btn-box" @click.stop="changeMonth('pre')">
 					<view class="uni-calendar__header-btn uni-calendar--left"></view>
 				</view>
+
 				<picker mode="date" :value="date" fields="month" @change="bindDateChange">
 					<text
 						class="uni-calendar__header-text">{{ (nowDate.year||'') + yearText + ( nowDate.month||'') + monthText}}</text>
 				</picker>
-				<view v-if="right" class="uni-calendar__header-btn-box" @click.stop="next">
+
+				<view class="uni-calendar__header-btn-box" @click.stop="changeMonth('next')">
 					<view class="uni-calendar__header-btn uni-calendar--right"></view>
 				</view>
-				<view v-if="!insert" class="dialog-close" @click="clean">
+
+				<view v-if="!insert" class="dialog-close" @click="close">
 					<view class="dialog-close-plus" data-id="close"></view>
 					<view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
 				</view>
-
-				<!-- <text class="uni-calendar__backtoday" @click="backtoday">回到今天</text> -->
 			</view>
 			<view class="uni-calendar__box">
+
 				<view v-if="showMonth" class="uni-calendar__box-bg">
 					<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
 				</view>
+
 				<view class="uni-calendar__weeks" style="padding-bottom: 7px;">
 					<view class="uni-calendar__weeks-day">
 						<text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
@@ -49,28 +55,30 @@
 						<text class="uni-calendar__weeks-day-text">{{SATText}}</text>
 					</view>
 				</view>
+
 				<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
 					<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
 						<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar"
-							:selected="selected" :lunar="lunar" :checkHover="range" @change="choiceDate"
+							:selected="selected" :checkHover="range" @change="choiceDate"
 							@handleMouse="handleMouse">
 						</calendar-item>
 					</view>
 				</view>
 			</view>
-			<view v-if="!insert && !range && typeHasTime" class="uni-date-changed uni-calendar--fixed-top"
+
+			<view v-if="!insert && !range && hasTime" class="uni-date-changed uni-calendar--fixed-top"
 				style="padding: 0 80px;">
 				<view class="uni-date-changed--time-date">{{tempSingleDate ? tempSingleDate : selectDateText}}</view>
-				<time-picker type="time" :start="reactStartTime" :end="reactEndTime" v-model="time"
+				<time-picker type="time" :start="timepickerStartTime" :end="timepickerEndTime" v-model="time"
 					:disabled="!tempSingleDate" :border="false" :hide-second="hideSecond" class="time-picker-style">
 				</time-picker>
 			</view>
 
-			<view v-if="!insert && range && typeHasTime" class="uni-date-changed uni-calendar--fixed-top">
+			<view v-if="!insert && range && hasTime" class="uni-date-changed uni-calendar--fixed-top">
 				<view class="uni-date-changed--time-start">
 					<view class="uni-date-changed--time-date">{{tempRange.before ? tempRange.before : startDateText}}
 					</view>
-					<time-picker type="time" :start="reactStartTime" v-model="timeRange.startTime" :border="false"
+					<time-picker type="time" :start="timepickerStartTime" v-model="timeRange.startTime" :border="false"
 						:hide-second="hideSecond" :disabled="!tempRange.before" class="time-picker-style">
 					</time-picker>
 				</view>
@@ -79,15 +87,13 @@
 				</view>
 				<view class="uni-date-changed--time-end">
 					<view class="uni-date-changed--time-date">{{tempRange.after ? tempRange.after : endDateText}}</view>
-					<time-picker type="time" :end="reactEndTime" v-model="timeRange.endTime" :border="false"
+					<time-picker type="time" :end="timepickerEndTime" v-model="timeRange.endTime" :border="false"
 						:hide-second="hideSecond" :disabled="!tempRange.after" class="time-picker-style">
 					</time-picker>
 				</view>
 			</view>
+
 			<view v-if="!insert" class="uni-date-changed uni-date-btn--ok">
-				<!-- <view class="uni-calendar__header-btn-box">
-					<text class="uni-calendar__button-text uni-calendar--fixed-width">{{okText}}</text>
-				</view> -->
 				<view class="uni-datetime-picker--btn" @click="confirm">{{confirmText}}</view>
 			</view>
 		</view>
@@ -95,22 +101,19 @@
 </template>
 
 <script>
-	import Calendar from './util.js';
+	import { Calendar, getDate, getTime } from './util.js';
 	import calendarItem from './calendar-item.vue'
 	import timePicker from './time-picker.vue'
-	import {
-		initVueI18n
-	} from '@dcloudio/uni-i18n'
-	import messages from './i18n/index.js'
-	const {
-		t
-	} = initVueI18n(messages)
+
+	import { initVueI18n } from '@dcloudio/uni-i18n'
+	import i18nMessages from './i18n/index.js'
+	const { t } = initVueI18n(i18nMessages)
+
 	/**
 	 * Calendar 日历
 	 * @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
 	 * @tutorial https://ext.dcloud.net.cn/plugin?id=56
 	 * @property {String} date 自定义当前时间,默认为今天
-	 * @property {Boolean} lunar 显示农历
 	 * @property {String} startDate 日期选择范围-开始日期
 	 * @property {String} endDate 日期选择范围-结束日期
 	 * @property {Boolean} range 范围选择
@@ -120,10 +123,11 @@
 	 * @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
 	 * @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
 	 * @property {Boolean} showMonth 是否选择月份为背景
+	 * @property {[String} defaultValue 选择器打开时默认显示的时间
 	 * @event {Function} change 日期改变,`insert :ture` 时生效
 	 * @event {Function} confirm 确认选择`insert :false` 时生效
 	 * @event {Function} monthSwitch 切换月份时触发
-	 * @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
+	 * @example <uni-calendar :insert="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
 	 */
 	export default {
 		components: {
@@ -151,10 +155,6 @@
 					return []
 				}
 			},
-			lunar: {
-				type: Boolean,
-				default: false
-			},
 			startDate: {
 				type: String,
 				default: ''
@@ -163,11 +163,19 @@
 				type: String,
 				default: ''
 			},
+      startPlaceholder: {
+        type: String,
+				default: ''
+			},
+			endPlaceholder: {
+				type: String,
+				default: ''
+			},
 			range: {
 				type: Boolean,
 				default: false
 			},
-			typeHasTime: {
+			hasTime: {
 				type: Boolean,
 				default: false
 			},
@@ -183,14 +191,6 @@
 				type: Boolean,
 				default: true
 			},
-			left: {
-				type: Boolean,
-				default: true
-			},
-			right: {
-				type: Boolean,
-				default: true
-			},
 			checkHover: {
 				type: Boolean,
 				default: true
@@ -209,14 +209,18 @@
 						fulldate: ''
 					}
 				}
-			}
+			},
+      defaultValue: {
+        type: [String, Object, Array],
+        default: ''
+      }
 		},
 		data() {
 			return {
 				show: false,
 				weeks: [],
 				calendar: {},
-				nowDate: '',
+				nowDate: {},
 				aniMaskShow: false,
 				firstEnter: true,
 				time: '',
@@ -234,7 +238,7 @@
 		watch: {
 			date: {
 				immediate: true,
-				handler(newVal, oldVal) {
+				handler(newVal) {
 					if (!this.range) {
 						this.tempSingleDate = newVal
 						setTimeout(() => {
@@ -245,33 +249,44 @@
 			},
 			defTime: {
 				immediate: true,
-				handler(newVal, oldVal) {
+				handler(newVal) {
 					if (!this.range) {
 						this.time = newVal
 					} else {
-						// console.log('-----', newVal);
 						this.timeRange.startTime = newVal.start
 						this.timeRange.endTime = newVal.end
 					}
 				}
 			},
 			startDate(val) {
-				this.cale.resetSatrtDate(val)
+				// 字节小程序 watch 早于 created
+				if(!this.cale){
+					return
+				}
+				this.cale.setStartDate(val)
 				this.cale.setDate(this.nowDate.fullDate)
 				this.weeks = this.cale.weeks
 			},
 			endDate(val) {
-				this.cale.resetEndDate(val)
+				// 字节小程序 watch 早于 created
+				if(!this.cale){
+					return
+				}
+				this.cale.setEndDate(val)
 				this.cale.setDate(this.nowDate.fullDate)
 				this.weeks = this.cale.weeks
 			},
 			selected(newVal) {
+				// 字节小程序 watch 早于 created
+				if(!this.cale){
+					return
+				}
 				this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
 				this.weeks = this.cale.weeks
 			},
 			pleStatus: {
 				immediate: true,
-				handler(newVal, oldVal) {
+				handler(newVal) {
 					const {
 						before,
 						after,
@@ -294,11 +309,16 @@
 								this.cale.lastHover = false
 							}
 						} else {
+              // 字节小程序 watch 早于 created
+              if(!this.cale){
+                return
+              }
+
 							this.cale.setDefaultMultiple(before, after)
-							if (which === 'left') {
+							if (which === 'left' && before) {
 								this.setDate(before)
 								this.weeks = this.cale.weeks
-							} else {
+							} else if(after) {
 								this.setDate(after)
 								this.weeks = this.cale.weeks
 							}
@@ -309,15 +329,13 @@
 			}
 		},
 		computed: {
-			reactStartTime() {
+			timepickerStartTime() {
 				const activeDate = this.range ? this.tempRange.before : this.calendar.fullDate
-				const res = activeDate === this.startDate ? this.selectableTimes.start : ''
-				return res
+				return activeDate === this.startDate ? this.selectableTimes.start : ''
 			},
-			reactEndTime() {
+			timepickerEndTime() {
 				const activeDate = this.range ? this.tempRange.after : this.calendar.fullDate
-				const res = activeDate === this.endDate ? this.selectableTimes.end : ''
-				return res
+				return activeDate === this.endDate ? this.selectableTimes.end : ''
 			},
 			/**
 			 * for i18n
@@ -368,17 +386,13 @@
 		created() {
 			// 获取日历方法实例
 			this.cale = new Calendar({
-				// date: new Date(),
 				selected: this.selected,
 				startDate: this.startDate,
 				endDate: this.endDate,
 				range: this.range,
-				// multipleStatus: this.pleStatus
 			})
 			// 选中某一天
-			// this.cale.setDate(this.date)
 			this.init(this.date)
-			// this.setDay
 		},
 		methods: {
 			leaveCale() {
@@ -407,14 +421,9 @@
 				const [yearB, monthB] = B.split('-')
 				return yearA === yearB && monthA === monthB
 			},
-
-			// 取消穿透
-			clean() {
-				this.close()
-			},
-
 			// 蒙版点击事件
 			maskClick() {
+        this.close()
 				this.$emit('maskClose')
 			},
 
@@ -433,33 +442,49 @@
 					this.tempSingleDate = ''
 				}
 				this.calendar.fullDate = ''
-				this.setDate()
+				this.setDate(new Date())
 			},
 
 			bindDateChange(e) {
 				const value = e.detail.value + '-1'
-				this.init(value)
+				this.setDate(value)
 			},
 			/**
 			 * 初始化日期显示
 			 * @param {Object} date
 			 */
 			init(date) {
-				this.cale.setDate(date)
+        // 字节小程序 watch 早于 created
+				if(!this.cale){
+					return
+				}
+				this.cale.setDate(date || new Date())
 				this.weeks = this.cale.weeks
-				this.nowDate = this.calendar = this.cale.getInfo(date)
-			},
-			// choiceDate(weeks) {
-			// 	if (weeks.disable) return
-			// 	this.calendar = weeks
-			// 	// 设置多选
-			// 	this.cale.setMultiple(this.calendar.fullDate, true)
-			// 	this.weeks = this.cale.weeks
-			// 	this.tempSingleDate = this.calendar.fullDate
-			// 	this.tempRange.before = this.cale.multipleStatus.before
-			// 	this.tempRange.after = this.cale.multipleStatus.after
-			// 	this.change()
-			// },
+				this.nowDate = this.cale.getInfo(date)
+        this.calendar = {...this.nowDate}
+        if(!date){
+          // 优化date为空默认不选中今天
+          this.calendar.fullDate = ''
+          if(this.defaultValue && !this.range){
+            // 暂时只支持移动端非范围选择
+            const defaultDate = new Date(this.defaultValue)
+            const fullDate = getDate(defaultDate)
+            const year = defaultDate.getFullYear()
+            const month = defaultDate.getMonth()+1
+            const date = defaultDate.getDate()
+            const day = defaultDate.getDay()
+            this.calendar = {
+              fullDate,
+              year,
+              month,
+              date,
+              day
+            },
+            this.tempSingleDate = fullDate
+            this.time = getTime(defaultDate, this.hideSecond)
+          }
+        }
+			},
 			/**
 			 * 打开日历弹窗
 			 */
@@ -467,7 +492,6 @@
 				// 弹窗模式并且清理数据
 				if (this.clearDate && !this.insert) {
 					this.cale.cleanMultipleStatus()
-					// this.cale.setDate(this.date)
 					this.init(this.date)
 				}
 				this.show = true
@@ -521,12 +545,20 @@
 			 * @param {Object} name
 			 */
 			setEmit(name) {
+        if(!this.range){
+					if(!this.calendar.fullDate){
+					  this.calendar = this.cale.getInfo(new Date())
+					  this.tempSingleDate = this.calendar.fullDate
+					}
+					if(this.hasTime && !this.time) {
+					  this.time = getTime(new Date(), this.hideSecond)
+					}
+				}
 				let {
 					year,
 					month,
 					date,
 					fullDate,
-					lunar,
 					extraInfo
 				} = this.calendar
 				this.$emit(name, {
@@ -537,7 +569,6 @@
 					time: this.time,
 					timeRange: this.timeRange,
 					fulldate: fullDate,
-					lunar,
 					extraInfo: extraInfo || {}
 				})
 			},
@@ -553,7 +584,6 @@
 				this.cale.setMultiple(this.calendar.fullDate, true)
 				this.weeks = this.cale.weeks
 				this.tempSingleDate = this.calendar.fullDate
-				const beforeStatus = this.cale.multipleStatus.before
 				const beforeDate = new Date(this.cale.multipleStatus.before).getTime()
 				const afterDate = new Date(this.cale.multipleStatus.after).getTime()
 				if (beforeDate > afterDate && afterDate) {
@@ -565,46 +595,17 @@
 				}
 				this.change()
 			},
-			/**
-			 * 回到今天
-			 */
-			backtoday() {
-				let date = this.cale.getDate(new Date()).fullDate
-				// this.cale.setDate(date)
-				this.init(date)
-				this.change()
-			},
-			/**
-			 * 比较时间大小
-			 */
-			dateCompare(startDate, endDate) {
-				// 计算截止时间
-				startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
-				// 计算详细项的截止时间
-				endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
-				if (startDate <= endDate) {
-					return true
-				} else {
-					return false
-				}
-			},
-			/**
-			 * 上个月
-			 */
-			pre() {
-				const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
-				this.setDate(preDate)
-				this.monthSwitch()
+      changeMonth(type) {
+        let newDate
+        if(type === 'pre') {
+          newDate = this.cale.getPreMonthObj(this.nowDate.fullDate).fullDate
+        } else if(type === 'next') {
+          newDate = this.cale.getNextMonthObj(this.nowDate.fullDate).fullDate
+        }
 
-			},
-			/**
-			 * 下个月
-			 */
-			next() {
-				const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
-				this.setDate(nextDate)
+        this.setDate(newDate)
 				this.monthSwitch()
-			},
+      },
 			/**
 			 * 设置日期
 			 * @param {Object} date
@@ -854,14 +855,17 @@
 
 	.uni-date-changed--time-end {
 		/* #ifndef APP-NVUE */
-		display: flex;
+    display: flex;
 		/* #endif */
 		align-items: center;
 	}
 
 	.uni-date-changed--time-date {
-		color: #999;
+    color: #999;
 		line-height: 50px;
+    /* #ifdef MP-TOUTIAO */
+    font-size: 16px;
+    /* #endif */
 		margin-right: 5px;
 		// opacity: 0.6;
 	}

+ 1 - 1
src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json

@@ -1,7 +1,7 @@
 {
 	"uni-datetime-picker.selectDate": "select date",
 	"uni-datetime-picker.selectTime": "select time",
-	"uni-datetime-picker.selectDateTime": "select datetime",
+	"uni-datetime-picker.selectDateTime": "select date and time",
 	"uni-datetime-picker.startDate": "start date",
 	"uni-datetime-picker.endDate": "end date",
 	"uni-datetime-picker.startTime": "start time",

+ 16 - 36
src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue

@@ -77,21 +77,14 @@
 				</view>
 			</view>
 		</view>
-		<!-- #ifdef H5 -->
-		<!-- <keypress v-if="visible" @esc="tiggerTimePicker" @enter="setTime" /> -->
-		<!-- #endif -->
 	</view>
 </template>
 
 <script>
-	// #ifdef H5
-	import keypress from './keypress'
-	// #endif
-	import {
-		initVueI18n
-	} from '@dcloudio/uni-i18n'
-	import messages from './i18n/index.js'
-	const {	t	} = initVueI18n(messages)
+	import { initVueI18n } from '@dcloudio/uni-i18n'
+	import i18nMessages from './i18n/index.js'
+	const {	t	} = initVueI18n(i18nMessages)
+  import { fixIosDateFormat } from './util'
 
 	/**
 	 * DatetimePicker 时间选择器
@@ -108,11 +101,6 @@
 
 	export default {
 		name: 'UniDatetimePicker',
-		components: {
-			// #ifdef H5
-			keypress
-			// #endif
-		},
 		data() {
 			return {
 				indicatorStyle: `height: 50px;`,
@@ -187,12 +175,12 @@
 		watch: {
 			// #ifndef VUE3
 			value: {
-				handler(newVal, oldVal) {
-					if (newVal) {
-						this.parseValue(this.fixIosDateFormat(newVal)) //兼容 iOS、safari 日期格式
+				handler(newVal) {
+          if (newVal) {
+            this.parseValue(fixIosDateFormat(newVal))
 						this.initTime(false)
 					} else {
-						this.time = ''
+            this.time = ''
 						this.parseValue(Date.now())
 					}
 				},
@@ -201,9 +189,9 @@
 			// #endif
 			// #ifdef VUE3
 			modelValue: {
-				handler(newVal, oldVal) {
-					if (newVal) {
-						this.parseValue(this.fixIosDateFormat(newVal)) //兼容 iOS、safari 日期格式
+        handler(newVal) {
+          if (newVal) {
+						this.parseValue(fixIosDateFormat(newVal))
 						this.initTime(false)
 					} else {
 						this.time = ''
@@ -233,13 +221,13 @@
 			},
 			start: {
 				handler(newVal) {
-					this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'start') //兼容 iOS、safari 日期格式
+					this.parseDatetimeRange(fixIosDateFormat(newVal), 'start')
 				},
 				immediate: true
 			},
 			end: {
 				handler(newVal) {
-					this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'end') //兼容 iOS、safari 日期格式
+					this.parseDatetimeRange(fixIosDateFormat(newVal), 'end')
 				},
 				immediate: true
 			},
@@ -543,7 +531,7 @@
 					const day = now.getDate()
 					dateBase = year + '/' + month + '/' + day + ' '
 				}
-				if (Number(value) && typeof value !== NaN) {
+				if (Number(value)) {
 					value = parseInt(value)
 					dateBase = 0
 				}
@@ -614,7 +602,7 @@
 						pointType === 'start' ? this.startYear = this.year - 60 : this.endYear = this.year + 60
 						return
 					}
-					if (Number(point) && Number(point) !== NaN) {
+					if (Number(point)) {
 						point = parseInt(point)
 					}
 					// datetime 的 end 没有时分秒, 则不限制
@@ -661,14 +649,6 @@
 				return new Date(year, month, 0).getDate();
 			},
 
-			//兼容 iOS、safari 日期格式
-			fixIosDateFormat(value) {
-				if (typeof value === 'string') {
-					value = value.replace(/-/g, '/')
-				}
-				return value
-			},
-
 			/**
 			 * 生成时间戳
 			 * @param {Object} time
@@ -752,7 +732,7 @@
 			 */
 			initTimePicker() {
 				if (this.disabled) return
-				const value = this.fixIosDateFormat(this.value)
+				const value = fixIosDateFormat(this.time)
 				this.initPickerValue(value)
 				this.visible = !this.visible
 			},

File diff suppressed because it is too large
+ 336 - 287
src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue


+ 203 - 192
src/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js

@@ -1,27 +1,24 @@
 class Calendar {
 	constructor({
-		date,
 		selected,
 		startDate,
 		endDate,
 		range,
-		// multipleStatus
 	} = {}) {
 		// 当前日期
-		this.date = this.getDate(new Date()) // 当前初入日期
+		this.date = this.getDateObj(new Date()) // 当前初入日期
 		// 打点信息
 		this.selected = selected || [];
-		// 范围开始
+		// 起始时间
 		this.startDate = startDate
-		// 范围结束
+		// 终止时间
 		this.endDate = endDate
+		// 是否范围选择
 		this.range = range
 		// 多选状态
 		this.cleanMultipleStatus()
 		// 每周日期
 		this.weeks = {}
-		// this._getWeek(this.date.fullDate)
-		// this.multipleStatus = multipleStatus
 		this.lastHover = false
 	}
 	/**
@@ -29,8 +26,8 @@ class Calendar {
 	 * @param {Object} date
 	 */
 	setDate(date) {
-		this.selectDate = this.getDate(date)
-		this._getWeek(this.selectDate.fullDate)
+		const selectDate = this.getDateObj(date)
+		this.getWeeks(selectDate.fullDate)
 	}
 
 	/**
@@ -44,93 +41,82 @@ class Calendar {
 		}
 	}
 
-	/**
-	 * 重置开始日期
-	 */
-	resetSatrtDate(startDate) {
-		// 范围开始
+	setStartDate(startDate) {
 		this.startDate = startDate
-
 	}
 
-	/**
-	 * 重置结束日期
-	 */
-	resetEndDate(endDate) {
-		// 范围结束
+	setEndDate(endDate) {
 		this.endDate = endDate
 	}
 
-	/**
-	 * 获取任意时间
-	 */
-	getDate(date, AddDayCount = 0, str = 'day') {
-		if (!date) {
-			date = new Date()
-		}
-		if (typeof date !== 'object') {
-			date = date.replace(/-/g, '/')
+	getPreMonthObj(date) {
+		date = fixIosDateFormat(date)
+		date = new Date(date)
+
+		const oldMonth = date.getMonth()
+		date.setMonth(oldMonth - 1)
+		const newMonth = date.getMonth()
+		if (oldMonth !== 0 && newMonth - oldMonth === 0) {
+			date.setMonth(newMonth - 1)
 		}
-		const dd = new Date(date)
-		switch (str) {
-			case 'day':
-				dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
-				break
-			case 'month':
-				if (dd.getDate() === 31) {
-					dd.setDate(dd.getDate() + AddDayCount)
-				} else {
-					dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
-				}
-				break
-			case 'year':
-				dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
-				break
+		return this.getDateObj(date)
+	}
+	getNextMonthObj(date) {
+		date = fixIosDateFormat(date)
+		date = new Date(date)
+
+		const oldMonth = date.getMonth()
+		date.setMonth(oldMonth + 1)
+		const newMonth = date.getMonth()
+		if (newMonth - oldMonth > 1) {
+			date.setMonth(newMonth - 1)
 		}
-		const y = dd.getFullYear()
-		const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
-		const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
+		return this.getDateObj(date)
+	}
+
+	/**
+	 * 获取指定格式Date对象
+	 */
+	getDateObj(date) {
+		date = fixIosDateFormat(date)
+		date = new Date(date)
+
 		return {
-			fullDate: y + '-' + m + '-' + d,
-			year: y,
-			month: m,
-			date: d,
-			day: dd.getDay()
+			fullDate: getDate(date),
+			year: date.getFullYear(),
+			month: addZero(date.getMonth() + 1),
+			date: addZero(date.getDate()),
+			day: date.getDay()
 		}
 	}
 
-
 	/**
-	 * 获取上月剩余天数
+	 * 获取上一个月日期集合
 	 */
-	_getLastMonthDays(firstDay, full) {
-		let dateArr = []
-		for (let i = firstDay; i > 0; i--) {
-			const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
-			dateArr.push({
-				date: beforeDate,
-				month: full.month - 1,
+	getPreMonthDays(amount, dateObj) {
+		const result = []
+		for (let i = amount - 1; i >= 0; i--) {
+			const month = dateObj.month - 1
+			result.push({
+				date: new Date(dateObj.year, month, -i).getDate(),
+				month,
 				disable: true
 			})
 		}
-		return dateArr
+		return result
 	}
 	/**
-	 * 获取本月天数
+	 * 获取本月日期集合
 	 */
-	_currentMonthDys(dateData, full) {
-		let dateArr = []
-		let fullDate = this.date.fullDate
-		for (let i = 1; i <= dateData; i++) {
-			let isinfo = false
-			let nowDate = full.year + '-' + (full.month < 10 ?
-				full.month : full.month) + '-' + (i < 10 ?
-				'0' + i : i)
-			// 是否今天
-			let isDay = fullDate === nowDate
+	getCurrentMonthDays(amount, dateObj) {
+		const result = []
+		const fullDate = this.date.fullDate
+		for (let i = 1; i <= amount; i++) {
+			const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}`
+			const isToday = fullDate === currentDate
 			// 获取打点信息
-			let info = this.selected && this.selected.find((item) => {
-				if (this.dateEqual(nowDate, item.date)) {
+			const info = this.selected && this.selected.find((item) => {
+				if (this.dateEqual(currentDate, item.date)) {
 					return item
 				}
 			})
@@ -139,62 +125,53 @@ class Calendar {
 			let disableBefore = true
 			let disableAfter = true
 			if (this.startDate) {
-				// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
-				// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
-				disableBefore = this.dateCompare(this.startDate, nowDate)
+				disableBefore = dateCompare(this.startDate, currentDate)
 			}
 
 			if (this.endDate) {
-				// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
-				// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
-				disableAfter = this.dateCompare(nowDate, this.endDate)
+				disableAfter = dateCompare(currentDate, this.endDate)
 			}
+
 			let multiples = this.multipleStatus.data
-			let checked = false
 			let multiplesStatus = -1
-			if (this.range) {
-				if (multiples) {
-					multiplesStatus = multiples.findIndex((item) => {
-						return this.dateEqual(item, nowDate)
-					})
-				}
-				if (multiplesStatus !== -1) {
-					checked = true
-				}
+			if (this.range && multiples) {
+				multiplesStatus = multiples.findIndex((item) => {
+					return this.dateEqual(item, currentDate)
+				})
 			}
-			let data = {
-				fullDate: nowDate,
-				year: full.year,
+			const checked = multiplesStatus !== -1
+
+			result.push({
+				fullDate: currentDate,
+				year: dateObj.year,
 				date: i,
 				multiple: this.range ? checked : false,
-				beforeMultiple: this.isLogicBefore(nowDate, this.multipleStatus.before, this.multipleStatus.after),
-				afterMultiple: this.isLogicAfter(nowDate, this.multipleStatus.before, this.multipleStatus.after),
-				month: full.month,
-				disable: !(disableBefore && disableAfter),
-				isDay,
-				userChecked: false
-			}
-			if (info) {
-				data.extraInfo = info
-			}
-
-			dateArr.push(data)
+				beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after),
+				afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after),
+				month: dateObj.month,
+				disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare(
+					currentDate, this.endDate)),
+				isToday,
+				userChecked: false,
+				extraInfo: info
+			})
 		}
-		return dateArr
+		return result
 	}
 	/**
-	 * 获取下月天数
+	 * 获取下一个月日期集合
 	 */
-	_getNextMonthDays(surplus, full) {
-		let dateArr = []
-		for (let i = 1; i < surplus + 1; i++) {
-			dateArr.push({
+	_getNextMonthDays(amount, dateObj) {
+		const result = []
+		const month = dateObj.month + 1
+		for (let i = 1; i <= amount; i++) {
+			result.push({
 				date: i,
-				month: Number(full.month) + 1,
+				month,
 				disable: true
 			})
 		}
-		return dateArr
+		return result
 	}
 
 	/**
@@ -205,58 +182,37 @@ class Calendar {
 		if (!date) {
 			date = new Date()
 		}
-		const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
-		return dateInfo
-	}
 
-	/**
-	 * 比较时间大小
-	 */
-	dateCompare(startDate, endDate) {
-		// 计算截止时间
-		startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
-		// 计算详细项的截止时间
-		endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
-		if (startDate <= endDate) {
-			return true
-		} else {
-			return false
-		}
+		return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate)
 	}
 
 	/**
 	 * 比较时间是否相等
 	 */
 	dateEqual(before, after) {
-		// 计算截止时间
-		before = new Date(before.replace('-', '/').replace('-', '/'))
-		// 计算详细项的截止时间
-		after = new Date(after.replace('-', '/').replace('-', '/'))
-		if (before.getTime() - after.getTime() === 0) {
-			return true
-		} else {
-			return false
-		}
+		before = new Date(fixIosDateFormat(before))
+		after = new Date(fixIosDateFormat(after))
+		return before.valueOf() === after.valueOf()
 	}
 
 	/**
 	 *  比较真实起始日期
 	 */
 
-	isLogicBefore(currentDay, before, after) {
+	isLogicBefore(currentDate, before, after) {
 		let logicBefore = before
 		if (before && after) {
-			logicBefore = this.dateCompare(before, after) ? before : after
+			logicBefore = dateCompare(before, after) ? before : after
 		}
-		return this.dateEqual(logicBefore, currentDay)
+		return this.dateEqual(logicBefore, currentDate)
 	}
 
-	isLogicAfter(currentDay, before, after) {
+	isLogicAfter(currentDate, before, after) {
 		let logicAfter = after
 		if (before && after) {
-			logicAfter = this.dateCompare(before, after) ? after : before
+			logicAfter = dateCompare(before, after) ? after : before
 		}
-		return this.dateEqual(logicAfter, currentDay)
+		return this.dateEqual(logicAfter, currentDate)
 	}
 
 	/**
@@ -276,7 +232,7 @@ class Calendar {
 		var unixDe = de.getTime() - 24 * 60 * 60 * 1000
 		for (var k = unixDb; k <= unixDe;) {
 			k = k + 24 * 60 * 60 * 1000
-			arr.push(this.getDate(new Date(parseInt(k))).fullDate)
+			arr.push(this.getDateObj(new Date(parseInt(k))).fullDate)
 		}
 		return arr
 	}
@@ -285,11 +241,12 @@ class Calendar {
 	 *  获取多选状态
 	 */
 	setMultiple(fullDate) {
+		if (!this.range) return
+
 		let {
 			before,
 			after
 		} = this.multipleStatus
-		if (!this.range) return
 		if (before && after) {
 			if (!this.lastHover) {
 				this.lastHover = true
@@ -303,10 +260,11 @@ class Calendar {
 		} else {
 			if (!before) {
 				this.multipleStatus.before = fullDate
+				this.multipleStatus.after = undefined;
 				this.lastHover = false
 			} else {
 				this.multipleStatus.after = fullDate
-				if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+				if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
 					this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
 						.after);
 				} else {
@@ -316,32 +274,33 @@ class Calendar {
 				this.lastHover = true
 			}
 		}
-		this._getWeek(fullDate)
+		this.getWeeks(fullDate)
 	}
 
 	/**
 	 *  鼠标 hover 更新多选状态
 	 */
 	setHoverMultiple(fullDate) {
-		let {
-			before,
-			after
+		//抖音小程序点击会触发hover事件,需要避免一下
+		// #ifndef MP-TOUTIAO
+		if (!this.range || this.lastHover) return
+		const {
+			before
 		} = this.multipleStatus
 
-		if (!this.range) return
-		if (this.lastHover) return
-
 		if (!before) {
 			this.multipleStatus.before = fullDate
 		} else {
 			this.multipleStatus.after = fullDate
-			if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+			if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
 				this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
 			} else {
 				this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
 			}
 		}
-		this._getWeek(fullDate)
+		this.getWeeks(fullDate)
+		// #endif
+
 	}
 
 	/**
@@ -351,12 +310,12 @@ class Calendar {
 		this.multipleStatus.before = before
 		this.multipleStatus.after = after
 		if (before && after) {
-			if (this.dateCompare(before, after)) {
+			if (dateCompare(before, after)) {
 				this.multipleStatus.data = this.geDateAll(before, after);
-				this._getWeek(after)
+				this.getWeeks(after)
 			} else {
 				this.multipleStatus.data = this.geDateAll(after, before);
-				this._getWeek(before)
+				this.getWeeks(before)
 			}
 		}
 	}
@@ -365,46 +324,98 @@ class Calendar {
 	 * 获取每周数据
 	 * @param {Object} dateData
 	 */
-	_getWeek(dateData) {
+	getWeeks(dateData) {
 		const {
-			fullDate,
 			year,
 			month,
-			date,
-			day
-		} = this.getDate(dateData)
-		let firstDay = new Date(year, month - 1, 1).getDay()
-		let currentDay = new Date(year, month, 0).getDate()
-		let dates = {
-			lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
-			currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
-			nextMonthDays: [], // 下个月开始几天
-			weeks: []
-		}
-		let canlender = []
-		const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
-		dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
-		canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
-		let weeks = {}
-		// 拼接数组  上个月开始几天 + 本月天数+ 下个月开始几天
-		for (let i = 0; i < canlender.length; i++) {
-			if (i % 7 === 0) {
-				weeks[parseInt(i / 7)] = new Array(7)
+		} = this.getDateObj(dateData)
+
+		const preMonthDayAmount = new Date(year, month - 1, 1).getDay()
+		const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData))
+
+		const currentMonthDayAmount = new Date(year, month, 0).getDate()
+		const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData))
+
+		const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount
+		const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData))
+
+		const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays]
+
+		const weeks = new Array(6)
+		for (let i = 0; i < calendarDays.length; i++) {
+			const index = Math.floor(i / 7)
+			if (!weeks[index]) {
+				weeks[index] = new Array(7)
 			}
-			weeks[parseInt(i / 7)][i % 7] = canlender[i]
+			weeks[index][i % 7] = calendarDays[i]
 		}
-		this.canlender = canlender
+
+		this.calendar = calendarDays
 		this.weeks = weeks
 	}
+}
+
+function getDateTime(date, hideSecond) {
+	return `${getDate(date)} ${getTime(date, hideSecond)}`
+}
+
+function getDate(date) {
+	date = fixIosDateFormat(date)
+	date = new Date(date)
+	const year = date.getFullYear()
+	const month = date.getMonth() + 1
+	const day = date.getDate()
+	return `${year}-${addZero(month)}-${addZero(day)}`
+}
 
-	//静态方法
-	// static init(date) {
-	// 	if (!this.instance) {
-	// 		this.instance = new Calendar(date);
-	// 	}
-	// 	return this.instance;
-	// }
+function getTime(date, hideSecond) {
+	date = fixIosDateFormat(date)
+	date = new Date(date)
+	const hour = date.getHours()
+	const minute = date.getMinutes()
+	const second = date.getSeconds()
+	return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}`
 }
 
+function addZero(num) {
+	if (num < 10) {
+		num = `0${num}`
+	}
+	return num
+}
+
+function getDefaultSecond(hideSecond) {
+	return hideSecond ? '00:00' : '00:00:00'
+}
 
-export default Calendar
+function dateCompare(startDate, endDate) {
+	startDate = new Date(fixIosDateFormat(startDate))
+	endDate = new Date(fixIosDateFormat(endDate))
+	return startDate <= endDate
+}
+
+function checkDate(date) {
+	const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g
+	return date.match(dateReg)
+}
+//ios低版本15及以下,无法匹配 没有 ’秒‘ 时的情况,所以需要在末尾 秒 加上 问号
+const dateTimeReg = /^\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])( [0-5]?[0-9]:[0-5]?[0-9](:[0-5]?[0-9])?)?$/;
+
+function fixIosDateFormat(value) {
+	if (typeof value === 'string' && dateTimeReg.test(value)) {
+		value = value.replace(/-/g, '/')
+	}
+	return value
+}
+
+export {
+	Calendar,
+	getDateTime,
+	getDate,
+	getTime,
+	addZero,
+	getDefaultSecond,
+	dateCompare,
+	checkDate,
+	fixIosDateFormat
+}

+ 1 - 1
src/uni_modules/uni-datetime-picker/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-datetime-picker",
   "displayName": "uni-datetime-picker 日期选择器",
-  "version": "2.2.11",
+  "version": "2.2.30",
   "description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择",
   "keywords": [
     "uni-datetime-picker",

+ 18 - 1
src/uni_modules/uni-easyinput/changelog.md

@@ -1,10 +1,27 @@
+## 1.1.12(2024-01-29)
+- 补充 adjust-position文档属性补充
+## 1.1.11(2024-01-29)
+- 补充 adjust-position属性传递值:(Boolean)当键盘弹起时,是否自动上推页面
+## 1.1.10(2024-01-22)
+- 去除 移除无用的log输出
+## 1.1.9(2023-04-11)
+- 修复 vue3 下 keyboardheightchange 事件报错的bug
+## 1.1.8(2023-03-29)
+- 优化 trim 属性默认值
+## 1.1.7(2023-03-29)
+- 新增 cursor-spacing 属性
+## 1.1.6(2023-01-28)
+- 新增 keyboardheightchange 事件,可监听键盘高度变化
+## 1.1.5(2022-11-29)
+- 优化 主题样式
+## 1.1.4(2022-10-27)
+- 修复 props 中背景颜色无默认值的bug
 ## 1.1.0(2022-06-30)
 
 - 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容
 - 新增 clear 事件,点击右侧叉号图标触发
 - 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发
 - 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等
--
 
 ## 1.0.5(2022-06-07)
 

+ 122 - 137
src/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue

@@ -1,24 +1,7 @@
 <template>
-	<view
-		class="uni-easyinput"
-		:class="{ 'uni-easyinput-error': msg }"
-		:style="boxStyle"
-	>
-		<view
-			class="uni-easyinput__content"
-			:class="inputContentClass"
-			:style="inputContentStyle"
-		>
-			<slot name="prefixIcon">
-				<uni-icons
-					v-if="prefixIcon"
-					class="content-clear-icon"
-					:type="prefixIcon"
-					color="#c0c4cc"
-					@click="onClickIcon('prefix')"
-					size="22"
-				></uni-icons>
-			</slot>
+	<view class="uni-easyinput" :class="{ 'uni-easyinput-error': msg }" :style="boxStyle">
+		<view class="uni-easyinput__content" :class="inputContentClass" :style="inputContentStyle">
+			<uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" @click="onClickIcon('prefix')" size="22"></uni-icons>
 			<textarea
 				v-if="type === 'textarea'"
 				class="uni-easyinput__content-textarea"
@@ -32,10 +15,13 @@
 				:maxlength="inputMaxlength"
 				:focus="focused"
 				:autoHeight="autoHeight"
+				:cursor-spacing="cursorSpacing"
+				:adjust-position="adjustPosition"
 				@input="onInput"
 				@blur="_Blur"
 				@focus="_Focus"
 				@confirm="onConfirm"
+        @keyboardheightchange="onkeyboardheightchange"
 			></textarea>
 			<input
 				v-else
@@ -52,10 +38,13 @@
 				:maxlength="inputMaxlength"
 				:focus="focused"
 				:confirmType="confirmType"
+				:cursor-spacing="cursorSpacing"
+				:adjust-position="adjustPosition"
 				@focus="_Focus"
 				@blur="_Blur"
 				@input="onInput"
 				@confirm="onConfirm"
+        @keyboardheightchange="onkeyboardheightchange"
 			/>
 			<template v-if="type === 'password' && passwordIcon">
 				<!-- 开启密码时显示小眼睛 -->
@@ -67,20 +56,10 @@
 					:size="22"
 					:color="focusShow ? primaryColor : '#c0c4cc'"
 					@click="onEyes"
-				>
-				</uni-icons>
+				></uni-icons>
 			</template>
-			<template v-else-if="suffixIcon || $slots.suffixIcon">
-				<slot name="suffixIcon">
-					<uni-icons
-						v-if="suffixIcon"
-						class="content-clear-icon"
-						:type="suffixIcon"
-						color="#c0c4cc"
-						@click="onClickIcon('suffix')"
-						size="22"
-					></uni-icons>
-				</slot>
+			<template v-else-if="suffixIcon">
+				<uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc" @click="onClickIcon('suffix')" size="22"></uni-icons>
 			</template>
 			<template v-else>
 				<uni-icons
@@ -124,6 +103,8 @@
  * @property {String}	suffixIcon	输入框尾部图标
  * @property {String}	primaryColor	设置主题色(默认#2979ff)
  * @property {Boolean}	trim	是否自动去除两端的空格
+ * @property {Boolean}	cursorSpacing	指定光标与键盘的距离,单位 px
+ * @property {Boolean}  ajust-position 当键盘弹起时,是否上推内容,默认值:true
  * @value both	去除两端空格
  * @value left	去除左侧空格
  * @value right	去除右侧空格
@@ -139,12 +120,10 @@
  * @event {Function}	blur	输入框失去焦点时触发
  * @event {Function}	confirm	点击完成按钮时触发
  * @event {Function}	iconClick	点击图标时触发
- * @slot prefixIcon 输入框头部插槽
- * @slot suffixIcon 输入框尾部插槽
  * @example <uni-easyinput v-model="mobile"></uni-easyinput>
  */
 function obj2strClass(obj) {
-	let classess = "";
+	let classess = '';
 	for (let key in obj) {
 		const val = obj[key];
 		if (val) {
@@ -155,7 +134,7 @@ function obj2strClass(obj) {
 }
 
 function obj2strStyle(obj) {
-	let style = "";
+	let style = '';
 	for (let key in obj) {
 		const val = obj[key];
 		style += `${key}:${val};`;
@@ -163,35 +142,24 @@ function obj2strStyle(obj) {
 	return style;
 }
 export default {
-	name: "uni-easyinput",
-	emits: [
-		"click",
-		"iconClick",
-		"update:modelValue",
-		"input",
-		"focus",
-		"blur",
-		"confirm",
-		"clear",
-		"eyes",
-		"change",
-	],
+	name: 'uni-easyinput',
+	emits: ['click', 'iconClick', 'update:modelValue', 'input', 'focus', 'blur', 'confirm', 'clear', 'eyes', 'change', 'keyboardheightchange'],
 	model: {
-		prop: "modelValue",
-		event: "update:modelValue",
+		prop: 'modelValue',
+		event: 'update:modelValue'
 	},
 	options: {
-		virtualHost: true,
+		virtualHost: true
 	},
 	inject: {
 		form: {
-			from: "uniForm",
-			default: null,
+			from: 'uniForm',
+			default: null
 		},
 		formItem: {
-			from: "uniFormItem",
-			default: null,
-		},
+			from: 'uniFormItem',
+			default: null
+		}
 	},
 	props: {
 		name: String,
@@ -199,91 +167,101 @@ export default {
 		modelValue: [Number, String],
 		type: {
 			type: String,
-			default: "text",
+			default: 'text'
 		},
 		clearable: {
 			type: Boolean,
-			default: true,
+			default: true
 		},
 		autoHeight: {
 			type: Boolean,
-			default: false,
+			default: false
 		},
 		placeholder: {
 			type: String,
-			default: " ",
+			default: ' '
 		},
 		placeholderStyle: String,
 		focus: {
 			type: Boolean,
-			default: false,
+			default: false
 		},
 		disabled: {
 			type: Boolean,
-			default: false,
+			default: false
 		},
 		maxlength: {
 			type: [Number, String],
-			default: 140,
+			default: 140
 		},
 		confirmType: {
 			type: String,
-			default: "done",
+			default: 'done'
 		},
 		clearSize: {
 			type: [Number, String],
-			default: 24,
+			default: 24
 		},
 		inputBorder: {
 			type: Boolean,
-			default: true,
+			default: true
 		},
 		prefixIcon: {
 			type: String,
-			default: "",
+			default: ''
 		},
 		suffixIcon: {
 			type: String,
-			default: "",
+			default: ''
 		},
 		trim: {
 			type: [Boolean, String],
-			default: true,
+			default: false
+		},
+		cursorSpacing: {
+			type: Number,
+			default: 0
 		},
 		passwordIcon: {
 			type: Boolean,
-			default: true,
+			default: true
+		},
+		adjustPosition:{
+			type: Boolean,
+			default: true
 		},
 		primaryColor: {
 			type: String,
-			default: "#2979ff",
+			default: '#2979ff'
 		},
 		styles: {
 			type: Object,
 			default() {
 				return {
-					color: "#333",
-					disableColor: "#F7F6F6",
-					borderColor: "#e5e5e5",
+					color: '#333',
+					backgroundColor: '#fff',
+					disableColor: '#F7F6F6',
+					borderColor: '#e5e5e5'
 				};
-			},
+			}
 		},
 		errorMessage: {
 			type: [String, Boolean],
-			default: "",
-		},
+			default: ''
+		}
 	},
 	data() {
 		return {
 			focused: false,
-			val: "",
-			showMsg: "",
+			val: '',
+			showMsg: '',
 			border: false,
 			isFirstBorder: false,
 			showClearIcon: false,
 			showPassword: false,
 			focusShow: false,
-			localMsg: "",
+			localMsg: '',
+			isEnter: false // 用于判断当前是否是使用回车操作
 		};
 	},
 	computed: {
@@ -312,42 +290,34 @@ export default {
 
 		// 处理外层样式的style
 		boxStyle() {
-			return `color:${
-				this.inputBorder && this.msg ? "#e43d33" : this.styles.color
-			};`;
+			return `color:${this.inputBorder && this.msg ? '#e43d33' : this.styles.color};`;
 		},
 		// input 内容的类和样式处理
 		inputContentClass() {
 			return obj2strClass({
-				"is-input-border": this.inputBorder,
-				"is-input-error-border": this.inputBorder && this.msg,
-				"is-textarea": this.type === "textarea",
-				"is-disabled": this.disabled,
+				'is-input-border': this.inputBorder,
+				'is-input-error-border': this.inputBorder && this.msg,
+				'is-textarea': this.type === 'textarea',
+				'is-disabled': this.disabled,
+				'is-focused': this.focusShow
 			});
 		},
 		inputContentStyle() {
-			const focusColor = this.focusShow
-				? this.primaryColor
-				: this.styles.borderColor;
-			const borderColor = this.inputBorder && this.msg ? "#dd524d" : focusColor;
+			const focusColor = this.focusShow ? this.primaryColor : this.styles.borderColor;
+			const borderColor = this.inputBorder && this.msg ? '#dd524d' : focusColor;
 			return obj2strStyle({
-				"border-color": borderColor || "#e5e5e5",
-				"background-color": this.disabled
-					? this.styles.disableColor
-					: this.styles.backgroundColor,
+				'border-color': borderColor || '#e5e5e5',
+				'background-color': this.disabled ? this.styles.disableColor : this.styles.backgroundColor
 			});
 		},
 		// input右侧样式
 		inputStyle() {
-			const paddingRight =
-				this.type === "password" || this.clearable || this.prefixIcon
-					? ""
-					: "10px";
+			const paddingRight = this.type === 'password' || this.clearable || this.prefixIcon ? '' : '10px';
 			return obj2strStyle({
-				"padding-right": paddingRight,
-				"padding-left": this.prefixIcon ? "" : "10px",
+				'padding-right': paddingRight,
+				'padding-left': this.prefixIcon ? '' : '10px'
 			});
-		},
+		}
 	},
 	watch: {
 		value(newVal) {
@@ -361,13 +331,13 @@ export default {
 				this.focused = this.focus;
 				this.focusShow = this.focus;
 			});
-		},
+		}
 	},
 	created() {
 		this.init();
 		// TODO 处理头条vue3 computed 不监听 inject 更改的问题(formItem.errMsg)
 		if (this.form && this.formItem) {
-			this.$watch("formItem.errMsg", (newVal) => {
+			this.$watch('formItem.errMsg', newVal => {
 				this.localMsg = newVal;
 			});
 		}
@@ -385,7 +355,7 @@ export default {
 		init() {
 			if (this.value || this.value === 0) {
 				this.val = this.value;
-			} else if (this.modelValue || this.modelValue === 0) {
+			} else if (this.modelValue || this.modelValue === 0 || this.modelValue === '') {
 				this.val = this.modelValue;
 			} else {
 				this.val = null;
@@ -397,7 +367,7 @@ export default {
 		 * @param {Object} type
 		 */
 		onClickIcon(type) {
-			this.$emit("iconClick", type);
+			this.$emit('iconClick', type);
 		},
 
 		/**
@@ -405,7 +375,7 @@ export default {
 		 */
 		onEyes() {
 			this.showPassword = !this.showPassword;
-			this.$emit("eyes", this.showPassword);
+			this.$emit('eyes', this.showPassword);
 		},
 
 		/**
@@ -416,19 +386,19 @@ export default {
 			let value = event.detail.value;
 			// 判断是否去除空格
 			if (this.trim) {
-				if (typeof this.trim === "boolean" && this.trim) {
+				if (typeof this.trim === 'boolean' && this.trim) {
 					value = this.trimStr(value);
 				}
-				if (typeof this.trim === "string") {
+				if (typeof this.trim === 'string') {
 					value = this.trimStr(value, this.trim);
 				}
 			}
-			if (this.errMsg) this.errMsg = "";
+			if (this.errMsg) this.errMsg = '';
 			this.val = value;
 			// TODO 兼容 vue2
-			this.$emit("input", value);
+			this.$emit('input', value);
 			// TODO 兼容 vue3
-			this.$emit("update:modelValue", value);
+			this.$emit('update:modelValue', value);
 		},
 
 		/**
@@ -440,12 +410,12 @@ export default {
 			this.$nextTick(() => {
 				this.focused = true;
 			});
-			this.$emit("focus", null);
+			this.$emit('focus', null);
 		},
 
 		_Focus(event) {
 			this.focusShow = true;
-			this.$emit("focus", event);
+			this.$emit('focus', event);
 		},
 
 		/**
@@ -455,18 +425,20 @@ export default {
 		 */
 		onBlur() {
 			this.focused = false;
-			this.$emit("focus", null);
+			this.$emit('focus', null);
 		},
 		_Blur(event) {
 			let value = event.detail.value;
 			this.focusShow = false;
-			this.$emit("blur", event);
+			this.$emit('blur', event);
 			// 根据类型返回值,在event中获取的值理论上讲都是string
-			this.$emit("change", this.val);
+			if (this.isEnter === false) {
+				this.$emit('change', this.val);
+			}
 			// 失去焦点时参与表单校验
 			if (this.form && this.formItem) {
 				const { validateTrigger } = this.form;
-				if (validateTrigger === "blur") {
+				if (validateTrigger === 'blur') {
 					this.formItem.onFieldChange();
 				}
 			}
@@ -477,8 +449,12 @@ export default {
 		 * @param {Object} e
 		 */
 		onConfirm(e) {
-			this.$emit("confirm", this.val);
-			this.$emit("change", this.val);
+			this.$emit('confirm', this.val);
+			this.isEnter = true;
+			this.$emit('change', this.val);
+			this.$nextTick(() => {
+				this.isEnter = false;
+			});
 		},
 
 		/**
@@ -486,38 +462,47 @@ export default {
 		 * @param {Object} event
 		 */
 		onClear(event) {
-			this.val = "";
+			this.val = '';
 			// TODO 兼容 vue2
-			this.$emit("input", "");
+			this.$emit('input', '');
 			// TODO 兼容 vue2
 			// TODO 兼容 vue3
-			this.$emit("update:modelValue", "");
+			this.$emit('update:modelValue', '');
 			// 点击叉号触发
-			this.$emit("clear");
+			this.$emit('clear');
 		},
 
+    /**
+     * 键盘高度发生变化的时候触发此事件
+     * 兼容性:微信小程序2.7.0+、App 3.1.0+
+     * @param {Object} event
+     */
+    onkeyboardheightchange(event) {
+      this.$emit("keyboardheightchange",event);
+    },
+
 		/**
 		 * 去除空格
 		 */
-		trimStr(str, pos = "both") {
-			if (pos === "both") {
+		trimStr(str, pos = 'both') {
+			if (pos === 'both') {
 				return str.trim();
-			} else if (pos === "left") {
+			} else if (pos === 'left') {
 				return str.trimLeft();
-			} else if (pos === "right") {
+			} else if (pos === 'right') {
 				return str.trimRight();
-			} else if (pos === "start") {
+			} else if (pos === 'start') {
 				return str.trimStart();
-			} else if (pos === "end") {
+			} else if (pos === 'end') {
 				return str.trimEnd();
-			} else if (pos === "all") {
-				return str.replace(/\s+/g, "");
-			} else if (pos === "none") {
+			} else if (pos === 'all') {
+				return str.replace(/\s+/g, '');
+			} else if (pos === 'none') {
 				return str;
 			}
 			return str;
-		},
-	},
+		}
+	}
 };
 </script>
 

+ 1 - 1
src/uni_modules/uni-easyinput/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-easyinput",
   "displayName": "uni-easyinput 增强输入框",
-  "version": "1.1.3",
+  "version": "1.1.12",
   "description": "Easyinput 组件是对原生input组件的增强",
   "keywords": [
     "uni-ui",

+ 2 - 0
src/uni_modules/uni-fab/changelog.md

@@ -1,3 +1,5 @@
+## 1.2.5(2023-03-29)
+- 新增 pattern.icon 属性,可自定义图标
 ## 1.2.4(2022-09-07)
 小程序端由于 style 使用了对象导致报错,[详情](https://ask.dcloud.net.cn/question/152790?item_id=211778&rf=false)
 ## 1.2.3(2022-09-05)

+ 3 - 2
src/uni_modules/uni-fab/components/uni-fab/uni-fab.vue

@@ -35,7 +35,7 @@
 		  'uni-fab__circle--rightTop': rightTop,
 		  'uni-fab__content--other-platform': !isAndroidNvue
 		}" class="uni-fab__circle uni-fab__plus" :style="{ 'background-color': styles.buttonColor, 'bottom': nvueBottom }" @click="_onClick">
-			<uni-icons class="fab-circle-icon" type="plusempty" :color="styles.iconColor" size="32"
+			<uni-icons class="fab-circle-icon" :type="styles.icon" :color="styles.iconColor" size="32"
 				:class="{'uni-fab__plus--active': isShow && content.length > 0}"></uni-icons>
 			<!-- <view class="fab-circle-v"  :class="{'uni-fab__plus--active': isShow && content.length > 0}"></view>
 			<view class="fab-circle-h" :class="{'uni-fab__plus--active': isShow  && content.length > 0}"></view> -->
@@ -115,7 +115,8 @@
 					selectedColor: '#007AFF',
 					backgroundColor: '#fff',
 					buttonColor: '#007AFF',
-					iconColor: '#fff'
+					iconColor: '#fff',
+					icon: 'plusempty'
 				}
 			}
 		},

+ 1 - 1
src/uni_modules/uni-fab/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-fab",
   "displayName": "uni-fab 悬浮按钮",
-  "version": "1.2.4",
+  "version": "1.2.5",
   "description": "悬浮按钮 fab button ,点击可展开一个图标按钮菜单。",
   "keywords": [
     "uni-ui",

+ 8 - 0
src/uni_modules/uni-file-picker/changelog.md

@@ -1,3 +1,11 @@
+## 1.0.6(2024-01-06)
+- 新增 微信小程序不再调用chooseImage,而是调用chooseMedia
+## 1.0.5(2024-01-03)
+- 新增 上传文件至云存储携带本地文件名称
+## 1.0.4(2023-03-29)
+- 修复 手动上传删除一个文件后不能再上传的bug
+## 1.0.3(2022-12-19)
+- 新增 sourceType 属性, 可以自定义图片和视频选择的来源
 ## 1.0.2(2022-07-04)
 - 修复 在uni-forms下样式不生效的bug
 ## 1.0.1(2021-11-23)

+ 25 - 2
src/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js

@@ -7,10 +7,31 @@ function chooseImage(opts) {
 	const {
 		count,
 		sizeType = ['original', 'compressed'],
-		sourceType = ['album', 'camera'],
+		sourceType,
 		extension
 	} = opts
 	return new Promise((resolve, reject) => {
+		// #ifdef MP-WEIXIN
+		uni.chooseMedia({
+			count,
+			sizeType,
+			sourceType,
+			mediaType: ['image'],
+			extension,
+			success(res) {
+				res.tempFiles.forEach(item => {
+					item.path = item.tempFilePath;
+				})
+				resolve(normalizeChooseAndUploadFileRes(res, 'image'));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
+				});
+			},
+		})
+		// #endif
+		// #ifndef MP-WEIXIN
 		uni.chooseImage({
 			count,
 			sizeType,
@@ -25,6 +46,8 @@ function chooseImage(opts) {
 				});
 			},
 		});
+		// #endif
+
 	});
 }
 
@@ -33,7 +56,7 @@ function chooseVideo(opts) {
 		camera,
 		compressed,
 		maxDuration,
-		sourceType = ['album', 'camera'],
+		sourceType,
 		extension
 	} = opts;
 	return new Promise((resolve, reject) => {

+ 23 - 2
src/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue

@@ -185,6 +185,16 @@
 				default () {
 					return ['original', 'compressed']
 				}
+			},
+			sourceType: {
+				type: Array,
+				default () {
+					return  ['album', 'camera']
+				}
+			},
+			provider: {
+				type: String,
+				default: '' // 默认上传到 unicloud 内置存储 extStorage 扩展存储
 			}
 		},
 		data() {
@@ -325,7 +335,6 @@
 			 * 选择文件
 			 */
 			choose() {
-
 				if (this.disabled) return
 				if (this.files.length >= Number(this.limitLength) && this.showType !== 'grid' && this.returnType ===
 					'array') {
@@ -349,6 +358,7 @@
 						type: this.fileMediatype,
 						compressed: false,
 						sizeType: this.sizeType,
+						sourceType: this.sourceType,
 						// TODO 如果为空,video 有问题
 						extension: _extname.length > 0 ? _extname : undefined,
 						count: this.limitLength - this.files.length, //默认9
@@ -411,6 +421,13 @@
 				if (!this.autoUpload || this.noSpace) {
 					res.tempFiles = []
 				}
+				res.tempFiles.forEach((fileItem, index) => {
+					this.provider && (fileItem.provider = this.provider);
+					const fileNameSplit = fileItem.name.split('.')
+					const ext = fileNameSplit.pop()
+					const fileName = fileNameSplit.join('.').replace(/[\s\/\?<>\\:\*\|":]/g, '_')
+					fileItem.cloudPath = fileName + '_' + Date.now() + '_' + index + '.' + ext
+				})
 			},
 
 			/**
@@ -576,7 +593,11 @@
 						path: v.path,
 						size: v.size,
 						fileID:v.fileID,
-						url: v.url
+						url: v.url,
+						// 修改删除一个文件后不能再上传的bug, #694
+            uuid: v.uuid,
+            status: v.status,
+            cloudPath: v.cloudPath
 					})
 				})
 				return newFilesData

+ 4 - 7
src/uni_modules/uni-file-picker/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-file-picker",
   "displayName": "uni-file-picker 文件选择上传",
-  "version": "1.0.2",
+  "version": "1.0.6",
   "description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间",
   "keywords": [
     "uni-ui",
@@ -16,11 +16,7 @@
   "directories": {
     "example": "../../temps/example_temps"
   },
-  "dcloudext": {
-    "category": [
-      "前端组件",
-      "通用组件"
-    ],
+"dcloudext": {
     "sale": {
       "regular": {
         "price": "0.00"
@@ -37,7 +33,8 @@
       "data": "无",
       "permissions": "无"
     },
-    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
   },
   "uni_modules": {
     "dependencies": ["uni-scss"],

+ 4 - 0
src/uni_modules/uni-forms/changelog.md

@@ -1,3 +1,7 @@
+## 1.4.10(2023-11-03)
+- 优化 labelWidth 描述错误
+## 1.4.9(2023-02-10)
+- 修复 required 参数无法动态绑定
 ## 1.4.8(2022-08-23)
 - 优化 根据 rules 自动添加 required 的问题
 ## 1.4.7(2022-08-22)

+ 7 - 11
src/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue

@@ -2,9 +2,9 @@
 	<view class="uni-forms-item"
 		:class="['is-direction-' + localLabelPos ,border?'uni-forms-item--border':'' ,border && isFirstBorder?'is-first-border':'']">
 		<slot name="label">
-			<view class="uni-forms-item__label" :class="{'no-label':!label && !isRequired}"
+			<view class="uni-forms-item__label" :class="{'no-label':!label && !required}"
 				:style="{width:localLabelWidth,justifyContent: localLabelAlign}">
-				<text v-if="isRequired" class="is-required">*</text>
+				<text v-if="required" class="is-required">*</text>
 				<text>{{label}}</text>
 			</view>
 		</slot>
@@ -36,7 +36,7 @@
 	 * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
 	 * @property {Boolean} required 是否必填,左边显示红色"*"号
 	 * @property {String } 	label 				输入框左边的文字提示
-	 * @property {Number } 	labelWidth 			label的宽度,单位px(默认65
+	 * @property {Number } 	labelWidth 			label的宽度,单位px(默认70
 	 * @property {String } 	labelAlign = [left|center|right] label的文字对齐方式(默认left)
 	 * 	@value left		label 左侧显示
 	 * 	@value center	label 居中
@@ -91,7 +91,7 @@
 				type: String,
 				default: ''
 			},
-			// label的宽度 ,默认 80
+			// label的宽度
 			labelWidth: {
 				type: [String, Number],
 				default: ''
@@ -126,10 +126,9 @@
 		data() {
 			return {
 				errMsg: '',
-				isRequired: false,
 				userRules: null,
 				localLabelAlign: 'left',
-				localLabelWidth: '65px',
+				localLabelWidth: '70px',
 				localLabelPos: 'left',
 				border: false,
 				isFirstBorder: false,
@@ -315,7 +314,6 @@
 				this.localLabelWidth = this._labelWidthUnit(labelWidth)
 				// 标签位置
 				this.localLabelPos = this._labelPosition()
-				this.isRequired = this.required
 				// 将需要校验的子组件加入form 队列
 				this.form && type && childrens.push(this)
 
@@ -351,8 +349,6 @@
 				this.validator = validator
 				// 默认值赋予
 				this.itemSetValue(_getDataValue(this.name, localData))
-				this.isRequired = this._isRequired()
-
 			},
 			unInit() {
 				if (this.form) {
@@ -417,9 +413,9 @@
 				// 	const {
 				// 		labelWidth
 				// 	} = this.form
-				return this.num2px(this.labelWidth ? this.labelWidth : (labelWidth || (this.label ? 65 : 'auto')))
+				return this.num2px(this.labelWidth ? this.labelWidth : (labelWidth || (this.label ? 70 : 'auto')))
 				// }
-				// return '65px'
+				// return '70px'
 			},
 			// 处理 label 位置
 			_labelPosition() {

+ 1 - 1
src/uni_modules/uni-forms/components/uni-forms/uni-forms.vue

@@ -52,7 +52,7 @@
 	 * @property {String} labelPosition = [top|left]	label 位置 默认 left
 	 * @value top		顶部显示 label
 	 * @value left	左侧显示 label
-	 * @property {String} labelWidth	label 宽度,默认 65px
+	 * @property {String} labelWidth	label 宽度,默认 70px
 	 * @property {String} labelAlign = [left|center|right]	label 居中方式  默认 left
 	 * @value left		label 左侧显示
 	 * @value center	label 居中

+ 1 - 1
src/uni_modules/uni-forms/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-forms",
   "displayName": "uni-forms 表单",
-  "version": "1.4.8",
+  "version": "1.4.10",
   "description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据",
   "keywords": [
     "uni-ui",

+ 18 - 0
src/uni_modules/uni-icons/changelog.md

@@ -1,3 +1,21 @@
+## 2.0.9(2024-01-12)
+fix: 修复图标大小默认值错误的问题
+## 2.0.8(2023-12-14)
+- 修复 项目未使用 ts 情况下,打包报错的bug
+## 2.0.7(2023-12-14)
+- 修复 size 属性为 string 时,不加单位导致尺寸异常的bug
+## 2.0.6(2023-12-11)
+- 优化 兼容老版本icon类型,如 top ,bottom 等
+## 2.0.5(2023-12-11)
+- 优化 兼容老版本icon类型,如 top ,bottom 等
+## 2.0.4(2023-12-06)
+- 优化 uni-app x 下示例项目图标排序
+## 2.0.3(2023-12-06)
+- 修复 nvue下引入组件报错的bug
+## 2.0.2(2023-12-05)
+-优化 size 属性支持单位
+## 2.0.1(2023-12-05)
+- 新增 uni-app x 支持定义图标
 ## 1.3.5(2022-01-24)
 - 优化 size 属性可以传入不带单位的字符串数值
 ## 1.3.4(2022-01-24)

+ 91 - 0
src/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue

@@ -0,0 +1,91 @@
+<template>
+	<text class="uni-icons" :style="styleObj">
+		<slot>{{unicode}}</slot>
+	</text>
+</template>
+
+<script>
+	import { fontData, IconsDataItem } from './uniicons_file'
+
+	/**
+	 * Icons 图标
+	 * @description 用于展示 icon 图标
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=28
+	 * @property {Number} size 图标大小
+	 * @property {String} type 图标图案,参考示例
+	 * @property {String} color 图标颜色
+	 * @property {String} customPrefix 自定义图标
+	 * @event {Function} click 点击 Icon 触发事件
+	 */
+	export default {
+		name: "uni-icons",
+		props: {
+			type: {
+				type: String,
+				default: ''
+			},
+			color: {
+				type: String,
+				default: '#333333'
+			},
+			size: {
+				type: Object,
+				default: 16
+			},
+			fontFamily: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {};
+		},
+		computed: {
+			unicode() : string {
+				let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
+				if (codes !== null) {
+					return codes.unicode
+				}
+				return ''
+			},
+			iconSize() : string {
+				const size = this.size
+				if (typeof size == 'string') {
+					const reg = /^[0-9]*$/g
+					return reg.test(size as string) ? '' + size + 'px' : '' + size;
+					// return '' + this.size
+				}
+				return this.getFontSize(size as number)
+			},
+			styleObj() : UTSJSONObject {
+				if (this.fontFamily !== '') {
+					return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
+				}
+				return { color: this.color, fontSize: this.iconSize }
+			}
+		},
+		created() { },
+		methods: {
+			/**
+			 * 字体大小
+			 */
+			getFontSize(size : number) : string {
+				return size + 'px';
+			},
+		},
+	}
+</script>
+
+<style scoped>
+	@font-face {
+		font-family: UniIconsFontFamily;
+		src: url('./uniicons.ttf');
+	}
+
+	.uni-icons {
+		font-family: UniIconsFontFamily;
+		font-size: 18px;
+		font-style: normal;
+		color: #333;
+	}
+</style>

+ 31 - 17
src/uni_modules/uni-icons/components/uni-icons/uni-icons.vue

@@ -1,24 +1,28 @@
 <template>
 	<!-- #ifdef APP-NVUE -->
-	<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" @click="_onClick">{{unicode}}</text>
+	<text :style="styleObj" class="uni-icons" @click="_onClick">{{unicode}}</text>
 	<!-- #endif -->
 	<!-- #ifndef APP-NVUE -->
-	<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick"></text>
+	<text :style="styleObj" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick">
+		<slot></slot>
+	</text>
 	<!-- #endif -->
 </template>
 
 <script>
-	import icons from './icons.js';
+	import { fontData } from './uniicons_file_vue.js';
+
 	const getVal = (val) => {
 		const reg = /^[0-9]*$/g
-		return (typeof val === 'number' || reg.test(val) )? val + 'px' : val;
-	} 
+		return (typeof val === 'number' || reg.test(val)) ? val + 'px' : val;
+	}
+
 	// #ifdef APP-NVUE
 	var domModule = weex.requireModule('dom');
 	import iconUrl from './uniicons.ttf'
 	domModule.addRule('fontFace', {
 		'fontFamily': "uniicons",
-		'src': "url('"+iconUrl+"')"
+		'src': "url('" + iconUrl + "')"
 	});
 	// #endif
 
@@ -34,7 +38,7 @@
 	 */
 	export default {
 		name: 'UniIcons',
-		emits:['click'],
+		emits: ['click'],
 		props: {
 			type: {
 				type: String,
@@ -48,26 +52,36 @@
 				type: [Number, String],
 				default: 16
 			},
-			customPrefix:{
+			customPrefix: {
+				type: String,
+				default: ''
+			},
+			fontFamily: {
 				type: String,
 				default: ''
 			}
 		},
 		data() {
 			return {
-				icons: icons.glyphs
+				icons: fontData
 			}
 		},
-		computed:{
-			unicode(){
-				let code = this.icons.find(v=>v.font_class === this.type)
-				if(code){
-					return unescape(`%u${code.unicode}`)
+		computed: {
+			unicode() {
+				let code = this.icons.find(v => v.font_class === this.type)
+				if (code) {
+					return code.unicode
 				}
 				return ''
 			},
-			iconSize(){
+			iconSize() {
 				return getVal(this.size)
+			},
+			styleObj() {
+				if (this.fontFamily !== '') {
+					return `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`
+				}
+				return `color: ${this.color}; font-size: ${this.iconSize};`
 			}
 		},
 		methods: {
@@ -81,9 +95,10 @@
 <style lang="scss">
 	/* #ifndef APP-NVUE */
 	@import './uniicons.css';
+
 	@font-face {
 		font-family: uniicons;
-		src: url('./uniicons.ttf') format('truetype');
+		src: url('./uniicons.ttf');
 	}
 
 	/* #endif */
@@ -92,5 +107,4 @@
 		text-decoration: none;
 		text-align: center;
 	}
-
 </style>

+ 32 - 31
src/uni_modules/uni-icons/components/uni-icons/uniicons.css

@@ -1,3 +1,12 @@
+
+.uniui-cart-filled:before {
+  content: "\e6d0";
+}
+
+.uniui-gift-filled:before {
+  content: "\e6c4";
+}
+
 .uniui-color:before {
   content: "\e6cf";
 }
@@ -58,10 +67,6 @@
   content: "\e6c3";
 }
 
-.uniui-gift-filled:before {
-  content: "\e6c4";
-}
-
 .uniui-fire-filled:before {
   content: "\e6c5";
 }
@@ -82,6 +87,18 @@
   content: "\e698";
 }
 
+.uniui-arrowthinleft:before {
+  content: "\e6d2";
+}
+
+.uniui-arrowthinup:before {
+  content: "\e6d3";
+}
+
+.uniui-arrowthindown:before {
+  content: "\e6d4";
+}
+
 .uniui-back:before {
   content: "\e6b9";
 }
@@ -94,55 +111,43 @@
   content: "\e6bb";
 }
 
-.uniui-arrowthinright:before {
-  content: "\e6bb";
-}
-
 .uniui-arrow-left:before {
   content: "\e6bc";
 }
 
-.uniui-arrowthinleft:before {
-  content: "\e6bc";
-}
-
 .uniui-arrow-up:before {
   content: "\e6bd";
 }
 
-.uniui-arrowthinup:before {
-  content: "\e6bd";
-}
-
 .uniui-arrow-down:before {
   content: "\e6be";
 }
 
-.uniui-arrowthindown:before {
-  content: "\e6be";
+.uniui-arrowthinright:before {
+  content: "\e6d1";
 }
 
-.uniui-bottom:before {
+.uniui-down:before {
   content: "\e6b8";
 }
 
-.uniui-arrowdown:before {
+.uniui-bottom:before {
   content: "\e6b8";
 }
 
-.uniui-right:before {
-  content: "\e6b5";
+.uniui-arrowright:before {
+  content: "\e6d5";
 }
 
-.uniui-arrowright:before {
+.uniui-right:before {
   content: "\e6b5";
 }
 
-.uniui-top:before {
+.uniui-up:before {
   content: "\e6b6";
 }
 
-.uniui-arrowup:before {
+.uniui-top:before {
   content: "\e6b6";
 }
 
@@ -150,8 +155,8 @@
   content: "\e6b7";
 }
 
-.uniui-arrowleft:before {
-  content: "\e6b7";
+.uniui-arrowup:before {
+  content: "\e6d6";
 }
 
 .uniui-eye:before {
@@ -638,10 +643,6 @@
   content: "\e627";
 }
 
-.uniui-cart-filled:before {
-  content: "\e629";
-}
-
 .uniui-checkbox:before {
   content: "\e62b";
 }

BIN
src/uni_modules/uni-icons/components/uni-icons/uniicons.ttf


+ 664 - 0
src/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts

@@ -0,0 +1,664 @@
+
+export type IconsData = {
+	id : string
+	name : string
+	font_family : string
+	css_prefix_text : string
+	description : string
+	glyphs : Array<IconsDataItem>
+}
+
+export type IconsDataItem = {
+	font_class : string
+	unicode : string
+}
+
+
+export const fontData = [
+  {
+    "font_class": "arrow-down",
+    "unicode": "\ue6be"
+  },
+  {
+    "font_class": "arrow-left",
+    "unicode": "\ue6bc"
+  },
+  {
+    "font_class": "arrow-right",
+    "unicode": "\ue6bb"
+  },
+  {
+    "font_class": "arrow-up",
+    "unicode": "\ue6bd"
+  },
+  {
+    "font_class": "auth",
+    "unicode": "\ue6ab"
+  },
+  {
+    "font_class": "auth-filled",
+    "unicode": "\ue6cc"
+  },
+  {
+    "font_class": "back",
+    "unicode": "\ue6b9"
+  },
+  {
+    "font_class": "bars",
+    "unicode": "\ue627"
+  },
+  {
+    "font_class": "calendar",
+    "unicode": "\ue6a0"
+  },
+  {
+    "font_class": "calendar-filled",
+    "unicode": "\ue6c0"
+  },
+  {
+    "font_class": "camera",
+    "unicode": "\ue65a"
+  },
+  {
+    "font_class": "camera-filled",
+    "unicode": "\ue658"
+  },
+  {
+    "font_class": "cart",
+    "unicode": "\ue631"
+  },
+  {
+    "font_class": "cart-filled",
+    "unicode": "\ue6d0"
+  },
+  {
+    "font_class": "chat",
+    "unicode": "\ue65d"
+  },
+  {
+    "font_class": "chat-filled",
+    "unicode": "\ue659"
+  },
+  {
+    "font_class": "chatboxes",
+    "unicode": "\ue696"
+  },
+  {
+    "font_class": "chatboxes-filled",
+    "unicode": "\ue692"
+  },
+  {
+    "font_class": "chatbubble",
+    "unicode": "\ue697"
+  },
+  {
+    "font_class": "chatbubble-filled",
+    "unicode": "\ue694"
+  },
+  {
+    "font_class": "checkbox",
+    "unicode": "\ue62b"
+  },
+  {
+    "font_class": "checkbox-filled",
+    "unicode": "\ue62c"
+  },
+  {
+    "font_class": "checkmarkempty",
+    "unicode": "\ue65c"
+  },
+  {
+    "font_class": "circle",
+    "unicode": "\ue65b"
+  },
+  {
+    "font_class": "circle-filled",
+    "unicode": "\ue65e"
+  },
+  {
+    "font_class": "clear",
+    "unicode": "\ue66d"
+  },
+  {
+    "font_class": "close",
+    "unicode": "\ue673"
+  },
+  {
+    "font_class": "closeempty",
+    "unicode": "\ue66c"
+  },
+  {
+    "font_class": "cloud-download",
+    "unicode": "\ue647"
+  },
+  {
+    "font_class": "cloud-download-filled",
+    "unicode": "\ue646"
+  },
+  {
+    "font_class": "cloud-upload",
+    "unicode": "\ue645"
+  },
+  {
+    "font_class": "cloud-upload-filled",
+    "unicode": "\ue648"
+  },
+  {
+    "font_class": "color",
+    "unicode": "\ue6cf"
+  },
+  {
+    "font_class": "color-filled",
+    "unicode": "\ue6c9"
+  },
+  {
+    "font_class": "compose",
+    "unicode": "\ue67f"
+  },
+  {
+    "font_class": "contact",
+    "unicode": "\ue693"
+  },
+  {
+    "font_class": "contact-filled",
+    "unicode": "\ue695"
+  },
+  {
+    "font_class": "down",
+    "unicode": "\ue6b8"
+  },
+	{
+	  "font_class": "bottom",
+	  "unicode": "\ue6b8"
+	},
+  {
+    "font_class": "download",
+    "unicode": "\ue68d"
+  },
+  {
+    "font_class": "download-filled",
+    "unicode": "\ue681"
+  },
+  {
+    "font_class": "email",
+    "unicode": "\ue69e"
+  },
+  {
+    "font_class": "email-filled",
+    "unicode": "\ue69a"
+  },
+  {
+    "font_class": "eye",
+    "unicode": "\ue651"
+  },
+  {
+    "font_class": "eye-filled",
+    "unicode": "\ue66a"
+  },
+  {
+    "font_class": "eye-slash",
+    "unicode": "\ue6b3"
+  },
+  {
+    "font_class": "eye-slash-filled",
+    "unicode": "\ue6b4"
+  },
+  {
+    "font_class": "fire",
+    "unicode": "\ue6a1"
+  },
+  {
+    "font_class": "fire-filled",
+    "unicode": "\ue6c5"
+  },
+  {
+    "font_class": "flag",
+    "unicode": "\ue65f"
+  },
+  {
+    "font_class": "flag-filled",
+    "unicode": "\ue660"
+  },
+  {
+    "font_class": "folder-add",
+    "unicode": "\ue6a9"
+  },
+  {
+    "font_class": "folder-add-filled",
+    "unicode": "\ue6c8"
+  },
+  {
+    "font_class": "font",
+    "unicode": "\ue6a3"
+  },
+  {
+    "font_class": "forward",
+    "unicode": "\ue6ba"
+  },
+  {
+    "font_class": "gear",
+    "unicode": "\ue664"
+  },
+  {
+    "font_class": "gear-filled",
+    "unicode": "\ue661"
+  },
+  {
+    "font_class": "gift",
+    "unicode": "\ue6a4"
+  },
+  {
+    "font_class": "gift-filled",
+    "unicode": "\ue6c4"
+  },
+  {
+    "font_class": "hand-down",
+    "unicode": "\ue63d"
+  },
+  {
+    "font_class": "hand-down-filled",
+    "unicode": "\ue63c"
+  },
+  {
+    "font_class": "hand-up",
+    "unicode": "\ue63f"
+  },
+  {
+    "font_class": "hand-up-filled",
+    "unicode": "\ue63e"
+  },
+  {
+    "font_class": "headphones",
+    "unicode": "\ue630"
+  },
+  {
+    "font_class": "heart",
+    "unicode": "\ue639"
+  },
+  {
+    "font_class": "heart-filled",
+    "unicode": "\ue641"
+  },
+  {
+    "font_class": "help",
+    "unicode": "\ue679"
+  },
+  {
+    "font_class": "help-filled",
+    "unicode": "\ue674"
+  },
+  {
+    "font_class": "home",
+    "unicode": "\ue662"
+  },
+  {
+    "font_class": "home-filled",
+    "unicode": "\ue663"
+  },
+  {
+    "font_class": "image",
+    "unicode": "\ue670"
+  },
+  {
+    "font_class": "image-filled",
+    "unicode": "\ue678"
+  },
+  {
+    "font_class": "images",
+    "unicode": "\ue650"
+  },
+  {
+    "font_class": "images-filled",
+    "unicode": "\ue64b"
+  },
+  {
+    "font_class": "info",
+    "unicode": "\ue669"
+  },
+  {
+    "font_class": "info-filled",
+    "unicode": "\ue649"
+  },
+  {
+    "font_class": "left",
+    "unicode": "\ue6b7"
+  },
+  {
+    "font_class": "link",
+    "unicode": "\ue6a5"
+  },
+  {
+    "font_class": "list",
+    "unicode": "\ue644"
+  },
+  {
+    "font_class": "location",
+    "unicode": "\ue6ae"
+  },
+  {
+    "font_class": "location-filled",
+    "unicode": "\ue6af"
+  },
+  {
+    "font_class": "locked",
+    "unicode": "\ue66b"
+  },
+  {
+    "font_class": "locked-filled",
+    "unicode": "\ue668"
+  },
+  {
+    "font_class": "loop",
+    "unicode": "\ue633"
+  },
+  {
+    "font_class": "mail-open",
+    "unicode": "\ue643"
+  },
+  {
+    "font_class": "mail-open-filled",
+    "unicode": "\ue63a"
+  },
+  {
+    "font_class": "map",
+    "unicode": "\ue667"
+  },
+  {
+    "font_class": "map-filled",
+    "unicode": "\ue666"
+  },
+  {
+    "font_class": "map-pin",
+    "unicode": "\ue6ad"
+  },
+  {
+    "font_class": "map-pin-ellipse",
+    "unicode": "\ue6ac"
+  },
+  {
+    "font_class": "medal",
+    "unicode": "\ue6a2"
+  },
+  {
+    "font_class": "medal-filled",
+    "unicode": "\ue6c3"
+  },
+  {
+    "font_class": "mic",
+    "unicode": "\ue671"
+  },
+  {
+    "font_class": "mic-filled",
+    "unicode": "\ue677"
+  },
+  {
+    "font_class": "micoff",
+    "unicode": "\ue67e"
+  },
+  {
+    "font_class": "micoff-filled",
+    "unicode": "\ue6b0"
+  },
+  {
+    "font_class": "minus",
+    "unicode": "\ue66f"
+  },
+  {
+    "font_class": "minus-filled",
+    "unicode": "\ue67d"
+  },
+  {
+    "font_class": "more",
+    "unicode": "\ue64d"
+  },
+  {
+    "font_class": "more-filled",
+    "unicode": "\ue64e"
+  },
+  {
+    "font_class": "navigate",
+    "unicode": "\ue66e"
+  },
+  {
+    "font_class": "navigate-filled",
+    "unicode": "\ue67a"
+  },
+  {
+    "font_class": "notification",
+    "unicode": "\ue6a6"
+  },
+  {
+    "font_class": "notification-filled",
+    "unicode": "\ue6c1"
+  },
+  {
+    "font_class": "paperclip",
+    "unicode": "\ue652"
+  },
+  {
+    "font_class": "paperplane",
+    "unicode": "\ue672"
+  },
+  {
+    "font_class": "paperplane-filled",
+    "unicode": "\ue675"
+  },
+  {
+    "font_class": "person",
+    "unicode": "\ue699"
+  },
+  {
+    "font_class": "person-filled",
+    "unicode": "\ue69d"
+  },
+  {
+    "font_class": "personadd",
+    "unicode": "\ue69f"
+  },
+  {
+    "font_class": "personadd-filled",
+    "unicode": "\ue698"
+  },
+  {
+    "font_class": "personadd-filled-copy",
+    "unicode": "\ue6d1"
+  },
+  {
+    "font_class": "phone",
+    "unicode": "\ue69c"
+  },
+  {
+    "font_class": "phone-filled",
+    "unicode": "\ue69b"
+  },
+  {
+    "font_class": "plus",
+    "unicode": "\ue676"
+  },
+  {
+    "font_class": "plus-filled",
+    "unicode": "\ue6c7"
+  },
+  {
+    "font_class": "plusempty",
+    "unicode": "\ue67b"
+  },
+  {
+    "font_class": "pulldown",
+    "unicode": "\ue632"
+  },
+  {
+    "font_class": "pyq",
+    "unicode": "\ue682"
+  },
+  {
+    "font_class": "qq",
+    "unicode": "\ue680"
+  },
+  {
+    "font_class": "redo",
+    "unicode": "\ue64a"
+  },
+  {
+    "font_class": "redo-filled",
+    "unicode": "\ue655"
+  },
+  {
+    "font_class": "refresh",
+    "unicode": "\ue657"
+  },
+  {
+    "font_class": "refresh-filled",
+    "unicode": "\ue656"
+  },
+  {
+    "font_class": "refreshempty",
+    "unicode": "\ue6bf"
+  },
+  {
+    "font_class": "reload",
+    "unicode": "\ue6b2"
+  },
+  {
+    "font_class": "right",
+    "unicode": "\ue6b5"
+  },
+  {
+    "font_class": "scan",
+    "unicode": "\ue62a"
+  },
+  {
+    "font_class": "search",
+    "unicode": "\ue654"
+  },
+  {
+    "font_class": "settings",
+    "unicode": "\ue653"
+  },
+  {
+    "font_class": "settings-filled",
+    "unicode": "\ue6ce"
+  },
+  {
+    "font_class": "shop",
+    "unicode": "\ue62f"
+  },
+  {
+    "font_class": "shop-filled",
+    "unicode": "\ue6cd"
+  },
+  {
+    "font_class": "smallcircle",
+    "unicode": "\ue67c"
+  },
+  {
+    "font_class": "smallcircle-filled",
+    "unicode": "\ue665"
+  },
+  {
+    "font_class": "sound",
+    "unicode": "\ue684"
+  },
+  {
+    "font_class": "sound-filled",
+    "unicode": "\ue686"
+  },
+  {
+    "font_class": "spinner-cycle",
+    "unicode": "\ue68a"
+  },
+  {
+    "font_class": "staff",
+    "unicode": "\ue6a7"
+  },
+  {
+    "font_class": "staff-filled",
+    "unicode": "\ue6cb"
+  },
+  {
+    "font_class": "star",
+    "unicode": "\ue688"
+  },
+  {
+    "font_class": "star-filled",
+    "unicode": "\ue68f"
+  },
+  {
+    "font_class": "starhalf",
+    "unicode": "\ue683"
+  },
+  {
+    "font_class": "trash",
+    "unicode": "\ue687"
+  },
+  {
+    "font_class": "trash-filled",
+    "unicode": "\ue685"
+  },
+  {
+    "font_class": "tune",
+    "unicode": "\ue6aa"
+  },
+  {
+    "font_class": "tune-filled",
+    "unicode": "\ue6ca"
+  },
+  {
+    "font_class": "undo",
+    "unicode": "\ue64f"
+  },
+  {
+    "font_class": "undo-filled",
+    "unicode": "\ue64c"
+  },
+  {
+    "font_class": "up",
+    "unicode": "\ue6b6"
+  },
+	{
+	  "font_class": "top",
+	  "unicode": "\ue6b6"
+	},
+  {
+    "font_class": "upload",
+    "unicode": "\ue690"
+  },
+  {
+    "font_class": "upload-filled",
+    "unicode": "\ue68e"
+  },
+  {
+    "font_class": "videocam",
+    "unicode": "\ue68c"
+  },
+  {
+    "font_class": "videocam-filled",
+    "unicode": "\ue689"
+  },
+  {
+    "font_class": "vip",
+    "unicode": "\ue6a8"
+  },
+  {
+    "font_class": "vip-filled",
+    "unicode": "\ue6c6"
+  },
+  {
+    "font_class": "wallet",
+    "unicode": "\ue6b1"
+  },
+  {
+    "font_class": "wallet-filled",
+    "unicode": "\ue6c2"
+  },
+  {
+    "font_class": "weibo",
+    "unicode": "\ue68b"
+  },
+  {
+    "font_class": "weixin",
+    "unicode": "\ue691"
+  }
+] as IconsDataItem[]
+
+// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)

+ 649 - 0
src/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js

@@ -0,0 +1,649 @@
+
+export const fontData = [
+  {
+    "font_class": "arrow-down",
+    "unicode": "\ue6be"
+  },
+  {
+    "font_class": "arrow-left",
+    "unicode": "\ue6bc"
+  },
+  {
+    "font_class": "arrow-right",
+    "unicode": "\ue6bb"
+  },
+  {
+    "font_class": "arrow-up",
+    "unicode": "\ue6bd"
+  },
+  {
+    "font_class": "auth",
+    "unicode": "\ue6ab"
+  },
+  {
+    "font_class": "auth-filled",
+    "unicode": "\ue6cc"
+  },
+  {
+    "font_class": "back",
+    "unicode": "\ue6b9"
+  },
+  {
+    "font_class": "bars",
+    "unicode": "\ue627"
+  },
+  {
+    "font_class": "calendar",
+    "unicode": "\ue6a0"
+  },
+  {
+    "font_class": "calendar-filled",
+    "unicode": "\ue6c0"
+  },
+  {
+    "font_class": "camera",
+    "unicode": "\ue65a"
+  },
+  {
+    "font_class": "camera-filled",
+    "unicode": "\ue658"
+  },
+  {
+    "font_class": "cart",
+    "unicode": "\ue631"
+  },
+  {
+    "font_class": "cart-filled",
+    "unicode": "\ue6d0"
+  },
+  {
+    "font_class": "chat",
+    "unicode": "\ue65d"
+  },
+  {
+    "font_class": "chat-filled",
+    "unicode": "\ue659"
+  },
+  {
+    "font_class": "chatboxes",
+    "unicode": "\ue696"
+  },
+  {
+    "font_class": "chatboxes-filled",
+    "unicode": "\ue692"
+  },
+  {
+    "font_class": "chatbubble",
+    "unicode": "\ue697"
+  },
+  {
+    "font_class": "chatbubble-filled",
+    "unicode": "\ue694"
+  },
+  {
+    "font_class": "checkbox",
+    "unicode": "\ue62b"
+  },
+  {
+    "font_class": "checkbox-filled",
+    "unicode": "\ue62c"
+  },
+  {
+    "font_class": "checkmarkempty",
+    "unicode": "\ue65c"
+  },
+  {
+    "font_class": "circle",
+    "unicode": "\ue65b"
+  },
+  {
+    "font_class": "circle-filled",
+    "unicode": "\ue65e"
+  },
+  {
+    "font_class": "clear",
+    "unicode": "\ue66d"
+  },
+  {
+    "font_class": "close",
+    "unicode": "\ue673"
+  },
+  {
+    "font_class": "closeempty",
+    "unicode": "\ue66c"
+  },
+  {
+    "font_class": "cloud-download",
+    "unicode": "\ue647"
+  },
+  {
+    "font_class": "cloud-download-filled",
+    "unicode": "\ue646"
+  },
+  {
+    "font_class": "cloud-upload",
+    "unicode": "\ue645"
+  },
+  {
+    "font_class": "cloud-upload-filled",
+    "unicode": "\ue648"
+  },
+  {
+    "font_class": "color",
+    "unicode": "\ue6cf"
+  },
+  {
+    "font_class": "color-filled",
+    "unicode": "\ue6c9"
+  },
+  {
+    "font_class": "compose",
+    "unicode": "\ue67f"
+  },
+  {
+    "font_class": "contact",
+    "unicode": "\ue693"
+  },
+  {
+    "font_class": "contact-filled",
+    "unicode": "\ue695"
+  },
+  {
+    "font_class": "down",
+    "unicode": "\ue6b8"
+  },
+	{
+	  "font_class": "bottom",
+	  "unicode": "\ue6b8"
+	},
+  {
+    "font_class": "download",
+    "unicode": "\ue68d"
+  },
+  {
+    "font_class": "download-filled",
+    "unicode": "\ue681"
+  },
+  {
+    "font_class": "email",
+    "unicode": "\ue69e"
+  },
+  {
+    "font_class": "email-filled",
+    "unicode": "\ue69a"
+  },
+  {
+    "font_class": "eye",
+    "unicode": "\ue651"
+  },
+  {
+    "font_class": "eye-filled",
+    "unicode": "\ue66a"
+  },
+  {
+    "font_class": "eye-slash",
+    "unicode": "\ue6b3"
+  },
+  {
+    "font_class": "eye-slash-filled",
+    "unicode": "\ue6b4"
+  },
+  {
+    "font_class": "fire",
+    "unicode": "\ue6a1"
+  },
+  {
+    "font_class": "fire-filled",
+    "unicode": "\ue6c5"
+  },
+  {
+    "font_class": "flag",
+    "unicode": "\ue65f"
+  },
+  {
+    "font_class": "flag-filled",
+    "unicode": "\ue660"
+  },
+  {
+    "font_class": "folder-add",
+    "unicode": "\ue6a9"
+  },
+  {
+    "font_class": "folder-add-filled",
+    "unicode": "\ue6c8"
+  },
+  {
+    "font_class": "font",
+    "unicode": "\ue6a3"
+  },
+  {
+    "font_class": "forward",
+    "unicode": "\ue6ba"
+  },
+  {
+    "font_class": "gear",
+    "unicode": "\ue664"
+  },
+  {
+    "font_class": "gear-filled",
+    "unicode": "\ue661"
+  },
+  {
+    "font_class": "gift",
+    "unicode": "\ue6a4"
+  },
+  {
+    "font_class": "gift-filled",
+    "unicode": "\ue6c4"
+  },
+  {
+    "font_class": "hand-down",
+    "unicode": "\ue63d"
+  },
+  {
+    "font_class": "hand-down-filled",
+    "unicode": "\ue63c"
+  },
+  {
+    "font_class": "hand-up",
+    "unicode": "\ue63f"
+  },
+  {
+    "font_class": "hand-up-filled",
+    "unicode": "\ue63e"
+  },
+  {
+    "font_class": "headphones",
+    "unicode": "\ue630"
+  },
+  {
+    "font_class": "heart",
+    "unicode": "\ue639"
+  },
+  {
+    "font_class": "heart-filled",
+    "unicode": "\ue641"
+  },
+  {
+    "font_class": "help",
+    "unicode": "\ue679"
+  },
+  {
+    "font_class": "help-filled",
+    "unicode": "\ue674"
+  },
+  {
+    "font_class": "home",
+    "unicode": "\ue662"
+  },
+  {
+    "font_class": "home-filled",
+    "unicode": "\ue663"
+  },
+  {
+    "font_class": "image",
+    "unicode": "\ue670"
+  },
+  {
+    "font_class": "image-filled",
+    "unicode": "\ue678"
+  },
+  {
+    "font_class": "images",
+    "unicode": "\ue650"
+  },
+  {
+    "font_class": "images-filled",
+    "unicode": "\ue64b"
+  },
+  {
+    "font_class": "info",
+    "unicode": "\ue669"
+  },
+  {
+    "font_class": "info-filled",
+    "unicode": "\ue649"
+  },
+  {
+    "font_class": "left",
+    "unicode": "\ue6b7"
+  },
+  {
+    "font_class": "link",
+    "unicode": "\ue6a5"
+  },
+  {
+    "font_class": "list",
+    "unicode": "\ue644"
+  },
+  {
+    "font_class": "location",
+    "unicode": "\ue6ae"
+  },
+  {
+    "font_class": "location-filled",
+    "unicode": "\ue6af"
+  },
+  {
+    "font_class": "locked",
+    "unicode": "\ue66b"
+  },
+  {
+    "font_class": "locked-filled",
+    "unicode": "\ue668"
+  },
+  {
+    "font_class": "loop",
+    "unicode": "\ue633"
+  },
+  {
+    "font_class": "mail-open",
+    "unicode": "\ue643"
+  },
+  {
+    "font_class": "mail-open-filled",
+    "unicode": "\ue63a"
+  },
+  {
+    "font_class": "map",
+    "unicode": "\ue667"
+  },
+  {
+    "font_class": "map-filled",
+    "unicode": "\ue666"
+  },
+  {
+    "font_class": "map-pin",
+    "unicode": "\ue6ad"
+  },
+  {
+    "font_class": "map-pin-ellipse",
+    "unicode": "\ue6ac"
+  },
+  {
+    "font_class": "medal",
+    "unicode": "\ue6a2"
+  },
+  {
+    "font_class": "medal-filled",
+    "unicode": "\ue6c3"
+  },
+  {
+    "font_class": "mic",
+    "unicode": "\ue671"
+  },
+  {
+    "font_class": "mic-filled",
+    "unicode": "\ue677"
+  },
+  {
+    "font_class": "micoff",
+    "unicode": "\ue67e"
+  },
+  {
+    "font_class": "micoff-filled",
+    "unicode": "\ue6b0"
+  },
+  {
+    "font_class": "minus",
+    "unicode": "\ue66f"
+  },
+  {
+    "font_class": "minus-filled",
+    "unicode": "\ue67d"
+  },
+  {
+    "font_class": "more",
+    "unicode": "\ue64d"
+  },
+  {
+    "font_class": "more-filled",
+    "unicode": "\ue64e"
+  },
+  {
+    "font_class": "navigate",
+    "unicode": "\ue66e"
+  },
+  {
+    "font_class": "navigate-filled",
+    "unicode": "\ue67a"
+  },
+  {
+    "font_class": "notification",
+    "unicode": "\ue6a6"
+  },
+  {
+    "font_class": "notification-filled",
+    "unicode": "\ue6c1"
+  },
+  {
+    "font_class": "paperclip",
+    "unicode": "\ue652"
+  },
+  {
+    "font_class": "paperplane",
+    "unicode": "\ue672"
+  },
+  {
+    "font_class": "paperplane-filled",
+    "unicode": "\ue675"
+  },
+  {
+    "font_class": "person",
+    "unicode": "\ue699"
+  },
+  {
+    "font_class": "person-filled",
+    "unicode": "\ue69d"
+  },
+  {
+    "font_class": "personadd",
+    "unicode": "\ue69f"
+  },
+  {
+    "font_class": "personadd-filled",
+    "unicode": "\ue698"
+  },
+  {
+    "font_class": "personadd-filled-copy",
+    "unicode": "\ue6d1"
+  },
+  {
+    "font_class": "phone",
+    "unicode": "\ue69c"
+  },
+  {
+    "font_class": "phone-filled",
+    "unicode": "\ue69b"
+  },
+  {
+    "font_class": "plus",
+    "unicode": "\ue676"
+  },
+  {
+    "font_class": "plus-filled",
+    "unicode": "\ue6c7"
+  },
+  {
+    "font_class": "plusempty",
+    "unicode": "\ue67b"
+  },
+  {
+    "font_class": "pulldown",
+    "unicode": "\ue632"
+  },
+  {
+    "font_class": "pyq",
+    "unicode": "\ue682"
+  },
+  {
+    "font_class": "qq",
+    "unicode": "\ue680"
+  },
+  {
+    "font_class": "redo",
+    "unicode": "\ue64a"
+  },
+  {
+    "font_class": "redo-filled",
+    "unicode": "\ue655"
+  },
+  {
+    "font_class": "refresh",
+    "unicode": "\ue657"
+  },
+  {
+    "font_class": "refresh-filled",
+    "unicode": "\ue656"
+  },
+  {
+    "font_class": "refreshempty",
+    "unicode": "\ue6bf"
+  },
+  {
+    "font_class": "reload",
+    "unicode": "\ue6b2"
+  },
+  {
+    "font_class": "right",
+    "unicode": "\ue6b5"
+  },
+  {
+    "font_class": "scan",
+    "unicode": "\ue62a"
+  },
+  {
+    "font_class": "search",
+    "unicode": "\ue654"
+  },
+  {
+    "font_class": "settings",
+    "unicode": "\ue653"
+  },
+  {
+    "font_class": "settings-filled",
+    "unicode": "\ue6ce"
+  },
+  {
+    "font_class": "shop",
+    "unicode": "\ue62f"
+  },
+  {
+    "font_class": "shop-filled",
+    "unicode": "\ue6cd"
+  },
+  {
+    "font_class": "smallcircle",
+    "unicode": "\ue67c"
+  },
+  {
+    "font_class": "smallcircle-filled",
+    "unicode": "\ue665"
+  },
+  {
+    "font_class": "sound",
+    "unicode": "\ue684"
+  },
+  {
+    "font_class": "sound-filled",
+    "unicode": "\ue686"
+  },
+  {
+    "font_class": "spinner-cycle",
+    "unicode": "\ue68a"
+  },
+  {
+    "font_class": "staff",
+    "unicode": "\ue6a7"
+  },
+  {
+    "font_class": "staff-filled",
+    "unicode": "\ue6cb"
+  },
+  {
+    "font_class": "star",
+    "unicode": "\ue688"
+  },
+  {
+    "font_class": "star-filled",
+    "unicode": "\ue68f"
+  },
+  {
+    "font_class": "starhalf",
+    "unicode": "\ue683"
+  },
+  {
+    "font_class": "trash",
+    "unicode": "\ue687"
+  },
+  {
+    "font_class": "trash-filled",
+    "unicode": "\ue685"
+  },
+  {
+    "font_class": "tune",
+    "unicode": "\ue6aa"
+  },
+  {
+    "font_class": "tune-filled",
+    "unicode": "\ue6ca"
+  },
+  {
+    "font_class": "undo",
+    "unicode": "\ue64f"
+  },
+  {
+    "font_class": "undo-filled",
+    "unicode": "\ue64c"
+  },
+  {
+    "font_class": "up",
+    "unicode": "\ue6b6"
+  },
+	{
+	  "font_class": "top",
+	  "unicode": "\ue6b6"
+	},
+  {
+    "font_class": "upload",
+    "unicode": "\ue690"
+  },
+  {
+    "font_class": "upload-filled",
+    "unicode": "\ue68e"
+  },
+  {
+    "font_class": "videocam",
+    "unicode": "\ue68c"
+  },
+  {
+    "font_class": "videocam-filled",
+    "unicode": "\ue689"
+  },
+  {
+    "font_class": "vip",
+    "unicode": "\ue6a8"
+  },
+  {
+    "font_class": "vip-filled",
+    "unicode": "\ue6c6"
+  },
+  {
+    "font_class": "wallet",
+    "unicode": "\ue6b1"
+  },
+  {
+    "font_class": "wallet-filled",
+    "unicode": "\ue6c2"
+  },
+  {
+    "font_class": "weibo",
+    "unicode": "\ue68b"
+  },
+  {
+    "font_class": "weixin",
+    "unicode": "\ue691"
+  }
+]
+
+// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)

+ 14 - 12
src/uni_modules/uni-icons/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-icons",
   "displayName": "uni-icons 图标",
-  "version": "1.3.5",
+  "version": "2.0.9",
   "description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
   "keywords": [
     "uni-ui",
@@ -16,11 +16,7 @@
   "directories": {
     "example": "../../temps/example_temps"
   },
-  "dcloudext": {
-    "category": [
-      "前端组件",
-      "通用组件"
-    ],
+"dcloudext": {
     "sale": {
       "regular": {
         "price": "0.00"
@@ -37,7 +33,8 @@
       "data": "无",
       "permissions": "无"
     },
-    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
   },
   "uni_modules": {
     "dependencies": ["uni-scss"],
@@ -50,7 +47,8 @@
       "client": {
         "App": {
           "app-vue": "y",
-          "app-nvue": "y"
+          "app-nvue": "y",
+          "app-uvue": "y"
         },
         "H5-mobile": {
           "Safari": "y",
@@ -70,11 +68,15 @@
           "阿里": "y",
           "百度": "y",
           "字节跳动": "y",
-          "QQ": "y"
+          "QQ": "y",
+					"钉钉": "y",
+					"快手": "y",
+					"飞书": "y",
+					"京东": "y"
         },
         "快应用": {
-          "华为": "u",
-          "联盟": "u"
+          "华为": "y",
+          "联盟": "y"
         },
         "Vue": {
             "vue2": "y",
@@ -83,4 +85,4 @@
       }
     }
   }
-}
+}

+ 26 - 0
src/uni_modules/uni-list/changelog.md

@@ -1,3 +1,29 @@
+## 1.2.14(2023-04-14)
+- 优化 uni-list-chat 具名插槽`header` 非app端套一层元素,方便使用时通过外层元素定位实现样式修改
+## 1.2.13(2023-03-03)
+- uni-list-chat 新增 支持具名插槽`header`
+## 1.2.12(2023-02-01)
+- 新增 列表图标新增 customPrefix 属性 ,用法 [详见](https://uniapp.dcloud.net.cn/component/uniui/uni-icons.html#icons-props)
+## 1.2.11(2023-01-31)
+- 修复 无反馈效果呈现的bug
+## 1.2.9(2022-11-22)
+- 修复 uni-list-chat 在vue3下跳转报错的bug
+## 1.2.8(2022-11-21)
+- 修复 uni-list-chat avatar属性 值为本地路径时错误的问题
+## 1.2.7(2022-11-21)
+- 修复 uni-list-chat avatar属性 在腾讯云版uniCloud下错误的问题
+## 1.2.6(2022-11-18)
+- 修复 uni-list-chat note属性 支持:“草稿”字样功能 文本少1位的问题
+## 1.2.5(2022-11-15)
+- 修复 uni-list-item 的 customStyle 属性 padding值在 H5端 无效的bug
+## 1.2.4(2022-11-15)
+- 修复 uni-list-item 的 customStyle 属性 padding值在nvue(vue2)下无效的bug
+## 1.2.3(2022-11-14)
+- uni-list-chat 新增 avatar 支持 fileId
+## 1.2.2(2022-11-11)
+- uni-list 新增属性 render-reverse 详情参考:[https://uniapp.dcloud.net.cn/component/list.html](https://uniapp.dcloud.net.cn/component/list.html)
+- uni-list-chat note属性 支持:“草稿”字样 加红显示 详情参考uni-im:[https://ext.dcloud.net.cn/plugin?name=uni-im](https://ext.dcloud.net.cn/plugin?name=uni-im)
+- uni-list-item 新增属性 customStyle 支持设置padding、backgroundColor
 ## 1.2.1(2022-03-30)
 - 删除无用文件
 ## 1.2.0(2021-11-23)

+ 62 - 7
src/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue

@@ -7,7 +7,7 @@
 			<view class="uni-list-chat__container">
 				<view class="uni-list-chat__header-warp">
 					<view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }">
-						<image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatar" mode="aspectFill"></image>
+						<image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatarUrl" mode="aspectFill"></image>
 					</view>
 					<!-- 头像组 -->
 					<view v-else class="uni-list-chat__header">
@@ -18,13 +18,23 @@
 						</view>
 					</view>
 				</view>
+				<!-- #ifndef APP -->
+				<view class="slot-header">
+				<!-- #endif -->
+					<slot name="header"></slot>
+				<!-- #ifndef APP -->
+				</view>
+				<!-- #endif -->
 				<view v-if="badgeText && badgePositon === 'left'" class="uni-list-chat__badge uni-list-chat__badge-pos" :class="[isSingle]">
 					<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
 				</view>
 				<view class="uni-list-chat__content">
 					<view class="uni-list-chat__content-main">
 						<text class="uni-list-chat__content-title uni-ellipsis">{{ title }}</text>
-						<text class="uni-list-chat__content-note uni-ellipsis">{{ note }}</text>
+						<view style="flex-direction: row;">
+							<text class="draft" v-if="isDraft">[草稿]</text>
+							<text class="uni-list-chat__content-note uni-ellipsis">{{isDraft?note.slice(14):note}}</text>
+						</view>
 					</view>
 					<view class="uni-list-chat__content-extra">
 						<slot>
@@ -121,6 +131,9 @@
 		},
 		// inject: ['list'],
 		computed: {
+			isDraft(){
+				return this.note.slice(0,14) == '[uni-im-draft]'
+			},
 			isSingle() {
 				if (this.badgeText === 'dot') {
 					return 'uni-badge--dot';
@@ -146,12 +159,32 @@
 				}
 			}
 		},
+		watch: {
+			avatar:{
+				handler(avatar) {
+					if(avatar.substr(0,8) == 'cloud://'){
+						uniCloud.getTempFileURL({
+							fileList: [avatar]
+						}).then(res=>{
+							// console.log(res);
+							// 兼容uniCloud私有化部署
+							let fileList = res.fileList || res.result.fileList
+							this.avatarUrl = fileList[0].tempFileURL
+						})
+					}else{
+						this.avatarUrl = avatar
+					}
+				},
+				immediate: true
+			}
+		},
 		data() {
 			return {
 				isFirstChild: false,
 				border: true,
 				// avatarList: 3,
-				imageWidth: 50
+				imageWidth: 50,
+				avatarUrl:''
 			};
 		},
 		mounted() {
@@ -198,7 +231,7 @@
 				}
 			},
 			pageApi(api) {
-				uni[api]({
+				let callback = {
 					url: this.to,
 					success: res => {
 						this.$emit('click', {
@@ -209,9 +242,24 @@
 						this.$emit('click', {
 							data: err
 						});
-						console.error(err.errMsg);
 					}
-				});
+				}
+				switch (api) {
+					case 'navigateTo':
+						uni.navigateTo(callback)
+						break
+					case 'redirectTo':
+						uni.redirectTo(callback)
+						break
+					case 'reLaunch':
+						uni.reLaunch(callback)
+						break
+					case 'switchTab':
+						uni.switchTab(callback)
+						break
+					default:
+					uni.navigateTo(callback)
+				}
 			}
 		}
 	};
@@ -445,13 +493,20 @@
 		overflow: hidden;
 	}
 
-	.uni-list-chat__content-note {
+	.draft ,.uni-list-chat__content-note {
 		margin-top: 3px;
 		color: $note-color;
 		font-size: $note-size;
 		font-weight: $title-weight;
 		overflow: hidden;
 	}
+	.draft{
+		color: #eb3a41;
+		/* #ifndef APP-NVUE */
+		flex-shrink: 0;
+		/* #endif */
+		padding-right: 3px;
+	}
 
 	.uni-list-chat__content-extra {
 		/* #ifndef APP-NVUE */

+ 94 - 14
src/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue

@@ -1,21 +1,21 @@
 <template>
 	<!-- #ifdef APP-NVUE -->
-	<cell>
+	<cell :keep-scroll-position="keepScrollPosition">
 		<!-- #endif -->
-
-		<view :class="{ 'uni-list-item--disabled': disabled }"
+		<view :class="{ 'uni-list-item--disabled': disabled }" :style="{'background-color':customStyle.backgroundColor}"
 			:hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uni-list-item--hover'"
 			class="uni-list-item" @click="onClick">
 			<view v-if="!isFirstChild" class="border--left" :class="{ 'uni-list--border': border }"></view>
 			<view class="uni-list-item__container"
-				:class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column' }">
+				:class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column'}"
+				:style="{paddingTop:padding.top,paddingLeft:padding.left,paddingRight:padding.right,paddingBottom:padding.bottom}">
 				<slot name="header">
 					<view class="uni-list-item__header">
 						<view v-if="thumb" class="uni-list-item__icon">
 							<image :src="thumb" class="uni-list-item__icon-img" :class="['uni-list--' + thumbSize]" />
 						</view>
 						<view v-else-if="showExtraIcon" class="uni-list-item__icon">
-							<uni-icons :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" />
+							<uni-icons :customPrefix="extraIcon.customPrefix" :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" />
 						</view>
 					</view>
 				</slot>
@@ -96,7 +96,7 @@
 				default: ''
 			},
 			ellipsis: {
-				type: [Number,String],
+				type: [Number, String],
 				default: 0
 			},
 			disabled: {
@@ -139,7 +139,7 @@
 				type: String,
 				default: 'success'
 			},
-			badgeStyle:{
+			badgeStyle: {
 				type: Object,
 				default () {
 					return {}
@@ -167,19 +167,75 @@
 					return {
 						type: '',
 						color: '#000000',
-						size: 20
+						size: 20,
+						customPrefix: ''
 					};
 				}
 			},
 			border: {
 				type: Boolean,
 				default: true
+			},
+			customStyle: {
+				type: Object,
+				default () {
+					return {
+						padding: '',
+						backgroundColor: '#FFFFFF'
+					}
+				}
+			},
+			keepScrollPosition: {
+				type: Boolean,
+				default: false
+			}
+		},
+		watch: {
+			'customStyle.padding': {
+				handler(padding) {
+					if(typeof padding == 'number'){
+						padding += ''
+					}
+					let paddingArr = padding.split(' ')
+					if (paddingArr.length === 1) {
+						const allPadding = paddingArr[0]
+						this.padding = {
+							"top": allPadding,
+							"right": allPadding,
+							"bottom": allPadding,
+							"left": allPadding
+						}
+					} else if (paddingArr.length === 2) {
+						const [verticalPadding, horizontalPadding] = paddingArr;
+						this.padding = {
+							"top": verticalPadding,
+							"right": horizontalPadding,
+							"bottom": verticalPadding,
+							"left": horizontalPadding
+						}
+					} else if (paddingArr.length === 4) {
+							const [topPadding, rightPadding, bottomPadding, leftPadding] = paddingArr;
+							this.padding = {
+								"top": topPadding,
+								"right": rightPadding,
+								"bottom": bottomPadding,
+								"left": leftPadding
+							}
+					}
+				},
+				immediate: true
 			}
 		},
 		// inject: ['list'],
 		data() {
 			return {
-				isFirstChild: false
+				isFirstChild: false,
+				padding: {
+					top: "",
+					right: "",
+					bottom: "",
+					left: ""
+				}
 			};
 		},
 		mounted() {
@@ -255,7 +311,7 @@
 						uni.switchTab(callback)
 						break
 					default:
-					uni.navigateTo(callback)
+						uni.navigateTo(callback)
 				}
 			}
 		}
@@ -275,6 +331,7 @@
 	$uni-bg-color-hover:#f1f1f1;
 	$uni-text-color-grey:#999;
 	$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
+
 	.uni-list-item {
 		/* #ifndef APP-NVUE */
 		display: flex;
@@ -289,12 +346,15 @@
 		cursor: pointer;
 		/* #endif */
 	}
+
 	.uni-list-item--disabled {
 		opacity: 0.3;
 	}
+
 	.uni-list-item--hover {
-		background-color: $uni-bg-color-hover;
+		background-color: $uni-bg-color-hover !important;
 	}
+
 	.uni-list-item__container {
 		position: relative;
 		/* #ifndef APP-NVUE */
@@ -307,9 +367,11 @@
 		overflow: hidden;
 		// align-items: center;
 	}
+
 	.container--right {
 		padding-right: 0;
 	}
+
 	// .border--left {
 	// 	margin-left: $uni-spacing-row-lg;
 	// }
@@ -324,6 +386,7 @@
 		border-top-width: 0.5px;
 		/* #endif */
 	}
+
 	/* #ifndef APP-NVUE */
 	.uni-list--border:after {
 		position: absolute;
@@ -336,6 +399,7 @@
 		transform: scaleY(0.5);
 		background-color: $uni-border-color;
 	}
+
 	/* #endif */
 	.uni-list-item__content {
 		/* #ifndef APP-NVUE */
@@ -349,20 +413,24 @@
 		justify-content: space-between;
 		overflow: hidden;
 	}
+
 	.uni-list-item__content--center {
 		justify-content: center;
 	}
+
 	.uni-list-item__content-title {
 		font-size: $uni-font-size-base;
 		color: #3b4144;
 		overflow: hidden;
 	}
+
 	.uni-list-item__content-note {
 		margin-top: 6rpx;
 		color: $uni-text-color-grey;
 		font-size: $uni-font-size-sm;
 		overflow: hidden;
 	}
+
 	.uni-list-item__extra {
 		// width: 25%;
 		/* #ifndef APP-NVUE */
@@ -372,6 +440,7 @@
 		justify-content: flex-end;
 		align-items: center;
 	}
+
 	.uni-list-item__header {
 		/* #ifndef APP-NVUE */
 		display: flex;
@@ -379,12 +448,14 @@
 		flex-direction: row;
 		align-items: center;
 	}
+
 	.uni-list-item__icon {
 		margin-right: 18rpx;
 		flex-direction: row;
 		justify-content: center;
 		align-items: center;
 	}
+
 	.uni-list-item__icon-img {
 		/* #ifndef APP-NVUE */
 		display: block;
@@ -393,6 +464,7 @@
 		width: $uni-img-size-base;
 		margin-right: 10px;
 	}
+
 	.uni-icon-wrapper {
 		/* #ifndef APP-NVUE */
 		display: flex;
@@ -400,33 +472,40 @@
 		align-items: center;
 		padding: 0 10px;
 	}
+
 	.flex--direction {
 		flex-direction: column;
 		/* #ifndef APP-NVUE */
 		align-items: initial;
 		/* #endif */
 	}
+
 	.flex--justify {
 		/* #ifndef APP-NVUE */
 		justify-content: initial;
 		/* #endif */
 	}
+
 	.uni-list--lg {
 		height: $uni-img-size-lg;
 		width: $uni-img-size-lg;
 	}
+
 	.uni-list--base {
 		height: $uni-img-size-base;
 		width: $uni-img-size-base;
 	}
+
 	.uni-list--sm {
 		height: $uni-img-size-sm;
 		width: $uni-img-size-sm;
 	}
+
 	.uni-list-item__extra-text {
 		color: $uni-text-color-grey;
 		font-size: $uni-font-size-sm;
 	}
+
 	.uni-ellipsis-1 {
 		/* #ifndef APP-NVUE */
 		overflow: hidden;
@@ -435,9 +514,10 @@
 		/* #endif */
 		/* #ifdef APP-NVUE */
 		lines: 1;
-		text-overflow:ellipsis;
+		text-overflow: ellipsis;
 		/* #endif */
 	}
+
 	.uni-ellipsis-2 {
 		/* #ifndef APP-NVUE */
 		overflow: hidden;
@@ -448,7 +528,7 @@
 		/* #endif */
 		/* #ifdef APP-NVUE */
 		lines: 2;
-		text-overflow:ellipsis;
+		text-overflow: ellipsis;
 		/* #endif */
 	}
-</style>
+</style>

+ 100 - 85
src/uni_modules/uni-list/components/uni-list/uni-list.vue

@@ -7,102 +7,117 @@
 	</view>
 	<!-- #endif -->
 	<!-- #ifdef APP-NVUE -->
-	<list class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop" loadmoreoffset="15"><slot /></list>
+	<list :bounce="false" :scrollable="true" show-scrollbar :render-reverse="renderReverse" @scroll="scroll" class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop"
+		loadmoreoffset="15">
+		<slot />
+	</list>
 	<!-- #endif -->
 </template>
 
 <script>
-/**
- * List 列表
- * @description 列表组件
- * @tutorial https://ext.dcloud.net.cn/plugin?id=24
- * @property {String} 	border = [true|false] 		标题
- */
-export default {
-	name: 'uniList',
-	'mp-weixin': {
-		options: {
-			multipleSlots: false
-		}
-	},
-	props: {
-		enableBackToTop: {
-			type: [Boolean, String],
-			default: false
+	/**
+	 * List 列表
+	 * @description 列表组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+	 * @property {String} 	border = [true|false] 		标题
+	 */
+	export default {
+		name: 'uniList',
+		'mp-weixin': {
+			options: {
+				multipleSlots: false
+			}
 		},
-		scrollY: {
-			type: [Boolean, String],
-			default: false
+		props: {
+			stackFromEnd:{
+				type: Boolean,
+				default:false
+			},
+			enableBackToTop: {
+				type: [Boolean, String],
+				default: false
+			},
+			scrollY: {
+				type: [Boolean, String],
+				default: false
+			},
+			border: {
+				type: Boolean,
+				default: true
+			},
+			renderReverse:{
+				type: Boolean,
+				default: false
+			}
 		},
-		border: {
-			type: Boolean,
-			default: true
-		}
-	},
-	// provide() {
-	// 	return {
-	// 		list: this
-	// 	};
-	// },
-	created() {
-		this.firstChildAppend = false;
-	},
-	methods: {
-		loadMore(e) {
-			this.$emit('scrolltolower');
+		// provide() {
+		// 	return {
+		// 		list: this
+		// 	};
+		// },
+		created() {
+			this.firstChildAppend = false;
+		},
+		methods: {
+			loadMore(e) {
+				this.$emit('scrolltolower');
+			},
+			scroll(e) {
+				this.$emit('scroll', e);
+			}
 		}
-	}
-};
+	};
 </script>
-<style lang="scss" >
-$uni-bg-color:#ffffff;
-$uni-border-color:#e5e5e5;
-.uni-list {
-	/* #ifndef APP-NVUE */
-	display: flex;
-	/* #endif */
-	background-color: $uni-bg-color;
-	position: relative;
-	flex-direction: column;
-}
+<style lang="scss">
+	$uni-bg-color:#ffffff;
+	$uni-border-color:#e5e5e5;
 
-.uni-list--border {
-	position: relative;
-	/* #ifdef APP-NVUE */
-	border-top-color: $uni-border-color;
-	border-top-style: solid;
-	border-top-width: 0.5px;
-	border-bottom-color: $uni-border-color;
-	border-bottom-style: solid;
-	border-bottom-width: 0.5px;
-	/* #endif */
-	z-index: -1;
-}
+	.uni-list {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		background-color: $uni-bg-color;
+		position: relative;
+		flex-direction: column;
+	}
 
-/* #ifndef APP-NVUE */
+	.uni-list--border {
+		position: relative;
+		/* #ifdef APP-NVUE */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		border-bottom-color: $uni-border-color;
+		border-bottom-style: solid;
+		border-bottom-width: 0.5px;
+		/* #endif */
+		z-index: -1;
+	}
 
-.uni-list--border-top {
-	position: absolute;
-	top: 0;
-	right: 0;
-	left: 0;
-	height: 1px;
-	-webkit-transform: scaleY(0.5);
-	transform: scaleY(0.5);
-	background-color: $uni-border-color;
-	z-index: 1;
-}
+	/* #ifndef APP-NVUE */
 
-.uni-list--border-bottom {
-	position: absolute;
-	bottom: 0;
-	right: 0;
-	left: 0;
-	height: 1px;
-	-webkit-transform: scaleY(0.5);
-	transform: scaleY(0.5);
-	background-color: $uni-border-color;
-}
+	.uni-list--border-top {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $uni-border-color;
+		z-index: 1;
+	}
 
-/* #endif */
+	.uni-list--border-bottom {
+		position: absolute;
+		bottom: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $uni-border-color;
+	}
+
+	/* #endif */
 </style>

+ 4 - 7
src/uni_modules/uni-list/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-list",
   "displayName": "uni-list 列表",
-  "version": "1.2.1",
+  "version": "1.2.14",
   "description": "List 组件 ,帮助使用者快速构建列表。",
   "keywords": [
     "",
@@ -18,11 +18,7 @@
   "directories": {
     "example": "../../temps/example_temps"
   },
-  "dcloudext": {
-    "category": [
-      "前端组件",
-      "通用组件"
-    ],
+"dcloudext": {
     "sale": {
       "regular": {
         "price": "0.00"
@@ -39,7 +35,8 @@
       "data": "无",
       "permissions": "无"
     },
-    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
   },
   "uni_modules": {
     "dependencies": [

+ 4 - 0
src/uni_modules/uni-nav-bar/changelog.md

@@ -1,3 +1,7 @@
+## 1.3.11(2023-03-29)
+- 修复 自定义状态栏高度闪动BUG
+## 1.3.10(2023-03-29)
+- 修复 暗黑模式下边线颜色错误的bug
 ## 1.3.9(2022-10-13)
 - 修复 条件编译错误的bug
 ## 1.3.8(2022-10-12)

+ 1 - 1
src/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue

@@ -1,7 +1,7 @@
 <template>
 	<view class="uni-navbar" :class="{'uni-dark':dark, 'uni-nvue-fixed': fixed}">
 		<view class="uni-navbar__content" :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }"
-			:style="{ 'background-color': themeBgColor }" >
+			:style="{ 'background-color': themeBgColor, 'border-bottom-color':themeColor }" >
 			<status-bar v-if="statusBar" />
 			<view :style="{ color: themeColor,backgroundColor: themeBgColor ,height:navbarHeight}"
 				class="uni-navbar__header">

+ 1 - 4
src/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue

@@ -9,11 +9,8 @@
 		name: 'UniStatusBar',
 		data() {
 			return {
-				statusBarHeight: 20
+				statusBarHeight: uni.getSystemInfoSync().statusBarHeight + 'px'
 			}
-		},
-		mounted() {
-			this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
 		}
 	}
 </script>

+ 1 - 1
src/uni_modules/uni-nav-bar/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-nav-bar",
   "displayName": "uni-nav-bar 自定义导航栏",
-  "version": "1.3.9",
+  "version": "1.3.11",
   "description": "自定义导航栏组件,主要用于头部导航。",
   "keywords": [
     "uni-ui",

+ 2 - 0
src/uni_modules/uni-notice-bar/changelog.md

@@ -1,3 +1,5 @@
+## 1.2.2(2023-12-20)
+- 修复动态绑定title时,滚动速度不一致的问题
 ## 1.2.1(2022-09-05)
 - 新增 属性 fontSize,可修改文字大小。
 ## 1.2.0(2021-11-19)

+ 5 - 0
src/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue

@@ -150,6 +150,11 @@
 				animationDelay: '0s'
 			}
 		},
+		watch:{
+			text:function(newValue,oldValue){
+				this.initSize();
+			}
+		},
 		computed: {
 			isShowGetMore() {
 				return this.showGetMore === true || this.showGetMore === 'true'

+ 1 - 1
src/uni_modules/uni-notice-bar/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-notice-bar",
   "displayName": "uni-notice-bar 通告栏",
-  "version": "1.2.1",
+  "version": "1.2.2",
   "description": "NoticeBar 通告栏组件,常用于展示公告信息,可设为滚动公告",
   "keywords": [
     "uni-ui",

+ 6 - 0
src/uni_modules/uni-number-box/changelog.md

@@ -1,3 +1,9 @@
+## 1.2.4(2024-02-02)
+- 修复 加减号垂直位置偏移样式问题
+## 1.2.3(2023-05-23)
+- 更新示例工程
+## 1.2.2(2023-05-08)
+- 修复 change 事件执行顺序错误的问题
 ## 1.2.1(2021-11-22)
 - 修复 vue3中某些scss变量无法找到的问题
 ## 1.2.0(2021-11-19)

+ 3 - 3
src/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue

@@ -114,11 +114,11 @@
 				}
 
 				this.inputValue = (value / scale).toFixed(String(scale).length - 1);
-				this.$emit("change", +this.inputValue);
 				// TODO vue2 兼容
 				this.$emit("input", +this.inputValue);
 				// TODO vue3 兼容
 				this.$emit("update:modelValue", +this.inputValue);
+				this.$emit("change", +this.inputValue);
 			},
 			_getDecimalScale() {
 
@@ -144,9 +144,9 @@
 				}
 				const scale = this._getDecimalScale();
 				this.inputValue = value.toFixed(String(scale).length - 1);
-				this.$emit("change", +this.inputValue);
 				this.$emit("input", +this.inputValue);
 				this.$emit("update:modelValue", +this.inputValue);
+				this.$emit("change", +this.inputValue);
 			},
 			_onFocus(event) {
 				this.$emit('focus', event)
@@ -206,7 +206,7 @@
 	.uni-numbox--text {
 		// fix nvue
 		line-height: 20px;
-
+		margin-bottom: 2px;
 		font-size: 20px;
 		font-weight: 300;
 		color: $color;

+ 4 - 7
src/uni_modules/uni-number-box/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-number-box",
   "displayName": "uni-number-box 数字输入框",
-  "version": "1.2.1",
+  "version": "1.2.4",
   "description": "NumberBox 带加减按钮的数字输入框组件,用户可以控制每次点击增加的数值,支持小数。",
   "keywords": [
     "uni-ui",
@@ -15,11 +15,7 @@
   "directories": {
     "example": "../../temps/example_temps"
   },
-  "dcloudext": {
-    "category": [
-      "前端组件",
-      "通用组件"
-    ],
+"dcloudext": {
     "sale": {
       "regular": {
         "price": "0.00"
@@ -36,7 +32,8 @@
       "data": "无",
       "permissions": "无"
     },
-    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
   },
   "uni_modules": {
     "dependencies": ["uni-scss"],

+ 16 - 0
src/uni_modules/uni-popup/changelog.md

@@ -1,3 +1,19 @@
+## 1.8.7(2024-02-02)
+- 新增 uni-popup-dialog 新增属性focus:input模式下,是否自动自动聚焦
+## 1.8.6(2024-01-30)
+- 新增 uni-popup-dialog 新增属性maxLength:限制输入框字数
+## 1.8.5(2024-01-26)
+- 新增 uni-popup-dialog 新增属性showClose:控制关闭按钮的显示
+## 1.8.4(2023-11-15)
+- 新增 uni-popup 支持uni-app-x 注意暂时仅支持 `maskClick` `@open` `@close`
+## 1.8.3(2023-04-17)
+- 修复 uni-popup 重复打开时的 bug
+## 1.8.2(2023-02-02)
+- uni-popup-dialog 组件新增 inputType 属性
+## 1.8.1(2022-12-01)
+- 修复 nvue 下 v-show 报错
+## 1.8.0(2022-11-29)
+- 优化 主题样式
 ## 1.7.9(2022-04-02)
 - 修复 弹出层内部无法滚动的bug
 ## 1.7.8(2022-03-28)

+ 41 - 18
src/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue

@@ -10,11 +10,12 @@
 		</view>
 		<view v-else class="uni-dialog-content">
 			<slot>
-				<input class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholderText" :focus="focus" >
+				<input class="uni-dialog-input" :maxlength="maxlength" v-model="val" :type="inputType"
+					:placeholder="placeholderText" :focus="focus">
 			</slot>
 		</view>
 		<view class="uni-dialog-button-group">
-			<view class="uni-dialog-button" @click="closeDialog">
+			<view class="uni-dialog-button" v-if="showClose" @click="closeDialog">
 				<text class="uni-dialog-button-text">{{closeText}}</text>
 			</view>
 			<view class="uni-dialog-button uni-border-left" @click="onOk">
@@ -28,16 +29,19 @@
 <script>
 	import popup from '../uni-popup/popup.js'
 	import {
-	initVueI18n
+		initVueI18n
 	} from '@dcloudio/uni-i18n'
 	import messages from '../uni-popup/i18n/index.js'
-	const {	t } = initVueI18n(messages)
+	const {
+		t
+	} = initVueI18n(messages)
 	/**
 	 * PopUp 弹出层-对话框样式
 	 * @description 弹出层-对话框样式
 	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
 	 * @property {String} value input 模式下的默认值
 	 * @property {String} placeholder input 模式下输入提示
+	 * @property {Boolean} focus input模式下是否自动聚焦,默认为true
 	 * @property {String} type = [success|warning|info|error] 主题样式
 	 *  @value success 成功
 	 * 	@value warning 提示
@@ -46,8 +50,10 @@
 	 * @property {String} mode = [base|input] 模式、
 	 * 	@value base 基础对话框
 	 * 	@value input 可输入对话框
+	 * @showClose {Boolean} 是否显示关闭按钮
 	 * @property {String} content 对话框内容
 	 * @property {Boolean} beforeClose 是否拦截取消事件
+	 * @property {Number} maxlength 输入
 	 * @event {Function} confirm 点击确认按钮触发
 	 * @event {Function} close 点击取消按钮触发
 	 */
@@ -55,8 +61,16 @@
 	export default {
 		name: "uniPopupDialog",
 		mixins: [popup],
-		emits:['confirm','close'],
+		emits: ['confirm', 'close'],
 		props: {
+			inputType: {
+				type: String,
+				default: 'text'
+			},
+			showClose: {
+				type: Boolean,
+				default: true
+			},
 			value: {
 				type: [String, Number],
 				default: ''
@@ -85,19 +99,26 @@
 				type: Boolean,
 				default: false
 			},
-			cancelText:{
+			cancelText: {
 				type: String,
 				default: ''
 			},
-			confirmText:{
+			confirmText: {
 				type: String,
 				default: ''
+			},
+			maxlength: {
+				type: Number,
+				default: -1,
+			},
+			focus:{
+				type: Boolean,
+				default: true,
 			}
 		},
 		data() {
 			return {
 				dialogType: 'error',
-				focus: false,
 				val: ""
 			}
 		},
@@ -125,7 +146,11 @@
 				}
 			},
 			value(val) {
-				this.val = val
+				if (this.maxlength != -1 && this.mode === 'input') {
+					this.val = val.slice(0, this.maxlength);
+				} else {
+					this.val = val
+				}
 			}
 		},
 		created() {
@@ -139,20 +164,18 @@
 				this.dialogType = this.type
 			}
 		},
-		mounted() {
-			this.focus = true
-		},
 		methods: {
 			/**
 			 * 点击确认按钮
 			 */
 			onOk() {
-				if (this.mode === 'input'){
+				if (this.mode === 'input') {
 					this.$emit('confirm', this.val)
-				}else{
+				} else {
 					this.$emit('confirm')
 				}
-				if(this.beforeClose) return
+				this.$emit("input",this.val);
+				if (this.beforeClose) return
 				this.popup.close()
 			},
 			/**
@@ -160,17 +183,17 @@
 			 */
 			closeDialog() {
 				this.$emit('close')
-				if(this.beforeClose) return
+				if (this.beforeClose) return
 				this.popup.close()
 			},
-			close(){
+			close() {
 				this.popup.close()
 			}
 		}
 	}
 </script>
 
-<style lang="scss" >
+<style lang="scss">
 	.uni-popup-dialog {
 		width: 300px;
 		border-radius: 11px;

+ 1 - 1
src/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue

@@ -47,7 +47,7 @@
 					{
 						text: '支付宝',
 						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png',
-						name: 'wx'
+						name: 'ali'
 					},
 					{
 						text: 'QQ',

+ 90 - 0
src/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue

@@ -0,0 +1,90 @@
+<template>
+  <view class="popup-root" v-if="isOpen" v-show="isShow" @click="clickMask">
+    <view @click.stop>
+      <slot></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+  type CloseCallBack = ()=> void;
+  let closeCallBack:CloseCallBack = () :void => {};
+  export default {
+    emits:["close","clickMask"],
+    data() {
+      return {
+        isShow:false,
+        isOpen:false
+      }
+    },
+    props: {
+      maskClick: {
+        type: Boolean,
+        default: true
+      },
+    },
+    watch: {
+      // 设置show = true 时,如果没有 open 需要设置为 open
+      isShow:{
+        handler(isShow) {
+          // console.log("isShow",isShow)
+          if(isShow && this.isOpen == false){
+            this.isOpen = true
+          }
+        },
+        immediate:true
+      },
+      // 设置isOpen = true 时,如果没有 isShow 需要设置为 isShow
+      isOpen:{
+        handler(isOpen) {
+          // console.log("isOpen",isOpen)
+          if(isOpen && this.isShow == false){
+            this.isShow = true
+          }
+        },
+        immediate:true
+      }
+    },
+    methods:{
+      open(){
+        // ...funs : CloseCallBack[]
+        // if(funs.length > 0){
+        //   closeCallBack = funs[0]
+        // }
+        this.isOpen = true;
+      },
+      clickMask(){
+        if(this.maskClick == true){
+          this.$emit('clickMask')
+          this.close()
+        }
+      },
+      close(): void{
+        this.isOpen = false;
+        this.$emit('close')
+        closeCallBack()
+      },
+      hiden(){
+        this.isShow = false
+      },
+      show(){
+        this.isShow = true
+      }
+    }
+  }
+</script>
+
+<style>
+.popup-root {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 750rpx;
+  height: 100%;
+  flex: 1;
+  background-color: rgba(0, 0, 0, 0.3);
+  justify-content: center;
+  align-items: center;
+  z-index: 99;
+}
+</style>

+ 4 - 10
src/uni_modules/uni-popup/components/uni-popup/uni-popup.vue

@@ -1,10 +1,10 @@
 <template>
-	<view v-if="showPopup||onceRender" v-show="showPopup"  class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']">
+	<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']">
 		<view @touchstart="touchstart">
 			<uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass"
 				:duration="duration" :show="showTrans" @click="onTap" />
 			<uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration"
-				:show="showTrans" @click="onTap" :once-render="onceRender">
+				:show="showTrans" @click="onTap">
 				<view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear">
 					<slot />
 				</view>
@@ -86,11 +86,6 @@
 				type: String,
 				default: 'rgba(0, 0, 0, 0.4)'
 			},
-			// 指定使用v-show指令,不重新渲染Pop组件
-			onceRender:{
-				type:Boolean,
-				default:false
-			},
 		},
 
 		watch: {
@@ -168,7 +163,7 @@
 				},
 				maskShow: true,
 				mkclick: true,
-				popupstyle: this.isDesktop ? 'fixforpc-top' : 'top'
+				popupstyle: 'top'
 			}
 		},
 		computed: {
@@ -274,8 +269,7 @@
 			open(direction) {
 				// fix by mehaotian 处理快速打开关闭的情况
 				if (this.showPopup) {
-					clearTimeout(this.timer)
-					this.showPopup = false
+					return
 				}
 				let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
 				if (!(direction && innerType.indexOf(direction) !== -1)) {

+ 5 - 8
src/uni_modules/uni-popup/package.json

@@ -1,7 +1,7 @@
 {
 	"id": "uni-popup",
 	"displayName": "uni-popup 弹出层",
-	"version": "1.7.9",
+	"version": "1.8.7",
 	"description": " Popup 组件,提供常用的弹层",
 	"keywords": [
         "uni-ui",
@@ -17,12 +17,8 @@
 	"directories": {
 		"example": "../../temps/example_temps"
 	},
-	"dcloudext": {
-		"category": [
-			"前端组件",
-			"通用组件"
-		],
-		"sale": {
+    "dcloudext": {
+        "sale": {
 			"regular": {
 				"price": "0.00"
 			},
@@ -38,7 +34,8 @@
 			"data": "无",
 			"permissions": "无"
 		},
-		"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+        "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+        "type": "component-vue"
 	},
 	"uni_modules": {
 		"dependencies": [

+ 4 - 0
src/uni_modules/uni-search-bar/changelog.md

@@ -1,3 +1,7 @@
+## 1.2.5(2024-01-31)
+- 修复 uni-search-bar居中问题,现在默认居左,并修复样式偏移问题
+## 1.2.4(2023-05-09)
+- 修复 i18n 国际化不正确的 Bug
 ## 1.2.3(2022-05-24)
 - 新增 readonly 属性,组件只读
 ## 1.2.2(2022-05-06)

+ 1 - 1
src/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json

@@ -1,4 +1,4 @@
 {
-	"uni-search-bar.cancel": "cancel",
+	"uni-search-bar.cancel": "取消",
 	"uni-search-bar.placeholder": "请输入搜索内容"
 }

+ 1 - 1
src/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json

@@ -1,4 +1,4 @@
 {
-	"uni-search-bar.cancel": "cancel",
+	"uni-search-bar.cancel": "取消",
 	"uni-search-bar.placeholder": "請輸入搜索內容"
 }

+ 6 - 3
src/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue

@@ -9,7 +9,7 @@
 			</view>
 			<input v-if="show || searchVal" :focus="showSync" :disabled="readonly" :placeholder="placeholderText" :maxlength="maxlength"
 				class="uni-searchbar__box-search-input" confirm-type="search" type="text" v-model="searchVal"
-				@confirm="confirm" @blur="blur" @focus="emitFocus" />
+				@confirm="confirm" @blur="blur" @focus="emitFocus"/>
 			<text v-else class="uni-searchbar__text-placeholder">{{ placeholder }}</text>
 			<view v-if="show && (clearButton==='always'||clearButton==='auto'&&searchVal!=='') &&!readonly"
 				class="uni-searchbar__box-icon-clear" @click="clear">
@@ -80,7 +80,7 @@
 			},
 			cancelText: {
 				type: String,
-				default: '取消'
+				default: ""
 			},
 			bgColor: {
 				type: String,
@@ -246,7 +246,7 @@
 		overflow: hidden;
 		position: relative;
 		flex: 1;
-		justify-content: center;
+		justify-content: left;
 		flex-direction: row;
 		align-items: center;
 		height: $uni-searchbar-height;
@@ -269,6 +269,8 @@
 		flex: 1;
 		font-size: 14px;
 		color: #333;
+		margin-left: 5px;
+		margin-top: 1px;
 	}
 
 	.uni-searchbar__box-icon-clear {
@@ -284,6 +286,7 @@
 		font-size: 14px;
 		color: #B3B3B3;
 		margin-left: 5px;
+		text-align: left;
 	}
 
 	.uni-searchbar__cancel {

+ 4 - 7
src/uni_modules/uni-search-bar/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-search-bar",
   "displayName": "uni-search-bar 搜索栏",
-  "version": "1.2.3",
+  "version": "1.2.5",
   "description": "搜索栏组件,通常用于搜索商品、文章等",
   "keywords": [
     "uni-ui",
@@ -16,11 +16,7 @@
   "directories": {
     "example": "../../temps/example_temps"
   },
-  "dcloudext": {
-    "category": [
-      "前端组件",
-      "通用组件"
-    ],
+"dcloudext": {
     "sale": {
       "regular": {
         "price": "0.00"
@@ -37,7 +33,8 @@
       "data": "无",
       "permissions": "无"
     },
-    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
   },
   "uni_modules": {
     "dependencies": [

+ 6 - 0
src/uni_modules/uni-swipe-action/changelog.md

@@ -1,3 +1,9 @@
+## 1.3.10(2024-01-17)
+- 修复 点击按钮时,按钮会被点击穿透导致自动收缩的 bug(兼容阿里/百度/抖音小程序)
+## 1.3.9(2024-01-17)
+- 修复 点击按钮时,按钮会被点击穿透导致自动收缩的 bug
+## 1.3.8(2023-04-13)
+- 修复`uni-swipe-action`和`uni-swipe-action-item`不同时使用导致 closeOther 方法报错的 bug
 ## 1.3.7(2022-06-06)
 - 修复 vue3 下使用组件不能正常运行的Bug
 ## 1.3.6(2022-05-31)

+ 2 - 2
src/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js

@@ -31,7 +31,7 @@ bindIngXMixins = {
 	},
 	created() {
 		this.swipeaction = this.getSwipeAction()
-		if (this.swipeaction.children !== undefined) {
+		if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
 			this.swipeaction.children.push(this)
 		}
 	},
@@ -74,7 +74,7 @@ bindIngXMixins = {
 			// 每次只触发一次,避免多次监听造成闪烁
 			if (this.stop) return
 			this.stop = true
-			if (this.autoClose) {
+			if (this.autoClose && this.swipeaction) {
 				this.swipeaction.closeOther(this)
 			}
 

+ 4 - 2
src/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js

@@ -21,7 +21,7 @@ export default {
 	},
 	created() {
 		this.swipeaction = this.getSwipeAction()
-		if (this.swipeaction.children !== undefined) {
+		if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
 			this.swipeaction.children.push(this)
 		}
 	},
@@ -65,7 +65,9 @@ export default {
 		touchstart(e) {
 			this.transition = false
 			this.isclose = true
-			this.autoClose && this.swipeaction.closeOther(this)
+			if (this.autoClose && this.swipeaction) {
+				this.swipeaction.closeOther(this)
+			}
 		},
 		touchmove(e) {},
 		touchend(e) {

Some files were not shown because too many files changed in this diff