Commit 7022605f authored by 潘永坪's avatar 潘永坪

分支合并

parent eb8ef934
This diff is collapsed.
<template>
<uvForm
ref="uForm"
:model="model"
:rules="rules"
:errorType="errorType"
:borderBottom="borderBottom"
:labelPosition="labelPosition"
:labelWidth="labelWidth"
:labelAlign="labelAlign"
:labelStyle="labelStyle"
:customStyle="customStyle"
>
<slot />
</uvForm>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u-form被uni-app官方占用了,u-form在nvue中相当于form组件
* 所以在nvue下,取名为u--form,内部其实还是u-form.vue,只不过做一层中转
*/
import uvForm from '../u-form/u-form.vue';
import props from '../u-form/props.js'
export default {
// #ifdef MP-WEIXIN
name: 'u-form',
// #endif
// #ifndef MP-WEIXIN
name: 'u--form',
// #endif
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvForm
},
created() {
this.children = []
},
methods: {
// 手动设置校验的规则,如果规则中有函数的话,微信小程序中会过滤掉,所以只能手动调用设置规则
setRules(rules) {
this.$refs.uForm.setRules(rules)
},
validate() {
/**
* 在微信小程序中,通过this.$parent拿到的父组件是u--form,而不是其内嵌的u-form
* 导致在u-form组件中,拿不到对应的children数组,从而校验无效,所以这里每次调用u-form组件中的
* 对应方法的时候,在小程序中都先将u--form的children赋值给u-form中的children
*/
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.validate()
},
validateField(value, callback) {
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.validateField(value, callback)
},
resetFields() {
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.resetFields()
},
clearValidate(props) {
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.clearValidate(props)
},
setMpData() {
this.$refs.uForm.children = this.children
}
},
}
</script>
<template>
<uvImage
:src="src"
:mode="mode"
:width="width"
:height="height"
:shape="shape"
:radius="radius"
:lazyLoad="lazyLoad"
:showMenuByLongpress="showMenuByLongpress"
:loadingIcon="loadingIcon"
:errorIcon="errorIcon"
:showLoading="showLoading"
:showError="showError"
:fade="fade"
:webp="webp"
:duration="duration"
:bgColor="bgColor"
:customStyle="customStyle"
@click="$emit('click')"
@error="$emit('error')"
@load="$emit('load')"
>
<template v-slot:loading>
<slot name="loading"></slot>
</template>
<template v-slot:error>
<slot name="error"></slot>
</template>
</uvImage>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u-image被uni-app官方占用了,u-image在nvue中相当于image组件
* 所以在nvue下,取名为u--image,内部其实还是u-iamge.vue,只不过做一层中转
*/
import uvImage from '../u-image/u-image.vue';
import props from '../u-image/props.js';
export default {
name: 'u--image',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvImage
},
}
</script>
\ No newline at end of file
<template>
<uvInput
:value="value"
:type="type"
:fixed="fixed"
:disabled="disabled"
:disabledColor="disabledColor"
:clearable="clearable"
:password="password"
:maxlength="maxlength"
:placeholder="placeholder"
:placeholderClass="placeholderClass"
:placeholderStyle="placeholderStyle"
:showWordLimit="showWordLimit"
:confirmType="confirmType"
:confirmHold="confirmHold"
:holdKeyboard="holdKeyboard"
:focus="focus"
:autoBlur="autoBlur"
:disableDefaultPadding="disableDefaultPadding"
:cursor="cursor"
:cursorSpacing="cursorSpacing"
:selectionStart="selectionStart"
:selectionEnd="selectionEnd"
:adjustPosition="adjustPosition"
:inputAlign="inputAlign"
:fontSize="fontSize"
:color="color"
:prefixIcon="prefixIcon"
:suffixIcon="suffixIcon"
:suffixIconStyle="suffixIconStyle"
:prefixIconStyle="prefixIconStyle"
:border="border"
:readonly="readonly"
:shape="shape"
:customStyle="customStyle"
:formatter="formatter"
:ignoreCompositionEvent="ignoreCompositionEvent"
@focus="$emit('focus')"
@blur="e => $emit('blur', e)"
@keyboardheightchange="$emit('keyboardheightchange')"
@change="e => $emit('change', e)"
@input="e => $emit('input', e)"
@confirm="e => $emit('confirm', e)"
@clear="$emit('clear')"
@click="$emit('click')"
>
<!-- #ifdef MP -->
<slot name="prefix"></slot>
<slot name="suffix"></slot>
<!-- #endif -->
<!-- #ifndef MP -->
<slot name="prefix" slot="prefix"></slot>
<slot name="suffix" slot="suffix"></slot>
<!-- #endif -->
</uvInput>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u-input被uni-app官方占用了,u-input在nvue中相当于input组件
* 所以在nvue下,取名为u--input,内部其实还是u-input.vue,只不过做一层中转
*/
import uvInput from '../u-input/u-input.vue';
import props from '../u-input/props.js'
export default {
name: 'u--input',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvInput
},
}
</script>
\ No newline at end of file
<template>
<uvText
:type="type"
:show="show"
:text="text"
:prefixIcon="prefixIcon"
:suffixIcon="suffixIcon"
:mode="mode"
:href="href"
:format="format"
:call="call"
:openType="openType"
:bold="bold"
:block="block"
:lines="lines"
:color="color"
:decoration="decoration"
:size="size"
:iconStyle="iconStyle"
:margin="margin"
:lineHeight="lineHeight"
:align="align"
:wordWrap="wordWrap"
:customStyle="customStyle"
@click="$emit('click')"
></uvText>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u-text被uni-app官方占用了,u-text在nvue中相当于input组件
* 所以在nvue下,取名为u--input,内部其实还是u-text.vue,只不过做一层中转
* 不使用v-bind="$attrs",而是分开独立写传参,是因为微信小程序不支持此写法
*/
import uvText from "../u-text/u-text.vue";
import props from "../u-text/props.js";
export default {
name: "u--text",
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvText,
},
};
</script>
<template>
<uvTextarea
:value="value"
:placeholder="placeholder"
:height="height"
:confirmType="confirmType"
:disabled="disabled"
:count="count"
:focus="focus"
:autoHeight="autoHeight"
:fixed="fixed"
:cursorSpacing="cursorSpacing"
:cursor="cursor"
:showConfirmBar="showConfirmBar"
:selectionStart="selectionStart"
:selectionEnd="selectionEnd"
:adjustPosition="adjustPosition"
:disableDefaultPadding="disableDefaultPadding"
:holdKeyboard="holdKeyboard"
:maxlength="maxlength"
:border="border"
:customStyle="customStyle"
:formatter="formatter"
:ignoreCompositionEvent="ignoreCompositionEvent"
@focus="e => $emit('focus')"
@blur="e => $emit('blur')"
@linechange="e => $emit('linechange', e)"
@confirm="e => $emit('confirm')"
@input="e => $emit('input', e)"
@keyboardheightchange="e => $emit('keyboardheightchange')"
></uvTextarea>
</template>
<script>
/**
* 此组件存在的理由是,在nvue下,u--textarea被uni-app官方占用了,u-textarea在nvue中相当于textarea组件
* 所以在nvue下,取名为u--textarea,内部其实还是u-textarea.vue,只不过做一层中转
*/
import uvTextarea from '../u-textarea/u-textarea.vue';
import props from '../u-textarea/props.js'
export default {
name: 'u--textarea',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvTextarea
},
}
</script>
export default {
props: {
// 操作菜单是否展示 (默认false)
show: {
type: Boolean,
default: uni.$u.props.actionSheet.show
},
// 标题
title: {
type: String,
default: uni.$u.props.actionSheet.title
},
// 选项上方的描述信息
description: {
type: String,
default: uni.$u.props.actionSheet.description
},
// 数据
actions: {
type: Array,
default: uni.$u.props.actionSheet.actions
},
// 取消按钮的文字,不为空时显示按钮
cancelText: {
type: String,
default: uni.$u.props.actionSheet.cancelText
},
// 点击某个菜单项时是否关闭弹窗
closeOnClickAction: {
type: Boolean,
default: uni.$u.props.actionSheet.closeOnClickAction
},
// 处理底部安全区(默认true)
safeAreaInsetBottom: {
type: Boolean,
default: uni.$u.props.actionSheet.safeAreaInsetBottom
},
// 小程序的打开方式
openType: {
type: String,
default: uni.$u.props.actionSheet.openType
},
// 点击遮罩是否允许关闭 (默认true)
closeOnClickOverlay: {
type: Boolean,
default: uni.$u.props.actionSheet.closeOnClickOverlay
},
// 圆角值
round: {
type: [Boolean, String, Number],
default: uni.$u.props.actionSheet.round
}
}
}
export default {
props: {
// 图片地址,Array<String>|Array<Object>形式
urls: {
type: Array,
default: uni.$u.props.album.urls
},
// 指定从数组的对象元素中读取哪个属性作为图片地址
keyName: {
type: String,
default: uni.$u.props.album.keyName
},
// 单图时,图片长边的长度
singleSize: {
type: [String, Number],
default: uni.$u.props.album.singleSize
},
// 多图时,图片边长
multipleSize: {
type: [String, Number],
default: uni.$u.props.album.multipleSize
},
// 多图时,图片水平和垂直之间的间隔
space: {
type: [String, Number],
default: uni.$u.props.album.space
},
// 单图时,图片缩放裁剪的模式
singleMode: {
type: String,
default: uni.$u.props.album.singleMode
},
// 多图时,图片缩放裁剪的模式
multipleMode: {
type: String,
default: uni.$u.props.album.multipleMode
},
// 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量
maxCount: {
type: [String, Number],
default: uni.$u.props.album.maxCount
},
// 是否可以预览图片
previewFullImage: {
type: Boolean,
default: uni.$u.props.album.previewFullImage
},
// 每行展示图片数量,如设置,singleSize和multipleSize将会无效
rowCount: {
type: [String, Number],
default: uni.$u.props.album.rowCount
},
// 超出maxCount时是否显示查看更多的提示
showMore: {
type: Boolean,
default: uni.$u.props.album.showMore
}
}
}
<template>
<view class="u-album">
<view
class="u-album__row"
ref="u-album__row"
v-for="(arr, index) in showUrls"
:forComputedUse="albumWidth"
:key="index"
>
<view
class="u-album__row__wrapper"
v-for="(item, index1) in arr"
:key="index1"
:style="[imageStyle(index + 1, index1 + 1)]"
@tap="previewFullImage ? onPreviewTap(getSrc(item)) : ''"
>
<image
:src="getSrc(item)"
:mode="
urls.length === 1
? imageHeight > 0
? singleMode
: 'widthFix'
: multipleMode
"
:style="[
{
width: imageWidth,
height: imageHeight
}
]"
></image>
<view
v-if="
showMore &&
urls.length > rowCount * showUrls.length &&
index === showUrls.length - 1 &&
index1 === showUrls[showUrls.length - 1].length - 1
"
class="u-album__row__wrapper__text"
>
<u--text
:text="`+${urls.length - maxCount}`"
color="#fff"
:size="multipleSize * 0.3"
align="center"
customStyle="justify-content: center"
></u--text>
</view>
</view>
</view>
</view>
</template>
<script>
import props from './props.js'
// #ifdef APP-NVUE
// 由于weex为阿里的KPI业绩考核的产物,所以不支持百分比单位,这里需要通过dom查询组件的宽度
const dom = uni.requireNativePlugin('dom')
// #endif
/**
* Album 相册
* @description 本组件提供一个类似相册的功能,让开发者开发起来更加得心应手。减少重复的模板代码
* @tutorial https://www.uviewui.com/components/album.html
*
* @property {Array} urls 图片地址列表 Array<String>|Array<Object>形式
* @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
* @property {String | Number} singleSize 单图时,图片长边的长度 (默认 180 )
* @property {String | Number} multipleSize 多图时,图片边长 (默认 70 )
* @property {String | Number} space 多图时,图片水平和垂直之间的间隔 (默认 6 )
* @property {String} singleMode 单图时,图片缩放裁剪的模式 (默认 'scaleToFill' )
* @property {String} multipleMode 多图时,图片缩放裁剪的模式 (默认 'aspectFill' )
* @property {String | Number} maxCount 取消按钮的提示文字 (默认 9 )
* @property {Boolean} previewFullImage 是否可以预览图片 (默认 true )
* @property {String | Number} rowCount 每行展示图片数量,如设置,singleSize和multipleSize将会无效 (默认 3 )
* @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
*
* @event {Function} albumWidth 某些特殊的情况下,需要让文字与相册的宽度相等,这里事件的形式对外发送 (回调参数 width )
* @example <u-album :urls="urls2" @albumWidth="width => albumWidth = width" multipleSize="68" ></u-album>
*/
export default {
name: 'u-album',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
// 单图的宽度
singleWidth: 0,
// 单图的高度
singleHeight: 0,
// 单图时,如果无法获取图片的尺寸信息,让图片宽度默认为容器的一定百分比
singlePercent: 0.6
}
},
watch: {
urls: {
immediate: true,
handler(newVal) {
if (newVal.length === 1) {
this.getImageRect()
}
}
}
},
computed: {
imageStyle() {
return (index1, index2) => {
const { space, rowCount, multipleSize, urls } = this,
{ addUnit, addStyle } = uni.$u,
rowLen = this.showUrls.length,
allLen = this.urls.length
const style = {
marginRight: addUnit(space),
marginBottom: addUnit(space)
}
// 如果为最后一行,则每个图片都无需下边框
if (index1 === rowLen) style.marginBottom = 0
// 每行的最右边一张和总长度的最后一张无需右边框
if (
index2 === rowCount ||
(index1 === rowLen &&
index2 === this.showUrls[index1 - 1].length)
)
style.marginRight = 0
return style
}
},
// 将数组划分为二维数组
showUrls() {
const arr = []
this.urls.map((item, index) => {
// 限制最大展示数量
if (index + 1 <= this.maxCount) {
// 计算该元素为第几个素组内
const itemIndex = Math.floor(index / this.rowCount)
// 判断对应的索引是否存在
if (!arr[itemIndex]) {
arr[itemIndex] = []
}
arr[itemIndex].push(item)
}
})
return arr
},
imageWidth() {
return uni.$u.addUnit(
this.urls.length === 1 ? this.singleWidth : this.multipleSize
)
},
imageHeight() {
return uni.$u.addUnit(
this.urls.length === 1 ? this.singleHeight : this.multipleSize
)
},
// 此变量无实际用途,仅仅是为了利用computed特性,让其在urls长度等变化时,重新计算图片的宽度
// 因为用户在某些特殊的情况下,需要让文字与相册的宽度相等,所以这里事件的形式对外发送
albumWidth() {
let width = 0
if (this.urls.length === 1) {
width = this.singleWidth
} else {
width =
this.showUrls[0].length * this.multipleSize +
this.space * (this.showUrls[0].length - 1)
}
this.$emit('albumWidth', width)
return width
}
},
methods: {
// 预览图片
onPreviewTap(url) {
const urls = this.urls.map((item) => {
return this.getSrc(item)
})
uni.previewImage({
current: url,
urls
})
},
// 获取图片的路径
getSrc(item) {
return uni.$u.test.object(item)
? (this.keyName && item[this.keyName]) || item.src
: item
},
// 单图时,获取图片的尺寸
// 在小程序中,需要将网络图片的的域名添加到小程序的download域名才可能获取尺寸
// 在没有添加的情况下,让单图宽度默认为盒子的一定宽度(singlePercent)
getImageRect() {
const src = this.getSrc(this.urls[0])
uni.getImageInfo({
src,
success: (res) => {
// 判断图片横向还是竖向展示方式
const isHorizotal = res.width >= res.height
this.singleWidth = isHorizotal
? this.singleSize
: (res.width / res.height) * this.singleSize
this.singleHeight = !isHorizotal
? this.singleSize
: (res.height / res.width) * this.singleWidth
},
fail: () => {
this.getComponentWidth()
}
})
},
// 获取组件的宽度
async getComponentWidth() {
// 延时一定时间,以获取dom尺寸
await uni.$u.sleep(30)
// #ifndef APP-NVUE
this.$uGetRect('.u-album__row').then((size) => {
this.singleWidth = size.width * this.singlePercent
})
// #endif
// #ifdef APP-NVUE
// 这里ref="u-album__row"所在的标签为通过for循环出来,导致this.$refs['u-album__row']是一个数组
const ref = this.$refs['u-album__row'][0]
ref &&
dom.getComponentRect(ref, (res) => {
this.singleWidth = res.size.width * this.singlePercent
})
// #endif
}
}
}
</script>
<style lang="scss" scoped>
@import '../../libs/css/components.scss';
.u-album {
@include flex(column);
&__row {
@include flex(row);
flex-wrap: wrap;
&__wrapper {
position: relative;
&__text {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.3);
@include flex(row);
justify-content: center;
align-items: center;
}
}
}
}
</style>
\ No newline at end of file
export default {
props: {
// 显示文字
title: {
type: String,
default: uni.$u.props.alert.title
},
// 主题,success/warning/info/error
type: {
type: String,
default: uni.$u.props.alert.type
},
// 辅助性文字
description: {
type: String,
default: uni.$u.props.alert.description
},
// 是否可关闭
closable: {
type: Boolean,
default: uni.$u.props.alert.closable
},
// 是否显示图标
showIcon: {
type: Boolean,
default: uni.$u.props.alert.showIcon
},
// 浅或深色调,light-浅色,dark-深色
effect: {
type: String,
default: uni.$u.props.alert.effect
},
// 文字是否居中
center: {
type: Boolean,
default: uni.$u.props.alert.center
},
// 字体大小
fontSize: {
type: [String, Number],
default: uni.$u.props.alert.fontSize
}
}
}
<template>
<u-transition
mode="fade"
:show="show"
>
<view
class="u-alert"
:class="[`u-alert--${type}--${effect}`]"
@tap.stop="clickHandler"
:style="[$u.addStyle(customStyle)]"
>
<view
class="u-alert__icon"
v-if="showIcon"
>
<u-icon
:name="iconName"
size="18"
:color="iconColor"
></u-icon>
</view>
<view
class="u-alert__content"
:style="[{
paddingRight: closable ? '20px' : 0
}]"
>
<text
class="u-alert__content__title"
v-if="title"
:style="[{
fontSize: $u.addUnit(fontSize),
textAlign: center ? 'center' : 'left'
}]"
:class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
>{{ title }}</text>
<text
class="u-alert__content__desc"
v-if="description"
:style="[{
fontSize: $u.addUnit(fontSize),
textAlign: center ? 'center' : 'left'
}]"
:class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
>{{ description }}</text>
</view>
<view
class="u-alert__close"
v-if="closable"
@tap.stop="closeHandler"
>
<u-icon
name="close"
:color="iconColor"
size="15"
></u-icon>
</view>
</view>
</u-transition>
</template>
<script>
import props from './props.js';
/**
* Alert 警告提示
* @description 警告提示,展现需要关注的信息。
* @tutorial https://www.uviewui.com/components/alertTips.html
*
* @property {String} title 显示的文字
* @property {String} type 使用预设的颜色 (默认 'warning' )
* @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选
* @property {Boolean} closable 关闭按钮(默认为叉号icon图标) (默认 false )
* @property {Boolean} showIcon 是否显示左边的辅助图标 ( 默认 false )
* @property {String} effect 多图时,图片缩放裁剪的模式 (默认 'light' )
* @property {Boolean} center 文字是否居中 (默认 false )
* @property {String | Number} fontSize 字体大小 (默认 14 )
* @property {Object} customStyle 定义需要用到的外部样式
* @event {Function} click 点击组件时触发
* @example <u-alert :title="title" type = "warning" :closable="closable" :description = "description"></u-alert>
*/
export default {
name: 'u-alert',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
show: true
}
},
computed: {
iconColor() {
return this.effect === 'light' ? this.type : '#fff'
},
// 不同主题对应不同的图标
iconName() {
switch (this.type) {
case 'success':
return 'checkmark-circle-fill';
break;
case 'error':
return 'close-circle-fill';
break;
case 'warning':
return 'error-circle-fill';
break;
case 'info':
return 'info-circle-fill';
break;
case 'primary':
return 'more-circle-fill';
break;
default:
return 'error-circle-fill';
}
}
},
methods: {
// 点击内容
clickHandler() {
this.$emit('click')
},
// 点击关闭按钮
closeHandler() {
this.show = false
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-alert {
position: relative;
background-color: $u-primary;
padding: 8px 10px;
@include flex(row);
align-items: center;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
&--primary--dark {
background-color: $u-primary;
}
&--primary--light {
background-color: #ecf5ff;
}
&--error--dark {
background-color: $u-error;
}
&--error--light {
background-color: #FEF0F0;
}
&--success--dark {
background-color: $u-success;
}
&--success--light {
background-color: #f5fff0;
}
&--warning--dark {
background-color: $u-warning;
}
&--warning--light {
background-color: #FDF6EC;
}
&--info--dark {
background-color: $u-info;
}
&--info--light {
background-color: #f4f4f5;
}
&__icon {
margin-right: 5px;
}
&__content {
@include flex(column);
flex: 1;
&__title {
color: $u-main-color;
font-size: 14px;
font-weight: bold;
color: #fff;
margin-bottom: 2px;
}
&__desc {
color: $u-main-color;
font-size: 14px;
flex-wrap: wrap;
color: #fff;
}
}
&__title--dark,
&__desc--dark {
color: #FFFFFF;
}
&__text--primary--light,
&__text--primary--light {
color: $u-primary;
}
&__text--success--light,
&__text--success--light {
color: $u-success;
}
&__text--warning--light,
&__text--warning--light {
color: $u-warning;
}
&__text--error--light,
&__text--error--light {
color: $u-error;
}
&__text--info--light,
&__text--info--light {
color: $u-info;
}
&__close {
position: absolute;
top: 11px;
right: 10px;
}
}
</style>
export default {
props: {
// 头像图片组
urls: {
type: Array,
default: uni.$u.props.avatarGroup.urls
},
// 最多展示的头像数量
maxCount: {
type: [String, Number],
default: uni.$u.props.avatarGroup.maxCount
},
// 头像形状
shape: {
type: String,
default: uni.$u.props.avatarGroup.shape
},
// 图片裁剪模式
mode: {
type: String,
default: uni.$u.props.avatarGroup.mode
},
// 超出maxCount时是否显示查看更多的提示
showMore: {
type: Boolean,
default: uni.$u.props.avatarGroup.showMore
},
// 头像大小
size: {
type: [String, Number],
default: uni.$u.props.avatarGroup.size
},
// 指定从数组的对象元素中读取哪个属性作为图片地址
keyName: {
type: String,
default: uni.$u.props.avatarGroup.keyName
},
// 头像之间的遮挡比例
gap: {
type: [String, Number],
validator(value) {
return value >= 0 && value <= 1
},
default: uni.$u.props.avatarGroup.gap
},
// 需额外显示的值
extraValue: {
type: [Number, String],
default: uni.$u.props.avatarGroup.extraValue
}
}
}
<template>
<view class="u-avatar-group">
<view
class="u-avatar-group__item"
v-for="(item, index) in showUrl"
:key="index"
:style="{
marginLeft: index === 0 ? 0 : $u.addUnit(-size * gap)
}"
>
<u-avatar
:size="size"
:shape="shape"
:mode="mode"
:src="$u.test.object(item) ? keyName && item[keyName] || item.url : item"
></u-avatar>
<view
class="u-avatar-group__item__show-more"
v-if="showMore && index === showUrl.length - 1 && (urls.length > maxCount || extraValue > 0)"
@tap="clickHandler"
>
<u--text
color="#ffffff"
:size="size * 0.4"
:text="`+${extraValue || urls.length - showUrl.length}`"
align="center"
customStyle="justify-content: center"
></u--text>
</view>
</view>
</view>
</template>
<script>
import props from './props.js';
/**
* AvatarGroup 头像组
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。
* @tutorial https://www.uviewui.com/components/avatar.html
*
* @property {Array} urls 头像图片组 (默认 [] )
* @property {String | Number} maxCount 最多展示的头像数量 ( 默认 5 )
* @property {String} shape 头像形状( 'circle' (默认) | 'square' )
* @property {String} mode 图片裁剪模式(默认 'scaleToFill' )
* @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true )
* @property {String | Number} size 头像大小 (默认 40 )
* @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
* @property {String | Number} gap 头像之间的遮挡比例(0.4代表遮挡40%) (默认 0.5 )
* @property {String | Number} extraValue 需额外显示的值
* @event {Function} showMore 头像组更多点击
* @example <u-avatar-group:urls="urls" size="35" gap="0.4" ></u-avatar-group:urls=>
*/
export default {
name: 'u-avatar-group',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
}
},
computed: {
showUrl() {
return this.urls.slice(0, this.maxCount)
}
},
methods: {
clickHandler() {
this.$emit('showMore')
}
},
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-avatar-group {
@include flex;
&__item {
margin-left: -10px;
position: relative;
&--no-indent {
// 如果你想质疑作者不会使用:first-child,说明你太年轻,因为nvue不支持
margin-left: 0;
}
&__show-more {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.3);
@include flex;
align-items: center;
justify-content: center;
border-radius: 100px;
}
}
}
</style>
export default {
props: {
// 头像图片路径(不能为相对路径)
src: {
type: String,
default: uni.$u.props.avatar.src
},
// 头像形状,circle-圆形,square-方形
shape: {
type: String,
default: uni.$u.props.avatar.shape
},
// 头像尺寸
size: {
type: [String, Number],
default: uni.$u.props.avatar.size
},
// 裁剪模式
mode: {
type: String,
default: uni.$u.props.avatar.mode
},
// 显示的文字
text: {
type: String,
default: uni.$u.props.avatar.text
},
// 背景色
bgColor: {
type: String,
default: uni.$u.props.avatar.bgColor
},
// 文字颜色
color: {
type: String,
default: uni.$u.props.avatar.color
},
// 文字大小
fontSize: {
type: [String, Number],
default: uni.$u.props.avatar.fontSize
},
// 显示的图标
icon: {
type: String,
default: uni.$u.props.avatar.icon
},
// 显示小程序头像,只对百度,微信,QQ小程序有效
mpAvatar: {
type: Boolean,
default: uni.$u.props.avatar.mpAvatar
},
// 是否使用随机背景色
randomBgColor: {
type: Boolean,
default: uni.$u.props.avatar.randomBgColor
},
// 加载失败的默认头像(组件有内置默认图片)
defaultUrl: {
type: String,
default: uni.$u.props.avatar.defaultUrl
},
// 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
colorIndex: {
type: [String, Number],
// 校验参数规则,索引在0-19之间
validator(n) {
return uni.$u.test.range(n, [0, 19]) || n === ''
},
default: uni.$u.props.avatar.colorIndex
},
// 组件标识符
name: {
type: String,
default: uni.$u.props.avatar.name
}
}
}
export default {
props: {
// 返回顶部的形状,circle-圆形,square-方形
mode: {
type: String,
default: uni.$u.props.backtop.mode
},
// 自定义图标
icon: {
type: String,
default: uni.$u.props.backtop.icon
},
// 提示文字
text: {
type: String,
default: uni.$u.props.backtop.text
},
// 返回顶部滚动时间
duration: {
type: [String, Number],
default: uni.$u.props.backtop.duration
},
// 滚动距离
scrollTop: {
type: [String, Number],
default: uni.$u.props.backtop.scrollTop
},
// 距离顶部多少距离显示,单位px
top: {
type: [String, Number],
default: uni.$u.props.backtop.top
},
// 返回顶部按钮到底部的距离,单位px
bottom: {
type: [String, Number],
default: uni.$u.props.backtop.bottom
},
// 返回顶部按钮到右边的距离,单位px
right: {
type: [String, Number],
default: uni.$u.props.backtop.right
},
// 层级
zIndex: {
type: [String, Number],
default: uni.$u.props.backtop.zIndex
},
// 图标的样式,对象形式
iconStyle: {
type: Object,
default: uni.$u.props.backtop.iconStyle
}
}
}
export default {
props: {
// 是否显示圆点
isDot: {
type: Boolean,
default: uni.$u.props.badge.isDot
},
// 显示的内容
value: {
type: [Number, String],
default: uni.$u.props.badge.value
},
// 是否显示
show: {
type: Boolean,
default: uni.$u.props.badge.show
},
// 最大值,超过最大值会显示 '{max}+'
max: {
type: [Number, String],
default: uni.$u.props.badge.max
},
// 主题类型,error|warning|success|primary
type: {
type: String,
default: uni.$u.props.badge.type
},
// 当数值为 0 时,是否展示 Badge
showZero: {
type: Boolean,
default: uni.$u.props.badge.showZero
},
// 背景颜色,优先级比type高,如设置,type参数会失效
bgColor: {
type: [String, null],
default: uni.$u.props.badge.bgColor
},
// 字体颜色
color: {
type: [String, null],
default: uni.$u.props.badge.color
},
// 徽标形状,circle-四角均为圆角,horn-左下角为直角
shape: {
type: String,
default: uni.$u.props.badge.shape
},
// 设置数字的显示方式,overflow|ellipsis|limit
// overflow会根据max字段判断,超出显示`${max}+`
// ellipsis会根据max判断,超出显示`${max}...`
// limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数
numberType: {
type: String,
default: uni.$u.props.badge.numberType
},
// 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
offset: {
type: Array,
default: uni.$u.props.badge.offset
},
// 是否反转背景和字体颜色
inverted: {
type: Boolean,
default: uni.$u.props.badge.inverted
},
// 是否绝对定位
absolute: {
type: Boolean,
default: uni.$u.props.badge.absolute
}
}
}
$u-button-active-opacity:0.75 !default;
$u-button-loading-text-margin-left:4px !default;
$u-button-text-color: #FFFFFF !default;
$u-button-text-plain-error-color:$u-error !default;
$u-button-text-plain-warning-color:$u-warning !default;
$u-button-text-plain-success-color:$u-success !default;
$u-button-text-plain-info-color:$u-info !default;
$u-button-text-plain-primary-color:$u-primary !default;
.u-button {
&--active {
opacity: $u-button-active-opacity;
}
&--active--plain {
background-color: rgb(217, 217, 217);
}
&__loading-text {
margin-left:$u-button-loading-text-margin-left;
}
&__text,
&__loading-text {
color:$u-button-text-color;
}
&__text--plain--error {
color:$u-button-text-plain-error-color;
}
&__text--plain--warning {
color:$u-button-text-plain-warning-color;
}
&__text--plain--success{
color:$u-button-text-plain-success-color;
}
&__text--plain--info {
color:$u-button-text-plain-info-color;
}
&__text--plain--primary {
color:$u-button-text-plain-primary-color;
}
}
\ No newline at end of file
/*
* @Author : LQ
* @Description :
* @version : 1.0
* @Date : 2021-08-16 10:04:04
* @LastAuthor : LQ
* @lastTime : 2021-08-16 10:04:24
* @FilePath : /u-view2.0/uview-ui/components/u-button/props.js
*/
export default {
props: {
// 是否细边框
hairline: {
type: Boolean,
default: uni.$u.props.button.hairline
},
// 按钮的预置样式,info,primary,error,warning,success
type: {
type: String,
default: uni.$u.props.button.type
},
// 按钮尺寸,large,normal,small,mini
size: {
type: String,
default: uni.$u.props.button.size
},
// 按钮形状,circle(两边为半圆),square(带圆角)
shape: {
type: String,
default: uni.$u.props.button.shape
},
// 按钮是否镂空
plain: {
type: Boolean,
default: uni.$u.props.button.plain
},
// 是否禁止状态
disabled: {
type: Boolean,
default: uni.$u.props.button.disabled
},
// 是否加载中
loading: {
type: Boolean,
default: uni.$u.props.button.loading
},
// 加载中提示文字
loadingText: {
type: [String, Number],
default: uni.$u.props.button.loadingText
},
// 加载状态图标类型
loadingMode: {
type: String,
default: uni.$u.props.button.loadingMode
},
// 加载图标大小
loadingSize: {
type: [String, Number],
default: uni.$u.props.button.loadingSize
},
// 开放能力,具体请看uniapp稳定关于button组件部分说明
// https://uniapp.dcloud.io/component/button
openType: {
type: String,
default: uni.$u.props.button.openType
},
// 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
// 取值为submit(提交表单),reset(重置表单)
formType: {
type: String,
default: uni.$u.props.button.formType
},
// 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效
// 只微信小程序、QQ小程序有效
appParameter: {
type: String,
default: uni.$u.props.button.appParameter
},
// 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效
hoverStopPropagation: {
type: Boolean,
default: uni.$u.props.button.hoverStopPropagation
},
// 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效
lang: {
type: String,
default: uni.$u.props.button.lang
},
// 会话来源,open-type="contact"时有效。只微信小程序有效
sessionFrom: {
type: String,
default: uni.$u.props.button.sessionFrom
},
// 会话内消息卡片标题,open-type="contact"时有效
// 默认当前标题,只微信小程序有效
sendMessageTitle: {
type: String,
default: uni.$u.props.button.sendMessageTitle
},
// 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效
// 默认当前分享路径,只微信小程序有效
sendMessagePath: {
type: String,
default: uni.$u.props.button.sendMessagePath
},
// 会话内消息卡片图片,open-type="contact"时有效
// 默认当前页面截图,只微信小程序有效
sendMessageImg: {
type: String,
default: uni.$u.props.button.sendMessageImg
},
// 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,
// 用户点击后可以快速发送小程序消息,open-type="contact"时有效
showMessageCard: {
type: Boolean,
default: uni.$u.props.button.showMessageCard
},
// 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取
dataName: {
type: String,
default: uni.$u.props.button.dataName
},
// 节流,一定时间内只能触发一次
throttleTime: {
type: [String, Number],
default: uni.$u.props.button.throttleTime
},
// 按住后多久出现点击态,单位毫秒
hoverStartTime: {
type: [String, Number],
default: uni.$u.props.button.hoverStartTime
},
// 手指松开后点击态保留时间,单位毫秒
hoverStayTime: {
type: [String, Number],
default: uni.$u.props.button.hoverStayTime
},
// 按钮文字,之所以通过props传入,是因为slot传入的话
// nvue中无法控制文字的样式
text: {
type: [String, Number],
default: uni.$u.props.button.text
},
// 按钮图标
icon: {
type: String,
default: uni.$u.props.button.icon
},
// 按钮图标
iconColor: {
type: String,
default: uni.$u.props.button.icon
},
// 按钮颜色,支持传入linear-gradient渐变色
color: {
type: String,
default: uni.$u.props.button.color
}
}
}
// nvue下hover-class无效
$u-button-before-top:50% !default;
$u-button-before-left:50% !default;
$u-button-before-width:100% !default;
$u-button-before-height:100% !default;
$u-button-before-transform:translate(-50%, -50%) !default;
$u-button-before-opacity:0 !default;
$u-button-before-background-color:#000 !default;
$u-button-before-border-color:#000 !default;
$u-button-active-before-opacity:.15 !default;
$u-button-icon-margin-left:4px !default;
$u-button-plain-u-button-info-color:$u-info;
$u-button-plain-u-button-success-color:$u-success;
$u-button-plain-u-button-error-color:$u-error;
$u-button-plain-u-button-warning-color:$u-error;
.u-button {
width: 100%;
&__text {
white-space: nowrap;
line-height: 1;
}
&:before {
position: absolute;
top:$u-button-before-top;
left:$u-button-before-left;
width:$u-button-before-width;
height:$u-button-before-height;
border: inherit;
border-radius: inherit;
transform:$u-button-before-transform;
opacity:$u-button-before-opacity;
content: " ";
background-color:$u-button-before-background-color;
border-color:$u-button-before-border-color;
}
&--active {
&:before {
opacity: .15
}
}
&__icon+&__text:not(:empty),
&__loading-text {
margin-left:$u-button-icon-margin-left;
}
&--plain {
&.u-button--primary {
color: $u-primary;
}
}
&--plain {
&.u-button--info {
color:$u-button-plain-u-button-info-color;
}
}
&--plain {
&.u-button--success {
color:$u-button-plain-u-button-success-color;
}
}
&--plain {
&.u-button--error {
color:$u-button-plain-u-button-error-color;
}
}
&--plain {
&.u-button--warning {
color:$u-button-plain-u-button-warning-color;
}
}
}
<template>
<view class="u-calendar-header u-border-bottom">
<text
class="u-calendar-header__title"
v-if="showTitle"
>{{ title }}</text>
<text
class="u-calendar-header__subtitle"
v-if="showSubtitle"
>{{ subtitle }}</text>
<view class="u-calendar-header__weekdays">
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
</view>
</view>
</template>
<script>
export default {
name: 'u-calendar-header',
mixins: [uni.$u.mpMixin, uni.$u.mixin],
props: {
// 标题
title: {
type: String,
default: ''
},
// 副标题
subtitle: {
type: String,
default: ''
},
// 是否显示标题
showTitle: {
type: Boolean,
default: true
},
// 是否显示副标题
showSubtitle: {
type: Boolean,
default: true
},
},
data() {
return {
}
},
methods: {
name() {
}
},
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-calendar-header {
padding-bottom: 4px;
&__title {
font-size: 16px;
color: $u-main-color;
text-align: center;
height: 42px;
line-height: 42px;
font-weight: bold;
}
&__subtitle {
font-size: 14px;
color: $u-main-color;
height: 40px;
text-align: center;
line-height: 40px;
font-weight: bold;
}
&__weekdays {
@include flex;
justify-content: space-between;
&__weekday {
font-size: 13px;
color: $u-main-color;
line-height: 30px;
flex: 1;
text-align: center;
}
}
}
</style>
This diff is collapsed.
export default {
props: {
// 日历顶部标题
title: {
type: String,
default: uni.$u.props.calendar.title
},
// 是否显示标题
showTitle: {
type: Boolean,
default: uni.$u.props.calendar.showTitle
},
// 是否显示副标题
showSubtitle: {
type: Boolean,
default: uni.$u.props.calendar.showSubtitle
},
// 日期类型选择,single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围
mode: {
type: String,
default: uni.$u.props.calendar.mode
},
// mode=range时,第一个日期底部的提示文字
startText: {
type: String,
default: uni.$u.props.calendar.startText
},
// mode=range时,最后一个日期底部的提示文字
endText: {
type: String,
default: uni.$u.props.calendar.endText
},
// 自定义列表
customList: {
type: Array,
default: uni.$u.props.calendar.customList
},
// 主题色,对底部按钮和选中日期有效
color: {
type: String,
default: uni.$u.props.calendar.color
},
// 最小的可选日期
minDate: {
type: [String, Number],
default: uni.$u.props.calendar.minDate
},
// 最大可选日期
maxDate: {
type: [String, Number],
default: uni.$u.props.calendar.maxDate
},
// 默认选中的日期,mode为multiple或range是必须为数组格式
defaultDate: {
type: [Array, String, Date, null],
default: uni.$u.props.calendar.defaultDate
},
// mode=multiple时,最多可选多少个日期
maxCount: {
type: [String, Number],
default: uni.$u.props.calendar.maxCount
},
// 日期行高
rowHeight: {
type: [String, Number],
default: uni.$u.props.calendar.rowHeight
},
// 日期格式化函数
formatter: {
type: [Function, null],
default: uni.$u.props.calendar.formatter
},
// 是否显示农历
showLunar: {
type: Boolean,
default: uni.$u.props.calendar.showLunar
},
// 是否显示月份背景色
showMark: {
type: Boolean,
default: uni.$u.props.calendar.showMark
},
// 确定按钮的文字
confirmText: {
type: String,
default: uni.$u.props.calendar.confirmText
},
// 确认按钮处于禁用状态时的文字
confirmDisabledText: {
type: String,
default: uni.$u.props.calendar.confirmDisabledText
},
// 是否显示日历弹窗
show: {
type: Boolean,
default: uni.$u.props.calendar.show
},
// 是否允许点击遮罩关闭日历
closeOnClickOverlay: {
type: Boolean,
default: uni.$u.props.calendar.closeOnClickOverlay
},
// 是否为只读状态,只读状态下禁止选择日期
readonly: {
type: Boolean,
default: uni.$u.props.calendar.readonly
},
// 是否展示确认按钮
showConfirm: {
type: Boolean,
default: uni.$u.props.calendar.showConfirm
},
// 日期区间最多可选天数,默认无限制,mode = range时有效
maxRange: {
type: [Number, String],
default: uni.$u.props.calendar.maxRange
},
// 范围选择超过最多可选天数时的提示文案,mode = range时有效
rangePrompt: {
type: String,
default: uni.$u.props.calendar.rangePrompt
},
// 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效
showRangePrompt: {
type: Boolean,
default: uni.$u.props.calendar.showRangePrompt
},
// 是否允许日期范围的起止时间为同一天,mode = range时有效
allowSameDay: {
type: Boolean,
default: uni.$u.props.calendar.allowSameDay
},
// 圆角值
round: {
type: [Boolean, String, Number],
default: uni.$u.props.calendar.round
},
// 最多展示月份数量
monthNum: {
type: [Number, String],
default: 3
}
}
}
export default {
methods: {
// 设置月份数据
setMonth() {
// 月初是周几
const day = dayjs(this.date).date(1).day()
const start = day == 0 ? 6 : day - 1
// 本月天数
const days = dayjs(this.date).endOf('month').format('D')
// 上个月天数
const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D')
// 日期数据
const arr = []
// 清空表格
this.month = []
// 添加上月数据
arr.push(
...new Array(start).fill(1).map((e, i) => {
const day = prevDays - start + i + 1
return {
value: day,
disabled: true,
date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD')
}
})
)
// 添加本月数据
arr.push(
...new Array(days - 0).fill(1).map((e, i) => {
const day = i + 1
return {
value: day,
date: dayjs(this.date).date(day).format('YYYY-MM-DD')
}
})
)
// 添加下个月
arr.push(
...new Array(42 - days - start).fill(1).map((e, i) => {
const day = i + 1
return {
value: day,
disabled: true,
date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD')
}
})
)
// 分割数组
for (let n = 0; n < arr.length; n += 7) {
this.month.push(
arr.slice(n, n + 7).map((e, i) => {
e.index = i + n
// 自定义信息
const custom = this.customList.find((c) => c.date == e.date)
// 农历
if (this.lunar) {
const {
IDayCn,
IMonthCn
} = this.getLunar(e.date)
e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn
}
return {
...e,
...custom
}
})
)
}
}
}
}
export default {
props: {
// 是否打乱键盘按键的顺序
random: {
type: Boolean,
default: false
},
// 输入一个中文后,是否自动切换到英文
autoChange: {
type: Boolean,
default: false
}
}
}
export default {
props: {
// 分组标题
title: {
type: String,
default: uni.$u.props.cellGroup.title
},
// 是否显示外边框
border: {
type: Boolean,
default: uni.$u.props.cellGroup.border
}
}
}
export default {
props: {
// 标题
title: {
type: [String, Number],
default: uni.$u.props.cell.title
},
// 标题下方的描述信息
label: {
type: [String, Number],
default: uni.$u.props.cell.label
},
// 右侧的内容
value: {
type: [String, Number],
default: uni.$u.props.cell.value
},
// 左侧图标名称,或者图片链接(本地文件建议使用绝对地址)
icon: {
type: String,
default: uni.$u.props.cell.icon
},
// 是否禁用cell
disabled: {
type: Boolean,
default: uni.$u.props.cell.disabled
},
// 是否显示下边框
border: {
type: Boolean,
default: uni.$u.props.cell.border
},
// 内容是否垂直居中(主要是针对右侧的value部分)
center: {
type: Boolean,
default: uni.$u.props.cell.center
},
// 点击后跳转的URL地址
url: {
type: String,
default: uni.$u.props.cell.url
},
// 链接跳转的方式,内部使用的是uView封装的route方法,可能会进行拦截操作
linkType: {
type: String,
default: uni.$u.props.cell.linkType
},
// 是否开启点击反馈(表现为点击时加上灰色背景)
clickable: {
type: Boolean,
default: uni.$u.props.cell.clickable
},
// 是否展示右侧箭头并开启点击反馈
isLink: {
type: Boolean,
default: uni.$u.props.cell.isLink
},
// 是否显示表单状态下的必填星号(此组件可能会内嵌入input组件)
required: {
type: Boolean,
default: uni.$u.props.cell.required
},
// 右侧的图标箭头
rightIcon: {
type: String,
default: uni.$u.props.cell.rightIcon
},
// 右侧箭头的方向,可选值为:left,up,down
arrowDirection: {
type: String,
default: uni.$u.props.cell.arrowDirection
},
// 左侧图标样式
iconStyle: {
type: [Object, String],
default: () => {
return uni.$u.props.cell.iconStyle
}
},
// 右侧箭头图标的样式
rightIconStyle: {
type: [Object, String],
default: () => {
return uni.$u.props.cell.rightIconStyle
}
},
// 标题的样式
titleStyle: {
type: [Object, String],
default: () => {
return uni.$u.props.cell.titleStyle
}
},
// 单位元的大小,可选值为large
size: {
type: String,
default: uni.$u.props.cell.size
},
// 点击cell是否阻止事件传播
stop: {
type: Boolean,
default: uni.$u.props.cell.stop
},
// 标识符,cell被点击时返回
name: {
type: [Number, String],
default: uni.$u.props.cell.name
}
}
}
<template>
<view class="u-cell" :class="[customClass]" :style="[$u.addStyle(customStyle)]"
:hover-class="(!disabled && (clickable || isLink)) ? 'u-cell--clickable' : ''" :hover-stay-time="250"
@tap="clickHandler">
<view class="u-cell__body" :class="[ center && 'u-cell--center', size === 'large' && 'u-cell__body--large']">
<view class="u-cell__body__content">
<view class="u-cell__left-icon-wrap" v-if="$slots.icon || icon">
<slot name="icon" v-if="$slots.icon">
</slot>
<u-icon v-else :name="icon" :custom-style="iconStyle" :size="size === 'large' ? 22 : 18"></u-icon>
</view>
<view class="u-cell__title">
<slot name="title">
<text v-if="title" class="u-cell__title-text" :style="[titleTextStyle]"
:class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__title-text--large']">{{ title }}</text>
</slot>
<slot name="label">
<text class="u-cell__label" v-if="label"
:class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__label--large']">{{ label }}</text>
</slot>
</view>
</view>
<slot name="value">
<text class="u-cell__value"
:class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__value--large']"
v-if="!$u.test.empty(value)">{{ value }}</text>
</slot>
<view class="u-cell__right-icon-wrap" v-if="$slots['right-icon'] || isLink"
:class="[`u-cell__right-icon-wrap--${arrowDirection}`]">
<slot name="right-icon" v-if="$slots['right-icon']">
</slot>
<u-icon v-else :name="rightIcon" :custom-style="rightIconStyle" :color="disabled ? '#c8c9cc' : 'info'"
:size="size === 'large' ? 18 : 16"></u-icon>
</view>
</view>
<u-line v-if="border"></u-line>
</view>
</template>
<script>
import props from './props.js';
/**
* cell 单元格
* @description cell单元格一般用于一组列表的情况,比如个人中心页,设置页等。
* @tutorial https://uviewui.com/components/cell.html
* @property {String | Number} title 标题
* @property {String | Number} label 标题下方的描述信息
* @property {String | Number} value 右侧的内容
* @property {String} icon 左侧图标名称,或者图片链接(本地文件建议使用绝对地址)
* @property {Boolean} disabled 是否禁用cell
* @property {Boolean} border 是否显示下边框 (默认 true )
* @property {Boolean} center 内容是否垂直居中(主要是针对右侧的value部分) (默认 false )
* @property {String} url 点击后跳转的URL地址
* @property {String} linkType 链接跳转的方式,内部使用的是uView封装的route方法,可能会进行拦截操作 (默认 'navigateTo' )
* @property {Boolean} clickable 是否开启点击反馈(表现为点击时加上灰色背景) (默认 false )
* @property {Boolean} isLink 是否展示右侧箭头并开启点击反馈 (默认 false )
* @property {Boolean} required 是否显示表单状态下的必填星号(此组件可能会内嵌入input组件) (默认 false )
* @property {String} rightIcon 右侧的图标箭头 (默认 'arrow-right')
* @property {String} arrowDirection 右侧箭头的方向,可选值为:left,up,down
* @property {Object | String} rightIconStyle 右侧箭头图标的样式
* @property {Object | String} titleStyle 标题的样式
* @property {Object | String} iconStyle 左侧图标样式
* @property {String} size 单位元的大小,可选值为 large,normal,mini
* @property {Boolean} stop 点击cell是否阻止事件传播 (默认 true )
* @property {Object} customStyle 定义需要用到的外部样式
*
* @event {Function} click 点击cell列表时触发
* @example 该组件需要搭配cell-group组件使用,见官方文档示例
*/
export default {
name: 'u-cell',
data() {
return {
}
},
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
computed: {
titleTextStyle() {
return uni.$u.addStyle(this.titleStyle)
}
},
methods: {
// 点击cell
clickHandler(e) {
if (this.disabled) return
this.$emit('click', {
name: this.name
})
// 如果配置了url(此props参数通过mixin引入)参数,跳转页面
this.openPage()
// 是否阻止事件传播
this.stop && this.preventEvent(e)
},
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
$u-cell-padding: 10px 15px !default;
$u-cell-font-size: 15px !default;
$u-cell-line-height: 24px !default;
$u-cell-color: $u-main-color !default;
$u-cell-icon-size: 16px !default;
$u-cell-title-font-size: 15px !default;
$u-cell-title-line-height: 22px !default;
$u-cell-title-color: $u-main-color !default;
$u-cell-label-font-size: 12px !default;
$u-cell-label-color: $u-tips-color !default;
$u-cell-label-line-height: 18px !default;
$u-cell-value-font-size: 14px !default;
$u-cell-value-color: $u-content-color !default;
$u-cell-clickable-color: $u-bg-color !default;
$u-cell-disabled-color: #c8c9cc !default;
$u-cell-padding-top-large: 13px !default;
$u-cell-padding-bottom-large: 13px !default;
$u-cell-value-font-size-large: 15px !default;
$u-cell-label-font-size-large: 14px !default;
$u-cell-title-font-size-large: 16px !default;
$u-cell-left-icon-wrap-margin-right: 4px !default;
$u-cell-right-icon-wrap-margin-left: 4px !default;
$u-cell-title-flex:1 !default;
$u-cell-label-margin-top:5px !default;
.u-cell {
&__body {
@include flex();
/* #ifndef APP-NVUE */
box-sizing: border-box;
/* #endif */
padding: $u-cell-padding;
font-size: $u-cell-font-size;
color: $u-cell-color;
// line-height: $u-cell-line-height;
align-items: center;
&__content {
@include flex(row);
align-items: center;
flex: 1;
}
&--large {
padding-top: $u-cell-padding-top-large;
padding-bottom: $u-cell-padding-bottom-large;
}
}
&__left-icon-wrap,
&__right-icon-wrap {
@include flex();
align-items: center;
// height: $u-cell-line-height;
font-size: $u-cell-icon-size;
}
&__left-icon-wrap {
margin-right: $u-cell-left-icon-wrap-margin-right;
}
&__right-icon-wrap {
margin-left: $u-cell-right-icon-wrap-margin-left;
transition: transform 0.3s;
&--up {
transform: rotate(-90deg);
}
&--down {
transform: rotate(90deg);
}
}
&__title {
flex: $u-cell-title-flex;
&-text {
font-size: $u-cell-title-font-size;
line-height: $u-cell-title-line-height;
color: $u-cell-title-color;
&--large {
font-size: $u-cell-title-font-size-large;
}
}
}
&__label {
margin-top: $u-cell-label-margin-top;
font-size: $u-cell-label-font-size;
color: $u-cell-label-color;
line-height: $u-cell-label-line-height;
&--large {
font-size: $u-cell-label-font-size-large;
}
}
&__value {
text-align: right;
font-size: $u-cell-value-font-size;
line-height: $u-cell-line-height;
color: $u-cell-value-color;
&--large {
font-size: $u-cell-value-font-size-large;
}
}
&--clickable {
background-color: $u-cell-clickable-color;
}
&--disabled {
color: $u-cell-disabled-color;
/* #ifndef APP-NVUE */
cursor: not-allowed;
/* #endif */
}
&--center {
align-items: center;
}
}
</style>
export default {
props: {
// 标识符
name: {
type: String,
default: uni.$u.props.checkboxGroup.name
},
// 绑定的值
value: {
type: Array,
default: uni.$u.props.checkboxGroup.value
},
// 形状,circle-圆形,square-方形
shape: {
type: String,
default: uni.$u.props.checkboxGroup.shape
},
// 是否禁用全部checkbox
disabled: {
type: Boolean,
default: uni.$u.props.checkboxGroup.disabled
},
// 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
activeColor: {
type: String,
default: uni.$u.props.checkboxGroup.activeColor
},
// 未选中的颜色
inactiveColor: {
type: String,
default: uni.$u.props.checkboxGroup.inactiveColor
},
// 整个组件的尺寸,默认px
size: {
type: [String, Number],
default: uni.$u.props.checkboxGroup.size
},
// 布局方式,row-横向,column-纵向
placement: {
type: String,
default: uni.$u.props.checkboxGroup.placement
},
// label的字体大小,px单位
labelSize: {
type: [String, Number],
default: uni.$u.props.checkboxGroup.labelSize
},
// label的字体颜色
labelColor: {
type: [String],
default: uni.$u.props.checkboxGroup.labelColor
},
// 是否禁止点击文本操作
labelDisabled: {
type: Boolean,
default: uni.$u.props.checkboxGroup.labelDisabled
},
// 图标颜色
iconColor: {
type: String,
default: uni.$u.props.checkboxGroup.iconColor
},
// 图标的大小,单位px
iconSize: {
type: [String, Number],
default: uni.$u.props.checkboxGroup.iconSize
},
// 勾选图标的对齐方式,left-左边,right-右边
iconPlacement: {
type: String,
default: uni.$u.props.checkboxGroup.iconPlacement
},
// 竖向配列时,是否显示下划线
borderBottom: {
type: Boolean,
default: uni.$u.props.checkboxGroup.borderBottom
}
}
}
export default {
props: {
// checkbox的名称
name: {
type: [String, Number, Boolean],
default: uni.$u.props.checkbox.name
},
// 形状,square为方形,circle为圆型
shape: {
type: String,
default: uni.$u.props.checkbox.shape
},
// 整体的大小
size: {
type: [String, Number],
default: uni.$u.props.checkbox.size
},
// 是否默认选中
checked: {
type: Boolean,
default: uni.$u.props.checkbox.checked
},
// 是否禁用
disabled: {
type: [String, Boolean],
default: uni.$u.props.checkbox.disabled
},
// 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
activeColor: {
type: String,
default: uni.$u.props.checkbox.activeColor
},
// 未选中的颜色
inactiveColor: {
type: String,
default: uni.$u.props.checkbox.inactiveColor
},
// 图标的大小,单位px
iconSize: {
type: [String, Number],
default: uni.$u.props.checkbox.iconSize
},
// 图标颜色
iconColor: {
type: String,
default: uni.$u.props.checkbox.iconColor
},
// label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式
label: {
type: [String, Number],
default: uni.$u.props.checkbox.label
},
// label的字体大小,px单位
labelSize: {
type: [String, Number],
default: uni.$u.props.checkbox.labelSize
},
// label的颜色
labelColor: {
type: String,
default: uni.$u.props.checkbox.labelColor
},
// 是否禁止点击提示语选中复选框
labelDisabled: {
type: [String, Boolean],
default: uni.$u.props.checkbox.labelDisabled
}
}
}
export default {
props: {
percentage: {
type: [String, Number],
default: uni.$u.props.circleProgress.percentage
}
}
}
export default {
props: {
// 键盘弹起时,是否自动上推页面
adjustPosition: {
type: Boolean,
default: uni.$u.props.codeInput.adjustPosition
},
// 最大输入长度
maxlength: {
type: [String, Number],
default: uni.$u.props.codeInput.maxlength
},
// 是否用圆点填充
dot: {
type: Boolean,
default: uni.$u.props.codeInput.dot
},
// 显示模式,box-盒子模式,line-底部横线模式
mode: {
type: String,
default: uni.$u.props.codeInput.mode
},
// 是否细边框
hairline: {
type: Boolean,
default: uni.$u.props.codeInput.hairline
},
// 字符间的距离
space: {
type: [String, Number],
default: uni.$u.props.codeInput.space
},
// 预置值
value: {
type: [String, Number],
default: uni.$u.props.codeInput.value
},
// 是否自动获取焦点
focus: {
type: Boolean,
default: uni.$u.props.codeInput.focus
},
// 字体是否加粗
bold: {
type: Boolean,
default: uni.$u.props.codeInput.bold
},
// 字体颜色
color: {
type: String,
default: uni.$u.props.codeInput.color
},
// 字体大小
fontSize: {
type: [String, Number],
default: uni.$u.props.codeInput.fontSize
},
// 输入框的大小,宽等于高
size: {
type: [String, Number],
default: uni.$u.props.codeInput.size
},
// 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true
disabledKeyboard: {
type: Boolean,
default: uni.$u.props.codeInput.disabledKeyboard
},
// 边框和线条颜色
borderColor: {
type: String,
default: uni.$u.props.codeInput.borderColor
},
// 是否禁止输入"."符号
disabledDot: {
type: Boolean,
default: uni.$u.props.codeInput.disabledDot
}
}
}
<template>
<view class="u-code-input">
<view
class="u-code-input__item"
:style="[itemStyle(index)]"
v-for="(item, index) in codeLength"
:key="index"
>
<view
class="u-code-input__item__dot"
v-if="dot && codeArray.length > index"
></view>
<text
v-else
:style="{
fontSize: $u.addUnit(fontSize),
fontWeight: bold ? 'bold' : 'normal',
color: color
}"
>{{codeArray[index]}}</text>
<view
class="u-code-input__item__line"
v-if="mode === 'line'"
:style="[lineStyle]"
></view>
<!-- #ifndef APP-PLUS -->
<view v-if="isFocus && codeArray.length === index" :style="{backgroundColor: color}" class="u-code-input__item__cursor"></view>
<!-- #endif -->
</view>
<input
:disabled="disabledKeyboard"
type="number"
:focus="focus"
:value="inputValue"
:maxlength="maxlength"
:adjustPosition="adjustPosition"
class="u-code-input__input"
@input="inputHandler"
:style="{
height: $u.addUnit(size)
}"
@focus="isFocus = true"
@blur="isFocus = false"
/>
</view>
</template>
<script>
import props from './props.js';
/**
* CodeInput 验证码输入
* @description 该组件一般用于验证用户短信验证码的场景,也可以结合uView的键盘组件使用
* @tutorial https://www.uviewui.com/components/codeInput.html
* @property {String | Number} maxlength 最大输入长度 (默认 6 )
* @property {Boolean} dot 是否用圆点填充 (默认 false )
* @property {String} mode 显示模式,box-盒子模式,line-底部横线模式 (默认 'box' )
* @property {Boolean} hairline 是否细边框 (默认 false )
* @property {String | Number} space 字符间的距离 (默认 10 )
* @property {String | Number} value 预置值
* @property {Boolean} focus 是否自动获取焦点 (默认 false )
* @property {Boolean} bold 字体和输入横线是否加粗 (默认 false )
* @property {String} color 字体颜色 (默认 '#606266' )
* @property {String | Number} fontSize 字体大小,单位px (默认 18 )
* @property {String | Number} size 输入框的大小,宽等于高 (默认 35 )
* @property {Boolean} disabledKeyboard 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true (默认 false )
* @property {String} borderColor 边框和线条颜色 (默认 '#c9cacc' )
* @property {Boolean} disabledDot 是否禁止输入"."符号 (默认 true )
*
* @event {Function} change 输入内容发生改变时触发,具体见上方说明 value:当前输入的值
* @event {Function} finish 输入字符个数达maxlength值时触发,见上方说明 value:当前输入的值
* @example <u-code-input v-model="value4" :focus="true"></u-code-input>
*/
export default {
name: 'u-code-input',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
inputValue: '',
isFocus: this.focus
}
},
watch: {
value: {
immediate: true,
handler(val) {
// 转为字符串,超出部分截掉
this.inputValue = String(val).substring(0, this.maxlength)
}
},
},
computed: {
// 根据长度,循环输入框的个数,因为头条小程序数值不能用于v-for
codeLength() {
return new Array(Number(this.maxlength))
},
// 循环item的样式
itemStyle() {
return index => {
const addUnit = uni.$u.addUnit
const style = {
width: addUnit(this.size),
height: addUnit(this.size)
}
// 盒子模式下,需要额外进行处理
if (this.mode === 'box') {
// 设置盒子的边框,如果是细边框,则设置为0.5px宽度
style.border = `${this.hairline ? 0.5 : 1}px solid ${this.borderColor}`
// 如果盒子间距为0的话
if (uni.$u.getPx(this.space) === 0) {
// 给第一和最后一个盒子设置圆角
if (index === 0) {
style.borderTopLeftRadius = '3px'
style.borderBottomLeftRadius = '3px'
}
if (index === this.codeLength.length - 1) {
style.borderTopRightRadius = '3px'
style.borderBottomRightRadius = '3px'
}
// 最后一个盒子的右边框需要保留
if (index !== this.codeLength.length - 1) {
style.borderRight = 'none'
}
}
}
if (index !== this.codeLength.length - 1) {
// 设置验证码字符之间的距离,通过margin-right设置,最后一个字符,无需右边框
style.marginRight = addUnit(this.space)
} else {
// 最后一个盒子的有边框需要保留
style.marginRight = 0
}
return style
}
},
// 将输入的值,转为数组,给item历遍时,根据当前的索引显示数组的元素
codeArray() {
return String(this.inputValue).split('')
},
// 下划线模式下,横线的样式
lineStyle() {
const style = {}
style.height = this.hairline ? '2px' : '4px'
style.width = uni.$u.addUnit(this.size)
// 线条模式下,背景色即为边框颜色
style.backgroundColor = this.borderColor
return style
}
},
methods: {
// 监听输入框的值发生变化
inputHandler(e) {
const value = e.detail.value
this.inputValue = value
// 是否允许输入“.”符号
if(this.disabledDot) {
this.$nextTick(() => {
this.inputValue = value.replace('.', '')
})
}
// 未达到maxlength之前,发送change事件,达到后发送finish事件
this.$emit('change', value)
// 修改通过v-model双向绑定的值
this.$emit('input', value)
// 达到用户指定输入长度时,发出完成事件
if (String(value).length >= Number(this.maxlength)) {
this.$emit('finish', value)
}
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
$u-code-input-cursor-width: 1px;
$u-code-input-cursor-height: 40%;
$u-code-input-cursor-animation-duration: 1s;
$u-code-input-cursor-animation-name: u-cursor-flicker;
.u-code-input {
@include flex;
position: relative;
overflow: hidden;
&__item {
@include flex;
justify-content: center;
align-items: center;
position: relative;
&__text {
font-size: 15px;
color: $u-content-color;
}
&__dot {
width: 7px;
height: 7px;
border-radius: 100px;
background-color: $u-content-color;
}
&__line {
position: absolute;
bottom: 0;
height: 4px;
border-radius: 100px;
width: 40px;
background-color: $u-content-color;
}
/* #ifndef APP-PLUS */
&__cursor {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
width: $u-code-input-cursor-width;
height: $u-code-input-cursor-height;
animation: $u-code-input-cursor-animation-duration u-cursor-flicker infinite;
}
/* #endif */
}
&__input {
// 之所以需要input输入框,是因为有它才能唤起键盘
// 这里将它设置为两倍的屏幕宽度,再将左边的一半移出屏幕,为了不让用户看到输入的内容
position: absolute;
left: -750rpx;
width: 1500rpx;
top: 0;
background-color: transparent;
text-align: left;
}
}
/* #ifndef APP-PLUS */
@keyframes u-cursor-flicker {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
/* #endif */
</style>
export default {
props: {
// 倒计时总秒数
seconds: {
type: [String, Number],
default: uni.$u.props.code.seconds
},
// 尚未开始时提示
startText: {
type: String,
default: uni.$u.props.code.startText
},
// 正在倒计时中的提示
changeText: {
type: String,
default: uni.$u.props.code.changeText
},
// 倒计时结束时的提示
endText: {
type: String,
default: uni.$u.props.code.endText
},
// 是否在H5刷新或各端返回再进入时继续倒计时
keepRunning: {
type: Boolean,
default: uni.$u.props.code.keepRunning
},
// 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
uniqueKey: {
type: String,
default: uni.$u.props.code.uniqueKey
}
}
}
<template>
<view class="u-code">
<!-- 此组件功能由js完成,无需写html逻辑 -->
</view>
</template>
<script>
import props from './props.js';
/**
* Code 验证码输入框
* @description 考虑到用户实际发送验证码的场景,可能是一个按钮,也可能是一段文字,提示语各有不同,所以本组件 不提供界面显示,只提供提示语,由用户将提示语嵌入到具体的场景
* @tutorial https://www.uviewui.com/components/code.html
* @property {String | Number} seconds 倒计时所需的秒数(默认 60 )
* @property {String} startText 开始前的提示语,见官网说明(默认 '获取验证码' )
* @property {String} changeText 倒计时期间的提示语,必须带有字母"x",见官网说明(默认 'X秒重新获取' )
* @property {String} endText 倒计结束的提示语,见官网说明(默认 '重新获取' )
* @property {Boolean} keepRunning 是否在H5刷新或各端返回再进入时继续倒计时( 默认false )
* @property {String} uniqueKey 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
*
* @event {Function} change 倒计时期间,每秒触发一次
* @event {Function} start 开始倒计时触发
* @event {Function} end 结束倒计时触发
* @example <u-code ref="uCode" @change="codeChange" seconds="20"></u-code>
*/
export default {
name: "u-code",
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
data() {
return {
secNum: this.seconds,
timer: null,
canGetCode: true, // 是否可以执行验证码操作
}
},
mounted() {
this.checkKeepRunning()
},
watch: {
seconds: {
immediate: true,
handler(n) {
this.secNum = n
}
}
},
methods: {
checkKeepRunning() {
// 获取上一次退出页面(H5还包括刷新)时的时间戳,如果没有上次的保存,此值可能为空
let lastTimestamp = Number(uni.getStorageSync(this.uniqueKey + '_$uCountDownTimestamp'))
if(!lastTimestamp) return this.changeEvent(this.startText)
// 当前秒的时间戳
let nowTimestamp = Math.floor((+ new Date()) / 1000)
// 判断当前的时间戳,是否小于上一次的本该按设定结束,却提前结束的时间戳
if(this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) {
// 剩余尚未执行完的倒计秒数
this.secNum = lastTimestamp - nowTimestamp
// 清除本地保存的变量
uni.removeStorageSync(this.uniqueKey + '_$uCountDownTimestamp')
// 开始倒计时
this.start()
} else {
// 如果不存在需要继续上一次的倒计时,执行正常的逻辑
this.changeEvent(this.startText)
}
},
// 开始倒计时
start() {
// 防止快速点击获取验证码的按钮而导致内部产生多个定时器导致混乱
if(this.timer) {
clearInterval(this.timer)
this.timer = null
}
this.$emit('start')
this.canGetCode = false
// 这里放这句,是为了一开始时就提示,否则要等setInterval的1秒后才会有提示
this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
this.timer = setInterval(() => {
if (--this.secNum) {
// 用当前倒计时的秒数替换提示字符串中的"x"字母
this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
} else {
clearInterval(this.timer)
this.timer = null
this.changeEvent(this.endText)
this.secNum = this.seconds
this.$emit('end')
this.canGetCode = true
}
}, 1000)
this.setTimeToStorage()
},
// 重置,可以让用户再次获取验证码
reset() {
this.canGetCode = true
clearInterval(this.timer)
this.secNum = this.seconds
this.changeEvent(this.endText)
},
changeEvent(text) {
this.$emit('change', text)
},
// 保存时间戳,为了防止倒计时尚未结束,H5刷新或者各端的右上角返回上一页再进来
setTimeToStorage() {
if(!this.keepRunning || !this.timer) return
// 记录当前的时间戳,为了下次进入页面,如果还在倒计时内的话,继续倒计时
// 倒计时尚未结束,结果大于0;倒计时已经开始,就会小于初始值,如果等于初始值,说明没有开始倒计时,无需处理
if(this.secNum > 0 && this.secNum <= this.seconds) {
// 获取当前时间戳(+ new Date()为特殊写法),除以1000变成秒,再去除小数部分
let nowTimestamp = Math.floor((+ new Date()) / 1000)
// 将本该结束时候的时间戳保存起来 => 当前时间戳 + 剩余的秒数
uni.setStorage({
key: this.uniqueKey + '_$uCountDownTimestamp',
data: nowTimestamp + Number(this.secNum)
})
}
}
},
// 组件销毁的时候,清除定时器,否则定时器会继续存在,系统不会自动清除
beforeDestroy() {
this.setTimeToStorage()
clearTimeout(this.timer)
this.timer = null
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
</style>
export default {
props: {
// 占父容器宽度的多少等分,总分为12份
span: {
type: [String, Number],
default: uni.$u.props.col.span
},
// 指定栅格左侧的间隔数(总12栏)
offset: {
type: [String, Number],
default: uni.$u.props.col.offset
},
// 水平排列方式,可选值为`start`(或`flex-start`)、`end`(或`flex-end`)、`center`、`around`(或`space-around`)、`between`(或`space-between`)
justify: {
type: String,
default: uni.$u.props.col.justify
},
// 垂直对齐方式,可选值为top、center、bottom、stretch
align: {
type: String,
default: uni.$u.props.col.align
},
// 文字对齐方式
textAlign: {
type: String,
default: uni.$u.props.col.textAlign
}
}
}
export default {
props: {
// 标题
title: {
type: String,
default: uni.$u.props.collapseItem.title
},
// 标题右侧内容
value: {
type: String,
default: uni.$u.props.collapseItem.value
},
// 标题下方的描述信息
label: {
type: String,
default: uni.$u.props.collapseItem.label
},
// 是否禁用折叠面板
disabled: {
type: Boolean,
default: uni.$u.props.collapseItem.disabled
},
// 是否展示右侧箭头并开启点击反馈
isLink: {
type: Boolean,
default: uni.$u.props.collapseItem.isLink
},
// 是否开启点击反馈
clickable: {
type: Boolean,
default: uni.$u.props.collapseItem.clickable
},
// 是否显示内边框
border: {
type: Boolean,
default: uni.$u.props.collapseItem.border
},
// 标题的对齐方式
align: {
type: String,
default: uni.$u.props.collapseItem.align
},
// 唯一标识符
name: {
type: [String, Number],
default: uni.$u.props.collapseItem.name
},
// 标题左侧图片,可为绝对路径的图片或内置图标
icon: {
type: String,
default: uni.$u.props.collapseItem.icon
},
// 面板展开收起的过渡时间,单位ms
duration: {
type: Number,
default: uni.$u.props.collapseItem.duration
}
}
}
export default {
props: {
// 当前展开面板的name,非手风琴模式:[<string | number>],手风琴模式:string | number
value: {
type: [String, Number, Array, null],
default: uni.$u.props.collapse.value
},
// 是否手风琴模式
accordion: {
type: Boolean,
default: uni.$u.props.collapse.accordion
},
// 是否显示外边框
border: {
type: Boolean,
default: uni.$u.props.collapse.border
}
}
}
export default {
props: {
// 显示的内容,字符串
text: {
type: [Array],
default: uni.$u.props.columnNotice.text
},
// 是否显示左侧的音量图标
icon: {
type: String,
default: uni.$u.props.columnNotice.icon
},
// 通告模式,link-显示右箭头,closable-显示右侧关闭图标
mode: {
type: String,
default: uni.$u.props.columnNotice.mode
},
// 文字颜色,各图标也会使用文字颜色
color: {
type: String,
default: uni.$u.props.columnNotice.color
},
// 背景颜色
bgColor: {
type: String,
default: uni.$u.props.columnNotice.bgColor
},
// 字体大小,单位px
fontSize: {
type: [String, Number],
default: uni.$u.props.columnNotice.fontSize
},
// 水平滚动时的滚动速度,即每秒滚动多少px(px),这有利于控制文字无论多少时,都能有一个恒定的速度
speed: {
type: [String, Number],
default: uni.$u.props.columnNotice.speed
},
// direction = row时,是否使用步进形式滚动
step: {
type: Boolean,
default: uni.$u.props.columnNotice.step
},
// 滚动一个周期的时间长,单位ms
duration: {
type: [String, Number],
default: uni.$u.props.columnNotice.duration
},
// 是否禁止用手滑动切换
// 目前HX2.6.11,只支持App 2.5.5+、H5 2.5.5+、支付宝小程序、字节跳动小程序
disableTouch: {
type: Boolean,
default: uni.$u.props.columnNotice.disableTouch
}
}
}
export default {
props: {
// 倒计时时长,单位ms
time: {
type: [String, Number],
default: uni.$u.props.countDown.time
},
// 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒
format: {
type: String,
default: uni.$u.props.countDown.format
},
// 是否自动开始倒计时
autoStart: {
type: Boolean,
default: uni.$u.props.countDown.autoStart
},
// 是否展示毫秒倒计时
millisecond: {
type: Boolean,
default: uni.$u.props.countDown.millisecond
}
}
}
// 补0,如1 -> 01
function padZero(num, targetLength = 2) {
let str = `${num}`
while (str.length < targetLength) {
str = `0${str}`
}
return str
}
const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
export function parseTimeData(time) {
const days = Math.floor(time / DAY)
const hours = Math.floor((time % DAY) / HOUR)
const minutes = Math.floor((time % HOUR) / MINUTE)
const seconds = Math.floor((time % MINUTE) / SECOND)
const milliseconds = Math.floor(time % SECOND)
return {
days,
hours,
minutes,
seconds,
milliseconds
}
}
export function parseFormat(format, timeData) {
let {
days,
hours,
minutes,
seconds,
milliseconds
} = timeData
// 如果格式化字符串中不存在DD(天),则将天的时间转为小时中去
if (format.indexOf('DD') === -1) {
hours += days * 24
} else {
// 对天补0
format = format.replace('DD', padZero(days))
}
// 其他同理于DD的格式化处理方式
if (format.indexOf('HH') === -1) {
minutes += hours * 60
} else {
format = format.replace('HH', padZero(hours))
}
if (format.indexOf('mm') === -1) {
seconds += minutes * 60
} else {
format = format.replace('mm', padZero(minutes))
}
if (format.indexOf('ss') === -1) {
milliseconds += seconds * 1000
} else {
format = format.replace('ss', padZero(seconds))
}
return format.replace('SSS', padZero(milliseconds, 3))
}
export function isSameSecond(time1, time2) {
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000)
}
export default {
props: {
// 开始的数值,默认从0增长到某一个数
startVal: {
type: [String, Number],
default: uni.$u.props.countTo.startVal
},
// 要滚动的目标数值,必须
endVal: {
type: [String, Number],
default: uni.$u.props.countTo.endVal
},
// 滚动到目标数值的动画持续时间,单位为毫秒(ms)
duration: {
type: [String, Number],
default: uni.$u.props.countTo.duration
},
// 设置数值后是否自动开始滚动
autoplay: {
type: Boolean,
default: uni.$u.props.countTo.autoplay
},
// 要显示的小数位数
decimals: {
type: [String, Number],
default: uni.$u.props.countTo.decimals
},
// 是否在即将到达目标数值的时候,使用缓慢滚动的效果
useEasing: {
type: Boolean,
default: uni.$u.props.countTo.useEasing
},
// 十进制分割
decimal: {
type: [String, Number],
default: uni.$u.props.countTo.decimal
},
// 字体颜色
color: {
type: String,
default: uni.$u.props.countTo.color
},
// 字体大小
fontSize: {
type: [String, Number],
default: uni.$u.props.countTo.fontSize
},
// 是否加粗字体
bold: {
type: Boolean,
default: uni.$u.props.countTo.bold
},
// 千位分隔符,类似金额的分割(¥23,321.05中的",")
separator: {
type: String,
default: uni.$u.props.countTo.separator
}
}
}
export default {
props: {
// 是否打开组件
show: {
type: Boolean,
default: uni.$u.props.datetimePicker.show
},
// 是否展示顶部的操作栏
showToolbar: {
type: Boolean,
default: uni.$u.props.datetimePicker.showToolbar
},
// 绑定值
value: {
type: [String, Number],
default: uni.$u.props.datetimePicker.value
},
// 顶部标题
title: {
type: String,
default: uni.$u.props.datetimePicker.title
},
// 展示格式,mode=date为日期选择,mode=time为时间选择,mode=year-month为年月选择,mode=datetime为日期时间选择
mode: {
type: String,
default: uni.$u.props.datetimePicker.mode
},
// 可选的最大时间
maxDate: {
type: Number,
// 最大默认值为后10年
default: uni.$u.props.datetimePicker.maxDate
},
// 可选的最小时间
minDate: {
type: Number,
// 最小默认值为前10年
default: uni.$u.props.datetimePicker.minDate
},
// 可选的最小小时,仅mode=time有效
minHour: {
type: Number,
default: uni.$u.props.datetimePicker.minHour
},
// 可选的最大小时,仅mode=time有效
maxHour: {
type: Number,
default: uni.$u.props.datetimePicker.maxHour
},
// 可选的最小分钟,仅mode=time有效
minMinute: {
type: Number,
default: uni.$u.props.datetimePicker.minMinute
},
// 可选的最大分钟,仅mode=time有效
maxMinute: {
type: Number,
default: uni.$u.props.datetimePicker.maxMinute
},
// 选项过滤函数
filter: {
type: [Function, null],
default: uni.$u.props.datetimePicker.filter
},
// 选项格式化函数
formatter: {
type: [Function, null],
default: uni.$u.props.datetimePicker.formatter
},
// 是否显示加载中状态
loading: {
type: Boolean,
default: uni.$u.props.datetimePicker.loading
},
// 各列中,单个选项的高度
itemHeight: {
type: [String, Number],
default: uni.$u.props.datetimePicker.itemHeight
},
// 取消按钮的文字
cancelText: {
type: String,
default: uni.$u.props.datetimePicker.cancelText
},
// 确认按钮的文字
confirmText: {
type: String,
default: uni.$u.props.datetimePicker.confirmText
},
// 取消按钮的颜色
cancelColor: {
type: String,
default: uni.$u.props.datetimePicker.cancelColor
},
// 确认按钮的颜色
confirmColor: {
type: String,
default: uni.$u.props.datetimePicker.confirmColor
},
// 每列中可见选项的数量
visibleItemCount: {
type: [String, Number],
default: uni.$u.props.datetimePicker.visibleItemCount
},
// 是否允许点击遮罩关闭选择器
closeOnClickOverlay: {
type: Boolean,
default: uni.$u.props.datetimePicker.closeOnClickOverlay
},
// 各列的默认索引
defaultIndex: {
type: Array,
default: uni.$u.props.datetimePicker.defaultIndex
}
}
}
This diff is collapsed.
export default {
props: {
// 是否虚线
dashed: {
type: Boolean,
default: uni.$u.props.divider.dashed
},
// 是否细线
hairline: {
type: Boolean,
default: uni.$u.props.divider.hairline
},
// 是否以点替代文字,优先于text字段起作用
dot: {
type: Boolean,
default: uni.$u.props.divider.dot
},
// 内容文本的位置,left-左边,center-中间,right-右边
textPosition: {
type: String,
default: uni.$u.props.divider.textPosition
},
// 文本内容
text: {
type: [String, Number],
default: uni.$u.props.divider.text
},
// 文本大小
textSize: {
type: [String, Number],
default: uni.$u.props.divider.textSize
},
// 文本颜色
textColor: {
type: String,
default: uni.$u.props.divider.textColor
},
// 线条颜色
lineColor: {
type: String,
default: uni.$u.props.divider.lineColor
}
}
}
export default {
props: {
// 当前选中项的value值
value: {
type: [Number, String, Array],
default: ''
},
// 菜单项标题
title: {
type: [String, Number],
default: ''
},
// 选项数据,如果传入了默认slot,此参数无效
options: {
type: Array,
default() {
return []
}
},
// 是否禁用此菜单项
disabled: {
type: Boolean,
default: false
},
// 下拉弹窗的高度
height: {
type: [Number, String],
default: 'auto'
},
// 点击遮罩是否可以收起弹窗
closeOnClickOverlay: {
type: Boolean,
default: true
}
}
}
export default {
props: {
// 标题选中时的样式
activeStyle: {
type: [String, Object],
default: () => ({
color: '#2979ff',
fontSize: '14px'
})
},
// 标题未选中时的样式
inactiveStyle: {
type: [String, Object],
default: () => ({
color: '#606266',
fontSize: '14px'
})
},
// 点击遮罩是否关闭菜单
closeOnClickMask: {
type: Boolean,
default: true
},
// 点击当前激活项标题是否关闭菜单
closeOnClickSelf: {
type: Boolean,
default: true
},
// 过渡时间
duration: {
type: [Number, String],
default: 300
},
// 标题菜单的高度
height: {
type: [Number, String],
default: 40
},
// 是否显示下边框
borderBottom: {
type: Boolean,
default: false
},
// 标题的字体大小
titleSize: {
type: [Number, String],
default: 14
},
// 下拉出来的内容部分的圆角值
borderRadius: {
type: [Number, String],
default: 0
},
// 菜单右侧的icon图标
menuIcon: {
type: String,
default: 'arrow-down'
},
// 菜单右侧图标的大小
menuIconSize: {
type: [Number, String],
default: 14
}
}
}
export default {
props: {
// 内置图标名称,或图片路径,建议绝对路径
icon: {
type: String,
default: uni.$u.props.empty.icon
},
// 提示文字
text: {
type: String,
default: uni.$u.props.empty.text
},
// 文字颜色
textColor: {
type: String,
default: uni.$u.props.empty.textColor
},
// 文字大小
textSize: {
type: [String, Number],
default: uni.$u.props.empty.textSize
},
// 图标的颜色
iconColor: {
type: String,
default: uni.$u.props.empty.iconColor
},
// 图标的大小
iconSize: {
type: [String, Number],
default: uni.$u.props.empty.iconSize
},
// 选择预置的图标类型
mode: {
type: String,
default: uni.$u.props.empty.mode
},
// 图标宽度,单位px
width: {
type: [String, Number],
default: uni.$u.props.empty.width
},
// 图标高度,单位px
height: {
type: [String, Number],
default: uni.$u.props.empty.height
},
// 是否显示组件
show: {
type: Boolean,
default: uni.$u.props.empty.show
},
// 组件距离上一个元素之间的距离,默认px单位
marginTop: {
type: [String, Number],
default: uni.$u.props.empty.marginTop
}
}
}
export default {
props: {
// input的label提示语
label: {
type: String,
default: uni.$u.props.formItem.label
},
// 绑定的值
prop: {
type: String,
default: uni.$u.props.formItem.prop
},
// 是否显示表单域的下划线边框
borderBottom: {
type: [String, Boolean],
default: uni.$u.props.formItem.borderBottom
},
// label的位置,left-左边,top-上边
labelPosition: {
type: String,
default: uni.$u.props.formItem.labelPosition
},
// label的宽度,单位px
labelWidth: {
type: [String, Number],
default: uni.$u.props.formItem.labelWidth
},
// 右侧图标
rightIcon: {
type: String,
default: uni.$u.props.formItem.rightIcon
},
// 左侧图标
leftIcon: {
type: String,
default: uni.$u.props.formItem.leftIcon
},
// 是否显示左边的必填星号,只作显示用,具体校验必填的逻辑,请在rules中配置
required: {
type: Boolean,
default: uni.$u.props.formItem.required
},
leftIconStyle: {
type: [String, Object],
default: uni.$u.props.formItem.leftIconStyle,
}
}
}
export default {
props: {
// 当前form的需要验证字段的集合
model: {
type: Object,
default: uni.$u.props.form.model
},
// 验证规则
rules: {
type: [Object, Function, Array],
default: uni.$u.props.form.rules
},
// 有错误时的提示方式,message-提示信息,toast-进行toast提示
// border-bottom-下边框呈现红色,none-无提示
errorType: {
type: String,
default: uni.$u.props.form.errorType
},
// 是否显示表单域的下划线边框
borderBottom: {
type: Boolean,
default: uni.$u.props.form.borderBottom
},
// label的位置,left-左边,top-上边
labelPosition: {
type: String,
default: uni.$u.props.form.labelPosition
},
// label的宽度,单位px
labelWidth: {
type: [String, Number],
default: uni.$u.props.form.labelWidth
},
// lable字体的对齐方式
labelAlign: {
type: String,
default: uni.$u.props.form.labelAlign
},
// lable的样式,对象形式
labelStyle: {
type: Object,
default: uni.$u.props.form.labelStyle
}
}
}
export default {
props: {
// 背景颜色(默认transparent)
bgColor: {
type: String,
default: uni.$u.props.gap.bgColor
},
// 分割槽高度,单位px(默认30)
height: {
type: [String, Number],
default: uni.$u.props.gap.height
},
// 与上一个组件的距离
marginTop: {
type: [String, Number],
default: uni.$u.props.gap.marginTop
},
// 与下一个组件的距离
marginBottom: {
type: [String, Number],
default: uni.$u.props.gap.marginBottom
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
export default {
props: {
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment