浏览代码

Merge branch 'next' of https://github.com/jdf2e/nutui into next

Drjnigfubo 3 年之前
父节点
当前提交
936e590996

+ 15 - 27
src/packages/__VUE/divider/doc.en-US.md

@@ -25,9 +25,7 @@ Default render one horizontal divider line.
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider />
-    </nut-cell>
+  <nut-divider />
 </template>
 </template>
 ```
 ```
 
 
@@ -41,9 +39,7 @@ Insert text into divider with default slot.
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider>text</nut-divider>
-    </nut-cell>
+  <nut-divider>text</nut-divider>
 </template>
 </template>
 ```
 ```
 
 
@@ -57,12 +53,8 @@ Set Content Position with content-position attribute.
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider content-position="left">text</nut-divider>
-    </nut-cell>
-    <nut-cell>
-        <nut-divider content-position="right">text</nut-divider>
-    </nut-cell>
+  <nut-divider content-position="left">text</nut-divider>
+  <nut-divider content-position="right">text</nut-divider>
 </template>
 </template>
 ```
 ```
 
 
@@ -77,9 +69,7 @@ Render dashed divider line with dashed attribute.
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider dashed>text</nut-divider>
-    </nut-cell>
+  <nut-divider dashed>text</nut-divider>
 </template>
 </template>
 ```
 ```
 
 
@@ -93,9 +83,7 @@ User can custom divider style with style attribute.
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider :style="{ color: '#1989fa', borderColor: '#1989fa', padding: '0 16px' }">text</nut-divider>
-    </nut-cell>
+  <nut-divider :style="{ color: '#1989fa', borderColor: '#1989fa', padding: '0 16px' }">text</nut-divider>
 </template>
 </template>
 ```
 ```
 
 
@@ -107,15 +95,15 @@ User can custom divider style with style attribute.
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <div :style="{fontSize: '14px'}">
-            Text
-            <nut-divider direction="vertical" />
-            <a href="#" :style="{ color: '#1989fa' }">Link</a>
-            <nut-divider direction="vertical" />
-            <a href="#" :style="{ color: '#1989fa' }">Link</a>
-        </div>
-    </nut-cell>
+  <nut-cell>
+    <div :style="{fontSize: '14px'}">
+      Text
+      <nut-divider direction="vertical" />
+      <a href="#" :style="{ color: '#1989fa' }">Link</a>
+      <nut-divider direction="vertical" />
+      <a href="#" :style="{ color: '#1989fa' }">Link</a>
+    </div>
+  </nut-cell>
 </template>
 </template>
 ```
 ```
 
 

+ 15 - 27
src/packages/__VUE/divider/doc.md

@@ -27,9 +27,7 @@ app.use(Divider);
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider />
-    </nut-cell>
+  <nut-divider />
 </template>
 </template>
 ```
 ```
 
 
@@ -43,9 +41,7 @@ app.use(Divider);
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider>文本</nut-divider>
-    </nut-cell>
+  <nut-divider>文本</nut-divider>
 </template>
 </template>
 ```
 ```
 
 
@@ -59,12 +55,8 @@ app.use(Divider);
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider content-position="left">文本</nut-divider>
-    </nut-cell>
-    <nut-cell>
-        <nut-divider content-position="right">文本</nut-divider>
-    </nut-cell>
+  <nut-divider content-position="left">文本</nut-divider>
+  <nut-divider content-position="right">文本</nut-divider>
 </template>
 </template>
 ```
 ```
 
 
@@ -78,9 +70,7 @@ app.use(Divider);
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider dashed>文本</nut-divider>
-    </nut-cell>
+  <nut-divider dashed>文本</nut-divider>
 </template>
 </template>
 ```
 ```
 
 
@@ -94,9 +84,7 @@ app.use(Divider);
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <nut-divider :style="{ color: '#1989fa', borderColor: '#1989fa', padding: '0 16px' }">文本</nut-divider>
-    </nut-cell>
+  <nut-divider :style="{ color: '#1989fa', borderColor: '#1989fa', padding: '0 16px' }">文本</nut-divider>
 </template>
 </template>
 ```
 ```
 
 
@@ -108,15 +96,15 @@ app.use(Divider);
 
 
 ``` html
 ``` html
 <template>
 <template>
-    <nut-cell>
-        <div :style="{fontSize: '14px'}">
-            文本
-            <nut-divider direction="vertical" />
-            <a href="#" :style="{ color: '#1989fa' }">链接</a>
-            <nut-divider direction="vertical" />
-            <a href="#" :style="{ color: '#1989fa' }">链接</a>
-        </div>
-    </nut-cell>
+  <nut-cell>
+    <div :style="{fontSize: '14px'}">
+      文本
+      <nut-divider direction="vertical" />
+      <a href="#" :style="{ color: '#1989fa' }">链接</a>
+      <nut-divider direction="vertical" />
+      <a href="#" :style="{ color: '#1989fa' }">链接</a>
+    </div>
+  </nut-cell>
 </template>
 </template>
 ```
 ```
 
 

+ 16 - 9
src/packages/__VUE/form/common.ts

@@ -1,13 +1,17 @@
-import { getPropByPath, isFunction, isObject, isPromise } from '@/packages/utils/util';
+import { getPropByPath, isObject, isPromise } from '@/packages/utils/util';
 import { computed, provide, reactive, VNode, watch } from 'vue';
 import { computed, provide, reactive, VNode, watch } from 'vue';
 import { FormItemRule } from '../formitem/types';
 import { FormItemRule } from '../formitem/types';
