first commit
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
import validation from './test.js';
|
||||
|
||||
// 添加单位,如果有rpx,%,px等单位结尾或者值为auto,直接返回,否则加上rpx单位结尾
|
||||
const addUnit = function(value = 'auto', unit = 'rpx') {
|
||||
value = String(value);
|
||||
// 用uView内置验证规则中的number判断是否为数值
|
||||
return validation.number(value) ? `${value}${unit}` : value;
|
||||
}
|
||||
|
||||
export default addUnit;
|
||||
167
uni_modules/vk-uview-ui/components/u-text/libs/function/digit.js
Normal file
167
uni_modules/vk-uview-ui/components/u-text/libs/function/digit.js
Normal file
@@ -0,0 +1,167 @@
|
||||
let _boundaryCheckingState = true; // 是否进行越界检查的全局开关
|
||||
|
||||
/**
|
||||
* 把错误的数据转正
|
||||
* @private
|
||||
* @example strip(0.09999999999999998)=0.1
|
||||
*/
|
||||
function strip(num, precision = 15) {
|
||||
return +parseFloat(Number(num).toPrecision(precision));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return digits length of a number
|
||||
* @private
|
||||
* @param {*number} num Input number
|
||||
*/
|
||||
function digitLength(num) {
|
||||
// Get digit length of e
|
||||
const eSplit = num.toString().split(/[eE]/);
|
||||
const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
|
||||
return len > 0 ? len : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把小数转成整数,如果是小数则放大成整数
|
||||
* @private
|
||||
* @param {*number} num 输入数
|
||||
*/
|
||||
function float2Fixed(num) {
|
||||
if (num.toString().indexOf('e') === -1) {
|
||||
return Number(num.toString().replace('.', ''));
|
||||
}
|
||||
const dLen = digitLength(num);
|
||||
return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测数字是否越界,如果越界给出提示
|
||||
* @private
|
||||
* @param {*number} num 输入数
|
||||
*/
|
||||
function checkBoundary(num) {
|
||||
if (_boundaryCheckingState) {
|
||||
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
|
||||
console.warn(`${num} 超出了精度限制,结果可能不正确`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把递归操作扁平迭代化
|
||||
* @param {number[]} arr 要操作的数字数组
|
||||
* @param {function} operation 迭代操作
|
||||
* @private
|
||||
*/
|
||||
function iteratorOperation(arr, operation) {
|
||||
const [num1, num2, ...others] = arr;
|
||||
let res = operation(num1, num2);
|
||||
|
||||
others.forEach((num) => {
|
||||
res = operation(res, num);
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度乘法
|
||||
* @export
|
||||
*/
|
||||
export function times(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, times);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
const num1Changed = float2Fixed(num1);
|
||||
const num2Changed = float2Fixed(num2);
|
||||
const baseNum = digitLength(num1) + digitLength(num2);
|
||||
const leftValue = num1Changed * num2Changed;
|
||||
|
||||
checkBoundary(leftValue);
|
||||
|
||||
return leftValue / Math.pow(10, baseNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度加法
|
||||
* @export
|
||||
*/
|
||||
export function plus(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, plus);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
// 取最大的小数位
|
||||
const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
|
||||
// 把小数都转为整数然后再计算
|
||||
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度减法
|
||||
* @export
|
||||
*/
|
||||
export function minus(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, minus);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
|
||||
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度除法
|
||||
* @export
|
||||
*/
|
||||
export function divide(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, divide);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
const num1Changed = float2Fixed(num1);
|
||||
const num2Changed = float2Fixed(num2);
|
||||
checkBoundary(num1Changed);
|
||||
checkBoundary(num2Changed);
|
||||
// 重要,这里必须用strip进行修正
|
||||
return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
|
||||
}
|
||||
|
||||
/**
|
||||
* 四舍五入
|
||||
* @export
|
||||
*/
|
||||
export function round(num, ratio) {
|
||||
const base = Math.pow(10, ratio);
|
||||
let result = divide(Math.round(Math.abs(times(num, base))), base);
|
||||
if (num < 0 && result !== 0) {
|
||||
result = times(result, -1);
|
||||
}
|
||||
// 位数不足则补0
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否进行边界检查,默认开启
|
||||
* @param flag 标记开关,true 为开启,false 为关闭,默认为 true
|
||||
* @export
|
||||
*/
|
||||
export function enableBoundaryChecking(flag = true) {
|
||||
_boundaryCheckingState = flag;
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
times,
|
||||
plus,
|
||||
minus,
|
||||
divide,
|
||||
round,
|
||||
enableBoundaryChecking,
|
||||
};
|
||||
|
||||
288
uni_modules/vk-uview-ui/components/u-text/libs/function/test.js
Normal file
288
uni_modules/vk-uview-ui/components/u-text/libs/function/test.js
Normal file
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
* 验证电子邮箱格式
|
||||
*/
|
||||
function email(value) {
|
||||
return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证手机格式
|
||||
*/
|
||||
function mobile(value) {
|
||||
return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证URL格式
|
||||
*/
|
||||
function url(value) {
|
||||
return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/
|
||||
.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证日期格式
|
||||
*/
|
||||
function date(value) {
|
||||
if (!value) return false
|
||||
// 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
|
||||
if (number(value)) value = +value
|
||||
return !/Invalid|NaN/.test(new Date(value).toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证ISO类型的日期格式
|
||||
*/
|
||||
function dateISO(value) {
|
||||
return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证十进制数字
|
||||
*/
|
||||
function number(value) {
|
||||
return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证字符串
|
||||
*/
|
||||
function string(value) {
|
||||
return typeof value === 'string'
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证整数
|
||||
*/
|
||||
function digits(value) {
|
||||
return /^\d+$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证身份证号码
|
||||
*/
|
||||
function idCard(value) {
|
||||
return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
|
||||
value
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否车牌号
|
||||
*/
|
||||
function carNo(value) {
|
||||
// 新能源车牌
|
||||
const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/
|
||||
// 旧车牌
|
||||
const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/
|
||||
if (value.length === 7) {
|
||||
return creg.test(value)
|
||||
} if (value.length === 8) {
|
||||
return xreg.test(value)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额,只允许2位小数
|
||||
*/
|
||||
function amount(value) {
|
||||
// 金额,只允许保留两位小数
|
||||
return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 中文
|
||||
*/
|
||||
function chinese(value) {
|
||||
const reg = /^[\u4e00-\u9fa5]+$/gi
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 只能输入字母
|
||||
*/
|
||||
function letter(value) {
|
||||
return /^[a-zA-Z]*$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 只能是字母或者数字
|
||||
*/
|
||||
function enOrNum(value) {
|
||||
// 英文或者数字
|
||||
const reg = /^[0-9a-zA-Z]*$/g
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否包含某个值
|
||||
*/
|
||||
function contains(value, param) {
|
||||
return value.indexOf(param) >= 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证一个值范围[min, max]
|
||||
*/
|
||||
function range(value, param) {
|
||||
return value >= param[0] && value <= param[1]
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证一个长度范围[min, max]
|
||||
*/
|
||||
function rangeLength(value, param) {
|
||||
return value.length >= param[0] && value.length <= param[1]
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否固定电话
|
||||
*/
|
||||
function landline(value) {
|
||||
const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为空
|
||||
*/
|
||||
function empty(value) {
|
||||
switch (typeof value) {
|
||||
case 'undefined':
|
||||
return true
|
||||
case 'string':
|
||||
if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
|
||||
break
|
||||
case 'boolean':
|
||||
if (!value) return true
|
||||
break
|
||||
case 'number':
|
||||
if (value === 0 || isNaN(value)) return true
|
||||
break
|
||||
case 'object':
|
||||
if (value === null || value.length === 0) return true
|
||||
for (const i in value) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否json字符串
|
||||
*/
|
||||
function jsonString(value) {
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
const obj = JSON.parse(value)
|
||||
if (typeof obj === 'object' && obj) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否数组
|
||||
*/
|
||||
function array(value) {
|
||||
if (typeof Array.isArray === 'function') {
|
||||
return Array.isArray(value)
|
||||
}
|
||||
return Object.prototype.toString.call(value) === '[object Array]'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否对象
|
||||
*/
|
||||
function object(value) {
|
||||
return Object.prototype.toString.call(value) === '[object Object]'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否短信验证码
|
||||
*/
|
||||
function code(value, len = 6) {
|
||||
return new RegExp(`^\\d{${len}}$`).test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否函数方法
|
||||
* @param {Object} value
|
||||
*/
|
||||
function func(value) {
|
||||
return typeof value === 'function'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否promise对象
|
||||
* @param {Object} value
|
||||
*/
|
||||
function promise(value) {
|
||||
return object(value) && func(value.then) && func(value.catch)
|
||||
}
|
||||
|
||||
/** 是否图片格式
|
||||
* @param {Object} value
|
||||
*/
|
||||
function image(value) {
|
||||
const newValue = value.split('?')[0]
|
||||
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
|
||||
return IMAGE_REGEXP.test(newValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否视频格式
|
||||
* @param {Object} value
|
||||
*/
|
||||
function video(value) {
|
||||
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i
|
||||
return VIDEO_REGEXP.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为正则对象
|
||||
* @param {Object}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function regExp(o) {
|
||||
return o && Object.prototype.toString.call(o) === '[object RegExp]'
|
||||
}
|
||||
|
||||
export default {
|
||||
email,
|
||||
mobile,
|
||||
url,
|
||||
date,
|
||||
dateISO,
|
||||
number,
|
||||
digits,
|
||||
idCard,
|
||||
carNo,
|
||||
amount,
|
||||
chinese,
|
||||
letter,
|
||||
enOrNum,
|
||||
contains,
|
||||
range,
|
||||
rangeLength,
|
||||
empty,
|
||||
isEmpty: empty,
|
||||
jsonString,
|
||||
landline,
|
||||
object,
|
||||
array,
|
||||
code,
|
||||
func,
|
||||
promise,
|
||||
video,
|
||||
image,
|
||||
regExp,
|
||||
string
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export default {
|
||||
props: {
|
||||
lang: String,
|
||||
sessionFrom: String,
|
||||
sendMessageTitle: String,
|
||||
sendMessagePath: String,
|
||||
sendMessageImg: String,
|
||||
showMessageCard: Boolean,
|
||||
appParameter: String,
|
||||
formType: String,
|
||||
openType: String
|
||||
}
|
||||
}
|
||||
160
uni_modules/vk-uview-ui/components/u-text/libs/mixin/mixin.js
Normal file
160
uni_modules/vk-uview-ui/components/u-text/libs/mixin/mixin.js
Normal file
@@ -0,0 +1,160 @@
|
||||
export default {
|
||||
// 定义每个组件都可能需要用到的外部样式以及类名
|
||||
props: {
|
||||
// 每个组件都有的父组件传递的样式,可以为字符串或者对象形式
|
||||
customStyle: {
|
||||
type: [Object, String],
|
||||
default: () => ({})
|
||||
},
|
||||
customClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 跳转的页面路径
|
||||
url: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 页面跳转的类型
|
||||
linkType: {
|
||||
type: String,
|
||||
default: 'navigateTo'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
onLoad() {
|
||||
// getRect挂载到$u上,因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出
|
||||
this.$u.getRect = this.$uGetRect
|
||||
},
|
||||
created() {
|
||||
// 组件当中,只有created声明周期,为了能在组件使用,故也在created中将方法挂载到$u
|
||||
this.$u.getRect = this.$uGetRect
|
||||
},
|
||||
computed: {
|
||||
// 在2.x版本中,将会把$u挂载到uni对象下,导致在模板中无法使用uni.$u.xxx形式
|
||||
// 所以这里通过computed计算属性将其附加到this.$u上,就可以在模板或者js中使用uni.$u.xxx
|
||||
// 只在nvue环境通过此方式引入完整的$u,其他平台会出现性能问题,非nvue则按需引入(主要原因是props过大)
|
||||
$u() {
|
||||
// #ifndef APP-NVUE
|
||||
// 在非nvue端,移除props,http,mixin等对象,避免在小程序setData时数据过大影响性能
|
||||
return uni.$u.deepMerge(uni.$u, {
|
||||
props: undefined,
|
||||
http: undefined,
|
||||
mixin: undefined
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
return uni.$u
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 生成bem规则类名
|
||||
* 由于微信小程序,H5,nvue之间绑定class的差异,无法通过:class="[bem()]"的形式进行同用
|
||||
* 故采用如下折中做法,最后返回的是数组(一般平台)或字符串(支付宝和字节跳动平台),类似['a', 'b', 'c']或'a b c'的形式
|
||||
* @param {String} name 组件名称
|
||||
* @param {Array} fixed 一直会存在的类名
|
||||
* @param {Array} change 会根据变量值为true或者false而出现或者隐藏的类名
|
||||
* @returns {Array|string}
|
||||
*/
|
||||
bem() {
|
||||
return function (name, fixed, change) {
|
||||
// 类名前缀
|
||||
const prefix = `u-${name}--`
|
||||
const classes = {}
|
||||
if (fixed) {
|
||||
fixed.map((item) => {
|
||||
// 这里的类名,会一直存在
|
||||
classes[prefix + this[item]] = true
|
||||
})
|
||||
}
|
||||
if (change) {
|
||||
change.map((item) => {
|
||||
// 这里的类名,会根据this[item]的值为true或者false,而进行添加或者移除某一个类
|
||||
this[item] ? (classes[prefix + item] = this[item]) : (delete classes[prefix + item])
|
||||
})
|
||||
}
|
||||
return Object.keys(classes)
|
||||
// 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
|
||||
// #ifdef MP-ALIPAY || MP-TOUTIAO || MP-LARK
|
||||
.join(' ')
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 跳转某一个页面
|
||||
openPage(urlKey = 'url') {
|
||||
const url = this[urlKey]
|
||||
if (url) {
|
||||
// 执行类似uni.navigateTo的方法
|
||||
uni[this.linkType]({
|
||||
url
|
||||
})
|
||||
}
|
||||
},
|
||||
// 查询节点信息
|
||||
// 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸,为支付宝的bug(2020-07-21)
|
||||
// 解决办法为在组件根部再套一个没有任何作用的view元素
|
||||
$uGetRect(selector, all) {
|
||||
return new Promise((resolve) => {
|
||||
uni.createSelectorQuery()
|
||||
.in(this)[all ? 'selectAll' : 'select'](selector)
|
||||
.boundingClientRect((rect) => {
|
||||
if (all && Array.isArray(rect) && rect.length) {
|
||||
resolve(rect)
|
||||
}
|
||||
if (!all && rect) {
|
||||
resolve(rect)
|
||||
}
|
||||
})
|
||||
.exec()
|
||||
})
|
||||
},
|
||||
getParentData(parentName = '') {
|
||||
// 避免在created中去定义parent变量
|
||||
if (!this.parent) this.parent = {}
|
||||
// 这里的本质原理是,通过获取父组件实例(也即类似u-radio的父组件u-radio-group的this)
|
||||
// 将父组件this中对应的参数,赋值给本组件(u-radio的this)的parentData对象中对应的属性
|
||||
// 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化
|
||||
// 此处并不会自动更新子组件的数据,而是依赖父组件u-radio-group去监听data的变化,手动调用更新子组件的方法去重新获取
|
||||
this.parent = uni.$u.$parent.call(this, parentName)
|
||||
if (this.parent.children) {
|
||||
// 如果父组件的children不存在本组件的实例,才将本实例添加到父组件的children中
|
||||
this.parent.children.indexOf(this) === -1 && this.parent.children.push(this)
|
||||
}
|
||||
if (this.parent && this.parentData) {
|
||||
// 历遍parentData中的属性,将parent中的同名属性赋值给parentData
|
||||
Object.keys(this.parentData).map((key) => {
|
||||
this.parentData[key] = this.parent[key]
|
||||
})
|
||||
}
|
||||
},
|
||||
// 阻止事件冒泡
|
||||
preventEvent(e) {
|
||||
e && typeof (e.stopPropagation) === 'function' && e.stopPropagation()
|
||||
},
|
||||
// 空操作
|
||||
noop(e) {
|
||||
this.preventEvent(e)
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
uni.$emit('uOnReachBottom')
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 判断当前页面是否存在parent和chldren,一般在checkbox和checkbox-group父子联动的场景会有此情况
|
||||
// 组件销毁时,移除子组件在父组件children数组中的实例,释放资源,避免数据混乱
|
||||
if (this.parent && uni.$u.test.array(this.parent.children)) {
|
||||
// 组件销毁时,移除父组件中的children数组中对应的实例
|
||||
const childrenList = this.parent.children
|
||||
childrenList.map((child, index) => {
|
||||
// 如果相等,则移除
|
||||
if (child === this) {
|
||||
childrenList.splice(index, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
export default {
|
||||
props: {
|
||||
openType: String
|
||||
},
|
||||
methods: {
|
||||
onGetUserInfo(event) {
|
||||
this.$emit('getuserinfo', event.detail)
|
||||
},
|
||||
onContact(event) {
|
||||
this.$emit('contact', event.detail)
|
||||
},
|
||||
onGetPhoneNumber(event) {
|
||||
this.$emit('getphonenumber', event.detail)
|
||||
},
|
||||
onError(event) {
|
||||
this.$emit('error', event.detail)
|
||||
},
|
||||
onLaunchApp(event) {
|
||||
this.$emit('launchapp', event.detail)
|
||||
},
|
||||
onOpenSetting(event) {
|
||||
this.$emit('opensetting', event.detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
export default {
|
||||
type: '',
|
||||
show: true,
|
||||
text: '',
|
||||
prefixIcon: '',
|
||||
suffixIcon: '',
|
||||
mode: '',
|
||||
href: '',
|
||||
format: '',
|
||||
call: false,
|
||||
openType: '',
|
||||
bold: false,
|
||||
block: false,
|
||||
lines: '',
|
||||
color: '#303133',
|
||||
size: 30,
|
||||
iconStyle: () => ({
|
||||
fontSize: '30rpx'
|
||||
}),
|
||||
decoration: 'none',
|
||||
margin: 0,
|
||||
lineHeight: '',
|
||||
align: 'left',
|
||||
wordWrap: 'normal',
|
||||
copyText: ""
|
||||
}
|
||||
116
uni_modules/vk-uview-ui/components/u-text/props.js
Normal file
116
uni_modules/vk-uview-ui/components/u-text/props.js
Normal file
@@ -0,0 +1,116 @@
|
||||
import propsDefaultValue from './props-default-value.js'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
// 主题颜色
|
||||
type: {
|
||||
type: String,
|
||||
default: propsDefaultValue.type
|
||||
},
|
||||
// 是否显示
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: propsDefaultValue.show
|
||||
},
|
||||
// 显示的值
|
||||
text: {
|
||||
type: [String, Number],
|
||||
default: propsDefaultValue.text
|
||||
},
|
||||
// 前置图标
|
||||
prefixIcon: {
|
||||
type: String,
|
||||
default: propsDefaultValue.prefixIcon
|
||||
},
|
||||
// 后置图标
|
||||
suffixIcon: {
|
||||
type: String,
|
||||
default: propsDefaultValue.suffixIcon
|
||||
},
|
||||
// 文本处理的匹配模式
|
||||
// text-普通文本,price-价格,phone-手机号,name-姓名,date-日期,link-超链接
|
||||
mode: {
|
||||
type: String,
|
||||
default: propsDefaultValue.mode
|
||||
},
|
||||
// mode=link下,配置的链接
|
||||
href: {
|
||||
type: String,
|
||||
default: propsDefaultValue.href
|
||||
},
|
||||
// 格式化规则
|
||||
format: {
|
||||
type: [String, Function],
|
||||
default: propsDefaultValue.format
|
||||
},
|
||||
// mode=phone时,点击文本是否拨打电话
|
||||
call: {
|
||||
type: Boolean,
|
||||
default: propsDefaultValue.call
|
||||
},
|
||||
// 小程序的打开方式
|
||||
openType: {
|
||||
type: String,
|
||||
default: propsDefaultValue.openType
|
||||
},
|
||||
// 是否粗体,默认normal
|
||||
bold: {
|
||||
type: Boolean,
|
||||
default: propsDefaultValue.bold
|
||||
},
|
||||
// 是否块状
|
||||
block: {
|
||||
type: Boolean,
|
||||
default: propsDefaultValue.block
|
||||
},
|
||||
// 文本显示的行数,如果设置,超出此行数,将会显示省略号
|
||||
lines: {
|
||||
type: [String, Number],
|
||||
default: propsDefaultValue.lines
|
||||
},
|
||||
// 文本颜色
|
||||
color: {
|
||||
type: String,
|
||||
default: propsDefaultValue.color
|
||||
},
|
||||
// 字体大小
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: propsDefaultValue.size
|
||||
},
|
||||
// 图标的样式
|
||||
iconStyle: {
|
||||
type: [Object, String],
|
||||
default: propsDefaultValue.iconStyle
|
||||
},
|
||||
// 文字装饰,下划线,中划线等,可选值 none|underline|line-through
|
||||
decoration: {
|
||||
type: String,
|
||||
default: propsDefaultValue.decoration
|
||||
},
|
||||
// 外边距,对象、字符串,数值形式均可
|
||||
margin: {
|
||||
type: [Object, String, Number],
|
||||
default: propsDefaultValue.margin
|
||||
},
|
||||
// 文本行高
|
||||
lineHeight: {
|
||||
type: [String, Number],
|
||||
default: propsDefaultValue.lineHeight
|
||||
},
|
||||
// 文本对齐方式,可选值left|center|right
|
||||
align: {
|
||||
type: String,
|
||||
default: propsDefaultValue.align
|
||||
},
|
||||
// 文字换行,可选值break-word|normal|anywhere
|
||||
wordWrap: {
|
||||
type: String,
|
||||
default: propsDefaultValue.wordWrap
|
||||
},
|
||||
copyText: {
|
||||
type: String,
|
||||
default: propsDefaultValue.copyText
|
||||
}
|
||||
}
|
||||
}
|
||||
40
uni_modules/vk-uview-ui/components/u-text/theme.scss
Normal file
40
uni_modules/vk-uview-ui/components/u-text/theme.scss
Normal file
@@ -0,0 +1,40 @@
|
||||
$u-main-color: #303133;
|
||||
$u-content-color: #606266;
|
||||
$u-tips-color: #909193;
|
||||
$u-light-color: #c0c4cc;
|
||||
$u-border-color: #dadbde;
|
||||
$u-bg-color: #f3f4f6;
|
||||
$u-disabled-color: #c8c9cc;
|
||||
|
||||
$u-primary: #3c9cff;
|
||||
$u-primary-dark: #398ade;
|
||||
$u-primary-disabled: #9acafc;
|
||||
$u-primary-light: #ecf5ff;
|
||||
|
||||
$u-warning: #f9ae3d;
|
||||
$u-warning-dark: #f1a532;
|
||||
$u-warning-disabled: #f9d39b;
|
||||
$u-warning-light: #fdf6ec;
|
||||
|
||||
$u-success: #5ac725;
|
||||
$u-success-dark: #53c21d;
|
||||
$u-success-disabled: #a9e08f;
|
||||
$u-success-light: #f5fff0;
|
||||
|
||||
$u-error: #f56c6c;
|
||||
$u-error-dark: #e45656;
|
||||
$u-error-disabled: #f7b2b2;
|
||||
$u-error-light: #fef0f0;
|
||||
|
||||
$u-info: #909399;
|
||||
$u-info-dark: #767a82;
|
||||
$u-info-disabled: #c4c6c9;
|
||||
$u-info-light: #f4f4f5;
|
||||
|
||||
// scss混入,为了少写几行#ifndef
|
||||
@mixin flex($direction: row) {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: $direction;
|
||||
}
|
||||
262
uni_modules/vk-uview-ui/components/u-text/u-text.vue
Normal file
262
uni_modules/vk-uview-ui/components/u-text/u-text.vue
Normal file
@@ -0,0 +1,262 @@
|
||||
<template>
|
||||
<view class="u-text" :class="[]"
|
||||
v-if="show"
|
||||
:style="{
|
||||
margin: margin,
|
||||
justifyContent: align === 'left' ? 'flex-start' : align === 'center' ? 'center' : 'flex-end'
|
||||
}"
|
||||
@tap="clickHandler"
|
||||
>
|
||||
<text :class="['u-text__price', type && `u-text__value--${type}`]" v-if="mode === 'price'" :style="[valueStyle]">¥</text>
|
||||
<view class="u-text__prefix-icon" v-if="prefixIcon">
|
||||
<u-icon :name="prefixIcon" :customStyle="$u.addStyle(iconStyle)"></u-icon>
|
||||
</view>
|
||||
<u-link v-if="mode === 'link'" :href="href" underLine :text="value"></u-link>
|
||||
<template v-else-if="openType && isMp">
|
||||
<button
|
||||
class="u-reset-button u-text__value"
|
||||
:style="[valueStyle]"
|
||||
:class="[
|
||||
type && `u-text__value--${type}`,
|
||||
]"
|
||||
:data-index="index"
|
||||
:openType="openType"
|
||||
:lang="lang"
|
||||
:session-from="sessionFrom"
|
||||
:send-message-title="sendMessageTitle"
|
||||
:send-message-path="sendMessagePath"
|
||||
:send-message-img="sendMessageImg"
|
||||
:show-message-card="showMessageCard"
|
||||
:app-parameter="appParameter"
|
||||
@getuserinfo="onGetUserInfo"
|
||||
@contact="onContact"
|
||||
@getphonenumber="onGetPhoneNumber"
|
||||
@error="onError"
|
||||
@launchapp="onLaunchApp"
|
||||
@opensetting="onOpenSetting"
|
||||
>
|
||||
{{ value }}
|
||||
</button>
|
||||
</template>
|
||||
<text
|
||||
v-else
|
||||
class="u-text__value"
|
||||
:style="[valueStyle]"
|
||||
:class="[
|
||||
type && `u-text__value--${type}`,
|
||||
lines && `u-line-${lines}`
|
||||
]"
|
||||
>{{ value }}</text>
|
||||
<view class="u-text__suffix-icon" v-if="suffixIcon">
|
||||
<u-icon :name="suffixIcon" :customStyle="$u.addStyle(iconStyle)"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import value from './value.js'
|
||||
import mixin from './libs/mixin/mixin.js'
|
||||
import button from './libs/mixin/button.js'
|
||||
import openType from './libs/mixin/openType.js'
|
||||
import addUnit from './libs/function/addUnit.js';
|
||||
import props from './props.js'
|
||||
|
||||
/**
|
||||
* Text 文本
|
||||
* @description 此组件集成了文本类在项目中的常用功能,包括状态,拨打电话,格式化日期,*替换,超链接...等功能。 您大可不必在使用特殊文本时自己定义,text组件几乎涵盖您能使用的大部分场景。
|
||||
* @tutorial https://www.uviewui.com/components/loading.html
|
||||
* @property {String} type 主题颜色
|
||||
* @property {Boolean} show 是否显示(默认 true )
|
||||
* @property {String | Number} text 显示的值
|
||||
* @property {String} prefixIcon 前置图标
|
||||
* @property {String} suffixIcon 后置图标
|
||||
* @property {String} mode 文本处理的匹配模式 text-普通文本,price-价格,phone-手机号,name-姓名,date-日期,link-超链接
|
||||
* @value text 普通文本(默认)
|
||||
* @value price 价格
|
||||
* @value phone 手机号
|
||||
* @value name 姓名
|
||||
* @value date 日期
|
||||
* @value link 超链接
|
||||
* @property {String} href mode=link下,配置的链接
|
||||
* @property {String | Function} format 格式化规则
|
||||
* @property {Boolean} call mode=phone时,点击文本是否拨打电话(默认 false )
|
||||
* @property {String} openType 小程序的打开方式
|
||||
* @property {Boolean} bold 是否粗体,默认normal(默认 false )
|
||||
* @property {Boolean} block 是否块状(默认 false )
|
||||
* @property {String | Number} lines 文本显示的行数,如果设置,超出此行数,将会显示省略号
|
||||
* @property {String} color 文本颜色(默认 '#303133' )
|
||||
* @property {String | Number} size 字体大小(默认 30rpx )
|
||||
* @property {Object | String} iconStyle 图标的样式 (默认 {fontSize: '30rpx'} )
|
||||
* @property {String} decoration 文字装饰,下划线,中划线等,可选值 none|underline|line-through(默认 'none' )
|
||||
* @value none none 不处理(默认)
|
||||
* @value underline underline 下划线
|
||||
* @value line-through line-through 中划线
|
||||
* @property {Object | String | Number} margin 外边距,对象、字符串,数值形式均可(默认 0 )
|
||||
* @property {String | Number} lineHeight 文本行高
|
||||
* @property {String} align 文本对齐方式,可选值left|center|right(默认 'left' )
|
||||
* @value left 左对齐(默认)
|
||||
* @value center 居中
|
||||
* @value right 右对齐
|
||||
* @property {String} wordWrap 文字换行,可选值break-word|normal|anywhere(默认 'normal' )
|
||||
* @value normal normal 不换行(默认)
|
||||
* @value break-word break-word 换行
|
||||
* @value anywhere anywhere 换行
|
||||
* @property {Boolean} copy 点击文字后是否复制,默认false
|
||||
* @event {Function} click 点击触发事件
|
||||
* @example <u-text text="我用十年青春,赴你最后之约"></u-text>
|
||||
* @example <u--text text="我用十年青春,赴你最后之约"></u--text>
|
||||
*/
|
||||
export default {
|
||||
name: 'u-text',
|
||||
emits: ["click","copy"],
|
||||
// #ifdef MP-WEIXIN
|
||||
// 将自定义节点设置成虚拟的,更加接近Vue组件的表现,能更好的使用flex属性
|
||||
options: {
|
||||
virtualHost: true
|
||||
},
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
mixins: [mixin, value, button, openType, props],
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
mixins: [mixin, value, props],
|
||||
// #endif
|
||||
computed: {
|
||||
valueStyle() {
|
||||
const style = {
|
||||
textDecoration: this.decoration,
|
||||
fontWeight: this.bold ? 'bold' : 'normal',
|
||||
wordWrap: this.wordWrap,
|
||||
fontSize: addUnit(this.size)
|
||||
};
|
||||
!this.type && (style.color = this.color);
|
||||
this.isNvue && this.lines && (style.lines = this.lines);
|
||||
this.lineHeight && (style.lineHeight = addUnit(this.lineHeight));
|
||||
!this.isNvue && this.block && (style.display = 'block');
|
||||
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle));
|
||||
},
|
||||
isNvue() {
|
||||
let nvue = false;
|
||||
// #ifdef APP-NVUE
|
||||
nvue = true;
|
||||
// #endif
|
||||
return nvue;
|
||||
},
|
||||
isMp() {
|
||||
let mp = false;
|
||||
// #ifdef MP
|
||||
mp = true;
|
||||
// #endif
|
||||
return mp;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
clickHandler() {
|
||||
// 如果为手机号模式,拨打电话
|
||||
if (this.call && this.mode === 'phone') {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: this.text
|
||||
});
|
||||
} else if (this.copyText) {
|
||||
uni.setClipboardData({
|
||||
data: this.copyText,
|
||||
success: () => {
|
||||
this.$emit('copy', this.copyText);
|
||||
}
|
||||
})
|
||||
}
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "./theme.scss";
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
// 由于uView是基于nvue环境进行开发的,此环境中普通元素默认为flex-direction: column;
|
||||
// 所以在非nvue中,需要对元素进行重置为flex-direction: column; 否则可能会表现异常
|
||||
view,
|
||||
scroll-view,
|
||||
swiper-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: auto;
|
||||
align-items: stretch;
|
||||
align-content: flex-start;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.u-text {
|
||||
@include flex(row);
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
|
||||
&__price {
|
||||
font-size: 14px;
|
||||
color: $u-content-color;
|
||||
}
|
||||
|
||||
&__value {
|
||||
font-size: 14px;
|
||||
@include flex;
|
||||
color: $u-content-color;
|
||||
flex-wrap: wrap;
|
||||
// flex: 1;
|
||||
text-overflow: ellipsis;
|
||||
align-items: center;
|
||||
|
||||
&--primary {
|
||||
color: $u-primary;
|
||||
}
|
||||
|
||||
&--warning {
|
||||
color: $u-warning;
|
||||
}
|
||||
|
||||
&--success {
|
||||
color: $u-success;
|
||||
}
|
||||
|
||||
&--info {
|
||||
color: $u-info;
|
||||
}
|
||||
|
||||
&--error {
|
||||
color: $u-error;
|
||||
}
|
||||
|
||||
&--main {
|
||||
color: $u-main-color;
|
||||
}
|
||||
|
||||
&--content {
|
||||
color: $u-content-color;
|
||||
}
|
||||
|
||||
&--tips {
|
||||
color: $u-tips-color;
|
||||
}
|
||||
|
||||
&--light {
|
||||
color: $u-light-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* #ifdef MP */
|
||||
.u-text{
|
||||
flex: inherit;
|
||||
width: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
130
uni_modules/vk-uview-ui/components/u-text/value.js
Normal file
130
uni_modules/vk-uview-ui/components/u-text/value.js
Normal file
@@ -0,0 +1,130 @@
|
||||
import { round } from './libs/function/digit.js'
|
||||
|
||||
const debug = process.env.NODE_ENV === 'development';
|
||||
|
||||
/**
|
||||
* @description 数字格式化
|
||||
* @param {number|string} number 要格式化的数字
|
||||
* @param {number} decimals 保留几位小数
|
||||
* @param {string} decimalPoint 小数点符号
|
||||
* @param {string} thousandsSeparator 千分位符号
|
||||
* @returns {string} 格式化后的数字
|
||||
*/
|
||||
function priceFormat(number, decimals = 0, decimalPoint = '.', thousandsSeparator = ',') {
|
||||
number = (`${number}`).replace(/[^0-9+-Ee.]/g, '');
|
||||
const n = !isFinite(+number) ? 0 : +number;
|
||||
const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals);
|
||||
const sep = (typeof thousandsSeparator === 'undefined') ? ',' : thousandsSeparator;
|
||||
const dec = (typeof decimalPoint === 'undefined') ? '.' : decimalPoint;
|
||||
let s = '';
|
||||
|
||||
s = (prec ? round(n, prec) + '' : `${Math.round(n)}`).split('.');
|
||||
const re = /(-?\d+)(\d{3})/;
|
||||
while (re.test(s[0])) {
|
||||
s[0] = s[0].replace(re, `$1${sep}$2`);
|
||||
}
|
||||
|
||||
if ((s[1] || '').length < prec) {
|
||||
s[1] = s[1] || '';
|
||||
s[1] += new Array(prec - s[1].length + 1).join('0');
|
||||
}
|
||||
return s.join(dec);
|
||||
}
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
// 经处理后需要显示的值
|
||||
value() {
|
||||
const {
|
||||
text,
|
||||
mode,
|
||||
format,
|
||||
href
|
||||
} = this
|
||||
// 价格类型
|
||||
if (mode === 'price') {
|
||||
// 如果text不为金额进行提示
|
||||
if (!/^\d+(\.\d+)?$/.test(text)) {
|
||||
if (debug) console.error('金额模式下,text参数需要为金额格式');
|
||||
}
|
||||
// 进行格式化,判断用户传入的format参数为正则,或者函数,如果没有传入format,则使用默认的金额格式化处理
|
||||
if (uni.$u.test.func(format)) {
|
||||
// 如果用户传入的是函数,使用函数格式化
|
||||
return format(text)
|
||||
}
|
||||
// 如果format非正则,非函数,则使用默认的金额格式化方法进行操作
|
||||
return priceFormat(text, 2)
|
||||
}
|
||||
if (mode === 'date') {
|
||||
// 判断是否合法的日期或者时间戳
|
||||
if (!uni.$u.test.date(text)) {
|
||||
if (debug) console.error('日期模式下,text参数需要为日期或时间戳格式');
|
||||
}
|
||||
// 进行格式化,判断用户传入的format参数为正则,或者函数,如果没有传入format,则使用默认的格式化处理
|
||||
if (uni.$u.test.func(format)) {
|
||||
// 如果用户传入的是函数,使用函数格式化
|
||||
return format(text);
|
||||
}
|
||||
if (format) {
|
||||
// 如果format非正则,非函数,则使用默认的时间格式化方法进行操作
|
||||
return uni.$u.timeFormat(text, format);
|
||||
}
|
||||
// 如果没有设置format,则设置为默认的时间格式化形式
|
||||
return uni.$u.timeFormat(text, 'yyyy-mm-dd');
|
||||
}
|
||||
if (mode === 'phone') {
|
||||
// 判断是否合法的手机号
|
||||
if (uni.$u.test.func(format)) {
|
||||
// 如果用户传入的是函数,使用函数格式化
|
||||
return format(text);
|
||||
}
|
||||
if (format === 'encrypt') {
|
||||
// 如果format为encrypt,则将手机号进行星号加密处理
|
||||
return `${text.substr(0, 3)}****${text.substr(7)}`;
|
||||
}
|
||||
return text
|
||||
}
|
||||
if (mode === 'name') {
|
||||
// 判断是否合法的字符粗
|
||||
if (!(typeof(text) === 'string')) {
|
||||
if (debug) console.error('姓名模式下,text参数需要为字符串格式');
|
||||
}
|
||||
if (uni.$u.test.func(format)) {
|
||||
// 如果用户传入的是函数,使用函数格式化
|
||||
return format(text)
|
||||
}
|
||||
if (format === 'encrypt') {
|
||||
// 如果format为encrypt,则将姓名进行星号加密处理
|
||||
return this.formatName(text);
|
||||
}
|
||||
return text
|
||||
}
|
||||
if (mode === 'link') {
|
||||
// 判断是否合法的字符粗
|
||||
if (!uni.$u.test.url(href)) {
|
||||
if (debug) console.error('超链接模式下,href参数需要为URL格式');
|
||||
}
|
||||
return text;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 默认的姓名脱敏规则
|
||||
formatName(name) {
|
||||
let value = '';
|
||||
if (name.length === 2) {
|
||||
value = name.substr(0, 1) + '*';
|
||||
} else if (name.length > 2) {
|
||||
let char = '';
|
||||
for (let i = 0, len = name.length - 2; i < len; i++) {
|
||||
char += '*';
|
||||
}
|
||||
value = name.substr(0, 1) + char + name.substr(-1, 1);
|
||||
} else {
|
||||
value = name;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user