wzx 2 년 전
부모
커밋
18abad59ca
100개의 변경된 파일3951개의 추가작업 그리고 2874개의 파일을 삭제
  1. 10 4
      App.vue
  2. 1 1
      grpc/app_api
  3. 500 29
      grpc/base_pb.js
  4. 202 19
      grpc/track_offical_grpc_web_pb.js
  5. 505 124
      grpc/track_offical_pb.js
  6. 3 1
      main.js
  7. 5 2
      manifest.json
  8. 7 1
      pages.json
  9. 7 1
      pages/AO/actionList.vue
  10. 0 264
      pages/AO/checkPointDetail.vue
  11. 132 0
      pages/AO/mapList.vue
  12. 390 231
      pages/AO/mapShow.vue
  13. 0 206
      pages/AO/mapShow1.vue
  14. 0 267
      pages/AO/mapShow2.vue
  15. 72 6
      store/index.js
  16. 2 0
      uni_modules/uni-badge/changelog.md
  17. 3 3
      uni_modules/uni-badge/components/uni-badge/uni-badge.vue
  18. 1 1
      uni_modules/uni-badge/package.json
  19. 13 7
      uni_modules/uni-calendar/changelog.md
  20. 4 5
      uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
  21. 24 20
      uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
  22. 12 2
      uni_modules/uni-calendar/components/uni-calendar/util.js
  23. 1 1
      uni_modules/uni-calendar/package.json
  24. 3 3
      uni_modules/uni-calendar/readme.md
  25. 1 1
      uni_modules/uni-combox/components/uni-combox/uni-combox.vue
  26. 9 0
      uni_modules/uni-data-picker/changelog.md
  27. 544 540
      uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
  28. 17 15
      uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
  29. 1 1
      uni_modules/uni-data-picker/package.json
  30. 13 0
      uni_modules/uni-data-select/changelog.md
  31. 132 55
      uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue
  32. 1 1
      uni_modules/uni-data-select/package.json
  33. 67 33
      uni_modules/uni-datetime-picker/changelog.md
  34. 3 13
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
  35. 141 127
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
  36. 1 1
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json
  37. 16 28
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue
  38. 335 282
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
  39. 186 193
      uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
  40. 1 1
      uni_modules/uni-datetime-picker/package.json
  41. 1 1
      uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue
  42. 12 1
      uni_modules/uni-easyinput/changelog.md
  43. 115 137
      uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
  44. 1 1
      uni_modules/uni-easyinput/package.json
  45. 2 0
      uni_modules/uni-fab/changelog.md
  46. 3 2
      uni_modules/uni-fab/components/uni-fab/uni-fab.vue
  47. 1 1
      uni_modules/uni-fab/package.json
  48. 4 0
      uni_modules/uni-file-picker/changelog.md
  49. 2 2
      uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
  50. 12 1
      uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
  51. 4 7
      uni_modules/uni-file-picker/package.json
  52. 2 0
      uni_modules/uni-forms/changelog.md
  53. 2 6
      uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
  54. 1 1
      uni_modules/uni-forms/package.json
  55. 1 1
      uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue
  56. 1 1
      uni_modules/uni-grid/components/uni-grid/uni-grid.vue
  57. 1 1
      uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue
  58. 2 2
      uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue
  59. 26 0
      uni_modules/uni-list/changelog.md
  60. 62 7
      uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
  61. 94 14
      uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
  62. 100 85
      uni_modules/uni-list/components/uni-list/uni-list.vue
  63. 4 7
      uni_modules/uni-list/package.json
  64. 4 0
      uni_modules/uni-nav-bar/changelog.md
  65. 1 1
      uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
  66. 1 4
      uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
  67. 1 1
      uni_modules/uni-nav-bar/package.json
  68. 2 0
      uni_modules/uni-number-box/changelog.md
  69. 2 2
      uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue
  70. 4 7
      uni_modules/uni-number-box/package.json
  71. 8 0
      uni_modules/uni-popup/changelog.md
  72. 5 1
      uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
  73. 3 9
      uni_modules/uni-popup/components/uni-popup/uni-popup.vue
  74. 5 8
      uni_modules/uni-popup/package.json
  75. 1 1
      uni_modules/uni-row/components/uni-col/uni-col.vue
  76. 1 1
      uni_modules/uni-row/components/uni-row/uni-row.vue
  77. 2 0
      uni_modules/uni-search-bar/changelog.md
  78. 1 1
      uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json
  79. 1 1
      uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json
  80. 1 1
      uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue
  81. 4 7
      uni_modules/uni-search-bar/package.json
  82. 1 1
      uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue
  83. 2 0
      uni_modules/uni-swipe-action/changelog.md
  84. 2 2
      uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
  85. 4 2
      uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js
  86. 4 3
      uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js
  87. 4 3
      uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js
  88. 5 8
      uni_modules/uni-swipe-action/package.json
  89. 1 1
      uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue
  90. 4 0
      uni_modules/uni-table/changelog.md
  91. 3 3
      uni_modules/uni-table/components/uni-table/uni-table.vue
  92. 16 8
      uni_modules/uni-table/components/uni-th/filter-dropdown.vue
  93. 10 3
      uni_modules/uni-table/components/uni-th/uni-th.vue
  94. 6 6
      uni_modules/uni-table/components/uni-tr/table-checkbox.vue
  95. 4 7
      uni_modules/uni-table/package.json
  96. 1 1
      uni_modules/uni-tag/components/uni-tag/uni-tag.vue
  97. 7 12
      uni_modules/uni-tooltip/package.json
  98. 2 0
      uni_modules/uni-transition/changelog.md
  99. 4 1
      uni_modules/uni-transition/components/uni-transition/createAnimation.js
  100. 6 1
      uni_modules/uni-transition/components/uni-transition/uni-transition.vue

+ 10 - 4
App.vue

@@ -2,6 +2,13 @@
 	export default {
 		onLaunch: function() {
 			console.log('App Launch')
+			// this.$global.getWindowInfo()
+			
+			uni.onWindowResize(res => {
+				// console.log('[APP onWindowResize]', res)
+				this.$global.getWindowInfo(res.size)
+				uni.$emit('windowResize')
+			});
 		},
 		onShow: function() {
 			console.log('App Show')
@@ -9,7 +16,7 @@
 		onHide: function() {
 			console.log('App Hide')
 		}
-	}
+	} 
 </script>
 
 <style lang="scss">
@@ -21,9 +28,8 @@
 
 	// 设置整个项目的背景色
 	page {
-		// background-color: #f5f5f5;
-		background-color: #fff;
+		background-color: #ffffff;
 	}
 
 	/* #endif */
-</style>
+</style>  

+ 1 - 1
grpc/app_api

@@ -1 +1 @@
-Subproject commit 008439ca46a165b39d9d1e696246df37dbe03524
+Subproject commit 2ddf59f369b7e300d5af43c8944dec68ba8edac8

+ 500 - 29
grpc/base_pb.js

