新增营销系统、分销系统、会员功能、门店、提现功能

This commit is contained in:
Shaw
2024-02-08 21:01:37 +08:00
parent 68b3f2dcc3
commit 17c043348a
1398 changed files with 81279 additions and 56269 deletions

View File

@ -10,14 +10,14 @@
2. 优化其他
## 1.0.52023-07-03
去除插槽判断避免某些平台不显示的BUG
## 1.0.42023-07-02
uv-form 由于弹出层uv-transition的修改组件内部做了相应的修改参数不变。
## 1.0.32023-06-18
1. 修改某些情况下的BUG
## 1.0.22023-06-15
1. 修复支付宝报错的BUG
## 1.0.12023-05-16
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.02023-05-10
uv-form 表单
## 1.0.42023-07-02
uv-form 由于弹出层uv-transition的修改组件内部做了相应的修改参数不变。
## 1.0.32023-06-18
1. 修改某些情况下的BUG
## 1.0.22023-06-15
1. 修复支付宝报错的BUG
## 1.0.12023-05-16
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.02023-05-10
uv-form 表单

View File

@ -1,49 +1,49 @@
export default {
props: {
// input的label提示语
label: {
type: String,
default: ''
},
// 绑定的值
prop: {
type: String,
default: ''
},
// 是否显示表单域的下划线边框
borderBottom: {
type: [Boolean],
default: false
},
// label的位置left-左边top-上边
labelPosition: {
type: String,
default: ''
},
// label的宽度单位px
labelWidth: {
type: [String, Number],
default: ''
},
// 右侧图标
rightIcon: {
type: String,
default: ''
},
// 左侧图标
leftIcon: {
type: String,
default: ''
},
// 是否显示左边的必填星号只作显示用具体校验必填的逻辑请在rules中配置
required: {
type: Boolean,
default: false
},
leftIconStyle: {
type: [String, Object],
default: ''
},
...uni.$uv?.props?.formItem
}
export default {
props: {
// input的label提示语
label: {
type: String,
default: ''
},
// 绑定的值
prop: {
type: String,
default: ''
},
// 是否显示表单域的下划线边框
borderBottom: {
type: [Boolean],
default: false
},
// label的位置left-左边top-上边
labelPosition: {
type: String,
default: ''
},
// label的宽度单位px
labelWidth: {
type: [String, Number],
default: ''
},
// 右侧图标
rightIcon: {
type: String,
default: ''
},
// 左侧图标
leftIcon: {
type: String,
default: ''
},
// 是否显示左边的必填星号只作显示用具体校验必填的逻辑请在rules中配置
required: {
type: Boolean,
default: false
},
leftIconStyle: {
type: [String, Object],
default: ''
},
...uni.$uv?.props?.formItem
}
}

View File

@ -1,226 +1,226 @@
<template>
<view class="uv-form-item">
<view
class="uv-form-item__body"
@tap="clickHandler"
:style="[$uv.addStyle(customStyle), {
flexDirection: (labelPosition || parentData.labelPosition) === 'left' ? 'row' : 'column'
}]"
>
<!-- 微信小程序中将一个参数设置空字符串结果会变成字符串"true" -->
<slot name="label">
<view
class="uv-form-item__body__left"
v-if="required || leftIcon || label"
:style="{
width: $uv.addUnit(labelWidth || parentData.labelWidth),
marginBottom: parentData.labelPosition === 'left' ? 0 : '5px',
}"
>
<!-- 为了块对齐 -->
<view class="uv-form-item__body__left__content">
<!-- nvue不支持伪元素before -->
<text
v-if="required"
class="uv-form-item__body__left__content__required"
>*</text>
<view
class="uv-form-item__body__left__content__icon"
v-if="leftIcon"
>
<uv-icon
:name="leftIcon"
:custom-style="leftIconStyle"
></uv-icon>
</view>
<text
class="uv-form-item__body__left__content__label"
:style="[parentData.labelStyle, {
justifyContent: parentData.labelAlign === 'left' ? 'flex-start' : parentData.labelAlign === 'center' ? 'center' : 'flex-end'
}]"
>{{ label }}</text>
</view>
</view>
</slot>
<view class="uv-form-item__body__right">
<view class="uv-form-item__body__right__content">
<view class="uv-form-item__body__right__content__slot">
<slot />
</view>
<view class="item__body__right__content__icon">
<slot name="right" />
</view>
</view>
</view>
</view>
<slot name="error">
<uv-transition
:show="true"
:duration="100"
mode="fade"
v-if="!!message && parentData.errorType === 'message'"
>
<text
class="uv-form-item__body__right__message"
:style="{
marginLeft: $uv.addUnit(parentData.labelPosition === 'top' ? 0 : (labelWidth || parentData.labelWidth))
}"
>{{ message }}</text>
</uv-transition>
</slot>
<uv-line
v-if="borderBottom"
:color="message && parentData.errorType === 'border-bottom' ? '#f56c6c' : '#d6d7d9'"
></uv-line>
</view>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
import props from './props.js';
/**
* Form 表单
* @description 此组件一般用于表单场景可以配置Input输入框Select弹出框进行表单验证等。
* @tutorial https://www.uvui.cn/components/form.html
* @property {String} label input的label提示语
* @property {String} prop 绑定的值
* @property {String | Boolean} borderBottom 是否显示表单域的下划线边框
* @property {String | Number} labelWidth label的宽度单位px
* @property {String} rightIcon 右侧图标
* @property {String} leftIcon 左侧图标
* @property {String | Object} leftIconStyle 左侧图标的样式
* @property {Boolean} required 是否显示左边的必填星号只作显示用具体校验必填的逻辑请在rules中配置 (默认 false )
*
* @example <uv-form-item label="姓名" prop="userInfo.name" borderBottom ref="item1"></uv-form-item>
*/
export default {
name: 'uv-form-item',
emits: ['click'],
mixins: [mpMixin, mixin, props],
data() {
return {
// 错误提示语
message: '',
parentData: {
// 提示文本的位置
labelPosition: 'left',
// 提示文本对齐方式
labelAlign: 'left',
// 提示文本的样式
labelStyle: {},
// 提示文本的宽度
labelWidth: 45,
// 错误提示方式
errorType: 'message'
}
}
},
created() {
this.init()
},
methods: {
init() {
// 父组件的实例
this.updateParentData()
if (!this.parent) {
this.$uv.error('uv-form-item需要结合uv-form组件使用')
}
},
// 获取父组件的参数
updateParentData() {
// 此方法写在mixin中
this.getParentData('uv-form');
},
// 移除uv-form-item的校验结果
clearValidate() {
this.message = null
},
// 清空当前的组件的校验结果,并重置为初始值
resetField() {
// 找到原始值
const value = this.$uv.getProperty(this.parent.originalModel, this.prop)
// 将uv-form的model的prop属性链还原原始值
this.$uv.setProperty(this.parent.model, this.prop, value)
// 移除校验结果
this.message = null
},
// 点击组件
clickHandler() {
this.$emit('click')
}
}
}
</script>
<style lang="scss" scoped>
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
.uv-form-item {
@include flex(column);
font-size: 14px;
color: $uv-main-color;
&__body {
@include flex;
padding: 10px 0;
&__left {
@include flex;
align-items: center;
&__content {
position: relative;
@include flex;
align-items: center;
padding-right: 10rpx;
flex: 1;
&__icon {
margin-right: 8rpx;
}
&__required {
position: absolute;
left: -9px;
color: $uv-error;
line-height: 20px;
font-size: 20px;
top: 3px;
}
&__label {
@include flex;
align-items: center;
flex: 1;
color: $uv-main-color;
font-size: 15px;
}
}
}
&__right {
flex: 1;
&__content {
@include flex;
align-items: center;
flex: 1;
&__slot {
flex: 1;
/* #ifndef MP */
@include flex;
align-items: center;
/* #endif */
}
&__icon {
margin-left: 10rpx;
color: $uv-light-color;
font-size: 30rpx;
}
}
&__message__box {
height: 16px;
line-height: 16px;
}
&__message {
margin-top: -6px;
line-height: 24px;
font-size: 12px;
color: $uv-error;
}
}
}
}
<template>
<view class="uv-form-item">
<view
class="uv-form-item__body"
@tap="clickHandler"
:style="[$uv.addStyle(customStyle), {
flexDirection: (labelPosition || parentData.labelPosition) === 'left' ? 'row' : 'column'
}]"
>
<!-- 微信小程序中将一个参数设置空字符串结果会变成字符串"true" -->
<slot name="label">
<view
class="uv-form-item__body__left"
v-if="required || leftIcon || label"
:style="{
width: $uv.addUnit(labelWidth || parentData.labelWidth),
marginBottom: parentData.labelPosition === 'left' ? 0 : '5px',
}"
>
<!-- 为了块对齐 -->
<view class="uv-form-item__body__left__content">
<!-- nvue不支持伪元素before -->
<text
v-if="required"
class="uv-form-item__body__left__content__required"
>*</text>
<view
class="uv-form-item__body__left__content__icon"
v-if="leftIcon"
>
<uv-icon
:name="leftIcon"
:custom-style="leftIconStyle"
></uv-icon>
</view>
<text
class="uv-form-item__body__left__content__label"
:style="[parentData.labelStyle, {
justifyContent: parentData.labelAlign === 'left' ? 'flex-start' : parentData.labelAlign === 'center' ? 'center' : 'flex-end'
}]"
>{{ label }}</text>
</view>
</view>
</slot>
<view class="uv-form-item__body__right">
<view class="uv-form-item__body__right__content">
<view class="uv-form-item__body__right__content__slot">
<slot />
</view>
<view class="item__body__right__content__icon">
<slot name="right" />
</view>
</view>
</view>
</view>
<slot name="error">
<uv-transition
:show="true"
:duration="100"
mode="fade"
v-if="!!message && parentData.errorType === 'message'"
>
<text
class="uv-form-item__body__right__message"
:style="{
marginLeft: $uv.addUnit(parentData.labelPosition === 'top' ? 0 : (labelWidth || parentData.labelWidth))
}"
>{{ message }}</text>
</uv-transition>
</slot>
<uv-line
v-if="borderBottom"
:color="message && parentData.errorType === 'border-bottom' ? '#f56c6c' : '#d6d7d9'"
></uv-line>
</view>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
import props from './props.js';
/**
* Form 表单
* @description 此组件一般用于表单场景可以配置Input输入框Select弹出框进行表单验证等。
* @tutorial https://www.uvui.cn/components/form.html
* @property {String} label input的label提示语
* @property {String} prop 绑定的值
* @property {String | Boolean} borderBottom 是否显示表单域的下划线边框
* @property {String | Number} labelWidth label的宽度单位px
* @property {String} rightIcon 右侧图标
* @property {String} leftIcon 左侧图标
* @property {String | Object} leftIconStyle 左侧图标的样式
* @property {Boolean} required 是否显示左边的必填星号只作显示用具体校验必填的逻辑请在rules中配置 (默认 false )
*
* @example <uv-form-item label="姓名" prop="userInfo.name" borderBottom ref="item1"></uv-form-item>
*/
export default {
name: 'uv-form-item',
emits: ['click'],
mixins: [mpMixin, mixin, props],
data() {
return {
// 错误提示语
message: '',
parentData: {
// 提示文本的位置
labelPosition: 'left',
// 提示文本对齐方式
labelAlign: 'left',
// 提示文本的样式
labelStyle: {},
// 提示文本的宽度
labelWidth: 45,
// 错误提示方式
errorType: 'message'
}
}
},
created() {
this.init()
},
methods: {
init() {
// 父组件的实例
this.updateParentData()
if (!this.parent) {
this.$uv.error('uv-form-item需要结合uv-form组件使用')
}
},
// 获取父组件的参数
updateParentData() {
// 此方法写在mixin中
this.getParentData('uv-form');
},
// 移除uv-form-item的校验结果
clearValidate() {
this.message = null
},
// 清空当前的组件的校验结果,并重置为初始值
resetField() {
// 找到原始值
const value = this.$uv.getProperty(this.parent.originalModel, this.prop)
// 将uv-form的model的prop属性链还原原始值
this.$uv.setProperty(this.parent.model, this.prop, value)
// 移除校验结果
this.message = null
},
// 点击组件
clickHandler() {
this.$emit('click')
}
}
}
</script>
<style lang="scss" scoped>
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
.uv-form-item {
@include flex(column);
font-size: 14px;
color: $uv-main-color;
&__body {
@include flex;
padding: 10px 0;
&__left {
@include flex;
align-items: center;
&__content {
position: relative;
@include flex;
align-items: center;
padding-right: 10rpx;
flex: 1;
&__icon {
margin-right: 8rpx;
}
&__required {
position: absolute;
left: -9px;
color: $uv-error;
line-height: 20px;
font-size: 20px;
top: 3px;
}
&__label {
@include flex;
align-items: center;
flex: 1;
color: $uv-main-color;
font-size: 15px;
}
}
}
&__right {
flex: 1;
&__content {
@include flex;
align-items: center;
flex: 1;
&__slot {
flex: 1;
/* #ifndef MP */
@include flex;
align-items: center;
/* #endif */
}
&__icon {
margin-left: 10rpx;
color: $uv-light-color;
font-size: 30rpx;
}
}
&__message__box {
height: 16px;
line-height: 16px;
}
&__message {
margin-top: -6px;
line-height: 24px;
font-size: 12px;
color: $uv-error;
}
}
}
}
</style>