-import { ErrorMessage, FormRule } from './types';
+import { ErrorMessage, FormRule, FormRules } from './types';
 
 
 export const component = {
 export const component = {
   props: {
   props: {
     modelValue: {
     modelValue: {
       type: Object,
       type: Object,
       default: {}
       default: {}
+    },
+    rules: {
+      type: Object,
+      default: {}
     }
     }
   },
   },
   components: {},
   components: {},
@@ -78,13 +82,16 @@ export const component = {
         console.warn('[NutUI] <FormItem> 使用 rules 校验规则时 , 必须设置 prop 参数');
         console.warn('[NutUI] <FormItem> 使用 rules 校验规则时 , 必须设置 prop 参数');
       }
       }
 
 
-      let value = getPropByPath(props.modelValue, prop || '');
+      const value = getPropByPath(props.modelValue, prop || '');
 
 
       // clear tips
       // clear tips
       tipMessage({ prop, message: '' });
       tipMessage({ prop, message: '' });
-      let _rules = [...rules];
+      const formRules: FormRules = props.rules || {};
+      const _rules = [...(formRules?.[prop] || []), ...rules];
       while (_rules.length) {
       while (_rules.length) {
-        const { required, validator, regex, message } = _rules.shift() as FormItemRule;
+        const rule = _rules.shift() as FormItemRule;
+        const { validator, ...ruleWithoutValidator } = rule;
+        const { required, regex, message } = ruleWithoutValidator;
         const errorMsg = { prop, message };
         const errorMsg = { prop, message };
         if (required) {
         if (required) {
           if (value === '' || value === undefined || value === null) {
           if (value === '' || value === undefined || value === null) {
@@ -95,7 +102,7 @@ export const component = {
           return _Promise(errorMsg);
           return _Promise(errorMsg);
         }
         }
         if (validator) {
         if (validator) {
-          const result = validator(value);
+          const result = validator(value, ruleWithoutValidator);
           if (isPromise(result)) {
           if (isPromise(result)) {
             return new Promise((r, j) => {
             return new Promise((r, j) => {
               result.then((res) => {
               result.then((res) => {
@@ -122,11 +129,11 @@ export const component = {
      * @param customProp 指定校验,用于用户自定义场景时触发,例如 blur、change 事件
      * @param customProp 指定校验,用于用户自定义场景时触发,例如 blur、change 事件
      * @returns
      * @returns
      */
      */
-    const validate = (customProp: string = '') => {
+    const validate = (customProp = '') => {
       return new Promise((resolve, reject) => {
       return new Promise((resolve, reject) => {
-        let task = findFormItem(slots.default());
+        const task = findFormItem(slots.default());
 
 
-        let errors = task.map((item) => {
+        const errors = task.map((item) => {
           if (customProp) {
           if (customProp) {
             if (customProp == item.prop) {
             if (customProp == item.prop) {
               return checkRule(item);
               return checkRule(item);

+ 20 - 1
src/packages/__VUE/form/demo.vue

@@ -57,7 +57,18 @@
       </nut-cell>
       </nut-cell>
     </nut-form>
     </nut-form>
     <h2>{{ translate('title2') }}</h2>
     <h2>{{ translate('title2') }}</h2>
-    <nut-form :model-value="formData" ref="ruleForm">
+    <nut-form
+      :model-value="formData"
+      :rules="{
+        name: [
+          {
+            message: '名称两个字以上',
+            validator: nameLengthValidator
+          }
+        ]
+      }"
+      ref="ruleForm"
+    >
       <nut-form-item
       <nut-form-item
         :label="translate('name')"
         :label="translate('name')"
         prop="name"
         prop="name"
@@ -79,6 +90,7 @@
         :rules="[
         :rules="[
           { required: true, message: translate('ageTip') },
           { required: true, message: translate('ageTip') },
           { validator: customValidator, message: translate('ageTip2') },
           { validator: customValidator, message: translate('ageTip2') },
+          { validator: customRulePropValidator, message: translate('ageTip2'), reg: /^\d+$/ },
           { regex: /^(\d{1,2}|1\d{2}|200)$/, message: translate('ageTip3') }
           { regex: /^(\d{1,2}|1\d{2}|200)$/, message: translate('ageTip3') }
         ]"
         ]"
       >
       >
@@ -168,6 +180,7 @@ import { reactive, ref } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { createComponent } from '@/packages/utils/create';
 const { createDemo, translate } = createComponent('form');
 const { createDemo, translate } = createComponent('form');
 import { useTranslate } from '@/sites/assets/util/useTranslate';
 import { useTranslate } from '@/sites/assets/util/useTranslate';
+import { FormItemRuleWithoutValidator } from '../formitem/types';
 const initTranslate = () =>
 const initTranslate = () =>
   useTranslate({
   useTranslate({
     'zh-CN': {
     'zh-CN': {
@@ -391,6 +404,10 @@ export default createDemo({
     };
     };
     // 函数校验
     // 函数校验
     const customValidator = (val: string) => /^\d+$/.test(val);
     const customValidator = (val: string) => /^\d+$/.test(val);
+    const customRulePropValidator = (val: string, rule: FormItemRuleWithoutValidator) => {
+      return (rule?.reg as RegExp).test(val);
+    };
+    const nameLengthValidator = (val: string) => val?.length >= 2;
     // Promise 异步校验
     // Promise 异步校验
     const asyncValidator = (val: string) => {
     const asyncValidator = (val: string) => {
       return new Promise((resolve) => {
       return new Promise((resolve) => {
@@ -406,6 +423,8 @@ export default createDemo({
       formData,
       formData,
       validate,
       validate,
       customValidator,
       customValidator,
+      customRulePropValidator,
+      nameLengthValidator,
       asyncValidator,
       asyncValidator,
       customBlurValidate,
       customBlurValidate,
       submit,
       submit,

+ 10 - 2
src/packages/__VUE/form/doc.en-US.md

@@ -130,7 +130,10 @@ export default {
 
 
 ```html
 ```html
 <template>
 <template>
-<nut-form :model-value="formData" ref="ruleForm">
+<nut-form :model-value="formData" :rules="{name: [{
+            message: 'Name should be at least two characters',
+            validator: nameLengthValidator
+          }]}" ref="ruleForm">
   <nut-form-item label="Name" prop="name" required :rules="[{ required: true, message: 'Please enter your name' }]">
   <nut-form-item label="Name" prop="name" required :rules="[{ required: true, message: 'Please enter your name' }]">
     <input class="nut-input-text" @blur="customBlurValidate('name')" v-model="formData.name"
     <input class="nut-input-text" @blur="customBlurValidate('name')" v-model="formData.name"
       placeholder="Please enter , blur event validate" type="text" />
       placeholder="Please enter , blur event validate" type="text" />
@@ -138,6 +141,7 @@ export default {
   <nut-form-item label="Age" prop="age" required :rules="[
   <nut-form-item label="Age" prop="age" required :rules="[
       { required: true, message: 'Please enter age' },
       { required: true, message: 'Please enter age' },
       { validator: customValidator, message: 'You must enter a number' },
       { validator: customValidator, message: 'You must enter a number' },
+      { validator: customRulePropValidator, message: 'You must enter a number', reg: /^\d+$/ },
       { regex: /^(\d{1,2}|1\d{2}|200)$/, message: 'The range 0-200 must be entered' }
       { regex: /^(\d{1,2}|1\d{2}|200)$/, message: 'The range 0-200 must be entered' }
     ]">
     ]">
     <input class="nut-input-text" v-model="formData.age" placeholder="Please enter the age, which must be numeric and in the range of 0-200" type="text" />
     <input class="nut-input-text" v-model="formData.age" placeholder="Please enter the age, which must be numeric and in the range of 0-200" type="text" />
@@ -196,6 +200,10 @@ setup(){
     };
     };
 
 
     const customValidator = (val: string) => /^\d+$/.test(val);
     const customValidator = (val: string) => /^\d+$/.test(val);
+    const customRulePropValidator = (val: string, rule: FormItemRuleWithoutValidator) => {
+      return (rule?.reg as RegExp).test(val);
+    };
+    const nameLengthValidator = (val: string) => val?.length >= 2;
     // Promise async validator
     // Promise async validator
     const asyncValidator = (val: string) => {
     const asyncValidator = (val: string) => {
       return new Promise((resolve) => {
       return new Promise((resolve) => {
@@ -206,7 +214,7 @@ setup(){
         }, 1000);
         }, 1000);
       });
       });
     };
     };
-    return { ruleForm, formData, validate, customValidator, asyncValidator, customBlurValidate, submit, reset };
+    return { ruleForm, formData, validate, customValidator, customRulePropValidator, nameLengthValidator, asyncValidator, customBlurValidate, submit, reset };
 }
 }
 }
 }
 </script>
 </script>

+ 10 - 2
src/packages/__VUE/form/doc.md

@@ -130,7 +130,10 @@ export default {
 
 
 ```html
 ```html
 <template>
 <template>
-<nut-form :model-value="formData" ref="ruleForm">
+<nut-form :model-value="formData" :rules="{name: [{
+            message: 'name 至少两个字符',
+            validator: nameLengthValidator
+          }]}" ref="ruleForm">
   <nut-form-item label="姓名" prop="name" required :rules="[{ required: true, message: '请填写姓名' }]">
   <nut-form-item label="姓名" prop="name" required :rules="[{ required: true, message: '请填写姓名' }]">
     <input class="nut-input-text" @blur="customBlurValidate('name')" v-model="formData.name"
     <input class="nut-input-text" @blur="customBlurValidate('name')" v-model="formData.name"
       placeholder="请输入姓名,blur 事件校验" type="text" />
       placeholder="请输入姓名,blur 事件校验" type="text" />
@@ -138,6 +141,7 @@ export default {
   <nut-form-item label="年龄" prop="age" required :rules="[
   <nut-form-item label="年龄" prop="age" required :rules="[
       { required: true, message: '请填写年龄' },
       { required: true, message: '请填写年龄' },
       { validator: customValidator, message: '必须输入数字' },
       { validator: customValidator, message: '必须输入数字' },
+      { validator: customRulePropValidator, message: '必须输入数字', reg: /^\d+$/ },
       { regex: /^(\d{1,2}|1\d{2}|200)$/, message: '必须输入0-200区间' }
       { regex: /^(\d{1,2}|1\d{2}|200)$/, message: '必须输入0-200区间' }
     ]">
     ]">
     <input class="nut-input-text" v-model="formData.age" placeholder="请输入年龄,必须数字且0-200区间" type="text" />
     <input class="nut-input-text" v-model="formData.age" placeholder="请输入年龄,必须数字且0-200区间" type="text" />
@@ -196,6 +200,10 @@ setup(){
     };
     };
     // 函数校验
     // 函数校验
     const customValidator = (val: string) => /^\d+$/.test(val);
     const customValidator = (val: string) => /^\d+$/.test(val);
+    const customRulePropValidator = (val: string, rule: FormItemRuleWithoutValidator) => {
+      return (rule?.reg as RegExp).test(val);
+    };
+    const nameLengthValidator = (val: string) => val?.length >= 2;
     // Promise 异步校验
     // Promise 异步校验
     const asyncValidator = (val: string) => {
     const asyncValidator = (val: string) => {
       return new Promise((resolve) => {
       return new Promise((resolve) => {
@@ -206,7 +214,7 @@ setup(){
         }, 1000);
         }, 1000);
       });
       });
     };
     };
-    return { ruleForm, formData, validate, customValidator, asyncValidator, customBlurValidate, submit, reset };
+    return { ruleForm, formData, validate, customValidator, customRulePropValidator, nameLengthValidator, asyncValidator, customBlurValidate, submit, reset };
 }
 }
 }
 }
 </script>
 </script>

+ 5 - 0
src/packages/__VUE/form/types.ts

@@ -1,9 +1,14 @@
 import { FormItemRule } from '../formitem/types';
 import { FormItemRule } from '../formitem/types';
 
 
+export type FormRules = {
+  [key: string]: FormItemRule[];
+};
+
 export type FormRule = {
 export type FormRule = {
   prop: string;
   prop: string;
   rules: FormItemRule[];
   rules: FormItemRule[];
 };
 };
+
 export type ErrorMessage = {
 export type ErrorMessage = {
   prop: string;
   prop: string;
   message: string;
   message: string;

+ 6 - 2
src/packages/__VUE/formitem/types.ts

@@ -1,6 +1,10 @@
-export class FormItemRule {
+export class FormItemRuleWithoutValidator {
   regex?: RegExp;
   regex?: RegExp;
   required?: boolean;
   required?: boolean;
   message!: string;
   message!: string;
-  validator?: (value: any) => boolean | string | Promise<boolean | string>;
+  [key: string]: any;
+}
+
+export class FormItemRule extends FormItemRuleWithoutValidator {
+  validator?: (value: any, ruleCfg: FormItemRuleWithoutValidator) => boolean | string | Promise<boolean | string>;
 }
 }

+ 3 - 2
src/packages/__VUE/imagepreview/doc.md

@@ -8,9 +8,10 @@
 
 
 ```javascript
 ```javascript
 import { createApp, reactive, toRefs } from 'vue';
 import { createApp, reactive, toRefs } from 'vue';
-
+//vue
 import { ImagePreview } from '@nutui/nutui';
 import { ImagePreview } from '@nutui/nutui';
-
+//taro
+import { ImagePreview } from '@nutui/nutui-taro';
 
 
 const app = createApp();
 const app = createApp();
 app.use(ImagePreview);
 app.use(ImagePreview);

+ 11 - 11
src/packages/__VUE/imagepreview/imagePreviewItem.vue

@@ -4,22 +4,22 @@
       <img :src="image.src" class="nut-imagepreview-img" @load="imageLoad" />
       <img :src="image.src" class="nut-imagepreview-img" @load="imageLoad" />
     </view>
     </view>
 
 
-    <view class="nut-imagepreview-box" v-if="video">
+    <view class="nut-imagepreview-box" v-if="video && video.source">
       <nut-video :source="video.source" :options="video.options"></nut-video>
       <nut-video :source="video.source" :options="video.options"></nut-video>
     </view>
     </view>
   </nut-swiper-item>
   </nut-swiper-item>
 </template>
 </template>
 <script lang="ts">
 <script lang="ts">
-import { toRefs, reactive, watch, onMounted, ref, computed, CSSProperties } from 'vue';
+import { toRefs, reactive, watch, computed, CSSProperties, PropType } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { createComponent } from '@/packages/utils/create';
 import Popup from '../popup/index.vue';
 import Popup from '../popup/index.vue';
 import Video from '../video/index.vue';
 import Video from '../video/index.vue';
 import Swiper from '../swiper/index.vue';
 import Swiper from '../swiper/index.vue';
 import SwiperItem from '../swiperitem/index.vue';
 import SwiperItem from '../swiperitem/index.vue';
 import Icon from '../icon/index.vue';
 import Icon from '../icon/index.vue';
-import { isPromise } from '@/packages/utils/util.ts';
 import { useTouch } from '@/packages/utils/useTouch';
 import { useTouch } from '@/packages/utils/useTouch';
-const { componentName, create } = createComponent('imagepreviewitem');
+import { ImageInterface } from './types';
+const { create } = createComponent('imagepreviewitem');
 
 
 export default create({
 export default create({
   props: {
   props: {
@@ -29,12 +29,12 @@ export default create({
     },
     },
     initNo: Number,
     initNo: Number,
     image: {
     image: {
-      type: Object,
-      default: () => {}
+      type: Object as PropType<ImageInterface>,
+      default: () => ({})
     },
     },
     video: {
     video: {
-      type: Array,
-      default: () => {}
+      type: Object,
+      default: () => ({})
     },
     },
 
 
     showIndex: {
     showIndex: {
@@ -126,7 +126,7 @@ export default create({
     });
     });
 
 
     // 图片加载完成
     // 图片加载完成
-    const imageLoad = (event: any) => {
+    const imageLoad = (event: TouchEvent) => {
       const { naturalWidth, naturalHeight } = event.target as HTMLImageElement;
       const { naturalWidth, naturalHeight } = event.target as HTMLImageElement;
       state.imageRatio = naturalHeight / naturalWidth;
       state.imageRatio = naturalHeight / naturalWidth;
     };
     };
@@ -165,7 +165,7 @@ export default create({
     let startMoveY: number;
     let startMoveY: number;
     let startScale: number;
     let startScale: number;
     let startDistance: number;
     let startDistance: number;
-    let doubleTapTimer: null;
+    let doubleTapTimer: number | null;
     let touchStartTime: number;
     let touchStartTime: number;
     let fingerNum: number;
     let fingerNum: number;
 
 
@@ -279,7 +279,7 @@ export default create({
     };
     };
 
 
     // 阻止
     // 阻止
-    const preventDefault = (event: any, isStopPropagation?: boolean) => {
+    const preventDefault = (event: Event, isStopPropagation?: boolean) => {
       if (typeof event.cancelable !== 'boolean' || event.cancelable) {
       if (typeof event.cancelable !== 'boolean' || event.cancelable) {
         event.preventDefault();
         event.preventDefault();
       }
       }

+ 18 - 22
src/packages/__VUE/imagepreview/index.taro.vue

@@ -28,15 +28,15 @@
   </nut-popup>
   </nut-popup>
 </template>
 </template>
 <script lang="ts">
 <script lang="ts">
-import { toRefs, reactive, watch, onMounted, computed } from 'vue';
+import { toRefs, reactive, watch, onMounted, computed, CSSProperties, PropType } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { createComponent } from '@/packages/utils/create';
 import Popup from '../popup/index.taro.vue';
 import Popup from '../popup/index.taro.vue';
-// import Video from '../video/index.vue';
 import Swiper from '../swiper/index.taro.vue';
 import Swiper from '../swiper/index.taro.vue';
 import SwiperItem from '../swiperitem/index.taro.vue';
 import SwiperItem from '../swiperitem/index.taro.vue';
 import Icon from '../icon/index.taro.vue';
 import Icon from '../icon/index.taro.vue';
-import { isPromise } from '@/packages/utils/util.ts';
-const { componentName, create } = createComponent('imagepreview');
+import { isPromise } from '@/packages/utils/util';
+import { ImageInterface } from './types';
+const { create } = createComponent('imagepreview');
 
 
 export default create({
 export default create({
   props: {
   props: {
@@ -45,13 +45,9 @@ export default create({
       default: false
       default: false
     },
     },
     images: {
     images: {
-      type: Array,
+      type: Array as PropType<ImageInterface[]>,
       default: () => []
       default: () => []
     },
     },
-    // videos: {
-    //   type: Array,
-    //   default: () => []
-    // },
     contentClose: {
     contentClose: {
       type: Boolean,
       type: Boolean,
       default: false
       default: false
@@ -100,8 +96,6 @@ export default create({
   },
   },
 
 
   setup(props, { emit }) {
   setup(props, { emit }) {
-    const { show, images } = toRefs(props);
-
     const state = reactive({
     const state = reactive({
       showPop: false,
       showPop: false,
       active: 1,
       active: 1,
@@ -114,16 +108,18 @@ export default create({
         muted: true,
         muted: true,
         controls: true
         controls: true
       },
       },
-      eleImg: null,
+      eleImg: null as HTMLElement | null,
       store: {
       store: {
         scale: 1,
         scale: 1,
-        moveable: false
+        moveable: false,
+        originScale: 1,
+        oriDistance: 1
       },
       },
       lastTouchEndTime: 0 // 用来辅助监听双击
       lastTouchEndTime: 0 // 用来辅助监听双击
     });
     });
 
 
     const styles = computed(() => {
     const styles = computed(() => {
-      let style = {};
+      let style: CSSProperties = {};
       if (props.closeIconPosition == 'top-right') {
       if (props.closeIconPosition == 'top-right') {
         style.right = '10px';
         style.right = '10px';
       } else {
       } else {
@@ -171,7 +167,7 @@ export default create({
     };
     };
 
 
     // 计算两个点的距离
     // 计算两个点的距离
-    const getDistance = (first: any, second: any) => {
+    const getDistance = (first: { x: number; y: number }, second: { x: number; y: number }) => {
       // 计算两个点起始时刻的距离和终止时刻的距离,终止时刻距离变大了则放大,变小了则缩小
       // 计算两个点起始时刻的距离和终止时刻的距离,终止时刻距离变大了则放大,变小了则缩小
       // 放大 k 倍则 scale 也 扩大 k 倍
       // 放大 k 倍则 scale 也 扩大 k 倍
       return Math.hypot(Math.abs(second.x - first.x), Math.abs(second.y - first.y));
       return Math.hypot(Math.abs(second.x - first.x), Math.abs(second.y - first.y));
@@ -179,11 +175,11 @@ export default create({
 
 
     const scaleNow = () => {
     const scaleNow = () => {
       if (state.eleImg != null) {
       if (state.eleImg != null) {
-        (state.eleImg as any).style.transform = 'scale(' + state.store.scale + ')';
+        state.eleImg.style.transform = 'scale(' + state.store.scale + ')';
       }
       }
     };
     };
 
 
-    const onTouchStart = (event: any) => {
+    const onTouchStart = (event: TouchEvent) => {
       // console.log('start');
       // console.log('start');
       // 如果已经放大,双击应变回原尺寸;如果是原尺寸,双击应放大
       // 如果已经放大,双击应变回原尺寸;如果是原尺寸,双击应放大
       const curTouchTime = new Date().getTime();
       const curTouchTime = new Date().getTime();
@@ -203,7 +199,7 @@ export default create({
 
 
       // event.preventDefault();
       // event.preventDefault();
 
 
-      const store = state.store as any;
+      const store = state.store;
       store.moveable = true;
       store.moveable = true;
 
 
       if (events2) {
       if (events2) {
@@ -223,11 +219,11 @@ export default create({
       store.originScale = store.scale || 1;
       store.originScale = store.scale || 1;
     };
     };
 
 
-    const onTouchMove = (event: any) => {
+    const onTouchMove = (event: TouchEvent) => {
       if (!state.store.moveable) {
       if (!state.store.moveable) {
         return;
         return;
       }
       }
-      const store = state.store as any;
+      const store = state.store;
       // event.preventDefault();
       // event.preventDefault();
       var touches = event.touches;
       var touches = event.touches;
       var events = touches[0];
       var events = touches[0];
@@ -264,7 +260,7 @@ export default create({
     const onTouchEnd = () => {
     const onTouchEnd = () => {
       // console.log('end');
       // console.log('end');
       state.lastTouchEndTime = new Date().getTime();
       state.lastTouchEndTime = new Date().getTime();
-      const store = state.store as any;
+      const store = state.store;
       store.moveable = false;
       store.moveable = false;
       if ((store.scale < 1.1 && store.scale > 1) || store.scale < 1) {
       if ((store.scale < 1.1 && store.scale > 1) || store.scale < 1) {
         store.scale = 1;
         store.scale = 1;
@@ -273,7 +269,7 @@ export default create({
     };
     };
 
 
     const init = () => {
     const init = () => {
-      state.eleImg = document.querySelector('.nut-imagepreview') as any;
+      state.eleImg = document.querySelector('.nut-imagepreview');
       document.addEventListener('touchmove', onTouchMove);
       document.addEventListener('touchmove', onTouchMove);
       document.addEventListener('touchend', onTouchEnd);
       document.addEventListener('touchend', onTouchEnd);
       document.addEventListener('touchcancel', onTouchEnd);
       document.addEventListener('touchcancel', onTouchEnd);

+ 10 - 10
src/packages/__VUE/imagepreview/index.ts

@@ -1,13 +1,13 @@
 import ImagePreview from './index.vue';
 import ImagePreview from './index.vue';
-import { render, createVNode, h } from 'vue';
+import { render, createVNode, h, VNode } from 'vue';
 import { ImageInterface } from './types';
 import { ImageInterface } from './types';
 export class ImagePreviewOptions {
 export class ImagePreviewOptions {
-  show: Boolean = false;
+  show = false;
   images: ImageInterface[] = [];
   images: ImageInterface[] = [];
-  initNo: Number = 1;
-  paginationVisible: Boolean = false;
-  paginationColor: string = '';
-  teleport: String | HTMLElement = 'body';
+  initNo = 1;
+  paginationVisible = false;
+  paginationColor = '';
+  teleport: string | HTMLElement = 'body';
 
 
   // function
   // function
   onClose?: Function = () => {};
   onClose?: Function = () => {};
@@ -17,9 +17,9 @@ class ImagePreviewFunction {
   options: ImagePreviewOptions = new ImagePreviewOptions();
   options: ImagePreviewOptions = new ImagePreviewOptions();
 
 
   constructor(_options: ImagePreviewOptions) {
   constructor(_options: ImagePreviewOptions) {
-    let options = Object.assign(this.options, _options);
+    const options = Object.assign(this.options, _options);
     let elWarp: HTMLElement = document.body;
     let elWarp: HTMLElement = document.body;
-    let teleport = options.teleport as string;
+    const teleport = options.teleport as string;
     if (teleport != 'body') {
     if (teleport != 'body') {
       if (typeof teleport == 'string') {
       if (typeof teleport == 'string') {
         elWarp = document.querySelector(teleport) as HTMLElement;
         elWarp = document.querySelector(teleport) as HTMLElement;
@@ -40,13 +40,13 @@ class ImagePreviewFunction {
         };
         };
       }
       }
     };
     };
-    const instance: any = createVNode(Wrapper);
+    const instance: VNode = createVNode(Wrapper);
     elWarp.appendChild(root);
     elWarp.appendChild(root);
     render(instance, root);
     render(instance, root);
   }
   }
 }
 }
 
 
-const _ImagePreview = function (options: ImagePreviewOptions) {
+const _ImagePreview = (options: ImagePreviewOptions): ImagePreviewFunction => {
   return new ImagePreviewFunction(options);
   return new ImagePreviewFunction(options);
 };
 };
 _ImagePreview.install = (app: any) => {
 _ImagePreview.install = (app: any) => {

+ 5 - 6
src/packages/__VUE/imagepreview/index.vue

@@ -5,6 +5,7 @@
     :isWrapTeleport="isWrapTeleport"
     :isWrapTeleport="isWrapTeleport"
     @click="onClose"
     @click="onClose"
     style="width: 100%"
     style="width: 100%"
+    lock-scroll
   >
   >
     <!-- @click.stop="closeOnImg" @touchstart.capture="onTouchStart" -->
     <!-- @click.stop="closeOnImg" @touchstart.capture="onTouchStart" -->
     <view class="nut-imagepreview" ref="swipeRef">
     <view class="nut-imagepreview" ref="swipeRef">
@@ -54,7 +55,7 @@
   </nut-popup>
   </nut-popup>
 </template>
 </template>
 <script lang="ts">
 <script lang="ts">
-import { toRefs, reactive, watch, onMounted, ref, computed } from 'vue';
+import { toRefs, reactive, watch, onMounted, ref, computed, CSSProperties } from 'vue';
 import type { PropType } from 'vue';
 import type { PropType } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { createComponent } from '@/packages/utils/create';
 import Popup from '../popup/index.vue';
 import Popup from '../popup/index.vue';
@@ -62,10 +63,10 @@ import Video from '../video/index.vue';
 import Swiper from '../swiper/index.vue';
 import Swiper from '../swiper/index.vue';
 import SwiperItem from '../swiperitem/index.vue';
 import SwiperItem from '../swiperitem/index.vue';
 import Icon from '../icon/index.vue';
 import Icon from '../icon/index.vue';
-import { isPromise } from '@/packages/utils/util.ts';
+import { isPromise } from '@/packages/utils/util';
 import ImagePreviewItem from './imagePreviewItem.vue';
 import ImagePreviewItem from './imagePreviewItem.vue';
 import { ImageInterface } from './types';
 import { ImageInterface } from './types';
-const { componentName, create } = createComponent('imagepreview');
+const { create } = createComponent('imagepreview');
 
 
 export default create({
 export default create({
   props: {
   props: {
@@ -142,8 +143,6 @@ export default create({
   },
   },
 
 
   setup(props, { emit }) {
   setup(props, { emit }) {
-    const { show, images } = toRefs(props);
-
     const swipeRef = ref();
     const swipeRef = ref();
 
 
     const state = reactive({
     const state = reactive({
@@ -155,7 +154,7 @@ export default create({
     });
     });
 
 
     const styles = computed(() => {
     const styles = computed(() => {
-      let style: any = {};
+      let style: CSSProperties = {};
       if (props.closeIconPosition == 'top-right') {
       if (props.closeIconPosition == 'top-right') {
         style.right = '10px';
         style.right = '10px';
       } else {
       } else {

+ 1 - 1
src/packages/__VUE/list/doc.en-US.md

@@ -98,7 +98,7 @@ body {
 |--------------|----------------------------------|--------|------------------|
 |--------------|----------------------------------|--------|------------------|
 | height         | The height of the list item               | Number | `50`                |
 | height         | The height of the list item               | Number | `50`                |
 | list-data         | List data               | any[] | `[]`                |
 | list-data         | List data               | any[] | `[]`                |
-| container-height `v3.1.19`        | Container height              | Number | `Visual area height`                |
+| container-height `v3.1.19`        | Container height(The maximum value cannot exceed the viewable area)              | Number | `Visual area height`                |
 
 
 ### Slot
 ### Slot
 
 

+ 1 - 1
src/packages/__VUE/list/doc.md

@@ -98,7 +98,7 @@ body {
 |--------------|----------------------------------|--------|------------------|
 |--------------|----------------------------------|--------|------------------|
 | height         | 列表项的高度               | Number | `50`                |
 | height         | 列表项的高度               | Number | `50`                |
 | list-data         | 列表数据               | any[] | `[]`                |
 | list-data         | 列表数据               | any[] | `[]`                |
-| container-height `v3.1.19`        | 容器高度              | Number | `可视区高度`                |
+| container-height `v3.1.19`        | 容器高度(最大值不能超过可视区)              | Number | `可视区高度`                |
 
 
 ### Slot
 ### Slot
 
 

+ 0 - 1
src/packages/__VUE/list/index.scss

@@ -1,6 +1,5 @@
 .nut-list {
 .nut-list {
   width: 100%;
   width: 100%;
-  height: 100%;
   overflow: scroll;
   overflow: scroll;
   position: relative;
   position: relative;
   -webkit-overflow-scrolling: touch;
   -webkit-overflow-scrolling: touch;

+ 9 - 3
src/packages/__VUE/list/index.taro.vue

@@ -2,7 +2,7 @@
   <scroll-view
   <scroll-view
     :class="classes"
     :class="classes"
     :scroll-y="true"
     :scroll-y="true"
-    :style="{ height: containerHeight + 'px' }"
+    :style="{ height: `${getContainerHeight}px` }"
     scroll-top="0"
     scroll-top="0"
     @scroll="handleScrollEvent"
     @scroll="handleScrollEvent"
     ref="list"
     ref="list"
@@ -20,6 +20,7 @@ import { reactive, toRefs, computed, ref, Ref, watch } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { createComponent } from '@/packages/utils/create';
 import Taro from '@tarojs/taro';
 import Taro from '@tarojs/taro';
 const { componentName, create } = createComponent('list');
 const { componentName, create } = createComponent('list');
+const clientHeight = Taro.getSystemInfoSync().windowHeight;
 export default create({
 export default create({
   props: {
   props: {
     height: {
     height: {
@@ -34,7 +35,7 @@ export default create({
     },
     },
     containerHeight: {
     containerHeight: {
       type: [Number],
       type: [Number],
-      default: Taro.getSystemInfoSync().windowHeight || 667
+      default: clientHeight || 667
     }
     }
   },
   },
   emits: ['scroll', 'scroll-bottom'],
   emits: ['scroll', 'scroll-bottom'],
@@ -47,8 +48,12 @@ export default create({
       list: props.listData.slice()
       list: props.listData.slice()
     });
     });
 
 
+    const getContainerHeight = computed(() => {
+      return Math.min(props.containerHeight, clientHeight);
+    });
+
     const visibleCount = computed(() => {
     const visibleCount = computed(() => {
-      return Math.ceil(props.containerHeight / props.height);
+      return Math.ceil(getContainerHeight.value / props.height);
     });
     });
 
 
     const end = computed(() => {
     const end = computed(() => {
@@ -98,6 +103,7 @@ export default create({
       listHeight,
       listHeight,
       visibleData,
       visibleData,
       classes,
       classes,
+      getContainerHeight,
       handleScrollEvent
       handleScrollEvent
     };
     };
   }
   }

+ 10 - 4
src/packages/__VUE/list/index.vue

@@ -1,17 +1,18 @@
 <template>
 <template>
-  <view :class="classes" @scroll.passive="handleScrollEvent" ref="list">
+  <div :class="classes" :style="{ height: `${getContainerHeight}px` }" @scroll.passive="handleScrollEvent" ref="list">
     <div class="nut-list-phantom" :style="{ height: listHeight + 'px' }"></div>
     <div class="nut-list-phantom" :style="{ height: listHeight + 'px' }"></div>
     <div class="nut-list-container" :style="{ transform: getTransform }">
     <div class="nut-list-container" :style="{ transform: getTransform }">
       <div class="nut-list-item" :style="{ height: height + 'px' }" v-for="(item, index) in visibleData" :key="item">
       <div class="nut-list-item" :style="{ height: height + 'px' }" v-for="(item, index) in visibleData" :key="item">
         <slot :item="item" :index="index"></slot>
         <slot :item="item" :index="index"></slot>
       </div>
       </div>
     </div>
     </div>
-  </view>
+  </div>
 </template>
 </template>
 <script lang="ts">
 <script lang="ts">
 import { reactive, toRefs, computed, ref, Ref, watch } from 'vue';
 import { reactive, toRefs, computed, ref, Ref, watch } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { createComponent } from '@/packages/utils/create';
 const { componentName, create } = createComponent('list');
 const { componentName, create } = createComponent('list');
+const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
 export default create({
 export default create({
   props: {
   props: {
     height: {
     height: {
@@ -26,7 +27,7 @@ export default create({
     },
     },
     containerHeight: {
     containerHeight: {
       type: [Number],
       type: [Number],
-      default: document.documentElement.clientHeight || document.body.clientHeight || 667
+      default: clientHeight || 667
     }
     }
   },
   },
   emits: ['scroll', 'scroll-bottom'],
   emits: ['scroll', 'scroll-bottom'],
@@ -39,8 +40,12 @@ export default create({
       list: props.listData.slice()
       list: props.listData.slice()
     });
     });
 
 
+    const getContainerHeight = computed(() => {
+      return Math.min(props.containerHeight, clientHeight);
+    });
+
     const visibleCount = computed(() => {
     const visibleCount = computed(() => {
-      return Math.ceil(props.containerHeight / props.height);
+      return Math.ceil(getContainerHeight.value / props.height);
     });
     });
 
 
     const end = computed(() => {
     const end = computed(() => {
@@ -90,6 +95,7 @@ export default create({
       listHeight,
       listHeight,
       visibleData,
       visibleData,
       classes,
       classes,
+      getContainerHeight,
       handleScrollEvent
       handleScrollEvent
     };
     };
   }
   }

+ 2 - 2
src/packages/__VUE/pagination/demo.vue

@@ -22,7 +22,7 @@
 </template>
 </template>
 
 
 <script lang="ts">
 <script lang="ts">
-import { ref, reactive, toRefs } from 'vue';
+import { reactive, toRefs } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { createComponent } from '@/packages/utils/create';
 const { createDemo, translate } = createComponent('pagination');
 const { createDemo, translate } = createComponent('pagination');
 import { useTranslate } from '@/sites/assets/util/useTranslate';
 import { useTranslate } from '@/sites/assets/util/useTranslate';
@@ -51,7 +51,7 @@ export default createDemo({
       currentPage3: 1
       currentPage3: 1
     });
     });
     const pageChange = (value: number) => {
     const pageChange = (value: number) => {
-      console.log(value);
+      console.log('page change', value);
     };
     };
 
 
     return {
     return {

+ 9 - 8
src/packages/__VUE/pagination/index.taro.vue

@@ -34,9 +34,9 @@
   </view>
   </view>
 </template>
 </template>
 <script lang="ts">
 <script lang="ts">
-import { toRefs, onMounted, watchEffect, computed } from 'vue';
+import { toRefs, watchEffect, computed } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { createComponent } from '@/packages/utils/create';
-const { componentName, create, translate } = createComponent('pagination');
+const { create, translate } = createComponent('pagination');
 
 
 export default create({
 export default create({
   props: {
   props: {
@@ -78,6 +78,7 @@ export default create({
     }
     }
   },
   },
   components: {},
   components: {},
+
   emits: ['change', 'update:modelValue'],
   emits: ['change', 'update:modelValue'],
 
 
   setup(props, { emit }) {
   setup(props, { emit }) {
@@ -91,31 +92,31 @@ export default create({
     });
     });
 
 
     //点击选择page
     //点击选择page
-    const select = (curPage, isSelect) => {
+    const select = (curPage: number, isSelect: boolean) => {
       if (curPage > countRef.value || curPage < 1) return;
       if (curPage > countRef.value || curPage < 1) return;
       if (curPage != modelValue.value) emit('update:modelValue', curPage);
       if (curPage != modelValue.value) emit('update:modelValue', curPage);
       if (isSelect) emit('change', curPage);
       if (isSelect) emit('change', curPage);
     };
     };
     //set page 对象
     //set page 对象
-    const setPage = (number, text, active) => {
+    const setPage = (number: number, text: string | number, active = false) => {
       return { number, text, active };
       return { number, text, active };
     };
     };
     //生成pages数组,用来遍历
     //生成pages数组,用来遍历
     const pages = computed(() => {
     const pages = computed(() => {
+      if (mode.value == 'simple') return;
       let items = [];
       let items = [];
       const pageCount = countRef.value; //总的页面数量
       const pageCount = countRef.value; //总的页面数量
-      const pageSize = showPageSize.value; //展示的页面个数
+      const pageSize = +showPageSize.value; //展示的页面个数
       let startPage = 1;
       let startPage = 1;
       let endPage = pageCount;
       let endPage = pageCount;
-      if (mode.value == 'simple') return;
       const partialShow = pageCount > pageSize;
       const partialShow = pageCount > pageSize;
       if (partialShow) {
       if (partialShow) {
         //选中的page在展示的page中间
         //选中的page在展示的page中间
         startPage = Math.max(modelValue.value - Math.floor(pageSize / 2), 1);
         startPage = Math.max(modelValue.value - Math.floor(pageSize / 2), 1);
-        endPage = startPage + pageSize - 1;
+        endPage = startPage + +pageSize - 1;
         if (endPage > pageCount) {
         if (endPage > pageCount) {
           endPage = pageCount;
           endPage = pageCount;
-          startPage = endPage - pageSize + 1;
+          startPage = endPage - +pageSize + 1;
         }
         }
       }
       }
       //遍历生成数组
       //遍历生成数组

+ 7 - 7
src/packages/__VUE/pagination/index.vue

@@ -34,9 +34,9 @@
   </view>
   </view>
 </template>
 </template>
 <script lang="ts">
 <script lang="ts">
-import { toRefs, onMounted, watchEffect, computed } from 'vue';
+import { toRefs, watchEffect, computed } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { createComponent } from '@/packages/utils/create';
-const { componentName, create, translate } = createComponent('pagination');
+const { create, translate } = createComponent('pagination');
 
 
 export default create({
 export default create({
   props: {
   props: {
@@ -92,13 +92,13 @@ export default create({
     });
     });
 
 
     //点击选择page
     //点击选择page
-    const select = (curPage, isSelect) => {
+    const select = (curPage: number, isSelect: boolean) => {
       if (curPage > countRef.value || curPage < 1) return;
       if (curPage > countRef.value || curPage < 1) return;
       if (curPage != modelValue.value) emit('update:modelValue', curPage);
       if (curPage != modelValue.value) emit('update:modelValue', curPage);
       if (isSelect) emit('change', curPage);
       if (isSelect) emit('change', curPage);
     };
     };
     //set page 对象
     //set page 对象
-    const setPage = (number, text, active) => {
+    const setPage = (number: number, text: string | number, active = false) => {
       return { number, text, active };
       return { number, text, active };
     };
     };
     //生成pages数组,用来遍历
     //生成pages数组,用来遍历
@@ -106,17 +106,17 @@ export default create({
       if (mode.value == 'simple') return;
       if (mode.value == 'simple') return;
       let items = [];
       let items = [];
       const pageCount = countRef.value; //总的页面数量
       const pageCount = countRef.value; //总的页面数量
-      const pageSize = showPageSize.value; //展示的页面个数
+      const pageSize = +showPageSize.value; //展示的页面个数
       let startPage = 1;
       let startPage = 1;
       let endPage = pageCount;
       let endPage = pageCount;
       const partialShow = pageCount > pageSize;
       const partialShow = pageCount > pageSize;
       if (partialShow) {
       if (partialShow) {
         //选中的page在展示的page中间
         //选中的page在展示的page中间
         startPage = Math.max(modelValue.value - Math.floor(pageSize / 2), 1);
         startPage = Math.max(modelValue.value - Math.floor(pageSize / 2), 1);
-        endPage = startPage + pageSize - 1;
+        endPage = startPage + +pageSize - 1;
         if (endPage > pageCount) {
         if (endPage > pageCount) {
           endPage = pageCount;
           endPage = pageCount;
-          startPage = endPage - pageSize + 1;
+          startPage = endPage - +pageSize + 1;
         }
         }
       }
       }
       //遍历生成数组
       //遍历生成数组

+ 20 - 1
src/sites/mobile-taro/vue/src/dentry/pages/form/index.vue

@@ -43,7 +43,18 @@
       </nut-cell>
       </nut-cell>
     </nut-form>
     </nut-form>
     <h2>表单校验</h2>
     <h2>表单校验</h2>
-    <nut-form :model-value="formData" ref="ruleForm">
+    <nut-form
+      :model-value="formData"
+      :rules="{
+        name: [
+          {
+            message: 'Name should be at least two characters',
+            validator: nameLengthValidator
+          }
+        ]
+      }"
+      ref="ruleForm"
+    >
       <nut-form-item label="姓名" prop="name" required :rules="[{ required: true, message: '请填写姓名' }]">
       <nut-form-item label="姓名" prop="name" required :rules="[{ required: true, message: '请填写姓名' }]">
         <input
         <input
           class="nut-input-text"
           class="nut-input-text"
@@ -60,6 +71,7 @@
         :rules="[
         :rules="[
           { required: true, message: '请填写年龄' },
           { required: true, message: '请填写年龄' },
           { validator: customValidator, message: '必须输入数字' },
           { validator: customValidator, message: '必须输入数字' },
+          { validator: customRulePropValidator, message: '必须输入数字', reg: /^\d+$/ },
           { regex: /^(\d{1,2}|1\d{2}|200)$/, message: '必须输入0-200区间' }
           { regex: /^(\d{1,2}|1\d{2}|200)$/, message: '必须输入0-200区间' }
         ]"
         ]"
       >
       >
@@ -148,6 +160,7 @@
 
 
 <script lang="ts">
 <script lang="ts">
 import { reactive, ref } from 'vue';
 import { reactive, ref } from 'vue';
+import { FormItemRuleWithoutValidator } from '@/packages/__VUE/formitem/types';
 export default {
 export default {
   props: {},
   props: {},
   setup() {
   setup() {
@@ -289,6 +302,10 @@ export default {
     };
     };
     // 函数校验
     // 函数校验
     const customValidator = (val: string) => /^\d+$/.test(val);
     const customValidator = (val: string) => /^\d+$/.test(val);
+    const customRulePropValidator = (val: string, rule: FormItemRuleWithoutValidator) => {
+      return (rule?.reg as RegExp).test(val);
+    };
+    const nameLengthValidator = (val: string) => val?.length >= 2;
     // Promise 异步校验
     // Promise 异步校验
     const asyncValidator = (val: string) => {
     const asyncValidator = (val: string) => {
       return new Promise((resolve) => {
       return new Promise((resolve) => {
@@ -304,6 +321,8 @@ export default {
       formData,
       formData,
       validate,
       validate,
       customValidator,
       customValidator,
+      customRulePropValidator,
+      nameLengthValidator,
       asyncValidator,
       asyncValidator,
       customBlurValidate,
       customBlurValidate,
       submit,
       submit,

+ 0 - 3
src/sites/mobile-taro/vue/src/exhibition/pages/list/index.vue

@@ -37,9 +37,6 @@ export default defineComponent({
 </script>
 </script>
 <style lang="scss">
 <style lang="scss">
 .list-demo {
 .list-demo {
-  .nut-cell {
-    height: 100%;
-  }
   .list-item {
   .list-item {
     display: flex;
     display: flex;
     align-items: center;
     align-items: center;