uview-pro 0.3.13 → 0.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/changelog.md CHANGED
@@ -1,7 +1,48 @@
1
- ## 0.3.13(2025-11-11
2
- ### Bug Fixes | Bug 修复
3
-
4
- - **u-root-portal:** 修复根节点传送组件运行时报错问题 ([3c24a75](https://github.com/anyup/uView-Pro/commit/3c24a75de00982bbdc1388a413721377de4f1e3d))
1
+ ## 0.3.15(2025-11-14
2
+
3
+ ### ✨ Features | 新功能
4
+
5
+ - **u-dropdown:** u-dropdown中的u-dropdown-item中新增控制显示隐藏属性 ([e4ee28f](https://github.com/anyup/uView-Pro/commit/e4ee28fd0a66ceb6bbed07b7969862e936e5e573))
6
+ - **u-form:** 支持嵌套属性验证(a.b.c格式) ([1bbead8](https://github.com/anyup/uView-Pro/commit/1bbead8be764491844a7d3909480a360ff2dc4d4))
7
+ - **form:** 添加表单字段的嵌套校验演示示例 ([73b4abe](https://github.com/anyup/uView-Pro/commit/73b4abe98047ac5193b56b71cdacb05957760e93))
8
+
9
+ ### 🚀 Chore | 构建/工程依赖/工具
10
+
11
+ - 更新应用 logo 和图标 ([38d52e4](https://github.com/anyup/uView-Pro/commit/38d52e4a9e8656bcae89892a5f94a5201a1af7b2))
12
+
13
+ ### ♻️ Code Refactoring | 代码重构
14
+
15
+ - 更新 logo 图片地址 ([c0fe3d1](https://github.com/anyup/uView-Pro/commit/c0fe3d15d6f4498229feaba860ff78e43a5297e6))
16
+
17
+ ### 👥 Contributors
18
+
19
+ <a href="https://github.com/zuo-wentao"><img src="https://github.com/zuo-wentao.png?size=40" width="40" height="40" alt="zuo-wentao" title="zuo-wentao"/></a> <a href="https://github.com/elkelkelkelkelk"><img src="https://github.com/elkelkelkelkelk.png?size=40" width="40" height="40" alt="elkelkelkelkelk" title="elkelkelkelkelk"/></a> <a href="https://github.com/anyup"><img src="https://github.com/anyup.png?size=40" width="40" height="40" alt="anyup" title="anyup"/></a>
20
+
21
+ ## 0.3.14(2025-11-14)
22
+
23
+ ### ✨ Features | 新功能
24
+
25
+ - **app-harmony:** 更新应用信息并添加鸿蒙签名配置,鸿蒙应用打包差异性编译 ([81a33c1](https://github.com/anyup/uView-Pro/commit/81a33c13a471721848033cc5f7ac1e3b3b30abc6))
26
+ - **u-message-input:** 新增输入框类型prop,支持number,text等模式 ([68a865a](https://github.com/anyup/uView-Pro/commit/68a865a12b7e0b20db458ea403579d28a227aaeb))
27
+
28
+ ### ♻️ Code Refactoring | 代码重构
29
+
30
+ - **components:** 优化 u-icon 和 u-toast 组件样式和结构 ([3cfb01d](https://github.com/anyup/uView-Pro/commit/3cfb01ddb8612e274e1bccd43fca0b5bb4e0a405))
31
+
32
+ ### 👥 Contributors
33
+
34
+ <a href="https://github.com/anyup"><img src="https://github.com/anyup.png?size=40" width="40" height="40" alt="anyup" title="anyup"/></a>
35
+
36
+ ## 0.3.13(2025-11-11)
37
+
38
+ ### 🐛 Bug Fixes | Bug 修复
39
+
40
+ - **u-root-portal:** 修复根节点传送组件运行时报错问题 ([3c24a75](https://github.com/anyup/uView-Pro/commit/3c24a75de00982bbdc1388a413721377de4f1e3d))
41
+
42
+ ### 👥 Contributors
43
+
44
+ <a href="https://github.com/anyup"><img src="https://github.com/anyup.png?size=40" width="40" height="40" alt="anyup" title="anyup"/></a>
45
+
5
46
  ## 0.3.12(2025-11-10)
6
47
 
7
48
  ### 🐛 Bug Fixes | Bug 修复
@@ -149,9 +149,14 @@ onMounted(() => {
149
149
  function init() {
150
150
  menuList.value = [];
151
151
  children.forEach(child => {
152
+ // 过滤不显示的项
153
+ const show = child?.getExposed()?.props.show !== false;
154
+ if (!show) return;
155
+
152
156
  menuList.value.push({
153
157
  title: child?.getExposed()?.props.title ?? '',
154
- disabled: child?.getExposed()?.props.disabled ?? false
158
+ disabled: child?.getExposed()?.props.disabled ?? false,
159
+ childIndex: children.indexOf(child)
155
160
  });
156
161
  });
157
162
  }
@@ -167,8 +172,11 @@ function menuClick(index: number) {
167
172
  if (index === current.value && props.closeOnClickSelf) {
168
173
  close();
169
174
  // 等动画结束后,再移除下拉菜单中的内容,否则直接移除,也就没有下拉菜单收起的效果了
175
+ const childIndex = menuList.value[index]?.childIndex; //避免访问到show为false的项
170
176
  setTimeout(() => {
171
- if (children[index]) children[index]?.getExposed()?.setActive(false);
177
+ if (childIndex !== undefined && children[childIndex]) {
178
+ children[childIndex]?.getExposed()?.setActive(false);
179
+ }
172
180
  }, Number(props.duration));
173
181
  return;
174
182
  }
@@ -191,8 +199,9 @@ function open(index: number) {
191
199
  current.value = index;
192
200
  // 历遍所有的子元素,将索引匹配的项标记为激活状态,因为子元素是通过v-if控制切换的
193
201
  // 之所以不是因display: none,是因为nvue没有display这个属性
202
+ const childIndex = menuList.value[index]?.childIndex; //避免访问到show为false的项
194
203
  children.forEach((child, idx) => {
195
- child?.getExposed()?.setActive(index == idx ? true : false);
204
+ child?.getExposed()?.setActive(childIndex === idx ? true : false);
196
205
  });
197
206
  emit('open', current.value);
198
207
  }
@@ -10,6 +10,7 @@ import { baseProps } from '../common/props';
10
10
  * @property {OptionType[]} options 选项数据,如果传入了默认slot,此参数无效
11
11
  * @property {Boolean} disabled 是否禁用此选项卡(默认false)
12
12
  * @property {String|Number} height 弹窗下拉内容的高度(内容超出将会滚动)(默认auto)
13
+ * @property {Boolean} show 控制是否显示菜单项(默认true)
13
14
  */
14
15
 
15
16
  export const DropdownItemProps = {
@@ -23,7 +24,9 @@ export const DropdownItemProps = {
23
24
  /** 是否禁用此菜单项 */
24
25
  disabled: { type: Boolean, default: false },
25
26
  /** 下拉弹窗的高度 */
26
- height: { type: [Number, String] as PropType<number | string>, default: 'auto' }
27
+ height: { type: [Number, String] as PropType<number | string>, default: 'auto' },
28
+ /** 控制是否显示菜单项 */
29
+ show: { type: Boolean, default: true }
27
30
  };
28
31
 
29
32
  export type DropdownItemProps = ExtractPropTypes<typeof DropdownItemProps>;
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <view
3
- v-if="active"
3
+ v-if="show && active"
4
4
  class="u-dropdown-item"
5
5
  :class="customClass"
6
6
  :style="$u.toStyle(customStyle)"
@@ -62,6 +62,7 @@ import { DropdownItemProps } from './types';
62
62
  * @property {Boolean} disabled 是否禁用此选项卡(默认false)
63
63
  * @property {String | Number} duration 选项卡展开和收起的过渡时间,单位ms(默认300)
64
64
  * @property {String | Number} height 弹窗下拉内容的高度(内容超出将会滚动)(默认auto)
65
+ * @property {Boolean} show 控制是否显示菜单项(默认true)
65
66
  * @example <u-dropdown-item title="标题"></u-dropdown-item>
66
67
  */
67
68
 
@@ -84,7 +85,7 @@ const activeColor = computed(() => parentExposed.value?.props?.activeColor || $u
84
85
  const inactiveColor = computed(() => parentExposed.value?.props?.inactiveColor || $u.color.contentColor);
85
86
 
86
87
  // 监听props变化,通知父组件重新初始化
87
- const propsChange = computed(() => `${props.title}-${props.disabled}`);
88
+ const propsChange = computed(() => `${props.title}-${props.disabled}-${props.show}`);
88
89
 
89
90
  // 监听propsChange变化,通知父组件重新init
90
91
  watch(propsChange, () => {
@@ -218,6 +218,31 @@ function broadcastInputError() {
218
218
  broadcast('onFormItemError', validateState.value === 'error' && showError.value('border'));
219
219
  }
220
220
 
221
+ /**
222
+ * 根据路径获取对象的值(支持嵌套路径,如 'a.b.c')
223
+ * @param obj 对象
224
+ * @param path 路径字符串
225
+ */
226
+ function getPropByPath(obj: any, path: string) {
227
+ if (!obj || !path) return { o: obj, k: '', v: undefined };
228
+
229
+ const paths = path.split('.');
230
+ let current = obj;
231
+ let key = '';
232
+
233
+ for (let i = 0; i < paths.length; i++) {
234
+ key = paths[i];
235
+ if (!current) break;
236
+
237
+ if (i === paths.length - 1) {
238
+ return { o: current, k: key, v: current[key] };
239
+ }
240
+ current = current[key];
241
+ }
242
+
243
+ return { o: current, k: key, v: undefined };
244
+ }
245
+
221
246
  /**
222
247
  * 获取当前u-form-item的校验规则
223
248
  */
@@ -268,8 +293,10 @@ function getFilteredRule(triggerType = '') {
268
293
  * @param callback 校验回调
269
294
  */
270
295
  function validation(trigger: string, callback: (msg: string) => void = () => {}) {
271
- // 检验之前,先获取需要校验的值
272
- fieldValue.value = parentExposed?.value?.model?.value[props.prop];
296
+ // 检验之前,先获取需要校验的值(支持嵌套路径)
297
+ const propPath = getPropByPath(parentExposed?.value?.model?.value, props.prop);
298
+ fieldValue.value = propPath.v;
299
+
273
300
  // blur和change是否有当前方式的校验规则
274
301
  let rules = getFilteredRule(trigger);
275
302
  // 判断是否有验证规则,如果没有规则,也调用回调方法,否则父组件u-form会因为
@@ -282,7 +309,7 @@ function validation(trigger: string, callback: (msg: string) => void = () => {})
282
309
  validateState.value = 'validating';
283
310
  // 调用async-validator的方法
284
311
  let validator = new schema({ [props.prop]: rules });
285
- validator.validate({ [props.prop]: fieldValue.value }, { firstFields: true }, (errors: any, fields: any) => {
312
+ validator.validate({ [props.prop]: fieldValue.value }, { firstFields: true }, (errors: any) => {
286
313
  // 记录状态和报错信息
287
314
  validateState.value = !errors ? 'success' : 'error';
288
315
  validateMessage.value = errors ? errors[0].message : '';
@@ -296,7 +323,11 @@ function validation(trigger: string, callback: (msg: string) => void = () => {})
296
323
  */
297
324
  function resetField() {
298
325
  if (parentExposed?.value?.model?.value && props.prop) {
299
- parentExposed.value.model.value[props.prop] = initialValue.value;
326
+ // 支持嵌套路径的重置
327
+ const propPath = getPropByPath(parentExposed.value.model.value, props.prop);
328
+ if (propPath.o && propPath.k) {
329
+ propPath.o[propPath.k] = initialValue.value;
330
+ }
300
331
  }
301
332
  // 设置为`success`状态,只是为了清空错误标记
302
333
  // 延时50毫秒,如果立即清空状态,则无法清空错误标记
@@ -324,8 +355,9 @@ onMounted(() => {
324
355
  prop: props.prop
325
356
  });
326
357
  errorType.value = parentExposed?.value?.errorType || errorType.value;
327
- // 设置初始值
328
- fieldValue.value = parentExposed?.value?.model?.value[props.prop];
358
+ // 设置初始值(支持嵌套路径)
359
+ const propPath = getPropByPath(parentExposed?.value?.model?.value, props.prop);
360
+ fieldValue.value = propPath.v;
329
361
  // 设置初始值
330
362
  initialValue.value = fieldValue.value;
331
363
  }
@@ -1,10 +1,10 @@
1
1
  <template>
2
- <view :style="[customStyle]" class="u-icon" @click="onClick" :class="['u-icon--' + labelPos]">
2
+ <view :style="[customStyle]" class="u-icon" @click="onClick" :class="['u-icon--' + labelPos, customClass]">
3
3
  <image class="u-icon__img" v-if="isImg" :src="name" :mode="imgMode" :style="[imgStyle]" />
4
4
  <text
5
5
  v-else
6
6
  class="u-icon__icon"
7
- :class="customClass"
7
+ :class="iconClass"
8
8
  :style="[iconStyle]"
9
9
  :hover-class="hoverClass"
10
10
  @touchstart="onTouchstart"
@@ -83,7 +83,7 @@ const props = defineProps(IconProps);
83
83
  * 计算图标的类名集合
84
84
  * @returns {string[]}
85
85
  */
86
- const customClass = computed(() => {
86
+ const iconClass = computed(() => {
87
87
  let classes: string[] | string = [];
88
88
  classes.push(props.customPrefix + '-' + props.name);
89
89
  // uView的自定义图标类名为u-iconfont
@@ -1,12 +1,19 @@
1
1
  import type { ExtractPropTypes, PropType } from 'vue';
2
- import type { MessageInputMode } from '../../types/global';
2
+ import type { InputType, MessageInputMode } from '../../types/global';
3
3
  import { getColor } from '../../';
4
+ import { baseProps } from '../common/props';
4
5
 
5
6
  /**
6
7
  * u-message-input 组件 props 类型定义
7
8
  * @description 验证码/短信输入框,支持多种样式
8
9
  */
9
10
  export const MessageInputProps = {
11
+ ...baseProps,
12
+ /** 输入框的类型,textarea,text,number */
13
+ type: {
14
+ type: String as PropType<InputType>,
15
+ default: 'number'
16
+ },
10
17
  /** 最大输入长度 */
11
18
  maxlength: {
12
19
  type: [Number, String] as PropType<number | string>,
@@ -1,10 +1,10 @@
1
1
  <template>
2
- <view class="u-char-box">
2
+ <view class="u-char-box" :class="customClass" :style="$u.toStyle(customStyle)">
3
3
  <view class="u-char-flex">
4
4
  <input
5
5
  :disabled="props.disabledKeyboard"
6
6
  :value="valueModel"
7
- type="number"
7
+ :type="type"
8
8
  :focus="props.focus"
9
9
  :maxlength="props.maxlength"
10
10
  class="u-input"
@@ -86,6 +86,7 @@ export default {
86
86
  <script setup lang="ts">
87
87
  import { ref, computed, watch } from 'vue';
88
88
  import { MessageInputProps } from './types';
89
+ import { $u } from '../../';
89
90
 
90
91
  /**
91
92
  * messageInput 验证码输入框
@@ -5,7 +5,13 @@
5
5
  :style="$u.toStyle({ zIndex: uZIndex }, customStyle)"
6
6
  >
7
7
  <view class="u-icon-wrap">
8
- <u-icon v-if="tmpConfig.icon" class="u-icon" :name="iconName" :size="30" :color="tmpConfig.type"></u-icon>
8
+ <u-icon
9
+ v-if="tmpConfig.icon"
10
+ custom-class="u-toast_icon"
11
+ :name="iconName"
12
+ :size="30"
13
+ :color="tmpConfig.type"
14
+ ></u-icon>
9
15
  </view>
10
16
  <text class="u-text">{{ tmpConfig.title }}</text>
11
17
  </view>
@@ -175,8 +181,14 @@ defineExpose<ToastExpose>({
175
181
  opacity: 1;
176
182
  }
177
183
 
178
- .u-icon {
179
- margin-right: 10rpx;
184
+ .u-icon-wrap {
185
+ /* #ifdef H5 */
186
+ padding-top: 6rpx;
187
+ /* #endif */
188
+ }
189
+
190
+ :deep(.u-toast_icon) {
191
+ margin-right: 8rpx;
180
192
  @include vue-flex;
181
193
  align-items: center;
182
194
  line-height: normal;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "id": "uview-pro",
3
3
  "name": "uview-pro",
4
4
  "displayName": "【支持鸿蒙】uView Pro|基于Vue3+TS全面重构的80+精选UI组件库",
5
- "version": "0.3.13",
5
+ "version": "0.3.15",
6
6
  "description": "uView Pro,是全面支持Vue3的uni-app生态框架,80+精选组件已使用TypeScript重构,已全面支持uni-app Vue3.0",
7
7
  "main": "index.ts",
8
8
  "module": "index.ts",
package/readme.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img alt="logo" src="https://ik.imagekit.io/anyup/uview-pro/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
2
+ <img alt="logo" src="https://ik.imagekit.io/anyup/uview-pro/common/logo-new.png" width="120" height="120" style="margin-bottom: 10px;">
3
3
  </p>
4
4
  <h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView Pro</h3>
5
5
  <h3 align="center">uni-app Vue3 多平台快速开发的 UI 框架</h3>