View File

@ -1,46 +1,46 @@
export default {
props: {
// 当前form的需要验证字段的集合
model: {
type: Object,
default: () => ({})
},
// 验证规则
rules: {
type: [Object, Function, Array],
default: () => ({})
},
// 有错误时的提示方式message-提示信息toast-进行toast提示
// border-bottom-下边框呈现红色none-无提示
errorType: {
type: String,
default: 'message'
},
// 是否显示表单域的下划线边框
borderBottom: {
type: Boolean,
default: true
},
// label的位置left-左边top-上边
labelPosition: {
type: String,
default: 'left'
},
// label的宽度单位px
labelWidth: {
type: [String, Number],
default: 45
},
// lable字体的对齐方式
labelAlign: {
type: String,
default: 'left'
},
// lable的样式对象形式
labelStyle: {
type: Object,
default: () => ({})
},
...uni.$uv?.props?.form
}
export default {
props: {
// 当前form的需要验证字段的集合
model: {
type: Object,
default: () => ({})
},
// 验证规则
rules: {
type: [Object, Function, Array],
default: () => ({})
},
// 有错误时的提示方式message-提示信息toast-进行toast提示
// border-bottom-下边框呈现红色none-无提示
errorType: {
type: String,
default: 'message'
},
// 是否显示表单域的下划线边框
borderBottom: {
type: Boolean,
default: true
},
// label的位置left-左边top-上边
labelPosition: {
type: String,
default: 'left'
},
// label的宽度单位px
labelWidth: {
type: [String, Number],
default: 45
},
// lable字体的对齐方式
labelAlign: {
type: String,
default: 'left'
},
// lable的样式对象形式
labelStyle: {
type: Object,
default: () => ({})
},
...uni.$uv?.props?.form
}
}

View File

@ -1,209 +1,209 @@
<template>
<view class="uv-form">
<slot />
</view>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
import props from "./props.js";
import Schema from "./valid.js";
// 去除警告信息
Schema.warning = function() {};
/**
* Form 表单
* @description 此组件一般用于表单场景可以配置Input输入框Select弹出框进行表单验证等。
* @tutorial https://www.uvui.cn/components/form.html
* @property {Object} model 当前form的需要验证字段的集合
* @property {Object | Function | Array} rules 验证规则
* @property {String} errorType 错误的提示方式,见上方说明 ( 默认 message )
* @property {Boolean} borderBottom 是否显示表单域的下划线边框 ( 默认 true
* @property {String} labelPosition 表单域提示文字的位置left-左侧top-上方 ( 默认 'left'
* @property {String | Number} labelWidth 提示文字的宽度单位px ( 默认 45
* @property {String} labelAlign lable字体的对齐方式 ( 默认 left'
* @property {Object} labelStyle lable的样式对象形式
* @example <uv-form labelPosition="left" :model="model1" :rules="rules" ref="form1"></uv-form>
*/
export default {
name: "uv-form",
mixins: [mpMixin, mixin, props],
provide() {
return {
uForm: this,
};
},
data() {
return {
formRules: {},
// 规则校验器
validator: {},
// 原始的model快照用于resetFields方法重置表单时使用
originalModel: null,
};
},
watch: {
// 监听规则的变化
rules: {
immediate: true,
handler(n) {
this.setRules(n);
},
},
// 监听属性的变化通知子组件uv-form-item重新获取信息
propsChange(n) {
if (this.children?.length) {
this.children.map((child) => {
// 判断子组件(uv-form-item)如果有updateParentData方法的话就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
typeof child.updateParentData == "function" &&
child.updateParentData();
});
}
},
// 监听model的初始值作为重置表单的快照
model: {
immediate: true,
handler(n) {
if (!this.originalModel) {
this.originalModel = this.$uv.deepClone(n);
}
},
},
},
computed: {
propsChange() {
return [
this.errorType,
this.borderBottom,
this.labelPosition,
this.labelWidth,
this.labelAlign,
this.labelStyle,
];
},
},
created() {
// 存储当前form下的所有uv-form-item的实例
// 不能定义在data中否则微信小程序会造成循环引用而报错
this.children = [];
},
methods: {
// 手动设置校验的规则,如果规则中有函数的话,微信小程序中会过滤掉,所以只能手动调用设置规则
setRules(rules) {
// 判断是否有规则
if (Object.keys(rules).length === 0) return;
if (process.env.NODE_ENV === 'development' && Object.keys(this.model).length === 0) {
this.$uv.error('设置rulesmodel必须设置如果已经设置请刷新页面。');
return;
};
this.formRules = rules;
// 重新将规则赋予Validator
this.validator = new Schema(rules);
},
// 清空所有uv-form-item组件的内容本质上是调用了uv-form-item组件中的resetField()方法
resetFields() {
this.resetModel();
},
// 重置model为初始值的快照
resetModel(obj) {
// 历遍所有uv-form-item根据其prop属性还原model的原始快照
this.children.map((child) => {
const prop = child?.prop;
const value = this.$uv.getProperty(this.originalModel, prop);
this.$uv.setProperty(this.model, prop, value);
});
},
// 清空校验结果
clearValidate(props) {
props = [].concat(props);
this.children.map((child) => {
// 如果uv-form-item的prop在props数组中则清除对应的校验结果信息
if (props[0] === undefined || props.includes(child.prop)) {
child.message = null;
}
});
},
// 对部分表单字段进行校验
async validateField(value, callback, event = null) {
// $nextTick是必须的否则model的变更可能会延后于此方法的执行
this.$nextTick(() => {
// 校验错误信息返回给回调方法用于存放所有form-item的错误信息
const errorsRes = [];
// 如果为字符串,转为数组
value = [].concat(value);
// 历遍children所有子form-item
this.children.map((child) => {
// 用于存放form-item的错误信息
const childErrors = [];
if (value.includes(child.prop)) {
// 获取对应的属性,通过类似'a.b.c'的形式
const propertyVal = this.$uv.getProperty(
this.model,
child.prop
);
// 属性链数组
const propertyChain = child.prop.split(".");
const propertyName =
propertyChain[propertyChain.length - 1];
const rule = this.formRules[child.prop];
// 如果不存在对应的规则,直接返回,否则校验器会报错
if (!rule) return;
// rule规则可为数组形式也可为对象形式此处拼接成为数组
const rules = [].concat(rule);
// 对rules数组进行校验
for (let i = 0; i < rules.length; i++) {
const ruleItem = rules[i];
// 将uv-form-item的触发器转为数组形式
const trigger = [].concat(ruleItem?.trigger);
// 如果是有传入触发事件但是此form-item却没有配置此触发器的话不执行校验操作
if (event && !trigger.includes(event)) continue;
// 实例化校验对象,传入构造规则
const validator = new Schema({
[propertyName]: ruleItem,
});
validator.validate({
[propertyName]: propertyVal,
},
(errors, fields) => {
if (this.$uv.test.array(errors)) {
errorsRes.push(...errors);
childErrors.push(...errors);
}
this.$nextTick(() => {
child.message = childErrors[0]?.message ? childErrors[0]?.message : null;
})
}
);
}
}
});
// 执行回调函数
typeof callback === "function" && callback(errorsRes);
});
},
// 校验全部数据
validate(callback) {
return new Promise((resolve, reject) => {
// $nextTick是必须的否则model的变更可能会延后于validate方法
this.$nextTick(() => {
// 获取所有form-item的prop交给validateField方法进行校验
const formItemProps = this.children.map(
(item) => item.prop
);
this.validateField(formItemProps, (errors) => {
if (errors.length) {
// 如果错误提示方式为toast则进行提示
this.errorType === 'toast' && this.$uv.toast(errors[0].message)
reject(errors)
} else {
resolve(true)
}
});
});
});
},
},
};
<template>
<view class="uv-form">
<slot />
</view>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
import props from "./props.js";
import Schema from "./valid.js";
// 去除警告信息
Schema.warning = function() {};
/**
* Form 表单
* @description 此组件一般用于表单场景可以配置Input输入框Select弹出框进行表单验证等。
* @tutorial https://www.uvui.cn/components/form.html
* @property {Object} model 当前form的需要验证字段的集合
* @property {Object | Function | Array} rules 验证规则
* @property {String} errorType 错误的提示方式,见上方说明 ( 默认 message )
* @property {Boolean} borderBottom 是否显示表单域的下划线边框 ( 默认 true
* @property {String} labelPosition 表单域提示文字的位置left-左侧top-上方 ( 默认 'left'
* @property {String | Number} labelWidth 提示文字的宽度单位px ( 默认 45
* @property {String} labelAlign lable字体的对齐方式 ( 默认 left'
* @property {Object} labelStyle lable的样式对象形式
* @example <uv-form labelPosition="left" :model="model1" :rules="rules" ref="form1"></uv-form>
*/
export default {
name: "uv-form",
mixins: [mpMixin, mixin, props],
provide() {
return {
uForm: this,
};
},
data() {
return {
formRules: {},
// 规则校验器
validator: {},
// 原始的model快照用于resetFields方法重置表单时使用
originalModel: null,
};
},
watch: {
// 监听规则的变化
rules: {
immediate: true,
handler(n) {
this.setRules(n);
},
},
// 监听属性的变化通知子组件uv-form-item重新获取信息
propsChange(n) {
if (this.children?.length) {
this.children.map((child) => {
// 判断子组件(uv-form-item)如果有updateParentData方法的话就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
typeof child.updateParentData == "function" &&
child.updateParentData();
});
}
},
// 监听model的初始值作为重置表单的快照
model: {
immediate: true,
handler(n) {
if (!this.originalModel) {
this.originalModel = this.$uv.deepClone(n);
}
},
},
},
computed: {
propsChange() {
return [
this.errorType,
this.borderBottom,
this.labelPosition,
this.labelWidth,
this.labelAlign,
this.labelStyle,
];
},
},
created() {
// 存储当前form下的所有uv-form-item的实例
// 不能定义在data中否则微信小程序会造成循环引用而报错
this.children = [];
},
methods: {
// 手动设置校验的规则,如果规则中有函数的话,微信小程序中会过滤掉,所以只能手动调用设置规则
setRules(rules) {
// 判断是否有规则
if (Object.keys(rules).length === 0) return;
if (process.env.NODE_ENV === 'development' && Object.keys(this.model).length === 0) {
this.$uv.error('设置rulesmodel必须设置如果已经设置请刷新页面。');
return;
};
this.formRules = rules;
// 重新将规则赋予Validator
this.validator = new Schema(rules);
},
// 清空所有uv-form-item组件的内容本质上是调用了uv-form-item组件中的resetField()方法
resetFields() {
this.resetModel();
},
// 重置model为初始值的快照
resetModel(obj) {
// 历遍所有uv-form-item根据其prop属性还原model的原始快照
this.children.map((child) => {
const prop = child?.prop;
const value = this.$uv.getProperty(this.originalModel, prop);
this.$uv.setProperty(this.model, prop, value);
});
},
// 清空校验结果
clearValidate(props) {
props = [].concat(props);
this.children.map((child) => {
// 如果uv-form-item的prop在props数组中则清除对应的校验结果信息
if (props[0] === undefined || props.includes(child.prop)) {
child.message = null;
}
});
},
// 对部分表单字段进行校验
async validateField(value, callback, event = null) {
// $nextTick是必须的否则model的变更可能会延后于此方法的执行
this.$nextTick(() => {
// 校验错误信息返回给回调方法用于存放所有form-item的错误信息
const errorsRes = [];
// 如果为字符串,转为数组
value = [].concat(value);
// 历遍children所有子form-item
this.children.map((child) => {
// 用于存放form-item的错误信息
const childErrors = [];
if (value.includes(child.prop)) {
// 获取对应的属性,通过类似'a.b.c'的形式
const propertyVal = this.$uv.getProperty(
this.model,
child.prop
);
// 属性链数组
const propertyChain = child.prop.split(".");
const propertyName =
propertyChain[propertyChain.length - 1];
const rule = this.formRules[child.prop];
// 如果不存在对应的规则,直接返回,否则校验器会报错
if (!rule) return;
// rule规则可为数组形式也可为对象形式此处拼接成为数组
const rules = [].concat(rule);
// 对rules数组进行校验
for (let i = 0; i < rules.length; i++) {
const ruleItem = rules[i];
// 将uv-form-item的触发器转为数组形式
const trigger = [].concat(ruleItem?.trigger);
// 如果是有传入触发事件但是此form-item却没有配置此触发器的话不执行校验操作
if (event && !trigger.includes(event)) continue;
// 实例化校验对象,传入构造规则
const validator = new Schema({
[propertyName]: ruleItem,
});
validator.validate({
[propertyName]: propertyVal,
},
(errors, fields) => {
if (this.$uv.test.array(errors)) {
errorsRes.push(...errors);
childErrors.push(...errors);
}
this.$nextTick(() => {
child.message = childErrors[0]?.message ? childErrors[0]?.message : null;
})
}
);
}
}
});
// 执行回调函数
typeof callback === "function" && callback(errorsRes);
});
},
// 校验全部数据
validate(callback) {
return new Promise((resolve, reject) => {
// $nextTick是必须的否则model的变更可能会延后于validate方法
this.$nextTick(() => {
// 获取所有form-item的prop交给validateField方法进行校验
const formItemProps = this.children.map(
(item) => item.prop
);
this.validateField(formItemProps, (errors) => {
if (errors.length) {
// 如果错误提示方式为toast则进行提示
this.errorType === 'toast' && this.$uv.toast(errors[0].message)
reject(errors)
} else {
resolve(true)
}
});
});
});
},
},
};
</script>

File diff suppressed because it is too large Load Diff

View File

@ -1,93 +1,93 @@
{
"id": "uv-form",
"displayName": "uv-form 表单 全面兼容vue3+2、app、h5、小程序等多端",
"version": "1.0.9",
"description": "此组件一般用于表单场景可以配置Input输入框Textarea文本域Checkbox复选框Radio单选框开关选择器等进行表单验证等。",
"keywords": [
"form",
"uvui",
"uv-ui",
"表单",
"表单验证"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [
"uv-ui-tools",
"uv-icon",
"uv-line",
"uv-transition",
"uv-action-sheet",
"uv-input",
"uv-button"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
{
"id": "uv-form",
"displayName": "uv-form 表单 全面兼容vue3+2、app、h5、小程序等多端",
"version": "1.0.9",
"description": "此组件一般用于表单场景可以配置Input输入框Textarea文本域Checkbox复选框Radio单选框开关选择器等进行表单验证等。",
"keywords": [
"form",
"uvui",
"uv-ui",
"表单",
"表单验证"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [
"uv-ui-tools",
"uv-icon",
"uv-line",
"uv-transition",
"uv-action-sheet",
"uv-input",
"uv-button"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}