# 2022-02-22

### 1.3.7 开源社区版:
无
### 0.2.3 会员专业版:
【升级】升级uviewui框架到2.0.28版本,优化微信小程序框架流畅度。
【新增】后台商品管理新增获取单个商品的小程序二维码,方便进行宣传使用。
【优化】优化表单rules提示。
【修复】修复sku模型添加文本名称不对应的问题。#I4UPG1
【修复】修复商品列表页面点击进入商品过程,可能出现2次进入刷新闪屏的情况。
【修复】修复普通分类列表、为您推荐商品因文字一行导致的错位问题。
This commit is contained in:
JianWeie
2022-02-22 23:40:26 +08:00
parent 5c3861bb9b
commit 289c3fc5a1
28 changed files with 409 additions and 62 deletions

View File

@@ -214,7 +214,7 @@
<block v-for="(items,indexs) in shopRecommendData" :key="indexs">
<view :id="['scroll' + (indexs + 1 )]" class="recommend-scroll-item" @tap="goGoodsDetail(items.id)">
<u--image :src="items.image" mode="widthFix" width="91px" height="91px" radius="10"></u--image>
<view class="u-line-2 coreshop-font-sm coreshop-text-black coreshop-margin-top-10 coreshop-margin-bottom-10" style="min-height: 34px;">{{items.name}}</view>
<view class="u-line-2 coreshop-font-sm coreshop-text-black coreshop-margin-top-10 coreshop-margin-bottom-10 coreshop-min-height-34">{{items.name}}</view>
<view class="coreshop-text-red coreshop-text-price coreshop-margin-top-10 coreshop-margin-bottom-10 coreshop-font-md coreshop-flex-direction-row">
{{items.price}}
</view>
@@ -245,8 +245,8 @@
<u-grid col="2" :border="false" align="left">
<u-grid-item bg-color="transparent" :custom-style="{padding: '0px'}" v-for="(item, index) in otherRecommendData" :key="index" @click="goGoodsDetail(item.id)">
<view class="good_box">
<u--image :src="item.image" mode="widthFix" width="174px" height="174px" radius="10"></u--image>
<view class="good_title u-line-2">
<u--image :src="item.image" mode="widthFix" width="100%" height="174px" radius="10"></u--image>
<view class="good_title u-line-2 coreshop-min-height-34">
{{item.name}}
</view>
<view class="good-price">

View File

@@ -254,7 +254,7 @@
<block v-for="(items,indexs) in shopRecommendData" :key="indexs">
<view :id="['scroll' + (indexs + 1 )]" class="recommend-scroll-item" @tap="goGoodsDetail(items.id)">
<u--image :src="items.image" mode="widthFix" width="91px" height="91px" radius="10"></u--image>
<view class="u-line-1-2 coreshop-font-sm coreshop-text-black coreshop-margin-top-10 coreshop-margin-bottom-10 u-line-2" style="height: 34px;">{{items.name}}</view>
<view class="u-line-1-2 coreshop-font-sm coreshop-text-black coreshop-margin-top-10 coreshop-margin-bottom-10 u-line-2 coreshop-min-height-34">{{items.name}}</view>
<view class="coreshop-text-red coreshop-text-price coreshop-margin-top-10 coreshop-margin-bottom-10 coreshop-font-md coreshop-flex-direction-row">
{{items.price}}
</view>
@@ -356,8 +356,8 @@
<u-grid col="2" :border="false" align="left">
<u-grid-item bg-color="transparent" :custom-style="{padding: '0px'}" v-for="(item, index) in otherRecommendData" :key="index" @click="goGoodsDetail(item.id)">
<view class="good_box">
<u--image :src="item.image" mode="widthFix" width="174px" height="174px" radius="10"></u--image>
<view class="good_title u-line-2">
<u--image :src="item.image" mode="widthFix" width="100%" height="174px" radius="10"></u--image>
<view class="good_title u-line-2 coreshop-min-height-34">
{{item.name}}
</view>
<view class="good-price">

View File

@@ -218,7 +218,7 @@
<block v-for="(items,indexs) in shopRecommendData" :key="indexs">
<view :id="['scroll' + (indexs + 1 )]" class="recommend-scroll-item" @tap="goGoodsDetail(items.id)">
<u--image :src="items.image" mode="widthFix" width="91px" height="91px" radius="10"></u--image>
<view class="u-line-2 coreshop-font-sm coreshop-text-black coreshop-margin-top-10 coreshop-margin-bottom-10" style="min-height: 34px;">{{items.name}}</view>
<view class="u-line-2 coreshop-font-sm coreshop-text-black coreshop-margin-top-10 coreshop-margin-bottom-10 coreshop-min-height-34">{{items.name}}</view>
<view class="coreshop-text-red coreshop-text-price coreshop-margin-top-10 coreshop-margin-bottom-10 coreshop-font-md coreshop-flex-direction-row">
{{items.price}}
</view>
@@ -249,8 +249,8 @@
<u-grid col="2" :border="false" align="left">
<u-grid-item bg-color="transparent" :custom-style="{padding: '0px'}" v-for="(item, index) in otherRecommendData" :key="index" @click="goGoodsDetail(item.id)">
<view class="good_box">
<u--image :src="item.image" mode="widthFix" width="174px" height="174px" radius="10"></u--image>
<view class="good_title u-line-2">
<u--image :src="item.image" mode="widthFix" width="100%" height="174px" radius="10"></u--image>
<view class="good_title u-line-2 coreshop-min-height-34">
{{item.name}}
</view>
<view class="good-price">