@@ -17,10 +17,13 @@ var global = (function() { return this || window || global || self || Function('
 
 var google_protobuf_timestamp_pb = require('google-protobuf/google/protobuf/timestamp_pb.js');
 goog.object.extend(proto, google_protobuf_timestamp_pb);
+var google_protobuf_any_pb = require('google-protobuf/google/protobuf/any_pb.js');
+goog.object.extend(proto, google_protobuf_any_pb);
 goog.exportSymbol('proto.base.v1.BaseMapInfo', null, global);
 goog.exportSymbol('proto.base.v1.CType', null, global);
 goog.exportSymbol('proto.base.v1.ControlInfoList', null, global);
 goog.exportSymbol('proto.base.v1.ControlPoint', null, global);
+goog.exportSymbol('proto.base.v1.ControlPointDisplayInfoSingleChoice', null, global);
 goog.exportSymbol('proto.base.v1.ControlPointInfo', null, global);
 goog.exportSymbol('proto.base.v1.ControlPointSimple', null, global);
 goog.exportSymbol('proto.base.v1.CourseInfo', null, global);
@@ -33,6 +36,7 @@ goog.exportSymbol('proto.base.v1.GetSmsSendLeftTimeReply', null, global);
 goog.exportSymbol('proto.base.v1.GetSmsSendLeftTimeRequest', null, global);
 goog.exportSymbol('proto.base.v1.HeartRate', null, global);
 goog.exportSymbol('proto.base.v1.HrBandType', null, global);
+goog.exportSymbol('proto.base.v1.IdArrRequest', null, global);
 goog.exportSymbol('proto.base.v1.IdRequest', null, global);
 goog.exportSymbol('proto.base.v1.Image', null, global);
 goog.exportSymbol('proto.base.v1.LoginSource', null, global);
@@ -176,6 +180,27 @@ if (goog.DEBUG && !COMPILED) {
    */
   proto.base.v1.MapRoute.displayName = 'proto.base.v1.MapRoute';
 }
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.base.v1.IdArrRequest = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.base.v1.IdArrRequest.repeatedFields_, null);
+};
+goog.inherits(proto.base.v1.IdArrRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.base.v1.IdArrRequest.displayName = 'proto.base.v1.IdArrRequest';
+}
 /**
  * Generated by JsPbCodeGenerator.
  * @param {Array=} opt_data Optional initial data array, typically from a
@@ -407,6 +432,27 @@ if (goog.DEBUG && !COMPILED) {
    */
   proto.base.v1.ControlPointInfo.displayName = 'proto.base.v1.ControlPointInfo';
 }
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.base.v1.ControlPointDisplayInfoSingleChoice.repeatedFields_, null);
+};
+goog.inherits(proto.base.v1.ControlPointDisplayInfoSingleChoice, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.base.v1.ControlPointDisplayInfoSingleChoice.displayName = 'proto.base.v1.ControlPointDisplayInfoSingleChoice';
+}
 /**
  * Generated by JsPbCodeGenerator.
  * @param {Array=} opt_data Optional initial data array, typically from a
@@ -1579,6 +1625,164 @@ proto.base.v1.MapRoute.prototype.setIsnfc = function(value) {
 
 
 
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.base.v1.IdArrRequest.repeatedFields_ = [2];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.base.v1.IdArrRequest.prototype.toObject = function(opt_includeInstance) {
+  return proto.base.v1.IdArrRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.base.v1.IdArrRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.base.v1.IdArrRequest.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    idarrList: (f = jspb.Message.getRepeatedField(msg, 2)) == null ? undefined : f
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.base.v1.IdArrRequest}
+ */
+proto.base.v1.IdArrRequest.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.base.v1.IdArrRequest;
+  return proto.base.v1.IdArrRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.base.v1.IdArrRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.base.v1.IdArrRequest}
+ */
+proto.base.v1.IdArrRequest.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 2:
+      var values = /** @type {!Array<number>} */ (reader.isDelimited() ? reader.readPackedInt32() : [reader.readInt32()]);
+      for (var i = 0; i < values.length; i++) {
+        msg.addIdarr(values[i]);
+      }
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.base.v1.IdArrRequest.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.base.v1.IdArrRequest.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.base.v1.IdArrRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.base.v1.IdArrRequest.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getIdarrList();
+  if (f.length > 0) {
+    writer.writePackedInt32(
+      2,
+      f
+    );
+  }
+};
+
+
+/**
+ * repeated int32 IdArr = 2;
+ * @return {!Array<number>}
+ */
+proto.base.v1.IdArrRequest.prototype.getIdarrList = function() {
+  return /** @type {!Array<number>} */ (jspb.Message.getRepeatedField(this, 2));
+};
+
+
+/**
+ * @param {!Array<number>} value
+ * @return {!proto.base.v1.IdArrRequest} returns this
+ */
+proto.base.v1.IdArrRequest.prototype.setIdarrList = function(value) {
+  return jspb.Message.setField(this, 2, value || []);
+};
+
+
+/**
+ * @param {number} value
+ * @param {number=} opt_index
+ * @return {!proto.base.v1.IdArrRequest} returns this
+ */
+proto.base.v1.IdArrRequest.prototype.addIdarr = function(value, opt_index) {
+  return jspb.Message.addToRepeatedField(this, 2, value, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.base.v1.IdArrRequest} returns this
+ */
+proto.base.v1.IdArrRequest.prototype.clearIdarrList = function() {
+  return this.setIdarrList([]);
+};
+
+
+
 
 
 if (jspb.Message.GENERATE_TO_OBJECT) {
@@ -3053,8 +3257,7 @@ proto.base.v1.ControlPointInfo.prototype.toObject = function(opt_includeInstance
  */
 proto.base.v1.ControlPointInfo.toObject = function(includeInstance, msg) {
   var f, obj = {
-    image: (f = msg.getImage()) && proto.base.v1.NetImage.toObject(includeInstance, f),
-    content: jspb.Message.getFieldWithDefault(msg, 2, "")
+    displayinfo: (f = msg.getDisplayinfo()) && google_protobuf_any_pb.Any.toObject(includeInstance, f)
   };
 
   if (includeInstance) {
@@ -3092,13 +3295,9 @@ proto.base.v1.ControlPointInfo.deserializeBinaryFromReader = function(msg, reade
     var field = reader.getFieldNumber();
     switch (field) {
     case 1:
-      var value = new proto.base.v1.NetImage;
-      reader.readMessage(value,proto.base.v1.NetImage.deserializeBinaryFromReader);
-      msg.setImage(value);
-      break;
-    case 2:
-      var value = /** @type {string} */ (reader.readString());
-      msg.setContent(value);
+      var value = new google_protobuf_any_pb.Any;
+      reader.readMessage(value,google_protobuf_any_pb.Any.deserializeBinaryFromReader);
+      msg.setDisplayinfo(value);
       break;
     default:
       reader.skipField();
@@ -3129,18 +3328,217 @@ proto.base.v1.ControlPointInfo.prototype.serializeBinary = function() {
  */
 proto.base.v1.ControlPointInfo.serializeBinaryToWriter = function(message, writer) {
   var f = undefined;
-  f = message.getImage();
+  f = message.getDisplayinfo();
   if (f != null) {
     writer.writeMessage(
       1,
       f,
-      proto.base.v1.NetImage.serializeBinaryToWriter
+      google_protobuf_any_pb.Any.serializeBinaryToWriter
     );
   }
-  f = message.getContent();
+};
+
+
+/**
+ * optional google.protobuf.Any displayInfo = 1;
+ * @return {?proto.google.protobuf.Any}
+ */
+proto.base.v1.ControlPointInfo.prototype.getDisplayinfo = function() {
+  return /** @type{?proto.google.protobuf.Any} */ (
+    jspb.Message.getWrapperField(this, google_protobuf_any_pb.Any, 1));
+};
+
+
+/**
+ * @param {?proto.google.protobuf.Any|undefined} value
+ * @return {!proto.base.v1.ControlPointInfo} returns this
+*/
+proto.base.v1.ControlPointInfo.prototype.setDisplayinfo = function(value) {
+  return jspb.Message.setWrapperField(this, 1, value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.base.v1.ControlPointInfo} returns this
+ */
+proto.base.v1.ControlPointInfo.prototype.clearDisplayinfo = function() {
+  return this.setDisplayinfo(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.base.v1.ControlPointInfo.prototype.hasDisplayinfo = function() {
+  return jspb.Message.getField(this, 1) != null;
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.repeatedFields_ = [3];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.toObject = function(opt_includeInstance) {
+  return proto.base.v1.ControlPointDisplayInfoSingleChoice.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.base.v1.ControlPointDisplayInfoSingleChoice} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    question: jspb.Message.getFieldWithDefault(msg, 1, ""),
+    image: (f = msg.getImage()) && proto.base.v1.NetImage.toObject(includeInstance, f),
+    answerList: (f = jspb.Message.getRepeatedField(msg, 3)) == null ? undefined : f,
+    rightanswerindex: jspb.Message.getFieldWithDefault(msg, 4, 0),
+    qbid: jspb.Message.getFieldWithDefault(msg, 5, 0)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice}
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.base.v1.ControlPointDisplayInfoSingleChoice;
+  return proto.base.v1.ControlPointDisplayInfoSingleChoice.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.base.v1.ControlPointDisplayInfoSingleChoice} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice}
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setQuestion(value);
+      break;
+    case 2:
+      var value = new proto.base.v1.NetImage;
+      reader.readMessage(value,proto.base.v1.NetImage.deserializeBinaryFromReader);
+      msg.setImage(value);
+      break;
+    case 3:
+      var value = /** @type {string} */ (reader.readString());
+      msg.addAnswer(value);
+      break;
+    case 4:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setRightanswerindex(value);
+      break;
+    case 5:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setQbid(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.base.v1.ControlPointDisplayInfoSingleChoice.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.base.v1.ControlPointDisplayInfoSingleChoice} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getQuestion();
   if (f.length > 0) {
     writer.writeString(
+      1,
+      f
+    );
+  }
+  f = message.getImage();
+  if (f != null) {
+    writer.writeMessage(
       2,
+      f,
+      proto.base.v1.NetImage.serializeBinaryToWriter
+    );
+  }
+  f = message.getAnswerList();
+  if (f.length > 0) {
+    writer.writeRepeatedString(
+      3,
+      f
+    );
+  }
+  f = message.getRightanswerindex();
+  if (f !== 0) {
+    writer.writeInt32(
+      4,
+      f
+    );
+  }
+  f = message.getQbid();
+  if (f !== 0) {
+    writer.writeInt32(
+      5,
       f
     );
   }
@@ -3148,29 +3546,47 @@ proto.base.v1.ControlPointInfo.serializeBinaryToWriter = function(message, write
 
 
 /**
- * optional NetImage image = 1;
+ * optional string question = 1;
+ * @return {string}
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.getQuestion = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice} returns this
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.setQuestion = function(value) {
+  return jspb.Message.setProto3StringField(this, 1, value);
+};
+
+
+/**
+ * optional NetImage image = 2;
  * @return {?proto.base.v1.NetImage}
  */
-proto.base.v1.ControlPointInfo.prototype.getImage = function() {
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.getImage = function() {
   return /** @type{?proto.base.v1.NetImage} */ (
-    jspb.Message.getWrapperField(this, proto.base.v1.NetImage, 1));
+    jspb.Message.getWrapperField(this, proto.base.v1.NetImage, 2));
 };
 
 
 /**
  * @param {?proto.base.v1.NetImage|undefined} value
- * @return {!proto.base.v1.ControlPointInfo} returns this
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice} returns this
 */
-proto.base.v1.ControlPointInfo.prototype.setImage = function(value) {
-  return jspb.Message.setWrapperField(this, 1, value);
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.setImage = function(value) {
+  return jspb.Message.setWrapperField(this, 2, value);
 };
 
 
 /**
  * Clears the message field making it undefined.
- * @return {!proto.base.v1.ControlPointInfo} returns this
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice} returns this
  */
-proto.base.v1.ControlPointInfo.prototype.clearImage = function() {
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.clearImage = function() {
   return this.setImage(undefined);
 };
 
@@ -3179,26 +3595,81 @@ proto.base.v1.ControlPointInfo.prototype.clearImage = function() {
  * Returns whether this field is set.
  * @return {boolean}
  */
-proto.base.v1.ControlPointInfo.prototype.hasImage = function() {
-  return jspb.Message.getField(this, 1) != null;
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.hasImage = function() {
+  return jspb.Message.getField(this, 2) != null;
 };
 
 
 /**
- * optional string content = 2;
- * @return {string}
+ * repeated string answer = 3;
+ * @return {!Array<string>}
  */
-proto.base.v1.ControlPointInfo.prototype.getContent = function() {
-  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.getAnswerList = function() {
+  return /** @type {!Array<string>} */ (jspb.Message.getRepeatedField(this, 3));
+};
+
+
+/**
+ * @param {!Array<string>} value
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice} returns this
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.setAnswerList = function(value) {
+  return jspb.Message.setField(this, 3, value || []);
 };
 
 
 /**
  * @param {string} value
- * @return {!proto.base.v1.ControlPointInfo} returns this
+ * @param {number=} opt_index
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice} returns this
  */
-proto.base.v1.ControlPointInfo.prototype.setContent = function(value) {
-  return jspb.Message.setProto3StringField(this, 2, value);
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.addAnswer = function(value, opt_index) {
+  return jspb.Message.addToRepeatedField(this, 3, value, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice} returns this
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.clearAnswerList = function() {
+  return this.setAnswerList([]);
+};
+
+
+/**
+ * optional int32 rightAnswerIndex = 4;
+ * @return {number}
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.getRightanswerindex = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice} returns this
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.setRightanswerindex = function(value) {
+  return jspb.Message.setProto3IntField(this, 4, value);
+};
+
+
+/**
+ * optional int32 qbId = 5;
+ * @return {number}
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.getQbid = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.base.v1.ControlPointDisplayInfoSingleChoice} returns this
+ */
+proto.base.v1.ControlPointDisplayInfoSingleChoice.prototype.setQbid = function(value) {
+  return jspb.Message.setProto3IntField(this, 5, value);
 };
 
 

+ 202 - 19
grpc/track_offical_grpc_web_pb.js

@@ -325,15 +325,137 @@ proto.to.v1.ApiToPromiseClient.prototype.toSignOut =
  * @const
  * @type {!grpc.web.MethodDescriptor<
  *   !proto.base.v1.DefaultRequest,
+ *   !proto.to.v1.ToMapListReply>}
+ */
+const methodDescriptor_ApiTo_ToMapList = new grpc.web.MethodDescriptor(
+  '/to.v1.ApiTo/ToMapList',
+  grpc.web.MethodType.UNARY,
+  base_pb.DefaultRequest,
+  proto.to.v1.ToMapListReply,
+  /**
+   * @param {!proto.base.v1.DefaultRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.to.v1.ToMapListReply.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.base.v1.DefaultRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.RpcError, ?proto.to.v1.ToMapListReply)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.to.v1.ToMapListReply>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.to.v1.ApiToClient.prototype.toMapList =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/to.v1.ApiTo/ToMapList',
+      request,
+      metadata || {},
+      methodDescriptor_ApiTo_ToMapList,
+      callback);
+};
+
+
+/**
+ * @param {!proto.base.v1.DefaultRequest} request The
+ *     request proto
+ * @param {?Object<string, string>=} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.to.v1.ToMapListReply>}
+ *     Promise that resolves to the response
+ */
+proto.to.v1.ApiToPromiseClient.prototype.toMapList =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/to.v1.ApiTo/ToMapList',
+      request,
+      metadata || {},
+      methodDescriptor_ApiTo_ToMapList);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.base.v1.IdRequest,
+ *   !proto.to.v1.ToMapDetailReply>}
+ */
+const methodDescriptor_ApiTo_ToMapDetail = new grpc.web.MethodDescriptor(
+  '/to.v1.ApiTo/ToMapDetail',
+  grpc.web.MethodType.UNARY,
+  base_pb.IdRequest,
+  proto.to.v1.ToMapDetailReply,
+  /**
+   * @param {!proto.base.v1.IdRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.to.v1.ToMapDetailReply.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.base.v1.IdRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.RpcError, ?proto.to.v1.ToMapDetailReply)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.to.v1.ToMapDetailReply>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.to.v1.ApiToClient.prototype.toMapDetail =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/to.v1.ApiTo/ToMapDetail',
+      request,
+      metadata || {},
+      methodDescriptor_ApiTo_ToMapDetail,
+      callback);
+};
+
+
+/**
+ * @param {!proto.base.v1.IdRequest} request The
+ *     request proto
+ * @param {?Object<string, string>=} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.to.v1.ToMapDetailReply>}
+ *     Promise that resolves to the response
+ */
+proto.to.v1.ApiToPromiseClient.prototype.toMapDetail =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/to.v1.ApiTo/ToMapDetail',
+      request,
+      metadata || {},
+      methodDescriptor_ApiTo_ToMapDetail);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.base.v1.IdRequest,
  *   !proto.to.v1.ToActionListReply>}
  */
 const methodDescriptor_ApiTo_ToActionList = new grpc.web.MethodDescriptor(
   '/to.v1.ApiTo/ToActionList',
   grpc.web.MethodType.UNARY,
-  base_pb.DefaultRequest,
+  base_pb.IdRequest,
   proto.to.v1.ToActionListReply,
   /**
-   * @param {!proto.base.v1.DefaultRequest} request
+   * @param {!proto.base.v1.IdRequest} request
    * @return {!Uint8Array}
    */
   function(request) {
@@ -344,7 +466,7 @@ const methodDescriptor_ApiTo_ToActionList = new grpc.web.MethodDescriptor(
 
 
 /**
- * @param {!proto.base.v1.DefaultRequest} request The
+ * @param {!proto.base.v1.IdRequest} request The
  *     request proto
  * @param {?Object<string, string>} metadata User defined
  *     call metadata
@@ -365,7 +487,7 @@ proto.to.v1.ApiToClient.prototype.toActionList =
 
 
 /**
- * @param {!proto.base.v1.DefaultRequest} request The
+ * @param {!proto.base.v1.IdRequest} request The
  *     request proto
  * @param {?Object<string, string>=} metadata User defined
  *     call metadata
@@ -385,16 +507,16 @@ proto.to.v1.ApiToPromiseClient.prototype.toActionList =
 /**
  * @const
  * @type {!grpc.web.MethodDescriptor<
- *   !proto.base.v1.IdRequest,
+ *   !proto.to.v1.ToActionIdAndCourseIdRequest,
  *   !proto.to.v1.ToActionDetailReply>}
  */
 const methodDescriptor_ApiTo_ToActionDetail = new grpc.web.MethodDescriptor(
   '/to.v1.ApiTo/ToActionDetail',
   grpc.web.MethodType.UNARY,
-  base_pb.IdRequest,
+  proto.to.v1.ToActionIdAndCourseIdRequest,
   proto.to.v1.ToActionDetailReply,
   /**
-   * @param {!proto.base.v1.IdRequest} request
+   * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request
    * @return {!Uint8Array}
    */
   function(request) {
@@ -405,7 +527,7 @@ const methodDescriptor_ApiTo_ToActionDetail = new grpc.web.MethodDescriptor(
 
 
 /**
- * @param {!proto.base.v1.IdRequest} request The
+ * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request The
  *     request proto
  * @param {?Object<string, string>} metadata User defined
  *     call metadata
@@ -426,7 +548,7 @@ proto.to.v1.ApiToClient.prototype.toActionDetail =
 
 
 /**
- * @param {!proto.base.v1.IdRequest} request The
+ * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request The
  *     request proto
  * @param {?Object<string, string>=} metadata User defined
  *     call metadata
@@ -446,16 +568,16 @@ proto.to.v1.ApiToPromiseClient.prototype.toActionDetail =
 /**
  * @const
  * @type {!grpc.web.MethodDescriptor<
- *   !proto.base.v1.IdRequest,
+ *   !proto.to.v1.ToActionIdAndCourseIdRequest,
  *   !proto.to.v1.ToActionUsersDetailReply>}
  */
 const methodDescriptor_ApiTo_ToUsersInGameDetail = new grpc.web.MethodDescriptor(
   '/to.v1.ApiTo/ToUsersInGameDetail',
   grpc.web.MethodType.UNARY,
-  base_pb.IdRequest,
+  proto.to.v1.ToActionIdAndCourseIdRequest,
   proto.to.v1.ToActionUsersDetailReply,
   /**
-   * @param {!proto.base.v1.IdRequest} request
+   * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request
    * @return {!Uint8Array}
    */
   function(request) {
@@ -466,7 +588,7 @@ const methodDescriptor_ApiTo_ToUsersInGameDetail = new grpc.web.MethodDescriptor
 
 
 /**
- * @param {!proto.base.v1.IdRequest} request The
+ * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request The
  *     request proto
  * @param {?Object<string, string>} metadata User defined
  *     call metadata
@@ -487,7 +609,7 @@ proto.to.v1.ApiToClient.prototype.toUsersInGameDetail =
 
 
 /**
- * @param {!proto.base.v1.IdRequest} request The
+ * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request The
  *     request proto
  * @param {?Object<string, string>=} metadata User defined
  *     call metadata
@@ -507,16 +629,77 @@ proto.to.v1.ApiToPromiseClient.prototype.toUsersInGameDetail =
 /**
  * @const
  * @type {!grpc.web.MethodDescriptor<
- *   !proto.base.v1.IdRequest,
+ *   !proto.to.v1.ToActionIdAndCourseIdRequest,
+ *   !proto.to.v1.ToNextControlPointInGameReply>}
+ */
+const methodDescriptor_ApiTo_ToNextControlPointInGame = new grpc.web.MethodDescriptor(
+  '/to.v1.ApiTo/ToNextControlPointInGame',
+  grpc.web.MethodType.UNARY,
+  proto.to.v1.ToActionIdAndCourseIdRequest,
+  proto.to.v1.ToNextControlPointInGameReply,
+  /**
+   * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request
+   * @return {!Uint8Array}
+   */
+  function(request) {
+    return request.serializeBinary();
+  },
+  proto.to.v1.ToNextControlPointInGameReply.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request The
+ *     request proto
+ * @param {?Object<string, string>} metadata User defined
+ *     call metadata
+ * @param {function(?grpc.web.RpcError, ?proto.to.v1.ToNextControlPointInGameReply)}
+ *     callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.to.v1.ToNextControlPointInGameReply>|undefined}
+ *     The XHR Node Readable Stream
+ */
+proto.to.v1.ApiToClient.prototype.toNextControlPointInGame =
+    function(request, metadata, callback) {
+  return this.client_.rpcCall(this.hostname_ +
+      '/to.v1.ApiTo/ToNextControlPointInGame',
+      request,
+      metadata || {},
+      methodDescriptor_ApiTo_ToNextControlPointInGame,
+      callback);
+};
+
+
+/**
+ * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request The
+ *     request proto
+ * @param {?Object<string, string>=} metadata User defined
+ *     call metadata
+ * @return {!Promise<!proto.to.v1.ToNextControlPointInGameReply>}
+ *     Promise that resolves to the response
+ */
+proto.to.v1.ApiToPromiseClient.prototype.toNextControlPointInGame =
+    function(request, metadata) {
+  return this.client_.unaryCall(this.hostname_ +
+      '/to.v1.ApiTo/ToNextControlPointInGame',
+      request,
+      metadata || {},
+      methodDescriptor_ApiTo_ToNextControlPointInGame);
+};
+
+
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ *   !proto.to.v1.ToActionIdAndCourseIdRequest,
  *   !proto.to.v1.ToUserGpsQueryReply>}
  */
 const methodDescriptor_ApiTo_ToUsersInGameGpsQuery = new grpc.web.MethodDescriptor(
   '/to.v1.ApiTo/ToUsersInGameGpsQuery',
   grpc.web.MethodType.UNARY,
-  base_pb.IdRequest,
+  proto.to.v1.ToActionIdAndCourseIdRequest,
   proto.to.v1.ToUserGpsQueryReply,
   /**
-   * @param {!proto.base.v1.IdRequest} request
+   * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request
    * @return {!Uint8Array}
    */
   function(request) {
@@ -527,7 +710,7 @@ const methodDescriptor_ApiTo_ToUsersInGameGpsQuery = new grpc.web.MethodDescript
 
 
 /**
- * @param {!proto.base.v1.IdRequest} request The
+ * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request The
  *     request proto
  * @param {?Object<string, string>} metadata User defined
  *     call metadata
@@ -548,7 +731,7 @@ proto.to.v1.ApiToClient.prototype.toUsersInGameGpsQuery =
 
 
 /**
- * @param {!proto.base.v1.IdRequest} request The
+ * @param {!proto.to.v1.ToActionIdAndCourseIdRequest} request The
  *     request proto
  * @param {?Object<string, string>=} metadata User defined
  *     call metadata

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 505 - 124
grpc/track_offical_pb.js


+ 3 - 1
main.js

@@ -2,6 +2,7 @@
 import Vue from 'vue'
 import App from './App'
 import store from './store'
+import global from './utils/global.js'
 import {
 	ApiToClient
 } from "./grpc/track_offical_grpc_web_pb.js"
@@ -20,6 +21,8 @@ let client = new ApiToClient("http://otapi.beswell.com:10000", null, null)
 
 // 挂载为全局方法 
 Vue.prototype.$client = client
+Vue.prototype.$store = store
+Vue.prototype.$global = global
 
 // #ifdef APP-PLUS
 
@@ -27,7 +30,6 @@ Vue.prototype.$client = client
 import SqliteHelper from './utils/SqliteHelper.js'
 import nfc from './utils/ouu-nfc.js'
 
-Vue.prototype.$store = store
 Vue.prototype.$dbHelper = SqliteHelper
 Vue.prototype.$nfc = nfc
 nfc.listenNFCStatus();

+ 5 - 2
manifest.json

@@ -2,8 +2,8 @@
     "name" : "定向场控",
     "appid" : "__UNI__B2C7D60",
     "description" : "小飞龙定向场控系统",
-    "versionName" : "1.0.6",
-    "versionCode" : 106,
+    "versionName" : "1.0.7",
+    "versionCode" : 107,
     "transformPx" : false,
     "app-plus" : {
         /* 5+App特有相关 */
@@ -116,6 +116,9 @@
             "treeShaking" : {
                 "enable" : true
             }
+        },
+        "devServer" : {
+            "port" : ""
         }
     }
 }

+ 7 - 1
pages.json

@@ -1,9 +1,15 @@
 {
 	"pages": [{
+		"path": "pages/AO/mapList",
+		"style": {
+			"navigationBarTitleText": "地图列表",
+			"enablePullDownRefresh": false
+		}
+	}, {
 		"path": "pages/AO/actionList",
 		"style": {
 			"navigationBarTitleText": "活动列表",
-			"enablePullDownRefresh": true
+			"enablePullDownRefresh": false
 		}
 	}, {
 		"path": "pages/AO/mapShow",

+ 7 - 1
pages/AO/actionList.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="warp">
+	<view class="container" :style="{ height: $global.windowHeight + 'px' }">
 		<!-- <uni-section title="地点列表" type="line">
 			<uni-data-select v-model="placeId" :localdata="placeList" placeholder="请选择地点" @change="handleShopChange"
 				class="padding" />
@@ -89,6 +89,12 @@
 </script>
 
 <style lang="scss">
+	.container {
+		// height: 100vh;
+		// height: 100%;
+		// overflow: hidden;
+	}
+
 	.padding {
 		padding: 0 20rpx;
 	}

+ 0 - 264
pages/AO/checkPointDetail.vue

@@ -1,264 +0,0 @@
-<template>
-	<view class="warp">
-		<uni-card :title="'序号: ' + ciDetail.cicode" :extra="'ID: ' + ciDetail.ciid">
-			<view style="margin: 20rpx 0;">
-				<uni-tag :circle="true" text="系统位置" type="success" size="small"
-					style="font-weight: bold; margin-right: 30rpx;" />
-				<!-- <text style="padding-right: 36rpx;">检查点位置</text> -->
-				<text style="padding-right: 20rpx;"> 经度 {{ ciDetail.position.longitude }} </text>
-				<text>纬度 {{ ciDetail.position.latitude }}</text>
-				<!-- <text>高度 {{ ciDetail.position.altitude }}</text> -->
-			</view>
-			<view style="margin: 20rpx 0;">
-				<uni-tag :circle="true" text="当前位置" type="warning" size="small"
-					style="font-weight: bold; margin-right: 30rpx;" />
-				<!-- <text style="padding-right: 65rpx;">当前位置</text> -->
-				<text style="padding-right: 20rpx;">经度 {{ curPos.longitude }} </text>
-				<text>纬度 {{ curPos.latitude }}</text>
-				<!-- <text>高度 {{ curPos.altitude }}</text> -->
-			</view>
-			<view style="text-align: center; margin-top: 10rpx;">
-				<button @click="getCurPos()" class="mini-btn" type="primary" size="mini"
-					style="margin-right: 50rpx;">获取位置</button>
-				<button @click="savePos()" class="mini-btn" type="primary" size="mini">上报位置</button>
-			</view>
-		</uni-card>
-
-		<uni-section title="NFC列表" type="line">
-			<uni-list v-if="nfcList.length > 0">
-				<!-- <uni-list-item v-for="(item, index) in nfcList" :key="item.id" :title="item.id" :note="item.data"> -->
-				<uni-list-item v-for="(item, index) in nfcList" :key="item" :title="item">
-					<!-- 自定义 footer-->
-					<template v-slot:footer>
-						<button @click="delNfc(index)" class="mini-btn" type="warn" size="mini"
-							style="height: 60rpx;">删除</button>
-					</template>
-				</uni-list-item>
-			</uni-list>
-			<view v-else style="text-align: center;">
-				<text>NFC列表为空</text>
-			</view>
-		</uni-section>
-
-		<view style="text-align: center; margin-top: 30rpx;">
-			<button @click="readNfc()" class="mini-btn" type="primary" size="mini" style="margin-right: 50rpx;">读取
-				NFC</button>
-			<button @click="saveControlInfo()" class="mini-btn" type="primary" size="mini">上报 NFC</button>
-		</view>
-
-		<!-- 提示信息弹窗 -->
-		<uni-popup ref="message" type="message">
-			<uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>
-		</uni-popup>
-	</view>
-</template>
-
-<script>
-	// import nfc from '../../utils/ouu-nfc.js'
-	import {
-		IdRequest,
-		Position,
-	} from "@/grpc/base_pb.js"
-	
-	import {
-		AssControlInfoSaveRequest,
-		AssControlInfoGpsSaveRequest
-	} from "@/grpc/ass_api_pb.js"
-	
-	export default {
-		components: {},
-		data() {
-			return {
-				ciId: 0,
-				ciDetail: {
-					cicode: '',
-					ciid: '',
-					position: {
-						longitude: '',
-						latitude: '',
-						altitude: ''
-					},
-					nfccodelistList: []
-				},
-				nfcList: [],
-				curPos: {
-					longitude: '',
-					latitude: '',
-					altitude: ''
-				},
-				msgType: 'success',
-				messageText: '',
-			}
-		},
-		computed: {},
-		mounted() {
-			// console.log('[checkPointDetail] mounted')
-			
-			// const appAuthorizeSetting = uni.getAppAuthorizeSetting()
-			// console.log(appAuthorizeSetting.locationAuthorized)
-			// console.log(appAuthorizeSetting.locationAccuracy)
-		},
-		onLoad(option) {
-			// console.log('[checkPointDetail] onLoad')
-			// console.log(option.ciId)
-			if (option.ciId > 0) {
-				// nfc.listenNFCStatus()
-
-				this.ciId = option.ciId
-				this.getAssControlInfoDetail()
-				this.getCurPos()
-			}
-		},
-		onShow() {
-			console.log('[checkPointDetail] onShow')
-			uni.$off('NfcRead')
-			uni.$on('NfcRead', this.onNfcRead)
-		},
-		onHide() {
-			console.log('[checkPointDetail] onHide')
-		},
-		beforeDestroy() {
-			console.log('[checkPointDetail] beforeDestroy')
-			uni.$off('NfcRead')
-		},
-		methods: {
-			//msgType: success 成功 / warn 警告 / error 失败 / info 消息
-			messageToggle(messageText = '操作成功', msgType = 'success') {
-				this.msgType = msgType
-				this.messageText = messageText
-				this.$refs.message.open()
-			},
-			getAssControlInfoDetail() {
-				// 创建请求参数并赋值
-				var request = new IdRequest()
-				request.setId(this.ciId)
-				// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
-				this.$client.assControlInfoDetail(request, {}, (err, response) => {
-					if (err) {
-						console.log(`[assControlInfoDetail] err: code = ${err.code}` +
-							`, message = "${err.message}"`)
-						this.messageToggle('获取检查点信息失败', 'error')
-					} else {
-						// console.log(response)
-						let res = response.toObject()
-						console.log(res)
-						this.ciDetail = res
-
-						this.nfcList.length = 0
-						this.nfcList = res.nfccodelistList
-					}
-				});
-			},
-			getCurPos() {
-				let that = this
-				uni.getLocation({
-					type: 'wgs84',
-					// altitude: true,	// 传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度
-					highAccuracyExpireTime: 10000, // 高精度定位超时时间(ms),指定时间内返回最高精度,该值3000ms以上高精度定位才有效果
-					isHighAccuracy: true, // 开启高精度定位
-					success: function(res) {
-						console.log('res:' + JSON.stringify(res))
-						console.log('当前位置的经度:' + res.longitude)
-						console.log('当前位置的纬度:' + res.latitude)
-						// console.log('当前位置的高度:' + res.altitude)
-						
-						that.curPos.longitude = res.longitude
-						that.curPos.latitude = res.latitude
-						// that.curPos.altitude = res.altitude
-					}
-				});
-			},
-			savePos() {
-				// 创建请求参数并赋值
-				var request = new AssControlInfoGpsSaveRequest()
-				request.setCiid(this.ciId)
-				var position = new Position()
-				position.setLongitude(this.curPos.longitude)
-				position.setLatitude(this.curPos.latitude)
-				request.setPosition(position)
-				// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
-				this.$client.assControlInfoGpsSave(request, {}, (err, response) => {
-					if (err) {
-						console.log(`[assControlInfoGpsSave] err: code = ${err.code}` +
-							`, message = "${err.message}"`)
-						this.messageToggle('上报位置信息失败', 'error')
-					} else {
-						// console.log(response)
-						// let res = response.toObject()
-						// console.log(res)
-						this.getAssControlInfoDetail()
-						this.messageToggle('上报位置信息成功')
-					}
-				});
-			},
-			readNfc() {
-				this.$nfc.readData()
-			},
-			onNfcRead(data) {
-				console.log('监听到事件来自 nfcRead, data: ' + JSON.stringify(data))
-
-				let length = this.nfcList.length
-				let find = false
-				for (let i = 0; i < length; i++) {
-					// if (this.nfcList[i].id === data.id) {
-					if (this.nfcList[i] === data.id) {
-						find = true
-					}
-				}
-
-				if (!find) {
-					// this.nfcList.push(data)
-					this.nfcList.push(data.id)
-					console.log(this.nfcList)
-				} else {
-					uni.showToast({
-						title: 'NFC标签 [' + data.id + '] 已存在',
-						icon: 'none',
-						duration: 2000
-					})
-				}
-			},
-			delNfc(index) {
-				let that = this
-				uni.showModal({
-					title: '操作提示',
-					content: '确定删除该记录吗?',
-					success: function(res) {
-						if (res.confirm) {
-							console.log('用户点击确定');
-							that.nfcList.splice(index, 1)
-							that.messageToggle('删除成功')
-						} else if (res.cancel) {
-							console.log('用户点击取消');
-						}
-					}
-				});
-			},
-			saveControlInfo() {
-				// 创建请求参数并赋值
-				var request = new AssControlInfoSaveRequest()
-				request.setCiid(this.ciId)
-				request.setNfccodelistList(this.nfcList)
-				// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
-				this.$client.assControlInfoSave(request, {}, (err, response) => {
-					if (err) {
-						console.log(`[assControlInfoSave] err: code = ${err.code}` +
-							`, message = "${err.message}"`)
-						this.messageToggle('上报NFC信息失败', 'error')
-					} else {
-						console.log(response)
-						// let res = response.toObject()
-						// console.log(res)
-						this.messageToggle('上报NFC信息成功')
-					}
-				});
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
-	.padding {
-		padding: 0 20rpx;
-	}
-</style>

+ 132 - 0
pages/AO/mapList.vue

@@ -0,0 +1,132 @@
+<template>
+	<view class="container" :style="{ height: windowHeight + 'px' }">
+		<uni-section v-if="mapList.length > 0" title="地图列表" type="line">
+			<uni-list>
+				<uni-list-item v-for="item in mapList" :key="item.id" showArrow :title="item.name" :rightText="'活跃人数 ' + item.usernum" :clickable="true"
+					@click="handleItemClick(item.id)" />
+			</uni-list>
+		</uni-section>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState,
+		mapGetters
+	} from 'vuex'
+	import {
+		DefaultRequest,
+		IdRequest
+	} from "@/grpc/base_pb.js"
+
+	export default {
+		components: {},
+		data() {
+			return {
+				interval_loadData: null,
+				windowHeight: 0,
+				mapList: [],
+			}
+		},
+		computed: {
+			...mapState([
+				'username', // 映射 this.username 为 store.state.username
+			]),
+			...mapGetters([
+				'metadata'
+			]),
+		},
+		mounted() {
+			// this.$global.getWindowInfo()
+			// this.windowHeight = this.$global.windowHeight
+			// uni.$on('windowResize', this.layoutInit)
+		},
+		onLoad() {
+		},
+		onShow() {
+			console.log('[onShow]')
+			
+			this.$global.getWindowInfo()
+			this.windowHeight = this.$global.windowHeight
+			uni.$on('windowResize', this.layoutInit)
+			
+			this.loadData()
+		},
+		onHide() {
+			console.log('[onHide]')
+			clearInterval(this.interval_loadData)
+			uni.$off('windowResize', this.layoutInit)
+		},
+		beforeDestroy() {
+			console.log("[beforeDestroy]")
+			clearInterval(this.interval_loadData)
+			uni.$off('windowResize', this.layoutInit)
+		},
+		methods: {
+			layoutInit() {
+				console.log('[layoutInit]')
+				this.windowHeight = this.$global.windowHeight
+			},
+			async loadData() {
+				this.mapList = await this.getToMapList()
+				
+				if (this.interval_loadData != null) {
+					clearInterval(this.interval_loadData)
+				}
+				
+				let that = this
+				this.interval_loadData = setInterval(async function() {
+					that.mapList = await that.getToMapList()
+				}, 3000);
+			},
+			async getToMapList() {
+				try {
+					return new Promise((resolve, reject) => {
+						// 创建请求参数并赋值
+						var request = new DefaultRequest()
+						// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
+						this.$client.toMapList(request, this.metadata, (err,
+							response) => {
+							if (err) {
+								console.warn(`[toMapList] err: code = ${err.code}` +
+									`, message = "${err.message}"`)
+								reject(err)
+							} else {
+								let res = response.toObject()
+								// console.log('[toMapList]', res)
+								resolve(res.listList)
+							}
+						})
+					});
+				} catch (e) {
+					console.log('[getToMapList] err', e)
+					reject(e)
+				}
+			},
+			// handleShopChange(mapId) {
+			// 	console.log("mapId:" + mapId)
+			// 	this.getControlInfoList(mapId)
+			// 	this.getShopMap(mapId)
+			// },
+			handleItemClick(mapId) {
+				console.log("mapId:" + mapId)
+				uni.navigateTo({
+					// url: '/pages/checkPoint/checkPointDetail',
+					url: './mapShow?mapId=' + mapId
+				})
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.container {
+		// height: 100vh;
+		// height: 100%;
+		// overflow: hidden;
+	}
+
+	.padding {
+		padding: 0 20rpx;
+	}
+</style>

+ 390 - 231
pages/AO/mapShow.vue

@@ -1,72 +1,87 @@
 <template>
-	<view class="page" :style="{ height: pageHeight + 'px', flexDirection: flexDirection }">
-		<view id="map" :style="{ height: pageHeight + 'px' }" class='map' />
-
-		<!-- <view class="fab">
-			<uni-fab ref="fab" :pattern="fab.pattern" :content="fab.content" :horizontal="fab.horizontal"
-				:vertical="fab.vertical" :direction="fab.direction" @trigger="trigger" @fabClick="fabClick" />
-		</view> -->
-
-		<view v-show="popupShow" :style="extraIcon" class="popup">
-			<scroll-view :scroll-top="0" scroll-y="true"
-				:style="{ height: popupHeight + 'px', width: popupWidth + 'px' }" class="scroll-Y">
-				<uni-list v-for="(item, index) in players" :key="index" :border="true" class="list">
-					<uni-list-item :clickable="true" @click="onPlayerListItemClick(item)" class="list-item" :class="{ 
+	<view class="page" :style="{ height: windowHeight + 'px', flexDirection: flexDirection }">
+		<view id="map" :style="{ height: mapHeight + 'px', width: mapWidth + 'px' }" class='map' />
+
+		<view v-show="popupShow" class="popup" :style="{ height: popupHeight + 'px', width: popupWidth + 'px' }">
+			<!-- <uni-section title="活动路线列表" type="line"> -->
+				<uni-data-picker class="actionsTree" placeholder="请选择活动" popup-title="请选择活动路线" :localdata="actionsTree"
+					v-model="sltActRoute" @change="onActionChange" @popupopened="onActionsTreePopupOpened" @popupclosed="onActionsTreePopupClosed"></uni-data-picker>
+			<!-- </uni-section> -->
+
+			<!-- <uni-section title="玩家列表" type="line"> -->
+				<scroll-view :scroll-top="0" scroll-y="true" class="scroll-Y" :style="{ height: popupHeight - 35 + 'px'}">
+					<uni-list v-for="(item, index) in players" :key="index" :border="true" class="list">
+						<uni-list-item :clickable="true" @click="onPlayerListItemClick(item)" class="list-item" :class="{ 
 							'list-item-focus': focusPlayerId == item.id 
 							}">
-						<template v-slot:header>
-							<!-- <image class="slot-image" src="/static/logo.png" mode="widthFix"></image> -->
-							<div class="slot-image" :style="'background-color:' + getPlayerColor(item.id)"></div>
-						</template>
-						<template v-slot:body>
-							<view class="slot-box">
-								<view class="slot-title">
-									[{{index+1}}] <span class="slot-phone" @click="onPhoneClick(item.phone)">
-										{{item.name}} </span>
-									打点 {{item.effectivenum}}/{{item.totalcontrolnum}} 距离
-									{{item.distance}}米 配速 {{item.pace}}
+							<template v-slot:header>
+								<!-- <image class="slot-image" src="/static/logo.png" mode="widthFix"></image> -->
+								<div class="slot-image" :style="'background-color:' + getPlayerColor(item.id)"></div>
+							</template>
+							<template v-slot:body>
+								<view class="slot-box">
+									<view class="slot-title">
+										[{{index+1}}] <span class="slot-phone" @click="onPhoneClick(item.phone)">
+											{{item.name}} </span>
+										打点 {{item.effectivenum}}/{{item.totalcontrolnum}} 距离
+										{{item.distance}}米 配速 {{formatTime(item.pace, false)}}
+									</view>
+									<view class="slot-note">
+										心率 {{item.lasthr}} 平均 {{item.avghr}} 最大 {{item.maxhr}} | CAL
+										{{Math.round(item.calorie/1000)}} Ck {{Math.round(item.ck/1000)}} Ei
+										{{Math.round(item.ei*100)/100}}
+									</view>
 								</view>
-								<view class="slot-note">
-									心率 {{item.lasthr}} 平均 {{item.avghr}} 最大 {{item.maxhr}} | CAL
-									{{Math.round(item.calorie/1000)}} Ck {{Math.round(item.ck/1000)}} Ei {{Math.round(item.ei*100)/100}}
-								</view>
-							</view>
-						</template>
-						<!-- <template v-slot:footer>
+							</template>
+							<!-- <template v-slot:footer>
 							<image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
 						</template> -->
-					</uni-list-item>
-				</uni-list>
-			</scroll-view>
+						</uni-list-item>
+					</uni-list>
+				</scroll-view>
+			<!-- </uni-section> -->
 		</view>
 
 	</view>
 </template>
 
 <script>
-	import { mapState, mapGetters } from 'vuex'
+	import {
+		mapState,
+		mapGetters
+	} from 'vuex'
+
 	import {
 		DefaultRequest,
-		IdRequest
+		IdRequest,
 	} from "@/grpc/base_pb.js"
 
+	import {
+		ToActionIdAndCourseIdRequest
+	} from "@/grpc/track_offical_pb.js"
+	
+	import {
+		formatTime
+	} from "@/utils/util.js"
 
 	export default {
 		components: {},
 		data() {
 			return {
-				interval: null,
+				interval_loadActionsTree: null,
+				interval_loadData: null,
+				actionsTreePopup: false,
 
 				systemInfo: null,
-				deviceOrientation: 'portrait', // 设备方向(竖屏 portrait | 横屏 landscape)
 				flexDirection: 'column',
-				pageHeight: 0,
-				pageWidth: 0,
-				// mapHeight: 0,
+				windowHeight: 0,
+				windowWidth: 0,
+				mapHeight: 0,
+				mapWidth: 0,
 				popupHeight: 0,
 				popupWidth: 0,
-				popupHeightPortrait: 300, // 竖屏状态下的底部弹框高度
-				popupWidthlandscape: 390, // 横屏状态下的右侧弹框宽度
+				popupHeightPortrait: 360, // 竖屏状态下的底部弹框高度
+				popupWidthlandscape: 330, // 横屏状态下的右侧弹框宽度
 				popupType: 'bottom',
 				popupShow: false,
 				extraIcon: {
@@ -75,179 +90,248 @@
 					// type: 'gear-filled'
 				},
 
-				actionId: 2,
-				actionDetail: {},
+				mapId: 0,
+				mapDetail: {},
 				mapUrl: null,
 				mapInfo: {},
 
-				map: null,
-				checkPoints: [],
+				actionId: 0,
+				actionDetail: {},
+
+				routeId: 0,
+				routeDetail: {},
+
+				// checkPoints: [],
+				nextCP: [], // 用户即将到达控制点列表
 				players: [],
 				players_position: [],
 				focusPlayerId: 0,
-				trailTime: 90000,
+				trailTime: 0,
+
+				sltActRoute: '',
+				actionsTree: []
 			}
 		},
 		computed: {
 			...mapState([
-				'username',	// 映射 this.username 为 store.state.username
+				'username', // 映射 this.username 为 store.state.username
 			]),
 			...mapGetters([
 				'metadata'
 			]),
 		},
-		mounted() {},
-		onLoad(option) {
-			// console.log('[mapShow] onLoad')
-			// console.log(option.actionId)
-			if (option.actionId > 0) {
-				this.actionId = option.actionId
-				this.loadData(this.actionId)
-			}
-			// 逻辑层中触发自定义事件
-			// uni.$emit('myEvent', {
-			// 	name: 'Uniapp',
-			// 	version: '2.0.0'
-			// })
-		},
-		onReady() {
+		mounted() {
+			this.$global.getWindowInfo()
+			uni.$on('windowResize', this.reLoad)
+			this.popupShow = this.$store.state.mapPopupShow
 			this.layoutInit()
 		},
-		onShow() {
-			// console.log('[onShow]')
-			uni.onWindowResize(res => {
-				// console.log('[onWindowResize]', res)
-				this.layoutInit(res.size)
-			});
+		onLoad(option) {
+			console.log('[onLoad] mapId:' + option.mapId)
+			if (option.mapId > 0) {
+				this.mapId = option.mapId
+				this.loadMap(this.mapId)
+
+				if (this.mapId == this.$store.state.mapSltMapId) { // 页面重载
+					this.sltActRoute = this.$store.state.mapSltActRoute
+					this.loadData(this.sltActRoute)
+				}
+				
+				if (this.interval_loadActionsTree != null) {
+					clearInterval(this.interval_loadActionsTree)
+				}
+				
+				let that = this
+				this.interval_loadActionsTree = setInterval(async function() {
+					if (!that.actionsTreePopup) {
+						await that.loadActionsTree()
+					}
+				}, 3000);
+			}
 		},
 		beforeDestroy() {
-			// console.log("beforeDestroy")
-			clearInterval(this.interval)
+			console.log("[beforeDestroy]")
+			clearInterval(this.interval_loadActionsTree)
+			clearInterval(this.interval_loadData)
 			// leafletHelper.free()
+			uni.$off('windowResize', this.reLoad)
 		},
 		methods: {
-			// 全屏展示
-			fullscreen() {
-				if (document.fullscreenElement || document.webkitFullScreenElement || document.mozFullScreenElement ||
-					document.msFullScreenElement) {
-					// alert('当前是全屏')
-					if (document.webkitCancelFullScreen) {
-						document.webkitCancelFullScreen();
-					} else if (document.mozCancelFullScreen) {
-						document.mozCancelFullScreen();
-					} else if (document.exitFullscreen) {
-						document.exitFullscreen();
-					} else {
-						uni.showToast({
-							title: '浏览器不支持全屏API或已被禁用',
-							icon: 'none'
-						})
-					}
-				} else {
-					let elem = document.body;
-					if (elem.webkitRequestFullScreen) {
-						elem.webkitRequestFullScreen();
-					} else if (elem.mozRequestFullScreen) {
-						elem.mozRequestFullScreen();
-					} else if (elem.requestFullScreen) {
-						elem.requestFullscreen();
-					} else {
-						uni.showToast({
-							title: '浏览器不支持全屏API或已被禁用',
-							icon: 'none'
-						})
-					}
-				}
+			formatTime,
+			reLoad() {
+				this.$store.commit('setMapSltMapId', this.mapId)
+				this.savePlayersData()
+
+				var fullPath = this.$route.fullPath
+				console.log("[windowResize] reLaunch: " + fullPath)
+				uni.redirectTo({
+					url: fullPath
+				});
 			},
 			// 布局初始化 设置地图高度
-			layoutInit(windowSize = '') {
-				var windowHeight, windowWidth
-
-				if (windowSize == '') {
-					this.systemInfo = uni.getSystemInfoSync()
-					// console.log('[layoutInit] systemInfo', this.systemInfo)
-					windowHeight = this.systemInfo.windowHeight
-					windowWidth = this.systemInfo.windowWidth
-				} else {
-					windowHeight = windowSize.windowHeight
-					windowWidth = windowSize.windowWidth
-				}
-				this.pageHeight = windowHeight
-				this.pageWidth = windowWidth
-
-				if (windowHeight > windowWidth) {
-					console.log('[layoutInit] 竖屏')
-					this.deviceOrientation = 'portrait'
+			layoutInit() {
+				this.windowHeight = this.$global.windowHeight
+				this.windowWidth = this.$global.windowWidth
+				if (this.$global.deviceOrientation == 'portrait') { // 竖屏
 					this.flexDirection = 'column'
-					this.popupHeight = this.popupHeightPortrait
-					this.popupWidth = this.pageWidth
+					this.mapWidth = this.$global.windowWidth
+					this.mapHeight = this.$global.windowHeight
 					// if (this.popupShow) {
-					// 	this.mapHeight = this.pageHeight - this.popupHeight
+					// 	this.mapHeight = this.$global.windowHeight - this.popupHeightPortrait
 					// } else {
-					// 	this.mapHeight = this.pageHeight
+					// 	this.mapHeight = this.$global.windowHeight
 					// }
+					// console.log("竖屏", this.mapHeight)
+					this.popupHeight = this.popupHeightPortrait
+					this.popupWidth = this.$global.windowWidth
 				} else { // 横屏
-					console.log('[layoutInit] 横屏')
-					this.deviceOrientation = 'landscape'
 					this.flexDirection = 'row'
-					this.popupHeight = this.pageHeight
+					this.mapHeight = this.$global.windowHeight
+					this.mapWidth = this.$global.windowWidth
+					// if (this.popupShow) {
+					// 	this.mapWidth = this.$global.windowWidth - this.popupWidthlandscape
+					// } else {
+					// 	this.mapWidth = this.$global.windowWidth
+					// }
+					// console.log("横屏", this.mapWidth)
+					this.popupHeight = this.$global.windowHeight
 					this.popupWidth = this.popupWidthlandscape
-					// this.mapHeight = this.pageHeight
+					// console.log("横屏 popupHeight", this.popupHeight)
 				}
-
 			},
 			popupToggle() {
 				this.popupShow = !this.popupShow
-				window.focus()
+				this.$store.commit('setMapPopupShow', this.popupShow)
+				// this.layoutInit()
 			},
 			fullScreenToggle() {
-				this.fullscreen()
+				this.$global.fullscreen()
+				this.$global.getWindowInfo()
 				this.layoutInit()
 			},
-			async loadData() {
-				this.actionDetail = await this.getToActionDetail(this.actionId)
+			makeActionsTree(actselectrsList) {
+				this.actionsTree.length = 0 // 先清空数组
+				for (let i = 0; i < actselectrsList.length; i++) {
+					var act = actselectrsList[i]
+					var pushData = {
+						text: act.actname,
+						value: act.actid,
+						children: []
+					}
+
+					var actUserNum = 0
+					for (let j = 0; j < act.courseselectrsList.length; j++) {
+						var course = act.courseselectrsList[j]
+						actUserNum += course.courseusernum
+						pushData.children.push({
+							text: course.coursename + ' (' + course.courseusernum + '人)',
+							value: act.actid + '-' + course.courseid
+						})
+					}
+					if (actUserNum > 0) {
+						pushData.children.unshift({
+							text: '全部 (' + actUserNum + '人)',
+							value: act.actid + '-' + 0
+						})
+					}
+
+					pushData.text += ' (' + actUserNum + '人)'
+					this.actionsTree.push(pushData)
+				}
+				// console.log("[makeActionsTree]" + JSON.stringify(this.actionsTree))
+			},
+			async loadMap() {
+				await this.loadActionsTree()
 				uni.setNavigationBarTitle({
-					title: this.actionDetail.name
+					title: this.mapDetail.mapinfo.mapname
 				});
 				// console.log(this.actionDetail)
 
 				this.initMap()
-				this.handleMapDrawRoute()
+				this.handleMapToggle()
+			},
+			async loadActionsTree() {
+				this.mapDetail = await this.getToMapDetail(this.mapId)
+				this.makeActionsTree(this.mapDetail.actselectrsList)
+			},
+			async loadData(sltActRoute) {
+				console.log("[loadData] sltActRoute: ", sltActRoute)
+				if (sltActRoute == null || sltActRoute.length == 0) {
+					return
+				}
 
-				if (this.interval != null) {
-					clearInterval(this.interval)
+				var actRouteArr = sltActRoute[1].value.split('-')
+				this.actionId = actRouteArr[0]
+				this.routeId = actRouteArr[1]
+
+				this.actionDetail = await this.getToActionDetail(this.actionId, this.routeId)
+				uni.setNavigationBarTitle({
+					title: this.mapDetail.mapinfo.mapname + ' - ' + this.actionDetail.name
+				});
+				// console.log(this.actionDetail)
+
+				if (this.interval_loadData != null) {
+					clearInterval(this.interval_loadData)
 				}
 
-				let that = this
-				that.players = await that.getToUsersInGameDetail(that.actionId)
+				this.players = await this.getToUsersInGameDetail(this.actionId, this.routeId)
 				// console.log('players', that.players)
 				// leafletHelper.global.setPlayers(this.players)
 
-				that.players_position = await that.getToUsersInGameGpsQuery(that.actionId)
+				this.players_position = await this.getToUsersInGameGpsQuery(this.actionId, this.routeId)
 				// leafletHelper.global.setPlayersPosition(this.players_position)
+				
+				this.nextCP = await this.getToNextControlPointInGame(this.actionId, this.routeId)
+				
+				this.handleMapDrawRoute()
+				this.handleMapDrawPlayer()
+				this.handleMapDrawTrail()
 
-				that.handleMapDrawPlayer()
-				that.handleMapDrawTrail()
-
-				this.interval = setInterval(async function() {
-					that.players = await that.getToUsersInGameDetail(that.actionId)
-					that.players_position = await that.getToUsersInGameGpsQuery(that.actionId)
+				let that = this
+				this.interval_loadData = setInterval(async function() {
+					that.players = await that.getToUsersInGameDetail(that.actionId, that.routeId)
+					that.players_position = await that.getToUsersInGameGpsQuery(that.actionId, that
+						.routeId)
+					that.nextCP = await that.getToNextControlPointInGame(that.actionId, that.routeId)
 					//// leaflet.leafletHelper.global.setPlayers(that.players)
 					// leafletHelper.global.setPlayersPosition(that.players_position)
 					that.handleMapDrawPlayer()
 					that.handleMapDrawTrail()
 				}, 1000);
-
-				// await mapHelper.handleMapInfo(this, this.mapInfo)
-				this.handleMapToggle()
 			},
-			//场控端_活动详情
-			async getToActionDetail(actId) {
+			//场控端_地图详情
+			async getToMapDetail(mapId) {
 				try {
 					return new Promise((resolve, reject) => {
 						// 创建请求参数并赋值
 						var request = new IdRequest()
-						request.setId(actId)
+						request.setId(mapId)
+						// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
+						this.$client.toMapDetail(request, this.metadata, (err, response) => {
+							if (err) {
+								console.warn(`[toMapDetail] err: code = ${err.code}` +
+									`, message = "${err.message}"`)
+								reject(err)
+							} else {
+								let res = response.toObject()
+								// console.log('[toMapDetail]', res)
+								resolve(res)
+							}
+						})
+					});
+				} catch (e) {
+					console.log('[getToMapDetail] err', e)
+					reject(e)
+				}
+			},
+			//场控端_活动详情
+			async getToActionDetail(actId, routeId = 0) {
+				try {
+					return new Promise((resolve, reject) => {
+						// 创建请求参数并赋值
+						var request = new ToActionIdAndCourseIdRequest()
+						request.setActid(actId)
+						request.setCourseid(routeId)
 						// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
 						this.$client.toActionDetail(request, this.metadata, (err, response) => {
 							if (err) {
@@ -267,25 +351,26 @@
 				}
 			},
 			//场控端_正在进行中所有用户实时信息
-			async getToUsersInGameDetail(actId) {
+			async getToUsersInGameDetail(actId, routeId = 0) {
 				try {
 					return new Promise((resolve, reject) => {
 						// 创建请求参数并赋值
-						var request = new IdRequest()
-						request.setId(actId)
+						var request = new ToActionIdAndCourseIdRequest()
+						request.setActid(actId)
+						request.setCourseid(routeId)
 						// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
 						this.$client.toUsersInGameDetail(request, this.metadata, (err,
 							response) => {
-								if (err) {
-									console.warn(`[toUsersInGameDetail] err: code = ${err.code}` +
-										`, message = "${err.message}"`)
-									reject(err)
-								} else {
-									let res = response.toObject()
-									// console.log('[toUsersInGameDetail]', res)
-									resolve(res.usersList)
-								}
-							})
+							if (err) {
+								console.warn(`[toUsersInGameDetail] err: code = ${err.code}` +
+									`, message = "${err.message}"`)
+								reject(err)
+							} else {
+								let res = response.toObject()
+								// console.log('[toUsersInGameDetail]', res)
+								resolve(res.usersList)
+							}
+						})
 					});
 				} catch (e) {
 					console.log('[getToUsersInGameDetail] err', e)
@@ -293,31 +378,78 @@
 				}
 			},
 			//场控端_正在进行中所有用户实时gps查询
-			async getToUsersInGameGpsQuery(actId) {
+			async getToUsersInGameGpsQuery(actId, routeId = 0) {
 				try {
 					return new Promise((resolve, reject) => {
 						// 创建请求参数并赋值
-						var request = new IdRequest()
-						request.setId(actId)
+						var request = new ToActionIdAndCourseIdRequest()
+						request.setActid(actId)
+						request.setCourseid(routeId)
 						// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
 						this.$client.toUsersInGameGpsQuery(request, this.metadata, (err,
 							response) => {
-								if (err) {
-									console.warn(`[toUsersInGameGpsQuery] err: code = ${err.code}` +
-										`, message = "${err.message}"`)
-									reject(err)
-								} else {
-									let res = response.toObject()
-									// console.log('[toUsersInGameGpsQuery]', res)
-									resolve(res.gpsinfoList)
-								}
-							})
+							if (err) {
+								console.warn(`[toUsersInGameGpsQuery] err: code = ${err.code}` +
+									`, message = "${err.message}"`)
+								reject(err)
+							} else {
+								let res = response.toObject()
+								// console.log('[toUsersInGameGpsQuery]', res)
+								resolve(res.gpsinfoList)
+							}
+						})
 					});
 				} catch (e) {
 					console.log('[getToUsersInGameGpsQuery] err', e)
 					reject(e)
 				}
 			},
+			//场控端_正在进行中所有用户即将到达控制点列表,结果去重
+			async getToNextControlPointInGame(actId, routeId = 0) {
+				try {
+					return new Promise((resolve, reject) => {
+						// 创建请求参数并赋值
+						var request = new ToActionIdAndCourseIdRequest()
+						request.setActid(actId)
+						request.setCourseid(routeId)
+						// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
+						this.$client.toNextControlPointInGame(request, this.metadata, (err,
+							response) => {
+							if (err) {
+								console.warn(`[toNextControlPointInGame] err: code = ${err.code}` +
+									`, message = "${err.message}"`)
+								reject(err)
+							} else {
+								let res = response.toObject()
+								// console.log('[toNextControlPointInGame]', res)
+								resolve(res.nextcontrolpointrsList)
+							}
+						})
+					});
+				} catch (e) {
+					console.log('[getToUsersInGameGpsQuery] err', e)
+					reject(e)
+				}
+			},
+			onActionChange(e) {
+				const sltActRoute = e.detail.value
+				console.log("onActionChange", sltActRoute)
+				this.$store.commit('setMapSltActRoute', sltActRoute)
+
+				if (sltActRoute == null || sltActRoute.length == 0) {
+					this.reLoad()
+					return
+				}
+				this.loadData(sltActRoute)
+			},
+			onActionsTreePopupOpened() {
+				// console.log("onActionsTreePopupOpened")
+				this.actionsTreePopup = true
+			},
+			onActionsTreePopupClosed() {
+				// console.log("onActionsTreePopupClosed")
+				this.actionsTreePopup = false
+			},
 			onPlayerListItemClick(item) {
 				// console.log("onListItemClick", item)
 				this.handlePlayerListItemClick(item)
@@ -333,28 +465,7 @@
 						icon: 'none'
 					})
 				}
-			}
-			// trigger(e) {
-			// 	console.log(e)
-			// 	this.content[e.index].active = !e.item.active
-			// 	uni.showModal({
-			// 		title: '提示',
-			// 		content: `您${this.content[e.index].active ? '选中了' : '取消了'}${e.item.text}`,
-			// 		success: function(res) {
-			// 			if (res.confirm) {
-			// 				console.log('用户点击确定')
-			// 			} else if (res.cancel) {
-			// 				console.log('用户点击取消')
-			// 			}
-			// 		}
-			// 	})
-			// },
-			// fabClick() {
-			// 	uni.showToast({
-			// 		title: '点击了悬浮按钮',
-			// 		icon: 'none'
-			// 	})
-			// },
+			},
 		}
 	}
 </script>
@@ -379,7 +490,7 @@
 		// },
 		beforeDestroy() {
 			// console.log("beforeDestroy")
-			// clearInterval(this.interval)
+			// clearInterval(this.interval_loadData)
 			leafletHelper.free()
 		},
 		methods: {
@@ -387,23 +498,34 @@
 			// 	console.log('视图层接收到数据:', data);
 			// },
 			initMap() {
-				// leafletHelper.init(this, 'map', [36.67175772119628, 117.12792580603369], 17)
-
-				// const mapid = this.actionDetail.mapinfo.lid
-				const mapurl = this.actionDetail.mapinfo.mapurl
-				const centPoint = [this.actionDetail.mapinfo.centerlatitude, this.actionDetail.mapinfo.centerlongitude]
-				const zoomNum = this.actionDetail.mapinfo.defscale
-				leafletHelper.init(this, 'map', centPoint, zoomNum)
-				leafletHelper.addMapLayer(mapurl)
+				if (this.mapDetail != null && this.mapDetail.mapinfo != null) {
+					// const mapid = this.mapDetail.mapinfo.lid
+					const mapUrl = this.mapDetail.mapinfo.mapurl
+					const centPoint = [this.mapDetail.mapinfo.centerlatitude, this.mapDetail.mapinfo.centerlongitude]
+					const zoomNum = this.mapDetail.mapinfo.defscale
+					const mapOptions = {
+						center: centPoint,
+						zoom: zoomNum,
+						maxBounds: [
+							[36.659365, 117.105246],
+							[36.653753, 117.122841]
+						],
+					}
+					leafletHelper.init(this, 'map', mapUrl, mapOptions)
+				}
+			},
+			handleWindowResize() {
+				leafletHelper.onWindowResize()
 			},
 			handleMapDrawRoute() {
 				// leafletHelper.global.setCheckPoints(this.checkPoints)
+				// leafletHelper.global.setRoutes(this.mapDetail.routesList)
 				leafletHelper.global.setRoutes(this.actionDetail.routesList)
 
 				// leafletHelper.checkPoint.drawAllCheckPoints()
 				// leafletHelper.checkPoint.drawPath()
 				leafletHelper.route.drawAllRoutes()
-				leafletHelper.route.drawAllPath()
+				// leafletHelper.route.drawAllPath()
 			},
 			handleMapDrawPlayer() {
 				leafletHelper.global.setPlayers(this.players)
@@ -415,6 +537,7 @@
 				leafletHelper.global.dealStaleData()
 			},
 			handleMapDrawTrail() {
+				this.trailTime = leafletHelper.config.trailTime
 				// leafletHelper.player.drawOneTrail(2, 10000)
 				// leafletHelper.player.drawOneTrail(3, 10000)
 				// leafletHelper.player.drawOneTrail(2, 0, false)
@@ -422,10 +545,15 @@
 			},
 			handleMapToggle() {
 				// leafletHelper.checkPoint.toggle(true)
-				leafletHelper.route.toggle(true)
-				leafletHelper.player.togglePlayer(true)
-				leafletHelper.player.toggleTooltip(true)
-				leafletHelper.player.toggleTrail(true)
+				// leafletHelper.route.toggle(true)
+				// leafletHelper.player.togglePlayer(true)
+				// leafletHelper.player.toggleTooltip(true)
+				// leafletHelper.player.toggleTrail(true)
+
+				leafletHelper.route.toggle(this.$store.state.mapControlRoute)
+				leafletHelper.player.togglePlayer(this.$store.state.mapControlPlayer)
+				leafletHelper.player.toggleTooltip(this.$store.state.mapControlTooltip)
+				leafletHelper.player.toggleTrail(this.$store.state.mapControlTrail)
 			},
 			handlePlayerListItemClick(item) {
 				this.focusPlayerId = item.id
@@ -436,7 +564,11 @@
 					return leafletHelper.player.getPlayerColor(playerId)
 				else
 					return leafletHelper.config.gStyle.marker.focus.fillColor
-			}
+			},
+			// 页面reLoad前调用本方法,将用户数据先保存,页面重载后再进行数据恢复
+			savePlayersData() {
+				leafletHelper.global.savePlayersData()
+			},
 		},
 	}
 </script>
@@ -452,7 +584,7 @@
 	:focus-visible {
 		outline: none;
 	}
-	
+
 	.map {
 		flex: 1 1 auto;
 		background-color: white;
@@ -463,9 +595,28 @@
 	}
 
 	.popup {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
 		background-color: #f5f5f5;
-		// border-left: #ff0000 solid 5px;
-		// overflow: hidden;
+		border-left: #dedede solid 1px;
+		// border-top: #dedede solid 1px;
+		// overflow: scroll;
+	}
+	
+	.actionsTree {
+		width: 100%;
+		// background-color: #ffffff;
+		
+		/deep/ .input-value-border {
+		    border-top: 1px solid #e5e5e5;
+		    border-bottom: 1px solid #e5e5e5;
+		    border-radius: 0px;
+		}
+		
+		/deep/ .uni-scroll-view {
+		    overflow: unset !important;
+		}
 	}
 
 	.scroll-Y {
@@ -473,7 +624,7 @@
 	}
 
 	.list {
-		margin-left: 2px;
+		margin-left: -6px;
 	}
 
 	.list-item {
@@ -482,11 +633,11 @@
 		/* #endif */
 		flex-direction: row;
 		align-items: center;
-		height: 60px;
+		height: 46px;
 	}
 
 	.list-item-focus {
-		background-color: #fffaef;
+		background-color: #fffaef !important;
 	}
 
 	.slot-box {
@@ -495,30 +646,39 @@
 		/* #endif */
 		flex-direction: column;
 		align-items: flex-start;
+		max-width: 280px;
 	}
 
 	.slot-image {
 		/* #ifndef APP-NVUE */
 		display: block;
 		/* #endif */
-		margin-right: 10px;
+		margin-right: 6px;
 		width: 6px;
-		height: 39px;
+		height: 33px;
 		align-self: center;
 	}
 
 	.slot-title {
 		flex: 1;
-		font-size: 14px;
+		font-size: 13px;
 		color: #424242;
+		line-height: 18px;
 		// margin-right: 10px;
+		// overflow:hidden; //超出的文本隐藏
+		// text-overflow:ellipsis; //溢出用省略号显示
+		white-space: nowrap; //溢出不换行
 	}
 
 	.slot-note {
 		flex: 1;
-		font-size: 12px;
+		font-size: 12px;		
 		color: #7d8da7;
+		line-height: 18px;
 		// margin-right: 10px;
+		// overflow:hidden; //超出的文本隐藏
+		// text-overflow:ellipsis; //溢出用省略号显示
+		white-space: nowrap; //溢出不换行
 	}
 
 	.slot-phone {
@@ -527,8 +687,7 @@
 		font-weight: bold;
 	}
 
-	// .fab {
-	// 	z-index: 1000;
-	// 	width: 20px;
-	// }
+	/deep/ .uni-data-tree-dialog {
+		top: 39px;
+	}
 </style>

+ 0 - 206
pages/AO/mapShow1.vue

@@ -1,206 +0,0 @@
-<template>
-	<view class="warp">
-		<!-- <button @click="getShopMap(8)">加载地图</button> -->
-		<!-- <button @click="zoomOut()">放大</button><button @click="zoomIn()">缩小</button> -->
-		<movable-area :scale-area="true">
-			
-			<movable-view direction="all" :out-of-bounds="true" @change="handleMovableChange" @scale="handleMovableScale" :scale="true" :scale-min="0.5" :scale-max="10" :scale-value="scale">
-			<!-- <movable-view direction="all" :scale="true" :scale-min="0.5" :scale-max="10" :scale-value="scale"> -->
-				<!-- <canvas canvas-id="mapCanvas" style="width:100%;height:100%;position:absolute;"></canvas> -->
-				<canvas canvas-id="mapCanvas" style="width:100%;height:100%;overflow: hidden;"></canvas>
-				<canvas canvas-id="markerCanvas" style="width:100%;height:100%;position:absolute;z-index:1;"></canvas>
-				<canvas canvas-id="pathCanvas" style="width:100%;height:100%;position:absolute;z-index:2;"></canvas>
-			</movable-view>			
-		</movable-area>
-	</view>
-</template>
-
-<script>
-	import {
-		DefaultRequest,
-		IdRequest
-	} from "@/grpc/base_pb.js"
-
-	import mapHelper from '@/utils/mapHelper'
-
-	export default {
-		components: {},
-		data() {
-			return {
-				scale: 1, // 地图图片的缩放比例
-				translateX: 0, // 地图图片的横向偏移量
-				translateY: 0, // 地图图片的纵向偏移量,
-				windowWidth: uni.getSystemInfoSync().windowWidth, // 可视区域宽度
-				windowHeight: uni.getSystemInfoSync().windowHeight, // 可视区域高度
-				markerX: 100, // 标记位置 x 坐标
-				markerY: 100, // 标记位置 y 坐标
-				path: [
-					[100, 100],
-				], // 运动轨迹点坐标
-
-				shopId: 0,
-				mapUrl: null,
-				mapInfo: {},
-				shopList: [],
-				controlInfoList: []
-			}
-		},
-		computed: {},
-		mounted() {
-		},
-		onLoad() {
-			// this.getShopList()
-			this.getShopMap(8)
-		},
-		methods: {
-			zoomOut() {
-				this.scale++
-				// this.$nextTick(function() {
-				// 	this.scale++
-				// })
-			},
-			zoomIn() {
-				this.scale--
-				// this.$nextTick(function() {
-				// 	this.scale--
-				// })
-			},
-			async getShopMap(shopId) {
-				try {
-					// 创建请求参数并赋值
-					var request = new IdRequest()
-					request.setId(shopId)
-					// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
-					this.$client.assMapInfoDetail(request, {}, async (err, response) => {
-						if (err) {
-							console.log(`[assMapInfoDetail] err: code = ${err.code}` +
-								`, message = "${err.message}"`)
-						} else {
-							let res = response.toObject()
-							console.log('[assMapInfoDetail]', res)
-							this.mapInfo = res
-
-							await mapHelper.handleMapInfo(this, this.mapInfo)
-							this.handleDrawMap()
-						}
-					})
-				} catch (e) {
-					console.log('[getShopMap] err', e)
-				}
-			},
-			handleDrawMap() {
-				this.drawMap();
-				setInterval(() => {
-					// 更新标记位置
-					this.markerX += 10;
-					this.markerY += 10;
-
-					// 更新运动轨迹
-					this.path.push([this.markerX, this.markerY]);
-
-					const markerCtx = uni.createCanvasContext('markerCanvas', this);
-					markerCtx.clearRect(0, 0, this.windowWidth, this.windowHeight);
-					this.drawMarker(markerCtx);
-					markerCtx.draw(false);
-
-					const pathCtx = uni.createCanvasContext('pathCanvas', this);
-					pathCtx.clearRect(0, 0, this.windowWidth, this.windowHeight);
-					this.drawPath(pathCtx);
-					pathCtx.draw(false);
-				}, 1000);
-			},
-			handleMovableChange(e) {
-				console.log("[handleMovableChange] 拖动", e.detail)
-				// this.translateX = e.detail.x;
-				// this.translateY = e.detail.y;
-				// this.drawMap();
-			},
-			handleMovableScale(e) {
-				console.log("[handleMovableScale] 缩放", e.detail)
-				this.scale = e.detail.scale;
-				// this.translateX = (1 - e.detail.scale) * (e.detail.fingers[0].x + e.detail.fingers[1].x) / 2;
-				// this.translateY = (1 - e.detail.scale) * (e.detail.fingers[0].y + e.detail.fingers[1].y) / 2;
-				// this.drawMap();
-			},
-			drawMap() {
-				console.log("[drawMap]", this.mapUrl, this.windowWidth, this.windowHeight)
-				const mapCtx = uni.createCanvasContext('mapCanvas', this);
-				// mapCtx.drawImage('https://ewr1.vultrobjects.com/imgur1/000/001/033/244_7ad_50f.png', 0, 0, this.windowWidth, this.windowHeight-100)
-				mapCtx.drawImage(this.mapUrl, 0, 0, this.windowWidth, this.windowHeight-100)
-				// mapCtx.drawImage(this.mapUrl, 0, 0, this.windowWidth * this.scale, this.windowHeight * this.scale, -this.translateX, -this.translateY, this.windowWidth, this.windowHeight);
-				// mapCtx.drawImage(this.mapUrl, 0, 0, 3113, 3297, -this.translateX, -this.translateY, this.windowWidth, this.windowHeight);
-				mapCtx.draw();
-			},
-			drawMarker(ctx) {
-				// 绘制标记位置
-				ctx.beginPath();
-				ctx.arc(this.markerX, this.markerY, 10/this.scale, 0, 2 * Math.PI);
-				ctx.setFillStyle('#FF0000');
-				ctx.fill();
-				ctx.closePath();
-			},
-			drawPath(ctx) {
-				// 绘制运动轨迹
-				if (this.path.length <= 1) {
-					return;
-				}
-				ctx.beginPath();
-				ctx.setStrokeStyle('#0000FF');
-				ctx.setLineWidth(2/this.scale);
-				ctx.moveTo(this.path[0][0], this.path[0][1]);
-
-				for (let i = 1; i < this.path.length; i++) {
-					ctx.lineTo(this.path[i][0], this.path[i][1]);
-				}
-
-				ctx.stroke();
-				ctx.closePath();
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
-	.padding {
-		padding: 0 20rpx;
-	}
-
-	movable-area {
-		width: 100%;
-		height: 1000px;
-		// background-color: #D8D8D8;
-		overflow: hidden;
-	}
-
-	movable-view {
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		width: 100%;
-		height: 100%;
-		// height: 3000px;
-		// background-color: #007AFF;
-	}
-
-	.mapView {
-		// width: 100%;
-		// height: 300px;
-		// background-color: seagreen;
-	}
-
-	// .mapMovArea {
-	// 	width: 100%;
-	// 	height: 300px;
-	// 	background-color: cadetblue;
-	// }
-	// .mapMovView {
-	// 	width: 50%;
-	// 	height: 300px;
-	// 	background-color: yellow;
-	// }
-	.imageMap {
-		width: 100%;
-		// width: 600px;
-		height: 100%;
-	}
-</style>

+ 0 - 267
pages/AO/mapShow2.vue

@@ -1,267 +0,0 @@
-<template>
-	<view class="warp">
-		<!-- <button @click="getShopMap(8)">加载地图</button> -->
-		<!-- <button @click="zoomOut()">放大</button><button @click="zoomIn()">缩小</button> -->
-		<view style="width:100%;height:1000px;position:relative;" bindtouchstart="handleTouchStart" bindtouchmove="handleTouchMove"
-			bindtouchend="handleTouchEnd">
-			<canvas canvas-id="mapCanvas" style="width:100%;height:100%;overflow:visible;"></canvas>
-			<!-- <canvas canvas-id="mapCanvas"
-				style="position:absolute;top:0;left:0;width:100%;height:1000px;z-index:-1;"></canvas>
-			 --><!-- <canvas canvas-id="markerCanvas"
-				style="position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;"></canvas>
-			<canvas canvas-id="pathCanvas"
-				style="position:absolute;top:0;left:0;width:100%;height:100%;z-index:2;"></canvas> -->
-		</view>
-	</view>
-</template>
-
-<script>
-	import {
-		DefaultRequest,
-		IdRequest
-	} from "@/grpc/base_pb.js"
-
-	import mapHelper from '@/utils/mapHelper'
-
-	export default {
-		components: {},
-		data() {
-			return {
-				scale: 1, // 地图图片的缩放比例
-				offsetX: 0, // 地图图片的横向偏移量
-				offsetY: 0, // 地图图片的纵向偏移量
-				lastX: 0, // 上一次触摸事件的横坐标
-				lastY: 0, // 上一次触摸事件的纵坐标
-
-				windowWidth: uni.getSystemInfoSync().windowWidth, // 可视区域宽度
-				windowHeight: uni.getSystemInfoSync().windowHeight, // 可视区域高度
-				markerX: 100, // 标记位置 x 坐标
-				markerY: 100, // 标记位置 y 坐标
-				path: [
-					[100, 100],
-				], // 运动轨迹点坐标
-
-				shopId: 0,
-				mapUrl: null,
-				mapInfo: {},
-				shopList: [],
-				controlInfoList: []
-			}
-		},
-		computed: {},
-		mounted() {},
-		onLoad() {
-			// this.getShopList()
-			this.getShopMap(8)
-		},
-		methods: {
-			handleTouchStart(e) {
-				this.lastX = e.touches[0].clientX;
-				this.lastY = e.touches[0].clientY;
-			},
-
-			handleTouchMove(e) {
-				const deltaX = e.touches[0].clientX - this.lastX;
-				const deltaY = e.touches[0].clientY - this.lastY;
-				const mapCtx = uni.createCanvasContext('mapCanvas', this);
-				mapCtx.translate(this.offsetX + deltaX, this.offsetY + deltaY);
-				mapCtx.draw(true, () => {
-					this.offsetX += deltaX;
-					this.offsetY += deltaY;
-				});
-				this.lastX = e.touches[0].clientX;
-				this.lastY = e.touches[0].clientY;
-			},
-
-			handleTouchEnd() {
-				// do nothing
-			},
-
-			handleScale(e) {
-				const mapCtx = uni.createCanvasContext('mapCanvas', this);
-				const newScale = this.scale * e.detail.scale;
-				const deltaX = (this.windowWidth * (1 - newScale)) / 2 / newScale;
-				const deltaY = (this.windowHeight * (1 - newScale)) / 2 / newScale;
-				mapCtx.translate(this.offsetX - deltaX, this.offsetY - deltaY);
-				mapCtx.scale(e.detail.scale, e.detail.scale);
-				mapCtx.draw(true, () => {
-					this.offsetX -= deltaX;
-					this.offsetY -= deltaY;
-					this.scale = newScale;
-				});
-			},
-			zoomOut() {
-				this.scale++
-				// this.$nextTick(function() {
-				// 	this.scale++
-				// })
-			},
-			zoomIn() {
-				this.scale--
-				// this.$nextTick(function() {
-				// 	this.scale--
-				// })
-			},
-			async getShopMap(shopId) {
-				try {
-					// 创建请求参数并赋值
-					var request = new IdRequest()
-					request.setId(shopId)
-					// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
-					this.$client.assMapInfoDetail(request, {}, async (err, response) => {
-						if (err) {
-							console.log(`[assMapInfoDetail] err: code = ${err.code}` +
-								`, message = "${err.message}"`)
-						} else {
-							let res = response.toObject()
-							console.log('[assMapInfoDetail]', res)
-							this.mapInfo = res
-
-							await mapHelper.handleMapInfo(this, this.mapInfo)
-							this.handleDrawMap()
-						}
-					})
-				} catch (e) {
-					console.log('[getShopMap] err', e)
-				}
-			},
-			handleDrawMap() {
-				this.drawMap();
-				// setInterval(() => {
-				// 	// 更新标记位置
-				// 	this.markerX += 10;
-				// 	this.markerY += 10;
-
-				// 	// 更新运动轨迹
-				// 	this.path.push([this.markerX, this.markerY]);
-
-				// 	const markerCtx = uni.createCanvasContext('markerCanvas', this);
-				// 	markerCtx.clearRect(0, 0, this.windowWidth, this.windowHeight);
-				// 	this.drawMarker(markerCtx);
-				// 	markerCtx.draw(false);
-
-				// 	const pathCtx = uni.createCanvasContext('pathCanvas', this);
-				// 	pathCtx.clearRect(0, 0, this.windowWidth, this.windowHeight);
-				// 	this.drawPath(pathCtx);
-				// 	pathCtx.draw(false);
-				// }, 1000);
-			},
-			handleMovableChange(e) {
-				console.log("[handleMovableChange] 拖动", e.detail)
-				// this.translateX = e.detail.x;
-				// this.translateY = e.detail.y;
-				// this.drawMap();
-			},
-			handleMovableScale(e) {
-				console.log("[handleMovableScale] 缩放", e.detail)
-				// this.scale = e.detail.scale;
-				// this.translateX = (1 - e.detail.scale) * (e.detail.fingers[0].x + e.detail.fingers[1].x) / 2;
-				// this.translateY = (1 - e.detail.scale) * (e.detail.fingers[0].y + e.detail.fingers[1].y) / 2;
-				// this.drawMap();
-			},
-			drawMap() {
-				console.log("[drawMap]", this.mapUrl, this.windowWidth, this.windowHeight)
-				const mapCtx = uni.createCanvasContext('mapCanvas', this);
-				mapCtx.drawImage(this.mapUrl, 0, 0, this.windowWidth, this.windowHeight-100)
-				// mapCtx.drawImage('https://ewr1.vultrobjects.com/imgur1/000/001/033/244_7ad_50f.png', 0, 0, this.windowWidth, this.windowHeight-100)
-				mapCtx.draw();
-				
-				// const mapImg = new Image();
-				// mapImg.src = this.mapUrl;
-				// mapImg.onload = () => {
-				// 	mapCtx.drawImage(mapImg, 0, 0, this.windowWidth, this.windowHeight);
-				// 	// mapCtx.draw(false, () => {
-				// 	// 	setInterval(() => {
-				// 	// 		const markerCtx = uni.createCanvasContext('markerCanvas', this);
-				// 	// 		markerCtx.clearRect(0, 0, this.windowWidth, this.windowHeight);
-				// 	// 		this.drawMarker(markerCtx);
-				// 	// 		markerCtx.draw(false);
-
-				// 	// 		const pathCtx = uni.createCanvasContext('pathCanvas', this);
-				// 	// 		pathCtx.clearRect(0, 0, this.windowWidth, this.windowHeight);
-				// 	// 		this.drawPath(pathCtx);
-				// 	// 		pathCtx.draw(false);
-				// 	// 	}, 1000);
-				// 	// });
-				// };
-
-				// const mapCtx = uni.createCanvasContext('mapCanvas', this);
-				// mapCtx.drawImage(this.mapUrl, 0, 0, this.windowWidth, this.windowHeight-100)
-				// // mapCtx.drawImage(this.mapUrl, 0, 0, this.windowWidth * this.scale, this.windowHeight * this.scale, -this.translateX, -this.translateY, this.windowWidth, this.windowHeight);
-				// // mapCtx.drawImage(this.mapUrl, 0, 0, 3113, 3297, -this.translateX, -this.translateY, this.windowWidth, this.windowHeight);
-				// mapCtx.draw();
-			},
-			drawMarker(ctx) {
-				// 绘制标记位置
-				ctx.beginPath();
-				ctx.arc(this.markerX, this.markerY, 10, 0, 2 * Math.PI);
-				ctx.setFillStyle('#FF0000');
-				ctx.fill();
-				ctx.closePath();
-			},
-			drawPath(ctx) {
-				// 绘制运动轨迹
-				if (this.path.length <= 1) {
-					return;
-				}
-
-				ctx.beginPath();
-				ctx.setStrokeStyle('#0000FF');
-				ctx.setLineWidth(2);
-				ctx.moveTo(this.path[0][0], this.path[0][1]);
-
-				for (let i = 1; i < this.path.length; i++) {
-					ctx.lineTo(this.path[i][0], this.path[i][1]);
-				}
-
-				ctx.stroke();
-				ctx.closePath();
-			}
-		}
-	}
-</script>
-
-<style lang="scss">
-	.padding {
-		padding: 0 20rpx;
-	}
-
-	movable-area {
-		width: 100%;
-		height: 1000px;
-		// background-color: #D8D8D8;
-		overflow: hidden;
-	}
-
-	movable-view {
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		width: 100%;
-		height: 100%;
-		// height: 3000px;
-		// background-color: #007AFF;
-	}
-
-	.mapView {
-		// width: 100%;
-		// height: 300px;
-		// background-color: seagreen;
-	}
-
-	// .mapMovArea {
-	// 	width: 100%;
-	// 	height: 300px;
-	// 	background-color: cadetblue;
-	// }
-	// .mapMovView {
-	// 	width: 50%;
-	// 	height: 300px;
-	// 	background-color: yellow;
-	// }
-	.imageMap {
-		width: 100%;
-		// width: 600px;
-		height: 100%;
-	}
-</style>

+ 72 - 6
store/index.js

@@ -1,13 +1,29 @@
 import Vue from 'vue'
 import Vuex from 'vuex'
 
-Vue.use(Vuex); //vue的插件机制
+Vue.use(Vuex) //vue的插件机制
 
 //Vuex.Store 构造器选项
 const store = new Vuex.Store({
 	state: { //存放状态
-		username: "admin",
+		username: 'admin',
 		token: 'c74d427b805beeb5501345f87f1a55af',
+		fullScreen: false,
+		
+		// 场控地图页
+		// mapReload: false, // 页面是否重载 true: 需恢复暂存数据 false: 无需恢复暂存数据
+		mapPopupShow: false,
+		mapControlRoute: true,
+		mapControlPlayer: true,
+		mapControlTooltip: true,
+		mapControlTrail: true,
+		mapSltMapId: 0, // 存储用户选择的地图ID
+		mapSltActRoute: '', // 存储用户选择的活动路线信息 格式:活动ID-路线ID 例如:3-1 (0代表全部)
+		holdTime: null, // 暂存时间 用于数据过期管理
+		holdPlayersData: [{ // 暂存玩家数据 用于reload页面后重新恢复数据
+			id: 0, // 玩家ID
+			trailData: [], // 玩家轨迹信息(数据会追加并定时清理过期数据)
+		}],
 	},
 	getters: {
 		metadata: state => {
@@ -18,12 +34,62 @@ const store = new Vuex.Store({
 	},
 	mutations: {
 		setUsername(state, username) {
-            state.username = username;
-            console.log("[setUsername] state.username = " + username);
+            state.username = username
+            console.log("[setUsername] state.username = " + username)
         },
 		setToken(state, token) {
-		    state.token = token;
-		    console.log("[setUsername] state.token = " + token);
+		    state.token = token
+		    console.log("[setUsername] state.token = " + token)
+		},
+		setFullScreen(state, fullScreen) {
+		    state.fullScreen = fullScreen
+		    console.log("[setFullScreen] state.fullScreen = " + fullScreen)
+		},
+		
+		// setMapReload(state, mapReload) {
+		//     state.mapReload = mapReload
+		//     console.log("[setMapReload] state.mapReload = " + mapReload)
+		// },
+		setMapPopupShow(state, mapPopupShow) {
+		    state.mapPopupShow = mapPopupShow
+		    console.log("[setMapPopupShow] state.mapPopupShow = " + mapPopupShow)
+		},
+		setMapControlRoute(state, mapControlRoute) {
+		    state.mapControlRoute = mapControlRoute
+		    console.log("[setMapControlRoute] state.mapControlRoute = " + mapControlRoute)
+		},
+		setMapControlPlayer(state, mapControlPlayer) {
+		    state.mapControlPlayer = mapControlPlayer
+		    console.log("[setMapControlPlayer] state.mapControlPlayer = " + mapControlPlayer)
+		},
+		setMapControlTooltip(state, mapControlTooltip) {
+		    state.mapControlTooltip = mapControlTooltip
+		    console.log("[setUsername] state.mapControlTooltip = " + mapControlTooltip)
+		},
+		setMapControlTrail(state, mapControlTrail) {
+		    state.mapControlTrail = mapControlTrail
+		    console.log("[setMapControlTrail] state.mapControlTrail = " + mapControlTrail)
+		},
+		setMapSltMapId(state, mapSltMapId) {
+		    state.mapSltMapId = mapSltMapId
+		    console.log("[setMapSltMapId] state.mapSltMapId = " + mapSltMapId)
+		},
+		setMapSltActRoute(state, mapSltActRoute) {
+		    state.mapSltActRoute = mapSltActRoute
+		    console.log("[setMapSltActRoute] state.mapSltActRoute = " + mapSltActRoute)
+		},
+		
+		setHoldTime(state, holdTime) {
+		    state.holdTime = holdTime
+		    console.log("[setHoldTime] state.holdTime = " + holdTime)
+		},
+		pushHoldPlayersData(state, playerData) {
+		    state.holdPlayersData.push(playerData)
+		    console.log("[pushHoldPlayersData] state.holdPlayersData.push ", playerData)
+		},
+		clearHoldPlayersData(state) {
+		    state.holdPlayersData.length = 0 // 清空数组
+		    console.log("[clearHoldPlayersData] 清空 state.holdPlayersData")
 		},
 	}
 })

+ 2 - 0
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
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
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": [
     "",

+ 13 - 7
uni_modules/uni-calendar/changelog.md

@@ -1,20 +1,26 @@
+## 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
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: {

+ 24 - 20
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,16 @@
 			/**
 			 * 回到今天
 			 */
-			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}`
+
+        if(nowYearMonth !== todayYearMonth) {
+          this.monthSwitch()
+        }
+
+				this.init(date.fullDate)
 				this.change()
 			},
 			/**
@@ -446,7 +451,6 @@
 
 	.uni-calendar--fixed-width {
 		width: 50px;
-		// padding: 0 15px;
 	}
 
 	.uni-calendar__backtoday {

+ 12 - 2
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
uni_modules/uni-calendar/package.json

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

+ 3 - 3
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)

+ 1 - 1
uni_modules/uni-combox/components/uni-combox/uni-combox.vue

@@ -148,7 +148,7 @@
 	}
 </script>
 
-<style lang="scss" >
+<style lang="scss" scoped>
 	.uni-combox {
 		font-size: 14px;
 		border: 1px solid #DCDFE6;

+ 9 - 0
uni_modules/uni-data-picker/changelog.md

@@ -1,3 +1,12 @@
+## 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)

+ 544 - 540
uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue

@@ -1,547 +1,551 @@
 <template>
-  <view class="uni-data-tree">
-    <view class="uni-data-tree-input" @click="handleInput">
-      <slot :options="options" :data="inputSelected" :error="errorMessage">
-        <view class="input-value" :class="{'input-value-border': border}">
-          <text v-if="errorMessage" class="selected-area error-text">{{errorMessage}}</text>
-          <view v-else-if="loading && !isOpened" class="selected-area">
-            <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
-          </view>
-          <scroll-view v-else-if="inputSelected.length" class="selected-area" scroll-x="true">
-            <view class="selected-list">
-              <view class="selected-item" v-for="(item,index) in inputSelected" :key="index">
-                <text class="text-color">{{item.text}}</text><text v-if="index<inputSelected.length-1"
-                  class="input-split-line">{{split}}</text>
-              </view>
-            </view>
-          </scroll-view>
-          <text v-else class="selected-area placeholder">{{placeholder}}</text>
-          <view v-if="clearIcon && !readonly && inputSelected.length" class="icon-clear" @click.stop="clear">
-            <uni-icons type="clear" color="#c0c4cc" size="24"></uni-icons>
-          </view>
-          <view class="arrow-area" v-if="(!clearIcon || !inputSelected.length) && !readonly ">
-            <view class="input-arrow"></view>
-          </view>
-        </view>
-      </slot>
-    </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="title-area">
-          <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>
-      <data-picker-view class="picker-view" ref="pickerView" v-model="dataValue" :localdata="localdata"
-        :preload="preload" :collection="collection" :field="field" :orderby="orderby" :where="where"
-        :step-searh="stepSearh" :self-field="selfField" :parent-field="parentField" :managed-mode="true" :map="map"
-        :ellipsis="ellipsis" @change="onchange" @datachange="ondatachange" @nodeclick="onnodeclick">
-      </data-picker-view>
-    </view>
-  </view>
+	<view class="uni-data-tree">
+		<view class="uni-data-tree-input" @click="handleInput">
+			<slot :options="options" :data="inputSelected" :error="errorMessage">
+				<view class="input-value" :class="{'input-value-border': border}">
+					<text v-if="errorMessage" class="selected-area error-text">{{errorMessage}}</text>
+					<view v-else-if="loading && !isOpened" class="selected-area">
+						<uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
+					</view>
+					<scroll-view v-else-if="inputSelected.length" class="selected-area" scroll-x="true">
+						<view class="selected-list">
+							<view class="selected-item" v-for="(item,index) in inputSelected" :key="index">
+								<text class="text-color">{{item.text}}</text><text v-if="index<inputSelected.length-1"
+									class="input-split-line">{{split}}</text>
+							</view>
+						</view>
+					</scroll-view>
+					<text v-else class="selected-area placeholder">{{placeholder}}</text>
+					<view v-if="clearIcon && !readonly && inputSelected.length" class="icon-clear" @click.stop="clear">
+						<uni-icons type="clear" color="#c0c4cc" size="24"></uni-icons>
+					</view>
+					<view class="arrow-area" v-if="(!clearIcon || !inputSelected.length) && !readonly ">
+						<view class="input-arrow"></view>
+					</view>
+				</view>
+			</slot>
+		</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="title-area">
+					<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>
+			<data-picker-view class="picker-view" ref="pickerView" v-model="dataValue" :localdata="localdata"
+				:preload="preload" :collection="collection" :field="field" :orderby="orderby" :where="where"
+				:step-searh="stepSearh" :self-field="selfField" :parent-field="parentField" :managed-mode="true"
+				:map="map" :ellipsis="ellipsis" @change="onchange" @datachange="ondatachange" @nodeclick="onnodeclick">
+			</data-picker-view>
+		</view>
+	</view>
 </template>
 
 <script>
-  import dataPicker from "../uni-data-pickerview/uni-data-picker.js"
-  import DataPickerView from "../uni-data-pickerview/uni-data-pickerview.vue"
-
-  /**
-   * 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', 'input', 'change', 'update:modelValue'],
-    mixins: [dataPicker],
-    components: {
-      DataPickerView
-    },
-    props: {
-      options: {
-        type: [Object, Array],
-        default () {
-          return {}
-        }
-      },
-      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,
-        inputSelected: []
-      }
-    },
-    created() {
-      this.$nextTick(() => {
-        this.load();
-      })
-    },
-    methods: {
-      clear() {
-        this.modelValue = null;
-        this._dispatchEvent([]);
-      },
-      onPropsChange() {
-        this._treeData = [];
-        this.selectedIndex = 0;
-
-        this.load();
-      },
-      load() {
-        if (this.readonly) {
-          this._processReadonly(this.localdata, this.dataValue);
-          return;
-        }
-
-        if (!this.hasValue) {
-          return;
-        }
-
-        // 回显本地数据
-        if (this.isLocalData) {
-          this.loadData();
-          this.inputSelected = this.selected.slice(0);
-        } else if (this.isCloudDataList || this.isCloudDataTree) { // 回显 Cloud 数据
-          this.loading = true;
-          this.getCloudDataValue().then((res) => {
-            this.loading = false;
-            this.inputSelected = res;
-          }).catch((err) => {
-            this.loading = false;
-            this.errorMessage = err;
-          })
-        }
-      },
-      show() {
-        this.isOpened = true
-        setTimeout(() => {
-          this.$refs.pickerView.updateData({
-            treeData: this._treeData,
-            selected: this.selected,
-            selectedIndex: this.selectedIndex
-          })
-        }, 200)
-        this.$emit('popupopened')
-      },
-      hide() {
-        this.isOpened = false
-        this.$emit('popupclosed')
-      },
-      handleInput() {
-        if (this.readonly) {
-          return
-        }
-        this.show()
-      },
-      handleClose(e) {
-        this.hide()
-      },
-      onnodeclick(e) {
-        this.$emit('nodeclick', e)
-      },
-      ondatachange(e) {
-        this._treeData = this.$refs.pickerView._treeData
-      },
-      onchange(e) {
-        this.hide()
-        this.$nextTick(() => {
-          this.inputSelected = e;
-        })
-        this._dispatchEvent(e)
-      },
-      _processReadonly(dataList, value) {
-        var isTree = dataList.findIndex((item) => {
-          return item.children
-        })
-        if (isTree > -1) {
-          let inputValue
-          if (Array.isArray(value)) {
-            inputValue = value[value.length - 1]
-            if (typeof inputValue === 'object' && inputValue.value) {
-              inputValue = inputValue.value
-            }
-          } else {
-            inputValue = value
-          }
-          this.inputSelected = this._findNodePath(inputValue, this.localdata)
-          return
-        }
-
-        if (!this.hasValue) {
-          this.inputSelected = []
-          return
-        }
-
-        let result = []
-        for (let i = 0; i < value.length; i++) {
-          var val = value[i]
-          var item = dataList.find((v) => {
-            return v.value == val
-          })
-          if (item) {
-            result.push(item)
-          }
-        }
-        if (result.length) {
-          this.inputSelected = result
-        }
-      },
-      _filterForArray(data, valueArray) {
-        var result = []
-        for (let i = 0; i < valueArray.length; i++) {
-          var value = valueArray[i]
-          var found = data.find((item) => {
-            return item.value == value
-          })
-          if (found) {
-            result.push(found)
-          }
-        }
-        return result
-      },
-      _dispatchEvent(selected) {
-        let item = {}
-        if (selected.length) {
-          var value = new Array(selected.length)
-          for (var i = 0; i < selected.length; i++) {
-            value[i] = selected[i].value
-          }
-          item = selected[selected.length - 1]
-        } else {
-          item.value = ''
-        }
-        if (this.formItem) {
-          this.formItem.setValue(item.value)
-        }
-
-        this.$emit('input', item.value)
-        this.$emit('update:modelValue', item.value)
-        this.$emit('change', {
-          detail: {
-            value: selected
-          }
-        })
-      }
-    }
-  }
+	import dataPicker from "../uni-data-pickerview/uni-data-picker.js"
+	import DataPickerView from "../uni-data-pickerview/uni-data-pickerview.vue"
+
+	/**
+	 * 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', 'input', 'change', 'update:modelValue', 'inputclick'],
+		mixins: [dataPicker],
+		components: {
+			DataPickerView
+		},
+		props: {
+			options: {
+				type: [Object, Array],
+				default () {
+					return {}
+				}
+			},
+			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,
+				inputSelected: []
+			}
+		},
+		created() {
+			this.$nextTick(() => {
+				this.load();
+			})
+		},
+		watch: {
+			localdata: {
+				handler() {
+					this.load()
+				},
+				deep: true
+			},
+		},
+		methods: {
+			clear() {
+				this._dispatchEvent([]);
+			},
+			onPropsChange() {
+				this._treeData = [];
+				this.selectedIndex = 0;
+
+				this.load();
+			},
+			load() {
+				if (this.readonly) {
+					this._processReadonly(this.localdata, this.dataValue);
+					return;
+				}
+
+				// 回显本地数据
+				if (this.isLocalData) {
+					this.loadData();
+					this.inputSelected = this.selected.slice(0);
+				} else if (this.isCloudDataList || this.isCloudDataTree) { // 回显 Cloud 数据
+					this.loading = true;
+					this.getCloudDataValue().then((res) => {
+						this.loading = false;
+						this.inputSelected = res;
+					}).catch((err) => {
+						this.loading = false;
+						this.errorMessage = err;
+					})
+				}
+			},
+			show() {
+				this.isOpened = true
+				setTimeout(() => {
+					this.$refs.pickerView.updateData({
+						treeData: this._treeData,
+						selected: this.selected,
+						selectedIndex: this.selectedIndex
+					})
+				}, 200)
+				this.$emit('popupopened')
+			},
+			hide() {
+				this.isOpened = false
+				this.$emit('popupclosed')
+			},
+			handleInput() {
+				if (this.readonly) {
+					this.$emit('inputclick')
+					return
+				}
+				this.show()
+			},
+			handleClose(e) {
+				this.hide()
+			},
+			onnodeclick(e) {
+				this.$emit('nodeclick', e)
+			},
+			ondatachange(e) {
+				this._treeData = this.$refs.pickerView._treeData
+			},
+			onchange(e) {
+				this.hide()
+				this.$nextTick(() => {
+					this.inputSelected = e;
+				})
+				this._dispatchEvent(e)
+			},
+			_processReadonly(dataList, value) {
+				var isTree = dataList.findIndex((item) => {
+					return item.children
+				})
+				if (isTree > -1) {
+					let inputValue
+					if (Array.isArray(value)) {
+						inputValue = value[value.length - 1]
+						if (typeof inputValue === 'object' && inputValue.value) {
+							inputValue = inputValue.value
+						}
+					} else {
+						inputValue = value
+					}
+					this.inputSelected = this._findNodePath(inputValue, this.localdata)
+					return
+				}
+
+				if (!this.hasValue) {
+					this.inputSelected = []
+					return
+				}
+
+				let result = []
+				for (let i = 0; i < value.length; i++) {
+					var val = value[i]
+					var item = dataList.find((v) => {
+						return v.value == val
+					})
+					if (item) {
+						result.push(item)
+					}
+				}
+				if (result.length) {
+					this.inputSelected = result
+				}
+			},
+			_filterForArray(data, valueArray) {
+				var result = []
+				for (let i = 0; i < valueArray.length; i++) {
+					var value = valueArray[i]
+					var found = data.find((item) => {
+						return item.value == value
+					})
+					if (found) {
+						result.push(found)
+					}
+				}
+				return result
+			},
+			_dispatchEvent(selected) {
+				let item = {}
+				if (selected.length) {
+					var value = new Array(selected.length)
+					for (var i = 0; i < selected.length; i++) {
+						value[i] = selected[i].value
+					}
+					item = selected[selected.length - 1]
+				} else {
+					item.value = ''
+				}
+				if (this.formItem) {
+					this.formItem.setValue(item.value)
+				}
+
+				this.$emit('input', item.value)
+				this.$emit('update:modelValue', item.value)
+				this.$emit('change', {
+					detail: {
+						value: selected
+					}
+				})
+			}
+		}
+	}
 </script>
 
 <style>
-  .uni-data-tree {
-    flex: 1;
-    position: relative;
-    font-size: 14px;
-  }
-
-  .error-text {
-    color: #DD524D;
-  }
-
-  .input-value {
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    flex-direction: row;
-    align-items: center;
-    flex-wrap: nowrap;
-    font-size: 14px;
-    /* line-height: 35px; */
-    padding: 0 10px;
-    padding-right: 5px;
-    overflow: hidden;
-    height: 35px;
-    /* #ifndef APP-NVUE */
-    box-sizing: border-box;
-    /* #endif */
-  }
-
-  .input-value-border {
-    border: 1px solid #e5e5e5;
-    border-radius: 5px;
-  }
-
-  .selected-area {
-    flex: 1;
-    overflow: hidden;
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    flex-direction: row;
-  }
-
-  .load-more {
-    /* #ifndef APP-NVUE */
-    margin-right: auto;
-    /* #endif */
-    /* #ifdef APP-NVUE */
-    width: 40px;
-    /* #endif */
-  }
-
-  .selected-list {
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    flex-direction: row;
-    flex-wrap: nowrap;
-    /* padding: 0 5px; */
-  }
-
-  .selected-item {
-    flex-direction: row;
-    /* padding: 0 1px; */
-    /* #ifndef APP-NVUE */
-    white-space: nowrap;
-    /* #endif */
-  }
-
-  .text-color {
-    color: #333;
-  }
-
-  .placeholder {
-    color: grey;
-    font-size: 12px;
-  }
-
-  .input-split-line {
-    opacity: .5;
-  }
-
-  .arrow-area {
-    position: relative;
-    width: 20px;
-    /* #ifndef APP-NVUE */
-    margin-bottom: 5px;
-    margin-left: auto;
-    display: flex;
-    /* #endif */
-    justify-content: center;
-    transform: rotate(-45deg);
-    transform-origin: center;
-  }
-
-  .input-arrow {
-    width: 7px;
-    height: 7px;
-    border-left: 1px solid #999;
-    border-bottom: 1px solid #999;
-  }
-
-  .uni-data-tree-cover {
-    position: fixed;
-    left: 0;
-    top: 0;
-    right: 0;
-    bottom: 0;
-    background-color: rgba(0, 0, 0, .4);
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    flex-direction: column;
-    z-index: 100;
-  }
-
-  .uni-data-tree-dialog {
-    position: fixed;
-    left: 0;
-    /* #ifndef APP-NVUE */
-    top: 20%;
-    /* #endif */
-    /* #ifdef APP-NVUE */
-    top: 200px;
-    /* #endif */
-    right: 0;
-    bottom: 0;
-    background-color: #FFFFFF;
-    border-top-left-radius: 10px;
-    border-top-right-radius: 10px;
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    flex-direction: column;
-    z-index: 102;
-    overflow: hidden;
-    /* #ifdef APP-NVUE */
-    width: 750rpx;
-    /* #endif */
-  }
-
-  .dialog-caption {
-    position: relative;
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    flex-direction: row;
-    /* border-bottom: 1px solid #f0f0f0; */
-  }
-
-  .title-area {
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    align-items: center;
-    /* #ifndef APP-NVUE */
-    margin: auto;
-    /* #endif */
-    padding: 0 10px;
-  }
-
-  .dialog-title {
-    /* font-weight: bold; */
-    line-height: 44px;
-  }
-
-  .dialog-close {
-    position: absolute;
-    top: 0;
-    right: 0;
-    bottom: 0;
-    /* #ifndef APP-NVUE */
-    display: flex;
-    /* #endif */
-    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);
-  }
-
-  .picker-view {
-    flex: 1;
-    overflow: hidden;
-  }
-
-  .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;
-    }
-
-    .icon-clear {
-      /* margin-right: 5px; */
-    }
-  }
-
-  /* #endif */
-
-  /* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */
-  /* #ifndef APP-NVUE */
-  .uni-popper__arrow,
-  .uni-popper__arrow::after {
-    position: absolute;
-    display: block;
-    width: 0;
-    height: 0;
-    border-color: transparent;
-    border-style: solid;
-    border-width: 6px;
-  }
-
-  .uni-popper__arrow {
-    filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
-    top: -6px;
-    left: 10%;
-    margin-right: 3px;
-    border-top-width: 0;
-    border-bottom-color: #EBEEF5;
-  }
-
-  .uni-popper__arrow::after {
-    content: " ";
-    top: 1px;
-    margin-left: -6px;
-    border-top-width: 0;
-    border-bottom-color: #fff;
-  }
-
-  /* #endif */
-</style>
+	.uni-data-tree {
+		flex: 1;
+		position: relative;
+		font-size: 14px;
+	}
+
+	.error-text {
+		color: #DD524D;
+	}
+
+	.input-value {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		flex-wrap: nowrap;
+		font-size: 14px;
+		/* line-height: 35px; */
+		padding: 0 10px;
+		padding-right: 5px;
+		overflow: hidden;
+		height: 35px;
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+	}
+
+	.input-value-border {
+		border: 1px solid #e5e5e5;
+		border-radius: 5px;
+	}
+
+	.selected-area {
+		flex: 1;
+		overflow: hidden;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.load-more {
+		/* #ifndef APP-NVUE */
+		margin-right: auto;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		width: 40px;
+		/* #endif */
+	}
+
+	.selected-list {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex-wrap: nowrap;
+		/* padding: 0 5px; */
+	}
+
+	.selected-item {
+		flex-direction: row;
+		/* padding: 0 1px; */
+		/* #ifndef APP-NVUE */
+		white-space: nowrap;
+		/* #endif */
+	}
+
+	.text-color {
+		color: #333;
+	}
+
+	.placeholder {
+		color: grey;
+		font-size: 12px;
+	}
+
+	.input-split-line {
+		opacity: .5;
+	}
+
+	.arrow-area {
+		position: relative;
+		width: 20px;
+		/* #ifndef APP-NVUE */
+		margin-bottom: 5px;
+		margin-left: auto;
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		transform: rotate(-45deg);
+		transform-origin: center;
+	}
+
+	.input-arrow {
+		width: 7px;
+		height: 7px;
+		border-left: 1px solid #999;
+		border-bottom: 1px solid #999;
+	}
+
+	.uni-data-tree-cover {
+		position: fixed;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		background-color: rgba(0, 0, 0, .4);
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		z-index: 100;
+	}
+
+	.uni-data-tree-dialog {
+		position: fixed;
+		left: 0;
+		/* #ifndef APP-NVUE */
+		top: 20%;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		top: 200px;
+		/* #endif */
+		right: 0;
+		bottom: 0;
+		background-color: #FFFFFF;
+		border-top-left-radius: 10px;
+		border-top-right-radius: 10px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		z-index: 102;
+		overflow: hidden;
+		/* #ifdef APP-NVUE */
+		width: 750rpx;
+		/* #endif */
+	}
+
+	.dialog-caption {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		/* border-bottom: 1px solid #f0f0f0; */
+	}
+
+	.title-area {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		/* #ifndef APP-NVUE */
+		margin: auto;
+		/* #endif */
+		padding: 0 10px;
+	}
+
+	.dialog-title {
+		/* font-weight: bold; */
+		line-height: 44px;
+	}
+
+	.dialog-close {
+		position: absolute;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		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);
+	}
+
+	.picker-view {
+		flex: 1;
+		overflow: hidden;
+	}
+
+	.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;
+		}
+
+		.icon-clear {
+			/* margin-right: 5px; */
+		}
+	}
+
+	/* #endif */
+
+	/* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */
+	/* #ifndef APP-NVUE */
+	.uni-popper__arrow,
+	.uni-popper__arrow::after {
+		position: absolute;
+		display: block;
+		width: 0;
+		height: 0;
+		border-color: transparent;
+		border-style: solid;
+		border-width: 6px;
+	}
+
+	.uni-popper__arrow {
+		filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+		top: -6px;
+		left: 10%;
+		margin-right: 3px;
+		border-top-width: 0;
+		border-bottom-color: #EBEEF5;
+	}
+
+	.uni-popper__arrow::after {
+		content: " ";
+		top: 1px;
+		margin-left: -6px;
+		border-top-width: 0;
+		border-bottom-color: #fff;
+	}
+
+	/* #endif */
+</style>

+ 17 - 15
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>

+ 1 - 1
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": "1.1.2",
   "description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景",
   "keywords": [
     "uni-ui",

+ 13 - 0
uni_modules/uni-data-select/changelog.md

@@ -1,3 +1,16 @@
+## 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)

+ 132 - 55
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-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,6 +124,14 @@
 				return placeholder ?
 					common + placeholder :
 					common
+			},
+			valueCom(){
+				// #ifdef VUE3
+				return this.modelValue;
+				// #endif
+				// #ifndef VUE3
+				return this.value;
+				// #endif
 			}
 		},
 		watch: {
@@ -124,16 +143,9 @@
 					}
 				}
 			},
-			// #ifndef VUE3
-			value() {
-				this.initDefVal()
-			},
-			// #endif
-			// #ifdef VUE3
-			modelValue() {
+			valueCom(val, old) {
 				this.initDefVal()
 			},
-			// #endif
 			mixinDatacomResData: {
 				immediate: true,
 				handler(val) {
@@ -144,27 +156,46 @@
 			}
 		},
 		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 +220,7 @@
 			clearVal() {
 				this.emit('')
 				if (this.collection) {
-					uni.removeStorageSync(this.last)
+					this.removeCache()
 				}
 			},
 			change(item) {
@@ -200,18 +231,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 +252,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 +319,9 @@
 		display: flex;
 		align-items: center;
 		// padding: 15px;
+		/* #ifdef H5 */
 		cursor: pointer;
+		/* #endif */
 		width: 100%;
 		flex: 1;
 		box-sizing: border-box;
@@ -297,10 +365,10 @@
 		flex: 1;
 		height: 35px;
 
-    &--disabled{
-      background-color: #f5f7fa;
-      cursor: not-allowed;
-    }
+		&--disabled {
+			background-color: #f5f7fa;
+			cursor: not-allowed;
+		}
 	}
 
 	.uni-select__label {
@@ -357,6 +425,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 +512,6 @@
 		bottom: 0;
 		right: 0;
 		left: 0;
+		z-index: 2;
 	}
 </style>

+ 1 - 1
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.6",
   "description": "通过数据驱动的下拉框选择器",
   "keywords": [
     "uni-ui",

+ 67 - 33
uni_modules/uni-datetime-picker/changelog.md

@@ -1,41 +1,75 @@
+## 2.2.23(2023-05-02)
+- 修复 部分情况修改时间,开始时间未更新 [详情](https://github.com/dcloudio/uni-ui/issues/737)
+- 修复 部分平台及设备第一次点击无法显示弹框
+- 修复 ios 日期格式未补零显示及使用异常 [详情](https://ask.dcloud.net.cn/question/162979)
+## 2.2.22(2023-03-30)
+- 修复 日历 picker 修改年月后,自动选中当月1日 [详情](https://ask.dcloud.net.cn/question/165937)
+- 修复 小程序端 低版本 ios NaN [详情](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 属性支持配置选择器打开时默认显示的时间
+- 优化 非范围选择未选择日期时间,点击确认按钮选中当前日期时间
+- 优化 字节小程序日期时间范围选择,底部日期换行问题
+## 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 +77,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 +131,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
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%;

+ 141 - 127
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: '',
@@ -228,13 +232,14 @@
 				tempRange: {
 					before: '',
 					after: ''
-				}
+				},
+        isPhone: false
 			}
 		},
 		watch: {
 			date: {
 				immediate: true,
-				handler(newVal, oldVal) {
+				handler(newVal) {
 					if (!this.range) {
 						this.tempSingleDate = newVal
 						setTimeout(() => {
@@ -245,33 +250,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 +310,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 +330,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,18 +387,22 @@
 		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
 		},
+    mounted(){
+      if(typeof navigator !== "undefined"){
+        this.isPhone = navigator.userAgent.toLowerCase().indexOf('mobile') !== -1
+        return
+      }
+      const { windowWidth } = uni.getSystemInfoSync()
+      this.isPhone = windowWidth <= 500
+    },
 		methods: {
 			leaveCale() {
 				this.firstEnter = true
@@ -407,14 +430,9 @@
 				const [yearB, monthB] = B.split('-')
 				return yearA === yearB && monthA === monthB
 			},
-
-			// 取消穿透
-			clean() {
-				this.close()
-			},
-
 			// 蒙版点击事件
 			maskClick() {
+        this.close()
 				this.$emit('maskClose')
 			},
 
@@ -433,33 +451,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 +501,6 @@
 				// 弹窗模式并且清理数据
 				if (this.clearDate && !this.insert) {
 					this.cale.cleanMultipleStatus()
-					// this.cale.setDate(this.date)
 					this.init(this.date)
 				}
 				this.show = true
@@ -521,12 +554,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 +578,6 @@
 					time: this.time,
 					timeRange: this.timeRange,
 					fulldate: fullDate,
-					lunar,
 					extraInfo: extraInfo || {}
 				})
 			},
@@ -553,10 +593,10 @@
 				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) {
+        // 这里返回的 before after 为什么要做替换?导致PC端如果开始结束日期都是今天,第一次选择开始日期早于今天,开始日期不更新
+				if (beforeDate > afterDate && afterDate && !this.isPhone) {
 					this.tempRange.before = this.cale.multipleStatus.after
 					this.tempRange.after = this.cale.multipleStatus.before
 				} else {
@@ -565,46 +605,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 +865,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
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 - 28
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 没有时分秒, 则不限制
@@ -752,7 +740,7 @@
 			 */
 			initTimePicker() {
 				if (this.disabled) return
-				const value = this.fixIosDateFormat(this.value)
+				const value = fixIosDateFormat(this.time)
 				this.initPickerValue(value)
 				this.visible = !this.visible
 			},

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 335 - 282
uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue


+ 186 - 193
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
 	}
 
+  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)
+    }
+    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)
+    }
+    return this.getDateObj(date)
+  }
+
 	/**
-	 * 获取任意时间
+	 * 获取指定格式Date对象
 	 */
-	getDate(date, AddDayCount = 0, str = 'day') {
-		if (!date) {
-			date = new Date()
-		}
-		if (typeof date !== 'object') {
-			date = date.replace(/-/g, '/')
-		}
-		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
-		}
-		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
+	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,52 @@ 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 +181,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 +231,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 +240,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
@@ -306,7 +262,7 @@ class Calendar {
 				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 +272,28 @@ class Calendar {
 				this.lastHover = true
 			}
 		}
-		this._getWeek(fullDate)
+		this.getWeeks(fullDate)
 	}
 
 	/**
 	 *  鼠标 hover 更新多选状态
 	 */
 	setHoverMultiple(fullDate) {
-		let {
-			before,
-			after
-		} = this.multipleStatus
+    if (!this.range || this.lastHover) return
 
-		if (!this.range) return
-		if (this.lastHover) return
+		const { before } = this.multipleStatus
 
 		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)
 	}
 
 	/**
@@ -351,12 +303,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 +317,87 @@ 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)
-			}
-			weeks[parseInt(i / 7)][i % 7] = canlender[i]
+		} = 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[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)}`
+}
+
+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)}`
+}
 
-	//静态方法
-	// static init(date) {
-	// 	if (!this.instance) {
-	// 		this.instance = new Calendar(date);
-	// 	}
-	// 	return this.instance;
-	// }
+function addZero(num) {
+  if(num < 10){
+    num = `0${num}`
+  }
+  return num
 }
 
+function getDefaultSecond(hideSecond) {
+  return hideSecond ? '00:00' : '00:00:00'
+}
+
+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)
+}
+
+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 default Calendar
+export {Calendar, getDateTime, getDate, getTime, addZero, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat}

+ 1 - 1
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.23",
   "description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择",
   "keywords": [
     "uni-datetime-picker",

+ 1 - 1
uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue

@@ -105,7 +105,7 @@
 	}
 </script>
 
-<style lang="scss" >
+<style lang="scss" scoped>
 	$uni-mask: rgba($color: #000000, $alpha: 0.4) ;
 	// 抽屉宽度
 	$drawer-width: 220px;

+ 12 - 1
uni_modules/uni-easyinput/changelog.md

@@ -1,10 +1,21 @@
+## 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)
 

+ 115 - 137
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,12 @@
 				:maxlength="inputMaxlength"
 				:focus="focused"
 				:autoHeight="autoHeight"
+				:cursor-spacing="cursorSpacing"
 				@input="onInput"
 				@blur="_Blur"
 				@focus="_Focus"
 				@confirm="onConfirm"
+        @keyboardheightchange="onkeyboardheightchange"
 			></textarea>
 			<input
 				v-else
@@ -52,10 +37,12 @@
 				:maxlength="inputMaxlength"
 				:focus="focused"
 				:confirmType="confirmType"
+				:cursor-spacing="cursorSpacing"
 				@focus="_Focus"
 				@blur="_Blur"
 				@input="onInput"
 				@confirm="onConfirm"
+        @keyboardheightchange="onkeyboardheightchange"
 			/>
 			<template v-if="type === 'password' && passwordIcon">
 				<!-- 开启密码时显示小眼睛 -->
@@ -67,20 +54,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 +101,7 @@
  * @property {String}	suffixIcon	输入框尾部图标
  * @property {String}	primaryColor	设置主题色(默认#2979ff)
  * @property {Boolean}	trim	是否自动去除两端的空格
+ * @property {Boolean}	cursorSpacing	指定光标与键盘的距离,单位 px
  * @value both	去除两端空格
  * @value left	去除左侧空格
  * @value right	去除右侧空格
@@ -139,12 +117,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 +131,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 +139,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 +164,97 @@ 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
 		},
 		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 +283,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 +324,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 +348,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 +360,7 @@ export default {
 		 * @param {Object} type
 		 */
 		onClickIcon(type) {
-			this.$emit("iconClick", type);
+			this.$emit('iconClick', type);
 		},
 
 		/**
@@ -405,7 +368,7 @@ export default {
 		 */
 		onEyes() {
 			this.showPassword = !this.showPassword;
-			this.$emit("eyes", this.showPassword);
+			this.$emit('eyes', this.showPassword);
 		},
 
 		/**
@@ -416,19 +379,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 +403,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 +418,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 +442,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 +455,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
uni_modules/uni-easyinput/package.json

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

+ 2 - 0
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
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
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",

+ 4 - 0
uni_modules/uni-file-picker/changelog.md

@@ -1,3 +1,7 @@
+## 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)

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

@@ -7,7 +7,7 @@ function chooseImage(opts) {
 	const {
 		count,
 		sizeType = ['original', 'compressed'],
-		sourceType = ['album', 'camera'],
+		sourceType,
 		extension
 	} = opts
 	return new Promise((resolve, reject) => {
@@ -33,7 +33,7 @@ function chooseVideo(opts) {
 		camera,
 		compressed,
 		maxDuration,
-		sourceType = ['album', 'camera'],
+		sourceType,
 		extension
 	} = opts;
 	return new Promise((resolve, reject) => {

+ 12 - 1
uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue

@@ -185,6 +185,12 @@
 				default () {
 					return ['original', 'compressed']
 				}
+			},
+			sourceType: {
+				type: Array,
+				default () {
+					return  ['album', 'camera']
+				}
 			}
 		},
 		data() {
@@ -349,6 +355,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
@@ -576,7 +583,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
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.4",
   "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"],

+ 2 - 0
uni_modules/uni-forms/changelog.md

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

+ 2 - 6
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>
@@ -126,7 +126,6 @@
 		data() {
 			return {
 				errMsg: '',
-				isRequired: false,
 				userRules: null,
 				localLabelAlign: 'left',
 				localLabelWidth: '65px',
@@ -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) {

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

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

+ 1 - 1
uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue

@@ -68,7 +68,7 @@
 	}
 </script>
 
-<style lang="scss" >
+<style lang="scss" scoped>
 	.uni-grid-item {
 		/* #ifndef APP-NVUE */
 		height: 100%;

+ 1 - 1
uni_modules/uni-grid/components/uni-grid/uni-grid.vue

@@ -106,7 +106,7 @@
 	}
 </script>
 
-<style lang="scss" >
+<style lang="scss" scoped>
 	.uni-grid-wrap {
 		/* #ifndef APP-NVUE */
 		display: flex;

+ 1 - 1
uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue

@@ -53,7 +53,7 @@
 	}
 </script>
 
-<style lang="scss" >
+<style lang="scss" scoped>
 	.uni-indexed-list__list {
 		background-color: $uni-bg-color;
 		/* #ifndef APP-NVUE */

+ 2 - 2
uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue

@@ -140,7 +140,7 @@
 			setList() {
 				let index = 0;
 				this.lists = []
-				this.options.forEach((value) => {
+				this.options.forEach((value, index) => {
 					if (value.data.length === 0) {
 						return
 					}
@@ -282,7 +282,7 @@
 		}
 	}
 </script>
-<style lang="scss" >
+<style lang="scss" scoped>
 	.uni-indexed-list {
 		position: absolute;
 		left: 0;

+ 26 - 0
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
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
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
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
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
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
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
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
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
uni_modules/uni-number-box/changelog.md

@@ -1,3 +1,5 @@
+## 1.2.2(2023-05-08)
+- 修复 change 事件执行顺序错误的问题
 ## 1.2.1(2021-11-22)
 - 修复 vue3中某些scss变量无法找到的问题
 ## 1.2.0(2021-11-19)

+ 2 - 2
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)

+ 4 - 7
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.2",
   "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"],

+ 8 - 0
uni_modules/uni-popup/changelog.md

@@ -1,3 +1,11 @@
+## 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)

+ 5 - 1
uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue

@@ -10,7 +10,7 @@
 		</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" v-model="val" :type="inputType" :placeholder="placeholderText" :focus="focus" >
 			</slot>
 		</view>
 		<view class="uni-dialog-button-group">
@@ -57,6 +57,10 @@
 		mixins: [popup],
 		emits:['confirm','close'],
 		props: {
+			inputType:{
+				type: String,
+				default: 'text'
+			},
 			value: {
 				type: [String, Number],
 				default: ''

+ 3 - 9
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: {
@@ -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
uni_modules/uni-popup/package.json

@@ -1,7 +1,7 @@
 {
 	"id": "uni-popup",
 	"displayName": "uni-popup 弹出层",
-	"version": "1.7.9",
+	"version": "1.8.3",
 	"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": [

+ 1 - 1
uni_modules/uni-row/components/uni-col/uni-col.vue

@@ -212,7 +212,7 @@
 	}
 </script>
 
-<style lang='scss' >
+<style lang='scss' scoped>
 	/* breakpoints */
 	$--sm: 768px !default;
 	$--md: 992px !default;

+ 1 - 1
uni_modules/uni-row/components/uni-row/uni-row.vue

@@ -180,7 +180,7 @@
 	}
 
 	// 字节、QQ配置后不生效
-	// 此处用法无法使用
+	// 此处用法无法使用scoped
 	/* #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ */
 	:host {
 		display: block;

+ 2 - 0
uni_modules/uni-search-bar/changelog.md

@@ -1,3 +1,5 @@
+## 1.2.4(2023-05-09)
+- 修复 i18n 国际化不正确的 Bug
 ## 1.2.3(2022-05-24)
 - 新增 readonly 属性,组件只读
 ## 1.2.2(2022-05-06)

+ 1 - 1
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
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": "請輸入搜索內容"
 }

+ 1 - 1
uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue

@@ -80,7 +80,7 @@
 			},
 			cancelText: {
 				type: String,
-				default: '取消'
+				default: ""
 			},
 			bgColor: {
 				type: String,

+ 4 - 7
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.4",
   "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": [

+ 1 - 1
uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue

@@ -87,7 +87,7 @@
 	}
 </script>
 
-<style lang="scss" >
+<style lang="scss" scoped>
 	.segmented-control {
 		/* #ifndef APP-NVUE */
 		display: flex;

+ 2 - 0
uni_modules/uni-swipe-action/changelog.md

@@ -1,3 +1,5 @@
+## 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
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
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) {

+ 4 - 3
uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js

@@ -36,7 +36,7 @@ otherMixins = {
 	},
 	mounted() {
 		this.swipeaction = this.getSwipeAction()
-		if (this.swipeaction.children !== undefined) {
+		if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
 			this.swipeaction.children.push(this)
 		}
 		this.init()
@@ -53,8 +53,9 @@ otherMixins = {
 		},
 
 		closeSwipe(e) {
-			if (!this.autoClose) return
-			this.swipeaction.closeOther(this)
+			if (this.autoClose && this.swipeaction) {
+				this.swipeaction.closeOther(this)
+			}
 		},
 		appTouchStart(e) {
 			const {

+ 4 - 3
uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js

@@ -21,7 +21,7 @@ mpMixins = {
 	},
 	created() {
 		this.swipeaction = this.getSwipeAction()
-		if (this.swipeaction.children !== undefined) {
+		if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
 			this.swipeaction.children.push(this)
 		}
 	},
@@ -31,8 +31,9 @@ mpMixins = {
 	methods: {
 		// wxs 中调用
 		closeSwipe(e) {
-			if (!this.autoClose) return
-			this.swipeaction.closeOther(this)
+			if (this.autoClose && this.swipeaction) {
+				this.swipeaction.closeOther(this)
+			}
 		},
 
 		change(e) {

+ 5 - 8
uni_modules/uni-swipe-action/package.json

@@ -1,7 +1,7 @@
 {
 	"id": "uni-swipe-action",
 	"displayName": "uni-swipe-action 滑动操作",
-	"version": "1.3.7",
+	"version": "1.3.8",
 	"description": "SwipeAction 滑动操作操作组件",
 	"keywords": [
         "",
@@ -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": ["uni-scss"],

+ 1 - 1
uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue

@@ -120,7 +120,7 @@
 	}
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 	.uni-swiper__warp {
 		/* #ifndef APP-NVUE */
 		display: flex;

+ 4 - 0
uni_modules/uni-table/changelog.md

@@ -1,3 +1,7 @@
+## 1.2.3(2023-03-28)
+- 修复 在vue3模式下可能会出现错误的问题
+## 1.2.2(2022-11-29)
+- 优化 主题样式
 ## 1.2.1(2022-06-06)
 - 修复 微信小程序存在无使用组件的问题
 ## 1.2.0(2021-11-19)

+ 3 - 3
uni_modules/uni-table/components/uni-table/uni-table.vue

@@ -3,9 +3,9 @@
 		<!-- #ifdef H5 -->
 		<table class="uni-table" border="0" cellpadding="0" cellspacing="0" :class="{ 'table--stripe': stripe }" :style="{ 'min-width': minWidth + 'px' }">
 			<slot></slot>
-			<view v-if="noData" class="uni-table-loading">
-				<view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view>
-			</view>
+			<tr v-if="noData" class="uni-table-loading">
+				<td class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</td>
+			</tr>
 			<view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view>
 		</table>
 		<!-- #endif -->

+ 16 - 8
uni_modules/uni-table/components/uni-th/filter-dropdown.vue

@@ -112,6 +112,12 @@
 						value: 'value'
 					}
 				}
+			},
+			filterDefaultValue: {
+				type: [Array,String],
+				default () {
+					return ""
+				}
 			}
 		},
 		computed: {
@@ -157,7 +163,7 @@
 				enabled: true,
 				isOpened: false,
 				dataList: [],
-				filterValue: '',
+				filterValue: this.filterDefaultValue,
 				checkedValues: [],
 				gtValue: '',
 				ltValue: '',
@@ -286,6 +292,8 @@
 </script>
 
 <style lang="scss">
+	$uni-primary: #1890ff !default;
+	
 	.flex-r {
 		display: flex;
 		flex-direction: row;
@@ -315,8 +323,8 @@
 	}
 
 	.icon-select.active {
-		background-color: #1890ff;
-		border-top-color: #1890ff;
+		background-color: $uni-primary;
+		border-top-color: $uni-primary;
 	}
 
 	.icon-search {
@@ -343,11 +351,11 @@
 	}
 
 	.icon-search.active .icon-search-0 {
-		border-color: #1890ff;
+		border-color: $uni-primary;
 	}
 
 	.icon-search.active .icon-search-1 {
-		background-color: #1890ff;
+		background-color: $uni-primary;
 	}
 
 	.icon-calendar {
@@ -387,14 +395,14 @@
 	}
 
 	.icon-calendar.active {
-		color: #1890ff;
+		color: $uni-primary;
 	}
 
 	.icon-calendar.active .icon-calendar-0,
 	.icon-calendar.active .icon-calendar-1,
 	.icon-calendar.active .icon-calendar-0:before,
 	.icon-calendar.active .icon-calendar-0:after {
-		background-color: #1890ff;
+		background-color: $uni-primary;
 	}
 
 	.uni-filter-dropdown {
@@ -497,7 +505,7 @@
 	}
 
 	.btn-submit {
-		background-color: #1890ff;
+		background-color: $uni-primary;
 		color: #ffffff;
 	}
 </style>

+ 10 - 3
uni_modules/uni-table/components/uni-th/uni-th.vue

@@ -9,7 +9,7 @@
 					<text class="arrow down" :class="{ active: descending }" @click.stop="descendingFn"></text>
 				</view>
 			</view>
-			<dropdown v-if="filterType || filterData.length" :filterData="filterData" :filterType="filterType" @change="ondropdown"></dropdown>
+			<dropdown v-if="filterType || filterData.length" :filterDefaultValue="filterDefaultValue" :filterData="filterData" :filterType="filterType" @change="ondropdown"></dropdown>
 		</view>
 	</th>
 	<!-- #endif -->
@@ -79,6 +79,12 @@ export default {
 			default () {
 				return []
 			}
+		},
+		filterDefaultValue: {
+			type: [Array,String],
+			default () {
+				return ""
+			}
 		}
 	},
 	data() {
@@ -200,6 +206,7 @@ export default {
 
 <style lang="scss">
 $border-color: #ebeef5;
+$uni-primary: #007aff !default;
 
 .uni-table-th {
 	padding: 12px 10px;
@@ -254,7 +261,7 @@ $border-color: #ebeef5;
 	}
 	&.active {
 		::after {
-			background-color: #007aff;
+			background-color: $uni-primary;
 		}
 	}
 }
@@ -271,7 +278,7 @@ $border-color: #ebeef5;
 	}
 	&.active {
 		::after {
-			background-color: #007aff;
+			background-color: $uni-primary;
 		}
 	}
 }

+ 6 - 6
uni_modules/uni-table/components/uni-tr/table-checkbox.vue

@@ -77,7 +77,7 @@
 </script>
 
 <style lang="scss">
-	$checked-color: #007aff;
+	$uni-primary: #007aff !default;
 	$border-color: #DCDFE6;
 	$disable:0.4;
 
@@ -125,8 +125,8 @@
 			}
 
 			&.checkbox--indeterminate {
-				border-color: $checked-color;
-				background-color: $checked-color;
+				border-color: $uni-primary;
+				background-color: $uni-primary;
 
 				.checkbox__inner-icon {
 					position: absolute;
@@ -147,7 +147,7 @@
 				}
 			}
 			&:hover{
-				border-color: $checked-color;
+				border-color: $uni-primary;
 			}
 			// 禁用
 			&.is-disable {
@@ -160,8 +160,8 @@
 
 			// 选中
 			&.is-checked {
-				border-color: $checked-color;
-				background-color: $checked-color;
+				border-color: $uni-primary;
+				background-color: $uni-primary;
 
 				.checkbox__inner-icon {
 					opacity: 1;

+ 4 - 7
uni_modules/uni-table/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uni-table",
   "displayName": "uni-table 表格",
-  "version": "1.2.1",
+  "version": "1.2.3",
   "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","uni-datetime-picker"],

+ 1 - 1
uni_modules/uni-tag/components/uni-tag/uni-tag.vue

@@ -106,7 +106,7 @@
 	};
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 	$uni-primary: #2979ff !default;
 	$uni-success: #18bc37 !default;
 	$uni-warning: #f3a73f !default;

+ 7 - 12
uni_modules/uni-tooltip/package.json

@@ -1,6 +1,6 @@
 {
   "id": "uni-tooltip",
-  "displayName": "uni-tooltip 提示文字",
+  "displayName": "uni-tooltip",
   "version": "0.2.1",
   "description": "Tooltip 提示文字",
   "keywords": [
@@ -9,18 +9,14 @@
     "tooltip",
     "tip",
     "文字提示"
-  ],
-  "repository": "https://github.com/dcloudio/uni-ui",
-  "engines": {
-    "HBuilderX": ""
-  },
-  "directories": {
-    "example": "../../temps/example_temps"
+],
+  "repository": "",
+"engines": {
   },
   "dcloudext": {
     "category": [
-      "前端组件",
-      "通用组件"
+        "前端组件",
+        "通用组件"
     ],
     "sale": {
       "regular": {
@@ -75,8 +71,7 @@
           "阿里": "u",
           "百度": "u",
           "字节跳动": "u",
-          "QQ": "u",
-          "京东": "u"
+          "QQ": "u"
         },
         "快应用": {
           "华为": "u",

+ 2 - 0
uni_modules/uni-transition/changelog.md

@@ -1,3 +1,5 @@
+## 1.3.2(2023-05-04)
+- 修复 NVUE 平台报错的问题
 ## 1.3.1(2021-11-23)
 - 修复 init 方法初始化问题
 ## 1.3.0(2021-11-19)

+ 4 - 1
uni_modules/uni-transition/components/uni-transition/createAnimation.js

@@ -10,7 +10,10 @@ const nvueAnimation = uni.requireNativePlugin('animation')
 class MPAnimation {
 	constructor(options, _this) {
 		this.options = options
-		this.animation = uni.createAnimation(options)
+		// 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误
+		this.animation = uni.createAnimation({
+			...options
+		})
 		this.currentStepAnimates = {}
 		this.next = 0
 		this.$ = _this

+ 6 - 1
uni_modules/uni-transition/components/uni-transition/uni-transition.vue

@@ -1,5 +1,10 @@
 <template>
-	<view v-if="isShow||onceRender" v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
+  <!-- #ifndef APP-NVUE -->
+  <view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
+  <!-- #endif -->
+  <!-- #ifdef APP-NVUE -->
+  <view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
+  <!-- #endif -->
 </template>
 
 <script>

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.