View File

@@ -42,7 +42,7 @@
</view>
<view class="item-container coreshop-flex-direction-row">
<view class="thumb-box" v-for="(item1, index1) in item.child" :key="index1" @click="goClass(item1.id)">
<u--image width="60px" height="60px" :src="item1.imageUrl" @click="goClass(item1.id)"></u--image>
<u--image width="60px" height="60px" :src="item1.imageUrl"></u--image>
<view class="item-menu-name">{{item1.name}}</view>
</view>
</view>

View File

@@ -93,7 +93,7 @@
<u-grid-item bg-color="transparent" :custom-style="{padding: '1px'}" v-for="item in goodsList" :key="item.id" @click="goGoodsDetail(item.id)">
<view class="good_box">
<u--image :src="item.image" :index="item.id" width="100%" height="167px" mode="widthFix" radius="10"></u--image>
<view class="good_title u-line-2">
<view class="good_title u-line-2 coreshop-min-height-34">
{{item.name}}
</view>
<view class="good-price">

View File

@@ -167,7 +167,7 @@
<block v-for="(items,indexs) in shopRecommendData" :key="indexs">
<view :id="['scroll' + (indexs + 1 )]" class="recommend-scroll-item" @tap="goGoodsDetail(items.id)">
<u--image :src="items.image" mode="widthFix" width="91px" height="91px" radius="10"></u--image>
<view class="u-line-2 coreshop-font-sm coreshop-text-black coreshop-margin-top-10 coreshop-margin-bottom-10" style="min-height: 34px;">{{items.name}}</view>
<view class="u-line-2 coreshop-font-sm coreshop-text-black coreshop-margin-top-10 coreshop-margin-bottom-10 coreshop-min-height-34">{{items.name}}</view>
<view class="coreshop-text-red coreshop-text-price coreshop-margin-top-10 coreshop-margin-bottom-10 coreshop-font-md coreshop-flex-direction-row">
{{items.price}}
</view>
@@ -259,8 +259,8 @@
<u-grid col="2" :border="false" align="left">
<u-grid-item bg-color="transparent" :custom-style="{padding: '0px'}" v-for="(item, index) in otherRecommendData" :key="index" @click="goGoodsDetail(item.id)">
<view class="good_box">
<u--image :src="item.image" mode="widthFix" width="174px" height="174px" radius="10"></u--image>
<view class="good_title u-line-2">
<u--image :src="item.image" mode="widthFix" width="100%" height="174px" radius="10"></u--image>
<view class="good_title u-line-2 coreshop-min-height-34">
{{item.name}}
</view>
<view class="good-price">

View File

@@ -213,6 +213,10 @@ view, text { box-sizing: border-box; }
.coreshop-percent-#{$i} { width: $i#{'%'}; }
}
// 定义字体(px)单位
@for $i from 0 through 100 {
.coreshop-min-height-#{$i} { min-height: $i + px; }
}
// 定义flex等分
@for $i from 0 through 12 {

View File

@@ -1,3 +1,14 @@
## 2.0.282022-02-22
# uView2.0重磅发布,利剑出鞘,一统江湖
1. search组件新增searchIconSize属性
2. 兼容Safari/Webkit中传入时间格式如2022-02-17 12:00:56
3. 修复text value.js 判断日期出format错误问题
4. priceFormat格式化金额出现精度错误
5. priceFormat在部分情况下出现精度损失问题
6. 优化表单rules提示
7. 修复avatar组件src为空时展示状态不对
8. 其他修复
## 2.0.272022-01-28
# uView2.0重磅发布,利剑出鞘,一统江湖

View File

@@ -103,6 +103,10 @@
immediate: true,
handler(newVal) {
this.avatarUrl = newVal
// 如果没有传src则主动触发error事件用于显示默认的头像否则src为''空字符等的时候,会无内容展示
if(!newVal) {
this.errorHandler()
}
}
}
},

View File

@@ -34,6 +34,10 @@ export default {
required: {
type: Boolean,
default: uni.$u.props.formItem.required
},
leftIconStyle: {
type: [String, Object],
default: uni.$u.props.formItem.leftIconStyle,
}
}
}

View File

@@ -86,6 +86,7 @@
* @property {String | Number} labelWidth label的宽度单位px
* @property {String} rightIcon 右侧图标
* @property {String} leftIcon 左侧图标
* @property {String | Object} leftIconStyle 左侧图标的样式
* @property {Boolean} required 是否显示左边的必填星号只作显示用具体校验必填的逻辑请在rules中配置 (默认 false )
*
* @example <u-form-item label="姓名" prop="userInfo.name" borderBottom ref="item1"></u-form-item>

View File

@@ -123,11 +123,6 @@
},
// 对部分表单字段进行校验
async validateField(value, callback, event = null) {
// 开发环境才提示,生产环境不会提示
if (process.env.NODE_ENV === 'development' && Object.keys(this.formRules).length === 0) {
uni.$u.error('未设置rules请看文档说明如果已经设置请刷新页面。');
return;
}
// $nextTick是必须的否则model的变更可能会延后于此方法的执行
this.$nextTick(() => {
// 校验错误信息返回给回调方法用于存放所有form-item的错误信息
@@ -187,6 +182,11 @@
},
// 校验全部数据
validate(callback) {
// 开发环境才提示,生产环境不会提示
if (process.env.NODE_ENV === 'development' && Object.keys(this.formRules).length === 0) {
uni.$u.error('未设置rules请看文档说明如果已经设置请刷新页面。');
return;
}
return new Promise((resolve, reject) => {
// $nextTick是必须的否则model的变更可能会延后于validate方法
this.$nextTick(() => {

View File

@@ -80,6 +80,10 @@ export default {
type: String,
default: uni.$u.props.search.searchIcon
},
searchIconSize: {
type: [Number, String],
default: uni.$u.props.search.searchIconSize
},
// 组件与其他上下左右元素之间的距离,带单位的字符串形式,如"30px"、"30px 20px"等写法
margin: {
type: String,

View File

@@ -22,7 +22,7 @@
<view class="u-search__content__icon">
<u-icon
@tap="clickIcon"
:size="22"
:size="searchIconSize"
:name="searchIcon"
:color="searchIconColor ? searchIconColor : color"
></u-icon>
@@ -91,6 +91,7 @@
* @property {Boolean} disabled 是否启用输入框(默认 false
* @property {String} borderColor 边框颜色,配置了颜色,才会有边框 (默认 'transparent' )
* @property {String} searchIconColor 搜索图标的颜色,默认同输入框字体颜色 (默认 '#909399' )
* @property {Number | String} searchIconSize 搜索图标的字体默认26
* @property {String} color 输入框字体颜色(默认 '#606266'
* @property {String} placeholderColor placeholder的颜色默认 '#909399'
* @property {String} searchIcon 输入框左边的图标可以为uView图标名称或图片路径 (默认 'search' )

View File

@@ -30,12 +30,12 @@ export default {
type: [Boolean, String, Number],
default: uni.$u.props.switch.value
},
// 打开选择器时的值
// switch打开时的值
activeValue: {
type: [String, Number, Boolean],
default: uni.$u.props.switch.activeValue
},
// 关闭选择器时的值
// switch关闭时的值
inactiveValue: {
type: [String, Number, Boolean],
default: uni.$u.props.switch.inactiveValue

View File

@@ -33,7 +33,7 @@
* switch 开关选择器
* @description 选择开关一般用于只有两个选择,且只能选其一的场景。
* @tutorial https://www.uviewui.com/components/switch.html
* @property {Boolean} loading 是否处于加载中(默认 false
* @property {Boolean} loading 是否处于加载中(默认 false
* @property {Boolean} disabled 是否禁用(默认 false
* @property {String | Number} size 开关尺寸单位px (默认 25
* @property {String} activeColor 打开时的背景色 (默认 '#2979ff'
@@ -44,7 +44,7 @@
* @property {Boolean} asyncChange 是否开启异步变更,开启后需要手动控制输入值 (默认 false
* @property {String | Number} space 圆点与外边框的距离 (默认 0
* @property {Object} customStyle 定义需要用到的外部样式
*
*
* @event {Function} change 在switch打开或关闭时触发
* @example <u-switch v-model="checked" active-color="red" inactive-color="#eee"></u-switch>
*/
@@ -56,7 +56,7 @@
immediate: true,
handler(n) {
if(n !== this.inactiveValue && n !== this.activeValue) {
uni.$u.error('v-mode绑定的值必须为inactiveValue、activeValue二者之一')
uni.$u.error('v-model绑定的值必须为inactiveValue、activeValue二者之一')
}
}
}
@@ -76,7 +76,7 @@
// 如果自定义了“非激活”演示name边框颜色设置为透明(跟非激活颜色一致)
// 这里不能简单的设置为非激活的颜色,否则打开状态时,会有边框,所以需要透明
if(this.customInactiveColor) {
style.borderColor = 'rgba(0, 0, 0, 0)'
style.borderColor = 'rgba(0, 0, 0, 0)'
}
style.backgroundColor = this.value === this.activeValue ? this.activeColor : this.inactiveColor
return style;

View File

@@ -28,7 +28,7 @@ export default {
if (uni.$u.test.func(format)) {
// 如果用户传入的是函数,使用函数格式化
return format(text)
} if (this.formart) {
} if (format) {
// 如果format非正则非函数则使用默认的时间格式化方法进行操作
return uni.$u.timeFormat(text, format)
}

View File

@@ -1,5 +1,5 @@
// 此版本发布于2022-01-28
const version = '2.0.27'
// 此版本发布于2022-02-22
const version = '2.0.28'
// 开发环境才提示,生产环境不会提示
if (process.env.NODE_ENV === 'development') {

View File

@@ -16,6 +16,7 @@ export default {
labelWidth: '',
rightIcon: '',
leftIcon: '',
required: false
required: false,
leftIconStyle: '',
}
}

View File

@@ -23,6 +23,7 @@ export default {
disabled: false,
borderColor: 'transparent',
searchIconColor: '#909399',
searchIconSize: 22,
color: '#606266',
placeholderColor: '#909399',
searchIcon: 'search',

View 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,
};

View File

@@ -1,5 +1,5 @@
import test from './test.js'
import { round } from './digit.js'
/**
* @description 如果value小于min取min如果value大于max取max
* @param {number} min
@@ -278,29 +278,50 @@ if (!String.prototype.padStart) {
* @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
* @returns {string} 返回格式化后的字符串
*/
function timeFormat(dateTime = null, fmt = 'yyyy-mm-dd') {
// 如果为null,则格式化当前时间
if (!dateTime) dateTime = Number(new Date())
// 如果dateTime长度为10或者13则为秒和毫秒的时间戳如果超过13位则为其他的时间格式
if (dateTime.toString().length == 10) dateTime *= 1000
const date = new Date(dateTime)
let ret
const opt = {
'y+': date.getFullYear().toString(), // 年
'm+': (date.getMonth() + 1).toString(), // 月
'd+': date.getDate().toString(), // 日
'h+': date.getHours().toString(), // 时
'M+': date.getMinutes().toString(), // 分
's+': date.getSeconds().toString() // 秒
function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') {
let date
// 若传入时间为假值,则取当前时间
if (!dateTime) {
date = new Date()
}
// 若为unix秒时间戳则转为毫秒时间戳逻辑有点奇怪但不敢改以保证历史兼容
else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
date = new Date(dateTime * 1000)
}
// 若用户传入字符串格式时间戳new Date无法解析需做兼容
else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
date = new Date(Number(dateTime))
}
// 其他都认为符合 RFC 2822 规范
else {
// 处理平台性差异在Safari/Webkit中new Date仅支持/作为分割符的字符串时间
date = new Date(
typeof dateTime === 'string'
? dateTime.replace(/-/g, '/')
: dateTime
)
}
const timeSource = {
'y': date.getFullYear().toString(), // 年
'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
'd': date.getDate().toString().padStart(2, '0'), // 日
'h': date.getHours().toString().padStart(2, '0'), // 时
'M': date.getMinutes().toString().padStart(2, '0'), // 分
's': date.getSeconds().toString().padStart(2, '0') // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
}
for (const k in opt) {
ret = new RegExp(`(${k})`).exec(fmt)
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, '0')))
}
}
return fmt
for (const key in timeSource) {
const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
if (ret) {
// 年可能只需展示两位
const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
}
}
return formatStr
}
/**
@@ -490,12 +511,8 @@ function priceFormat(number, decimals = 0, decimalPoint = '.', thousandsSeparato
const sep = (typeof thousandsSeparator === 'undefined') ? ',' : thousandsSeparator
const dec = (typeof decimalPoint === 'undefined') ? '.' : decimalPoint
let s = ''
const toFixedFix = function(n, prec) {
const k = 10 ** prec
return `${Math.ceil(parseInt(n * k)) / k}`
}
s = (prec ? toFixedFix(n, prec) : `${Math.round(n)}`).split('.')
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`)

View File

@@ -2,7 +2,7 @@
"id": "uview-ui",
"name": "uview-ui",
"displayName": "uView2.0重磅发布,利剑出鞘,一统江湖",
"version": "2.0.27",
"version": "2.0.28",
"description": "uView UI已完美兼容nvue全面的组件和便捷的工具会让您信手拈来如鱼得水",
"keywords": [
"uview",