创建版本
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 286 B |
Binary file not shown.
|
After Width: | Height: | Size: 231 B |
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<view class="w-100">
|
||||
<view class="w-100 flex_wrap">
|
||||
<view class="imgs-view" v-for="(v,i) in imgArray" :key="i">
|
||||
<image @click="preview(v,i)" :src="v"></image>
|
||||
<view class="del-btn" @click="delImg(i)">
|
||||
<image src="@/components/my-components/imgs/delete.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="imgArray.length < imgCount" class="upload-img-view flex_xy_center" @click="upPhoto">
|
||||
<image src="@/components/my-components/imgs/jia.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tip">* 最多上传{{imgCount}}张图片(<label> {{imgArray.length}} </label>/{{imgCount}})</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'imgUpload',
|
||||
props: {
|
||||
imgArr: { // 图片数组
|
||||
type: [Array],
|
||||
},
|
||||
uploadImgCount: { // 一次上传图片数
|
||||
type: String,
|
||||
default: '3'
|
||||
},
|
||||
imgCount: { // 可上传图片总数
|
||||
type: String,
|
||||
default: '3'
|
||||
},
|
||||
imgSize: { //图片大小 单位M
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
imgType: {
|
||||
type: [Array],
|
||||
default: function() {
|
||||
return ['jpeg', 'png', 'jpg']
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.imgArray = this.imgArr;
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imgArray: []
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
methods: {
|
||||
upPhoto() {
|
||||
let me = this;
|
||||
if (Number(me.imgCount - me.imgArray.length) < Number(me.uploadImgCount)) {
|
||||
me.uploadImgCount = Number(me.imgCount - me.imgArray.length);
|
||||
}
|
||||
uni.chooseImage({
|
||||
count: Number(me.uploadImgCount),
|
||||
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
|
||||
sourceType: ['camera'], // 从相册选择
|
||||
success: function(res) {
|
||||
if (res) {
|
||||
if (res.tempFiles instanceof Array && res.tempFiles) {
|
||||
for (let item of res.tempFiles) {
|
||||
if (item.size > (me.imgSize * 1024 * 1024)) {
|
||||
uni.showToast({
|
||||
title: `图片不能大于${me.imgSize}M`,
|
||||
icon: 'none'
|
||||
})
|
||||
return false;
|
||||
}
|
||||
let r = me.imgType.some(v => {
|
||||
let type = item.type.split('/');
|
||||
if (type.length)
|
||||
return (v === type[1]);
|
||||
});
|
||||
if (!r) {
|
||||
uni.showToast({
|
||||
title: `只允许上传${me.imgType}的类型`,
|
||||
icon: 'none'
|
||||
})
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
me.imgArray = [...me.imgArray, ...res.tempFilePaths];
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
preview(url, index) {
|
||||
// 预览图片
|
||||
uni.previewImage({
|
||||
urls: [url]
|
||||
});
|
||||
},
|
||||
delImg(i) {
|
||||
const me = this;
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '是否删除这张照片?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
me.imgArray.splice(i, 1);
|
||||
} else if (res.cancel) {}
|
||||
}
|
||||
});
|
||||
},
|
||||
async upload(callback) {
|
||||
const me = this;
|
||||
if (me.imgArray) {
|
||||
let successNum = 0;
|
||||
let urlArr = [];
|
||||
for (let item of me.imgArray) {
|
||||
await me.uploadImg(item, res => {
|
||||
if (res.code == 200) { //接口回调值 *注意修改为自己接口对应的!!!
|
||||
successNum++;
|
||||
if (res.data.code == 200) { //接口回调值 *注意修改为自己接口对应的!!!
|
||||
urlArr.push(res.data.data);
|
||||
}
|
||||
} else {
|
||||
urlArr.push(res);
|
||||
}
|
||||
if (urlArr.length == me.imgArray.length) {
|
||||
callback(me.result(urlArr, successNum));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
result(urlArr, successNum) {
|
||||
let result = {
|
||||
urlArray: urlArr,
|
||||
success: successNum
|
||||
}
|
||||
return result;
|
||||
},
|
||||
uploadImg(item, callback) {
|
||||
const me = this;
|
||||
uni.uploadFile({
|
||||
url: $config.SERVER_URL + 'api/sys/user/modify/uploadPic', // 自行修改各自的对应的接口
|
||||
filePath: item,
|
||||
name: 'file',
|
||||
success: (uploadFileRes) => {
|
||||
if (uploadFileRes) {
|
||||
let res = JSON.parse(uploadFileRes.data);
|
||||
callback(res);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
.flex {
|
||||
/* 转为弹性盒模型*/
|
||||
display: flex;
|
||||
}
|
||||
.flex_bet {
|
||||
/* 两端左右*/
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.flex_wrap {
|
||||
/* 转为弹性盒模型并自动换行*/
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.upload-img-view {
|
||||
height: 200upx;
|
||||
width: 31.5%;
|
||||
border-radius: 0;
|
||||
border: 1upx solid #F1F1F1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.upload-img-view>image {
|
||||
width: 60upx;
|
||||
height: 60upx;
|
||||
}
|
||||
.imgs-view {
|
||||
height: 200upx;
|
||||
width: 32%;
|
||||
border-radius: 0;
|
||||
margin-right: 12upx;
|
||||
margin-bottom: 12upx;
|
||||
border: 1upx solid #F1F1F1;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
.imgs-view:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
.imgs-view>image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
}
|
||||
.tip {
|
||||
font-size: 24upx;
|
||||
color: #999;
|
||||
margin-top: 12upx;
|
||||
}
|
||||
.tip > label {
|
||||
color: #009100;
|
||||
}
|
||||
.del-btn {
|
||||
position: absolute;
|
||||
top: 2rpx;
|
||||
right: 2rpx;
|
||||
width: 32upx;
|
||||
height: 32upx;
|
||||
z-index: 999;
|
||||
}
|
||||
.del-btn>image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<text v-if="text" :class="inverted ? 'uni-badge--' + type + ' uni-badge--' + size + ' uni-badge--' + type + '-inverted' : 'uni-badge--' + type + ' uni-badge--' + size"
|
||||
:style="badgeStyle" class="uni-badge" @click="onClick()">{{ text }}</text>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Badge 数字角标
|
||||
* @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=21
|
||||
* @property {String} text 角标内容
|
||||
* @property {String} type = [default|primary|success|warning|error] 颜色类型
|
||||
* @value default 灰色
|
||||
* @value primary 蓝色
|
||||
* @value success 绿色
|
||||
* @value warning 黄色
|
||||
* @value error 红色
|
||||
* @property {String} size = [normal|small] Badge 大小
|
||||
* @value normal 一般尺寸
|
||||
* @value small 小尺寸
|
||||
* @property {String} inverted = [true|false] 是否无需背景颜色
|
||||
* @event {Function} click 点击 Badge 触发事件
|
||||
* @example <uni-badge text="1"></uni-badge>
|
||||
*/
|
||||
export default {
|
||||
name: 'UniBadge',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
inverted: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
text: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'normal'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
badgeStyle: ''
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
text() {
|
||||
this.setStyle()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.setStyle()
|
||||
},
|
||||
methods: {
|
||||
setStyle() {
|
||||
this.badgeStyle = `width: ${String(this.text).length * 8 + 12}px`
|
||||
},
|
||||
onClick() {
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$bage-size: 12px;
|
||||
$bage-small: scale(0.8);
|
||||
$bage-height: 20px;
|
||||
|
||||
.uni-badge {
|
||||
/* #ifndef APP-PLUS */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
flex-direction: row;
|
||||
height: $bage-height;
|
||||
line-height: $bage-height;
|
||||
color: $uni-text-color;
|
||||
border-radius: 100px;
|
||||
background-color: $uni-bg-color-hover;
|
||||
background-color: transparent;
|
||||
text-align: center;
|
||||
font-family: 'Helvetica Neue', Helvetica, sans-serif;
|
||||
font-size: $bage-size;
|
||||
padding: 0px 6px;
|
||||
}
|
||||
|
||||
.uni-badge--inverted {
|
||||
padding: 0 5px 0 0;
|
||||
color: $uni-bg-color-hover;
|
||||
}
|
||||
|
||||
.uni-badge--default {
|
||||
color: $uni-text-color;
|
||||
background-color: $uni-bg-color-hover;
|
||||
}
|
||||
|
||||
.uni-badge--default-inverted {
|
||||
color: $uni-text-color-grey;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--primary {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-primary;
|
||||
}
|
||||
|
||||
.uni-badge--primary-inverted {
|
||||
color: $uni-color-primary;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--success {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-success;
|
||||
}
|
||||
|
||||
.uni-badge--success-inverted {
|
||||
color: $uni-color-success;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--warning {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-warning;
|
||||
}
|
||||
|
||||
.uni-badge--warning-inverted {
|
||||
color: $uni-color-warning;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--error {
|
||||
color: $uni-text-color-inverse;
|
||||
background-color: $uni-color-error;
|
||||
}
|
||||
|
||||
.uni-badge--error-inverted {
|
||||
color: $uni-color-error;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.uni-badge--small {
|
||||
transform: $bage-small;
|
||||
transform-origin: center center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,428 @@
|
||||
<template>
|
||||
<view>
|
||||
<view v-if="popMenu && (leftBottom||rightBottom||leftTop||rightTop)" :class="{
|
||||
'uni-fab--leftBottom': leftBottom,
|
||||
'uni-fab--rightBottom': rightBottom,
|
||||
'uni-fab--leftTop': leftTop,
|
||||
'uni-fab--rightTop': rightTop
|
||||
}" class="uni-fab">
|
||||
<view :class="{
|
||||
'uni-fab__content--left': horizontal === 'left',
|
||||
'uni-fab__content--right': horizontal === 'right',
|
||||
'uni-fab__content--flexDirection': direction === 'vertical',
|
||||
'uni-fab__content--flexDirectionStart': flexDirectionStart,
|
||||
'uni-fab__content--flexDirectionEnd': flexDirectionEnd,
|
||||
'uni-fab__content--other-platform': !isAndroidNvue
|
||||
}" :style="{ width: boxWidth, height: boxHeight, backgroundColor: styles.backgroundColor }" class="uni-fab__content" elevation="5">
|
||||
<view v-if="flexDirectionStart || horizontalLeft" class="uni-fab__item uni-fab__item--first" />
|
||||
<view v-for="(item, index) in content" :key="index" :class="{ 'uni-fab__item--active': isShow }" class="uni-fab__item" @click="_onItemClick(index, item)">
|
||||
<image :src="item.active ? item.selectedIconPath : item.iconPath" class="uni-fab__item-image" mode="widthFix" />
|
||||
<text class="uni-fab__item-text" :style="{ color: item.active ? styles.selectedColor : styles.color }">{{ item.text }}</text>
|
||||
</view>
|
||||
<view v-if="flexDirectionEnd || horizontalRight" class="uni-fab__item uni-fab__item--first" />
|
||||
</view>
|
||||
</view>
|
||||
<view :class="{
|
||||
'uni-fab__circle--leftBottom': leftBottom,
|
||||
'uni-fab__circle--rightBottom': rightBottom,
|
||||
'uni-fab__circle--leftTop': leftTop,
|
||||
'uni-fab__circle--rightTop': rightTop,
|
||||
'uni-fab__content--other-platform': !isAndroidNvue
|
||||
}" class="uni-fab__circle uni-fab__plus" :style="{ 'background-color': styles.buttonColor }" @click="_onClick">
|
||||
<view class="fab-circle-v" :class="{'uni-fab__plus--active': isShow}"></view>
|
||||
<view class="fab-circle-h" :class="{'uni-fab__plus--active': isShow}"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let platform = 'other'
|
||||
// #ifdef APP-NVUE
|
||||
platform = uni.getSystemInfoSync().platform
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* Fab 悬浮按钮
|
||||
* @description 点击可展开一个图形按钮菜单
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=144
|
||||
* @property {Object} pattern 可选样式配置项
|
||||
* @property {Object} horizontal = [left | right] 水平对齐方式
|
||||
* @value left 左对齐
|
||||
* @value right 右对齐
|
||||
* @property {Object} vertical = [bottom | top] 垂直对齐方式
|
||||
* @value bottom 下对齐
|
||||
* @value top 上对齐
|
||||
* @property {Object} direction = [horizontal | vertical] 展开菜单显示方式
|
||||
* @value horizontal 水平显示
|
||||
* @value vertical 垂直显示
|
||||
* @property {Array} content 展开菜单内容配置项
|
||||
* @property {Boolean} popMenu 是否使用弹出菜单
|
||||
* @event {Function} trigger 展开菜单点击事件,返回点击信息
|
||||
* @event {Function} fabClick 悬浮按钮点击事件
|
||||
*/
|
||||
export default {
|
||||
name: 'UniFab',
|
||||
props: {
|
||||
pattern: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
horizontal: {
|
||||
type: String,
|
||||
default: 'left'
|
||||
},
|
||||
vertical: {
|
||||
type: String,
|
||||
default: 'bottom'
|
||||
},
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'horizontal'
|
||||
},
|
||||
content: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
popMenu: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fabShow: false,
|
||||
isShow: false,
|
||||
isAndroidNvue: platform === 'android',
|
||||
styles: {
|
||||
color: '#3c3e49',
|
||||
selectedColor: '#007AFF',
|
||||
backgroundColor: '#fff',
|
||||
buttonColor: '#3c3e49'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
contentWidth(e) {
|
||||
return (this.content.length + 1) * 55 + 10 + 'px'
|
||||
},
|
||||
contentWidthMin() {
|
||||
return 55 + 'px'
|
||||
},
|
||||
// 动态计算宽度
|
||||
boxWidth() {
|
||||
return this.getPosition(3, 'horizontal')
|
||||
},
|
||||
// 动态计算高度
|
||||
boxHeight() {
|
||||
return this.getPosition(3, 'vertical')
|
||||
},
|
||||
// 计算左下位置
|
||||
leftBottom() {
|
||||
return this.getPosition(0, 'left', 'bottom')
|
||||
},
|
||||
// 计算右下位置
|
||||
rightBottom() {
|
||||
return this.getPosition(0, 'right', 'bottom')
|
||||
},
|
||||
// 计算左上位置
|
||||
leftTop() {
|
||||
return this.getPosition(0, 'left', 'top')
|
||||
},
|
||||
rightTop() {
|
||||
return this.getPosition(0, 'right', 'top')
|
||||
},
|
||||
flexDirectionStart() {
|
||||
return this.getPosition(1, 'vertical', 'top')
|
||||
},
|
||||
flexDirectionEnd() {
|
||||
return this.getPosition(1, 'vertical', 'bottom')
|
||||
},
|
||||
horizontalLeft() {
|
||||
return this.getPosition(2, 'horizontal', 'left')
|
||||
},
|
||||
horizontalRight() {
|
||||
return this.getPosition(2, 'horizontal', 'right')
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
pattern(newValue, oldValue) {
|
||||
//console.log(JSON.stringify(newValue))
|
||||
this.styles = Object.assign({}, this.styles, newValue)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.isShow = this.show
|
||||
if (this.top === 0) {
|
||||
this.fabShow = true
|
||||
}
|
||||
// 初始化样式
|
||||
this.styles = Object.assign({}, this.styles, this.pattern)
|
||||
},
|
||||
methods: {
|
||||
_onClick() {
|
||||
this.$emit('fabClick')
|
||||
if (!this.popMenu) {
|
||||
return
|
||||
}
|
||||
this.isShow = !this.isShow
|
||||
},
|
||||
open() {
|
||||
this.isShow = true
|
||||
},
|
||||
close() {
|
||||
this.isShow = false
|
||||
},
|
||||
/**
|
||||
* 按钮点击事件
|
||||
*/
|
||||
_onItemClick(index, item) {
|
||||
this.$emit('trigger', {
|
||||
index,
|
||||
item
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 获取 位置信息
|
||||
*/
|
||||
getPosition(types, paramA, paramB) {
|
||||
if (types === 0) {
|
||||
return this.horizontal === paramA && this.vertical === paramB
|
||||
} else if (types === 1) {
|
||||
return this.direction === paramA && this.vertical === paramB
|
||||
} else if (types === 2) {
|
||||
return this.direction === paramA && this.horizontal === paramB
|
||||
} else {
|
||||
return this.isShow && this.direction === paramA ? this.contentWidth : this.contentWidthMin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.uni-fab {
|
||||
position: fixed;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.uni-fab--active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uni-fab--leftBottom {
|
||||
left: 5px;
|
||||
bottom: 20px;
|
||||
/* #ifdef H5 */
|
||||
bottom: calc(20px + var(--window-bottom));
|
||||
/* #endif */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.uni-fab--leftTop {
|
||||
left: 5px;
|
||||
top: 30px;
|
||||
/* #ifdef H5 */
|
||||
top: calc(30px + var(--window-top));
|
||||
/* #endif */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.uni-fab--rightBottom {
|
||||
right: 5px;
|
||||
bottom: 20px;
|
||||
/* #ifdef H5 */
|
||||
bottom: calc(20px + var(--window-bottom));
|
||||
/* #endif */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.uni-fab--rightTop {
|
||||
right: 5px;
|
||||
top: 30px;
|
||||
/* #ifdef H5 */
|
||||
top: calc(30px + var(--window-top));
|
||||
/* #endif */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.uni-fab__circle {
|
||||
position: fixed;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
background-color: #3c3e49;
|
||||
border-radius: 55px;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
.uni-fab__circle--leftBottom {
|
||||
left: 15px;
|
||||
bottom: 30px;
|
||||
/* #ifdef H5 */
|
||||
bottom: calc(30px + var(--window-bottom));
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-fab__circle--leftTop {
|
||||
left: 15px;
|
||||
top: 40px;
|
||||
/* #ifdef H5 */
|
||||
top: calc(40px + var(--window-top));
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-fab__circle--rightBottom {
|
||||
right: 15px;
|
||||
bottom: 30px;
|
||||
/* #ifdef H5 */
|
||||
bottom: calc(30px + var(--window-bottom));
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-fab__circle--rightTop {
|
||||
right: 15px;
|
||||
top: 40px;
|
||||
/* #ifdef H5 */
|
||||
top: calc(40px + var(--window-top));
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-fab__circle--left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.uni-fab__circle--right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.uni-fab__circle--top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.uni-fab__circle--bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.uni-fab__plus {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.fab-circle-v {
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 31px;
|
||||
left: 26px;
|
||||
top: 12px;
|
||||
background-color: white;
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.fab-circle-h {
|
||||
position: absolute;
|
||||
width: 31px;
|
||||
height: 3px;
|
||||
left: 12px;
|
||||
top: 26px;
|
||||
background-color: white;
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.uni-fab__plus--active {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
|
||||
.uni-fab__content {
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
border-radius: 55px;
|
||||
overflow: hidden;
|
||||
transition-property: width, height;
|
||||
transition-duration: 0.2s;
|
||||
width: 55px;
|
||||
border-color: #DDDDDD;
|
||||
border-width: 1rpx;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.uni-fab__content--other-platform {
|
||||
border-width: 0px;
|
||||
box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.uni-fab__content--left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.uni-fab__content--right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.uni-fab__content--flexDirection {
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.uni-fab__content--flexDirectionStart {
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.uni-fab__content--flexDirectionEnd {
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.uni-fab__item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.uni-fab__item--active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uni-fab__item-image {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.uni-fab__item-text {
|
||||
color: #FFFFFF;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.uni-fab__item--first {
|
||||
width: 55px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<view v-if="width" :style="'width:'+width+';'+(square?'height:'+width:'')" class="uni-grid-item">
|
||||
<view :class="{ 'uni-grid-item--border': showBorder, 'uni-grid-item--border-top': showBorder && index < column, 'uni-highlight': highlight }"
|
||||
:style="{ 'border-right-color': borderColor ,'border-bottom-color': borderColor ,'border-top-color': borderColor }"
|
||||
class="uni-grid-item__box" @click="_onClick">
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UniGridItem',
|
||||
inject: ['grid'],
|
||||
props: {
|
||||
index:{
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
column: 0,
|
||||
showBorder: true,
|
||||
square: true,
|
||||
highlight: true,
|
||||
left: 0,
|
||||
top: 0,
|
||||
openNum: 2,
|
||||
width: 0,
|
||||
borderColor: '#e5e5e5'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.column = this.grid.column
|
||||
this.showBorder = this.grid.showBorder
|
||||
this.square = this.grid.square
|
||||
this.highlight = this.grid.highlight
|
||||
this.top = this.hor === 0 ? this.grid.hor : this.hor
|
||||
this.left = this.ver === 0 ? this.grid.ver : this.ver
|
||||
this.borderColor = this.grid.borderColor
|
||||
this.grid.children.push(this)
|
||||
// this.grid.init()
|
||||
this.width = this.grid.width
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.grid.children.forEach((item, index) => {
|
||||
if (item === this) {
|
||||
this.grid.children.splice(index, 1)
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
_onClick() {
|
||||
this.grid.change({
|
||||
detail: {
|
||||
index: this.index
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-grid-item {
|
||||
/* #ifndef APP-NVUE */
|
||||
height: 100%;
|
||||
display: flex;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-grid-item__box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
}
|
||||
|
||||
.uni-grid-item--border {
|
||||
position: relative;
|
||||
border-bottom-color: $uni-border-color;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
border-right-color: $uni-border-color;
|
||||
border-right-style: solid;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
.uni-grid-item--border-top {
|
||||
border-top-color: $uni-border-color;
|
||||
border-top-style: solid;
|
||||
border-top-width: 1px;
|
||||
/* #ifndef APP-NVUE */
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-highlight:active {
|
||||
background-color: $uni-bg-color-hover;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<view class="uni-grid-wrap">
|
||||
<view :id="elId" ref="uni-grid" class="uni-grid" :class="{ 'uni-grid--border': showBorder }" :style="{ 'border-left-style':'solid','border-left-color':borderColor, 'border-left-width':showBorder?'1px':0 }">
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef APP-NVUE
|
||||
const dom = uni.requireNativePlugin('dom');
|
||||
// #endif
|
||||
export default {
|
||||
name: 'UniGrid',
|
||||
props: {
|
||||
// 每列显示个数
|
||||
column: {
|
||||
type: Number,
|
||||
default: 3
|
||||
},
|
||||
// 是否显示边框
|
||||
showBorder: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 边框颜色
|
||||
borderColor: {
|
||||
type: String,
|
||||
default: '#e5e5e5'
|
||||
},
|
||||
// 是否正方形显示,默认为 true
|
||||
square: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
highlight: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
grid: this
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
|
||||
return {
|
||||
elId,
|
||||
width: 0
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.children = []
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
setTimeout(() => {
|
||||
this._getSize((width) => {
|
||||
this.children.forEach((item, index) => {
|
||||
item.width = width
|
||||
})
|
||||
})
|
||||
}, 50)
|
||||
},
|
||||
change(e) {
|
||||
this.$emit('change', e)
|
||||
},
|
||||
_getSize(fn) {
|
||||
// #ifndef APP-NVUE
|
||||
uni.createSelectorQuery()
|
||||
.in(this)
|
||||
.select(`#${this.elId}`)
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
this.width = parseInt((ret[0].width-1) / this.column) + 'px'
|
||||
fn(this.width)
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
dom.getComponentRect(this.$refs['uni-grid'], (ret) => {
|
||||
this.width = parseInt((ret.size.width-1) / this.column) + 'px'
|
||||
fn(this.width)
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-grid-wrap {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
/* #ifdef H5 */
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-grid {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
// flex: 1;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.uni-grid--border {
|
||||
border-left-color: $uni-border-color;
|
||||
border-left-style: solid;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,96 @@
|
||||
export default {
|
||||
'contact': '\ue100',
|
||||
'person': '\ue101',
|
||||
'personadd': '\ue102',
|
||||
'contact-filled': '\ue130',
|
||||
'person-filled': '\ue131',
|
||||
'personadd-filled': '\ue132',
|
||||
'phone': '\ue200',
|
||||
'email': '\ue201',
|
||||
'chatbubble': '\ue202',
|
||||
'chatboxes': '\ue203',
|
||||
'phone-filled': '\ue230',
|
||||
'email-filled': '\ue231',
|
||||
'chatbubble-filled': '\ue232',
|
||||
'chatboxes-filled': '\ue233',
|
||||
'weibo': '\ue260',
|
||||
'weixin': '\ue261',
|
||||
'pengyouquan': '\ue262',
|
||||
'chat': '\ue263',
|
||||
'qq': '\ue264',
|
||||
'videocam': '\ue300',
|
||||
'camera': '\ue301',
|
||||
'mic': '\ue302',
|
||||
'location': '\ue303',
|
||||
'mic-filled': '\ue332',
|
||||
'speech': '\ue332',
|
||||
'location-filled': '\ue333',
|
||||
'micoff': '\ue360',
|
||||
'image': '\ue363',
|
||||
'map': '\ue364',
|
||||
'compose': '\ue400',
|
||||
'trash': '\ue401',
|
||||
'upload': '\ue402',
|
||||
'download': '\ue403',
|
||||
'close': '\ue404',
|
||||
'redo': '\ue405',
|
||||
'undo': '\ue406',
|
||||
'refresh': '\ue407',
|
||||
'star': '\ue408',
|
||||
'plus': '\ue409',
|
||||
'minus': '\ue410',
|
||||
'circle': '\ue411',
|
||||
'checkbox': '\ue411',
|
||||
'close-filled': '\ue434',
|
||||
'clear': '\ue434',
|
||||
'refresh-filled': '\ue437',
|
||||
'star-filled': '\ue438',
|
||||
'plus-filled': '\ue439',
|
||||
'minus-filled': '\ue440',
|
||||
'circle-filled': '\ue441',
|
||||
'checkbox-filled': '\ue442',
|
||||
'closeempty': '\ue460',
|
||||
'refreshempty': '\ue461',
|
||||
'reload': '\ue462',
|
||||
'starhalf': '\ue463',
|
||||
'spinner': '\ue464',
|
||||
'spinner-cycle': '\ue465',
|
||||
'search': '\ue466',
|
||||
'plusempty': '\ue468',
|
||||
'forward': '\ue470',
|
||||
'back': '\ue471',
|
||||
'left-nav': '\ue471',
|
||||
'checkmarkempty': '\ue472',
|
||||
'home': '\ue500',
|
||||
'navigate': '\ue501',
|
||||
'gear': '\ue502',
|
||||
'paperplane': '\ue503',
|
||||
'info': '\ue504',
|
||||
'help': '\ue505',
|
||||
'locked': '\ue506',
|
||||
'more': '\ue507',
|
||||
'flag': '\ue508',
|
||||
'home-filled': '\ue530',
|
||||
'gear-filled': '\ue532',
|
||||
'info-filled': '\ue534',
|
||||
'help-filled': '\ue535',
|
||||
'more-filled': '\ue537',
|
||||
'settings': '\ue560',
|
||||
'list': '\ue562',
|
||||
'bars': '\ue563',
|
||||
'loop': '\ue565',
|
||||
'paperclip': '\ue567',
|
||||
'eye': '\ue568',
|
||||
'arrowup': '\ue580',
|
||||
'arrowdown': '\ue581',
|
||||
'arrowleft': '\ue582',
|
||||
'arrowright': '\ue583',
|
||||
'arrowthinup': '\ue584',
|
||||
'arrowthindown': '\ue585',
|
||||
'arrowthinleft': '\ue586',
|
||||
'arrowthinright': '\ue587',
|
||||
'pulldown': '\ue588',
|
||||
'closefill': '\ue589',
|
||||
'sound': '\ue590',
|
||||
'scan': '\ue612'
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,272 @@
|
||||
<template>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<cell>
|
||||
<!-- #endif -->
|
||||
<view :class="disabled ? 'uni-list-item--disabled' : ''" :hover-class="disabled || showSwitch ? '' : 'uni-list-item--hover'"
|
||||
class="uni-list-item" @click="onClick">
|
||||
<view class="uni-list-item__container" :class="{'uni-list-item--first':isFirstChild}">
|
||||
<view v-if="thumb" class="uni-list-item__icon">
|
||||
<image :src="thumb" class="uni-list-item__icon-img" />
|
||||
</view>
|
||||
<view v-else-if="showExtraIcon" class="uni-list-item__icon">
|
||||
<uni-icons :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" class="uni-icon-wrapper" />
|
||||
</view>
|
||||
<view class="uni-list-item__content">
|
||||
<slot />
|
||||
<text class="uni-list-item__content-title">{{ title }}</text>
|
||||
<text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
|
||||
</view>
|
||||
<view class="uni-list-item__extra">
|
||||
<text v-if="rightText" class="uni-list-item__extra-text">{{rightText}}</text>
|
||||
<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" />
|
||||
<switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked" @change="onSwitchChange" />
|
||||
<slot name="right"></slot>
|
||||
<uni-icons v-if="showArrow" :size="20" class="uni-icon-wrapper" color="#bbb" type="arrowright" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
</cell>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniIcons from '../uni-icons/uni-icons.vue'
|
||||
import uniBadge from '../uni-badge/uni-badge.vue'
|
||||
|
||||
/**
|
||||
* ListItem 列表子组件
|
||||
* @description 列表子组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||
* @property {String} title 标题
|
||||
* @property {String} note 描述
|
||||
* @property {String} thumb 左侧缩略图,若thumb有值,则不会显示扩展图标
|
||||
* @property {String} badgeText 数字角标内容
|
||||
* @property {String} badgeType 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
|
||||
* @property {String} rightText 右侧文字内容
|
||||
* @property {Boolean} disabled = [true|false]是否禁用
|
||||
* @property {Boolean} showArrow = [true|false] 是否显示箭头图标
|
||||
* @property {Boolean} showBadge = [true|false] 是否显示数字角标
|
||||
* @property {Boolean} showSwitch = [true|false] 是否显示Switch
|
||||
* @property {Boolean} switchChecked = [true|false] Switch是否被选中
|
||||
* @property {Boolean} showExtraIcon = [true|false] 左侧是否显示扩展图标
|
||||
* @property {Boolean} scrollY = [true|false] 允许纵向滚动,需要显式的设置其宽高
|
||||
* @property {Object} extraIcon 扩展图标参数,格式为 {color: '#4cd964',size: '22',type: 'spinner'}
|
||||
* @event {Function} click 点击 uniListItem 触发事件
|
||||
* @event {Function} switchChange 点击切换 Switch 时触发
|
||||
*/
|
||||
export default {
|
||||
name: 'UniListItem',
|
||||
components: {
|
||||
uniIcons,
|
||||
uniBadge
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}, // 列表标题
|
||||
note: {
|
||||
type: String,
|
||||
default: ''
|
||||
}, // 列表描述
|
||||
disabled: {
|
||||
// 是否禁用
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showArrow: {
|
||||
// 是否显示箭头
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
showBadge: {
|
||||
// 是否显示数字角标
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showSwitch: {
|
||||
// 是否显示Switch
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
switchChecked: {
|
||||
// Switch是否被选中
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
badgeText: {
|
||||
// badge内容
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
badgeType: {
|
||||
// badge类型
|
||||
type: String,
|
||||
default: 'success'
|
||||
},
|
||||
rightText: {
|
||||
// 右侧文字内容
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
thumb: {
|
||||
// 缩略图
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
showExtraIcon: {
|
||||
// 是否显示扩展图标
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
extraIcon: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
type: 'contact',
|
||||
color: '#000000',
|
||||
size: 20
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
inject: ['list'],
|
||||
data() {
|
||||
return {
|
||||
isFirstChild: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (!this.list.firstChildAppend) {
|
||||
this.list.firstChildAppend = true
|
||||
this.isFirstChild = true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.$emit('click')
|
||||
},
|
||||
onSwitchChange(e) {
|
||||
this.$emit('switchChange', e.detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
|
||||
|
||||
.uni-list-item {
|
||||
font-size: $uni-font-size-lg;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: $uni-spacing-row-lg;
|
||||
}
|
||||
|
||||
.uni-list-item--disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.uni-list-item--hover {
|
||||
background-color: $uni-bg-color-hover;
|
||||
}
|
||||
|
||||
.uni-list-item__container {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
padding: $list-item-pd;
|
||||
padding-left: 0;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
/* #ifdef APP-PLUS */
|
||||
border-top-color: $uni-border-color;
|
||||
border-top-style: solid;
|
||||
border-top-width: 0.5px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-list-item--first {
|
||||
border-top-width: 0px;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-list-item__container:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
content: '';
|
||||
-webkit-transform: scaleY(.5);
|
||||
transform: scaleY(.5);
|
||||
background-color: $uni-border-color;
|
||||
}
|
||||
|
||||
.uni-list-item--first:after {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.uni-list-item__content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
color: #3b4144;
|
||||
|
||||
}
|
||||
|
||||
.uni-list-item__content-title {
|
||||
font-size: $uni-font-size-base;
|
||||
color: #3b4144;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-item__content-note {
|
||||
margin-top: 6rpx;
|
||||
color: $uni-text-color-grey;
|
||||
font-size: $uni-font-size-sm;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-list-item__extra {
|
||||
// width: 25%;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-list-item__icon {
|
||||
margin-right: 18rpx;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-list-item__icon-img {
|
||||
height: $uni-img-size-base;
|
||||
width: $uni-img-size-base;
|
||||
}
|
||||
|
||||
.uni-list-item__extra-text {
|
||||
color: $uni-text-color-grey;
|
||||
font-size: $uni-font-size-sm;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view class="uni-list">
|
||||
<slot />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<list class="uni-list" :enableBackToTop="enableBackToTop" loadmoreoffset="15" :scroll-y="scrollY" @loadmore="loadMore">
|
||||
<slot />
|
||||
</list>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* List 列表
|
||||
* @description 列表组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||
*/
|
||||
export default {
|
||||
name: 'UniList',
|
||||
'mp-weixin': {
|
||||
options: {
|
||||
multipleSlots: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
enableBackToTop: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
scrollY: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
list: this
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.firstChildAppend = false
|
||||
},
|
||||
methods: {
|
||||
loadMore(e) {
|
||||
this.$emit("scrolltolower");
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-list {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
background-color: $uni-bg-color;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
// border-bottom-color: $uni-border-color;
|
||||
// border-bottom-style: solid;
|
||||
// border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-list:before {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.uni-list:after {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
||||
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
|
||||
<slot />
|
||||
</refresh>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view ref="uni-refresh" class="uni-refresh" v-show="isShow">
|
||||
<slot />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UniRefresh',
|
||||
props: {
|
||||
display: {
|
||||
type: [String],
|
||||
default: "hide"
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pulling: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isShow() {
|
||||
if (this.display === "show" || this.pulling === true) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
onchange(value) {
|
||||
this.pulling = value;
|
||||
},
|
||||
onrefresh(e) {
|
||||
this.$emit("refresh", e);
|
||||
},
|
||||
onpullingdown(e) {
|
||||
// #ifdef APP-NVUE
|
||||
this.$emit("pullingdown", e);
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
var detail = {
|
||||
viewHeight: 90,
|
||||
pullingDistance: e.height
|
||||
}
|
||||
this.$emit("pullingdown", detail);
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.uni-refresh {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,87 @@
|
||||
var pullDown = {
|
||||
threshold: 95,
|
||||
maxHeight: 200,
|
||||
callRefresh: 'onrefresh',
|
||||
callPullingDown: 'onpullingdown',
|
||||
refreshSelector: '.uni-refresh'
|
||||
};
|
||||
|
||||
function ready(newValue, oldValue, ownerInstance, instance) {
|
||||
var state = instance.getState()
|
||||
state.canPullDown = newValue;
|
||||
// console.log(newValue);
|
||||
}
|
||||
|
||||
function touchStart(e, instance) {
|
||||
var state = instance.getState();
|
||||
state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
|
||||
state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
|
||||
if (!state.canPullDown) {
|
||||
return
|
||||
}
|
||||
|
||||
// console.log("touchStart");
|
||||
|
||||
state.height = 0;
|
||||
state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
|
||||
state.refreshInstance.setStyle({
|
||||
'height': 0
|
||||
});
|
||||
state.refreshInstance.callMethod("onchange", true);
|
||||
}
|
||||
|
||||
function touchMove(e, ownerInstance) {
|
||||
var instance = e.instance;
|
||||
var state = instance.getState();
|
||||
if (!state.canPullDown) {
|
||||
return
|
||||
}
|
||||
|
||||
var oldHeight = state.height;
|
||||
var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
|
||||
var height = endY - state.touchStartY;
|
||||
if (height > pullDown.maxHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
var refreshInstance = state.refreshInstance;
|
||||
refreshInstance.setStyle({
|
||||
'height': height + 'px'
|
||||
});
|
||||
|
||||
height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
|
||||
state.height = height;
|
||||
refreshInstance.callMethod(pullDown.callPullingDown, {
|
||||
height: height
|
||||
});
|
||||
}
|
||||
|
||||
function touchEnd(e, ownerInstance) {
|
||||
var state = e.instance.getState();
|
||||
if (!state.canPullDown) {
|
||||
return
|
||||
}
|
||||
|
||||
state.refreshInstance.callMethod("onchange", false);
|
||||
|
||||
var refreshInstance = state.refreshInstance;
|
||||
if (state.height > pullDown.threshold) {
|
||||
refreshInstance.callMethod(pullDown.callRefresh);
|
||||
return;
|
||||
}
|
||||
|
||||
refreshInstance.setStyle({
|
||||
'height': 0
|
||||
});
|
||||
}
|
||||
|
||||
function propObserver(newValue, oldValue, instance) {
|
||||
pullDown = newValue;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
touchmove: touchMove,
|
||||
touchstart: touchStart,
|
||||
touchend: touchEnd,
|
||||
propObserver: propObserver
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,235 @@
|
||||
<template>
|
||||
<view class="uni-navbar">
|
||||
<view :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }" :style="{ 'background-color': backgroundColor }" class="uni-navbar__content">
|
||||
<uni-status-bar v-if="statusBar" />
|
||||
<view :style="{ color: color,backgroundColor: backgroundColor }" class="uni-navbar__header uni-navbar__content_view">
|
||||
<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left uni-navbar__content_view">
|
||||
<view class="uni-navbar__content_view" v-if="leftIcon.length">
|
||||
<uni-icons :color="color" :type="leftIcon" size="24" />
|
||||
</view>
|
||||
<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length }" class="uni-navbar-btn-text uni-navbar__content_view" v-if="leftText.length">
|
||||
<text :style="{ color: color, fontSize: '14px' }">{{ leftText }}</text>
|
||||
</view>
|
||||
<slot name="left" />
|
||||
</view>
|
||||
<view class="uni-navbar__header-container uni-navbar__content_view">
|
||||
<view class="uni-navbar__header-container-inner uni-navbar__content_view" v-if="title.length">
|
||||
<text class="uni-nav-bar-text" :style="{color: color }">{{ title }}</text>
|
||||
</view>
|
||||
<!-- 标题插槽 -->
|
||||
<slot />
|
||||
</view>
|
||||
<view :class="title.length ? 'uni-navbar__header-btns-right' : ''" @tap="onClickRight" class="uni-navbar__header-btns uni-navbar__content_view">
|
||||
<view class="uni-navbar__content_view" v-if="rightIcon.length">
|
||||
<uni-icons :color="color" :type="rightIcon" size="24" />
|
||||
</view>
|
||||
<!-- 优先显示图标 -->
|
||||
<view class="uni-navbar-btn-text uni-navbar__content_view" v-if="rightText.length && !rightIcon.length">
|
||||
<text class="uni-nav-bar-right-text">{{ rightText }}</text>
|
||||
</view>
|
||||
<slot name="right" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-navbar__placeholder" v-if="fixed">
|
||||
<uni-status-bar v-if="statusBar" />
|
||||
<view class="uni-navbar__placeholder-view" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniStatusBar from "../uni-status-bar/uni-status-bar.vue";
|
||||
import uniIcons from "../uni-icons/uni-icons.vue";
|
||||
|
||||
/**
|
||||
* NavBar 自定义导航栏
|
||||
* @description 导航栏组件,主要用于头部导航
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=52
|
||||
* @property {String} title 标题文字
|
||||
* @property {String} leftText 左侧按钮文本
|
||||
* @property {String} rightText 右侧按钮文本
|
||||
* @property {String} leftIcon 左侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
|
||||
* @property {String} rightIcon 右侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
|
||||
* @property {String} color 图标和文字颜色
|
||||
* @property {String} backgroundColor 导航栏背景颜色
|
||||
* @property {Boolean} fixed = [true|false] 是否固定顶部
|
||||
* @property {Boolean} statusBar = [true|false] 是否包含状态栏
|
||||
* @property {Boolean} shadow = [true|false] 导航栏下是否有阴影
|
||||
* @event {Function} clickLeft 左侧按钮点击时触发
|
||||
* @event {Function} clickRight 右侧按钮点击时触发
|
||||
*/
|
||||
export default {
|
||||
name: "UniNavBar",
|
||||
components: {
|
||||
uniStatusBar,
|
||||
uniIcons
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
leftText: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
rightText: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
leftIcon: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
rightIcon: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
fixed: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: "#000000"
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: "#FFFFFF"
|
||||
},
|
||||
statusBar: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
shadow: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
border: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (uni.report && this.title !== '') {
|
||||
uni.report('title', this.title)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClickLeft() {
|
||||
this.$emit("clickLeft");
|
||||
},
|
||||
onClickRight() {
|
||||
this.$emit("clickRight");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.uni-nav-bar-text {
|
||||
/* #ifdef APP-PLUS */
|
||||
font-size: 34rpx;
|
||||
/* #endif */
|
||||
/* #ifndef APP-PLUS */
|
||||
font-size: 32rpx;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-nav-bar-right-text {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.uni-navbar__content {
|
||||
position: relative;
|
||||
background-color: #ffffff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-navbar__content_view {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
/* background-color: #FFFFFF;
|
||||
*/
|
||||
}
|
||||
|
||||
.uni-navbar__header {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
font-size: 16px;
|
||||
/* background-color: #ffffff;
|
||||
*/
|
||||
}
|
||||
|
||||
.uni-navbar__header-btns {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-wrap: nowrap;
|
||||
width: 120rpx;
|
||||
padding: 0 6px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-navbar__header-btns-left {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
width: 150rpx;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.uni-navbar__header-btns-right {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
width: 150rpx;
|
||||
padding-right: 30rpx;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.uni-navbar__header-container {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.uni-navbar__header-container-inner {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
|
||||
.uni-navbar__placeholder-view {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.uni-navbar--fixed {
|
||||
position: fixed;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
.uni-navbar--shadow {
|
||||
/* #ifndef APP-NVUE */
|
||||
box-shadow: 0 1px 6px #ccc;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-navbar--border {
|
||||
border-bottom-width: 1rpx;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: #e5e5e5;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,392 @@
|
||||
<template>
|
||||
<view v-if="show" class="uni-noticebar" :style="{ backgroundColor: backgroundColor }" @click="onClick">
|
||||
<!-- #ifdef MP-ALIPAY -->
|
||||
<view v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close" @click="close">
|
||||
<uni-icons type="closeempty" :color="color" size="12" />
|
||||
</view>
|
||||
<view v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon">
|
||||
<uni-icons type="sound" :color="color" size="14" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-ALIPAY -->
|
||||
<uni-icons v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close" type="closeempty" :color="color" size="12" @click="close" />
|
||||
<uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound" :color="color" size="14" />
|
||||
<!-- #endif -->
|
||||
<view ref="textBox" class="uni-noticebar__content-wrapper" :class="{'uni-noticebar__content-wrapper--scrollable':scrollable, 'uni-noticebar__content-wrapper--single':!scrollable && (single || moreText)}">
|
||||
<view :id="elIdBox" class="uni-noticebar__content" :class="{'uni-noticebar__content--scrollable':scrollable, 'uni-noticebar__content--single':!scrollable && (single || moreText)}">
|
||||
<text :id="elId" ref="animationEle" class="uni-noticebar__content-text" :class="{'uni-noticebar__content-text--scrollable':scrollable,'uni-noticebar__content-text--single':!scrollable && (single || moreText)}" :style="{color:color, width:wrapWidth+'px', 'animationDuration': animationDuration, '-webkit-animationDuration': animationDuration ,animationPlayState: webviewHide?'paused':animationPlayState,'-webkit-animationPlayState':webviewHide?'paused':animationPlayState, animationDelay: animationDelay, '-webkit-animationDelay':animationDelay}">{{text}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="showGetMore === true || showGetMore === 'true'" class="uni-noticebar__more" @click="clickMore">
|
||||
<text v-if="moreText" :style="{ color: moreColor }" class="uni-noticebar__more-text">{{ moreText }}</text>
|
||||
<uni-icons type="arrowright" :color="moreColor" size="14" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniIcons from '../uni-icons/uni-icons.vue'
|
||||
// #ifdef APP-NVUE
|
||||
const dom = weex.requireModule('dom');
|
||||
const animation = weex.requireModule('animation');
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* NoticeBar 自定义导航栏
|
||||
* @description 通告栏组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=30
|
||||
* @property {Number} speed 文字滚动的速度,默认100px/秒
|
||||
* @property {String} text 显示文字
|
||||
* @property {String} backgroundColor 背景颜色
|
||||
* @property {String} color 文字颜色
|
||||
* @property {String} moreColor 查看更多文字的颜色
|
||||
* @property {String} moreText 设置“查看更多”的文本
|
||||
* @property {Boolean} single = [true|false] 是否单行
|
||||
* @property {Boolean} scrollable = [true|false] 是否滚动,为true时,NoticeBar为单行
|
||||
* @property {Boolean} showIcon = [true|false] 是否显示左侧喇叭图标
|
||||
* @property {Boolean} showClose = [true|false] 是否显示左侧关闭按钮
|
||||
* @property {Boolean} showGetMore = [true|false] 是否显示右侧查看更多图标,为true时,NoticeBar为单行
|
||||
* @event {Function} click 点击 NoticeBar 触发事件
|
||||
* @event {Function} close 关闭 NoticeBar 触发事件
|
||||
* @event {Function} getmore 点击”查看更多“时触发事件
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniNoticeBar',
|
||||
components: {
|
||||
uniIcons
|
||||
},
|
||||
props: {
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
moreText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: '#fffbe8'
|
||||
},
|
||||
speed: {
|
||||
// 默认1s滚动100px
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#de8c17'
|
||||
},
|
||||
moreColor: {
|
||||
type: String,
|
||||
default: '#999999'
|
||||
},
|
||||
single: {
|
||||
// 是否单行
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
scrollable: {
|
||||
// 是否滚动,添加后控制单行效果取消
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showIcon: {
|
||||
// 是否显示左侧icon
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showGetMore: {
|
||||
// 是否显示右侧查看更多
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showClose: {
|
||||
// 是否显示左侧关闭按钮
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
|
||||
const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
|
||||
return {
|
||||
textWidth: 0,
|
||||
boxWidth: 0,
|
||||
wrapWidth: '',
|
||||
webviewHide: false,
|
||||
// #ifdef APP-NVUE
|
||||
stopAnimation: false,
|
||||
// #endif
|
||||
elId: elId,
|
||||
elIdBox: elIdBox,
|
||||
show: true,
|
||||
animationDuration: 'none',
|
||||
animationPlayState: 'paused',
|
||||
animationDelay: '0s'
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef APP-PLUS
|
||||
var pages = getCurrentPages();
|
||||
var page = pages[pages.length - 1];
|
||||
var currentWebview = page.$getAppWebview();
|
||||
currentWebview.addEventListener('hide', () => {
|
||||
this.webviewHide = true
|
||||
})
|
||||
currentWebview.addEventListener('show', () => {
|
||||
this.webviewHide = false
|
||||
})
|
||||
// #endif
|
||||
this.$nextTick(() => {
|
||||
this.initSize()
|
||||
})
|
||||
},
|
||||
// #ifdef APP-NVUE
|
||||
beforeDestroy() {
|
||||
this.stopAnimation = true
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
initSize() {
|
||||
if (this.scrollable) {
|
||||
// #ifndef APP-NVUE
|
||||
let query = [],
|
||||
boxWidth = 0,
|
||||
textWidth = 0;
|
||||
let textQuery = new Promise((resolve, reject) => {
|
||||
uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select(`#${this.elId}`)
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
this.textWidth = ret[0].width
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
let boxQuery = new Promise((resolve, reject) => {
|
||||
uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select(`#${this.elIdBox}`)
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
this.boxWidth = ret[0].width
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
query.push(textQuery)
|
||||
query.push(boxQuery)
|
||||
Promise.all(query).then(() => {
|
||||
this.animationDuration = `${this.textWidth / this.speed}s`
|
||||
this.animationDelay = `-${this.boxWidth / this.speed}s`
|
||||
setTimeout(() => {
|
||||
this.animationPlayState = 'running'
|
||||
}, 1000)
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
dom.getComponentRect(this.$refs['animationEle'], (res) => {
|
||||
let winWidth = uni.getSystemInfoSync().windowWidth
|
||||
this.textWidth = res.size.width
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateX(-${winWidth}px)`
|
||||
},
|
||||
duration: 0,
|
||||
timingFunction: 'linear',
|
||||
delay: 0
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateX(-${this.textWidth}px)`
|
||||
},
|
||||
timingFunction: 'linear',
|
||||
duration: (this.textWidth - winWidth) / this.speed * 1000,
|
||||
delay: 1000
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
this.loopAnimation()
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
// #ifdef APP-NVUE
|
||||
if (!this.scrollable && (this.single || this.moreText)) {
|
||||
dom.getComponentRect(this.$refs['textBox'], (res) => {
|
||||
this.wrapWidth = res.size.width
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
loopAnimation() {
|
||||
// #ifdef APP-NVUE
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateX(0px)`
|
||||
},
|
||||
duration: 0
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateX(-${this.textWidth}px)`
|
||||
},
|
||||
duration: this.textWidth / this.speed * 1000,
|
||||
timingFunction: 'linear',
|
||||
delay: 0
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
this.loopAnimation()
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
clickMore() {
|
||||
this.$emit('getmore')
|
||||
},
|
||||
close() {
|
||||
this.show = false;
|
||||
this.$emit('close')
|
||||
},
|
||||
onClick() {
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.uni-noticebar {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.uni-noticebar-close {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.uni-noticebar-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.uni-noticebar__content-wrapper {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-noticebar__content-wrapper--single {
|
||||
/* #ifndef APP-NVUE */
|
||||
line-height: 18px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content-wrapper--single,
|
||||
.uni-noticebar__content-wrapper--scrollable {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-noticebar__content-wrapper--scrollable {
|
||||
position: relative;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.uni-noticebar__content--scrollable {
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 0;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
flex: 1;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content--single {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
flex: none;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content-text {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
/* #ifndef APP-NVUE */
|
||||
word-break: break-all;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content-text--single {
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 1;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
/* #endif */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.uni-noticebar__content-text--scrollable {
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 1;
|
||||
padding-left: 750rpx;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
padding-left: 100%;
|
||||
animation: notice 10s 0s linear infinite both;
|
||||
animation-play-state: paused;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__more {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: inline-flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.uni-noticebar__more-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@keyframes notice {
|
||||
100% {
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,264 @@
|
||||
<template>
|
||||
<view v-if="showPopup" class="uni-popup" @touchmove.stop.prevent="clear">
|
||||
<uni-transition :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
|
||||
<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
|
||||
<view class="uni-popup__wrapper-box" @click.stop="clear">
|
||||
<slot />
|
||||
</view>
|
||||
</uni-transition>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniTransition from '../uni-transition/uni-transition.vue'
|
||||
|
||||
/**
|
||||
* PopUp 弹出层
|
||||
* @description 弹出层组件,为了解决遮罩弹层的问题
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} type = [top|center|bottom] 弹出方式
|
||||
* @value top 顶部弹出
|
||||
* @value center 中间弹出
|
||||
* @value bottom 底部弹出
|
||||
* @property {Boolean} animation = [ture|false] 是否开启动画
|
||||
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
|
||||
* @event {Function} change 打开关闭弹窗触发,e={show: false}
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniPopup',
|
||||
components: {
|
||||
uniTransition
|
||||
},
|
||||
props: {
|
||||
// 开启动画
|
||||
animation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
|
||||
type: {
|
||||
type: String,
|
||||
default: 'center'
|
||||
},
|
||||
// maskClick
|
||||
maskClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
duration: 300,
|
||||
ani: [],
|
||||
showPopup: false,
|
||||
showTrans: false,
|
||||
maskClass: {
|
||||
'position': 'fixed',
|
||||
'bottom': 0,
|
||||
'top': 0,
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
'backgroundColor': 'rgba(0, 0, 0, 0.4)'
|
||||
},
|
||||
transClass: {
|
||||
'position': 'fixed',
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
type: {
|
||||
handler: function(newVal) {
|
||||
switch (this.type) {
|
||||
case 'top':
|
||||
this.ani = ['slide-top']
|
||||
this.transClass = {
|
||||
'position': 'fixed',
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
}
|
||||
break
|
||||
case 'bottom':
|
||||
this.ani = ['slide-bottom']
|
||||
this.transClass = {
|
||||
'position': 'fixed',
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
'bottom': 0
|
||||
}
|
||||
break
|
||||
case 'center':
|
||||
this.ani = ['zoom-out', 'fade']
|
||||
this.transClass = {
|
||||
'position': 'fixed',
|
||||
/* #ifndef APP-NVUE */
|
||||
'display': 'flex',
|
||||
'flexDirection': 'column',
|
||||
/* #endif */
|
||||
'bottom': 0,
|
||||
'left': 0,
|
||||
'right': 0,
|
||||
'top': 0,
|
||||
'justifyContent': 'center',
|
||||
'alignItems': 'center'
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.animation) {
|
||||
this.duration = 300
|
||||
} else {
|
||||
this.duration = 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clear(e) {
|
||||
// TODO nvue 取消冒泡
|
||||
e.stopPropagation()
|
||||
},
|
||||
open() {
|
||||
this.showPopup = true
|
||||
this.$nextTick(() => {
|
||||
clearTimeout(this.timer)
|
||||
this.timer = setTimeout(() => {
|
||||
this.showTrans = true
|
||||
}, 50);
|
||||
})
|
||||
this.$emit('change', {
|
||||
show: true
|
||||
})
|
||||
},
|
||||
close(type) {
|
||||
this.showTrans = false
|
||||
this.$nextTick(() => {
|
||||
clearTimeout(this.timer)
|
||||
this.timer = setTimeout(() => {
|
||||
this.$emit('change', {
|
||||
show: false
|
||||
})
|
||||
this.showPopup = false
|
||||
}, 300)
|
||||
})
|
||||
},
|
||||
onTap() {
|
||||
if (!this.maskClick) return
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.uni-popup {
|
||||
position: fixed;
|
||||
/* #ifdef H5 */
|
||||
top: var(--window-top);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
top: 0;
|
||||
/* #endif */
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 99;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-popup__mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.mask-ani {
|
||||
transition-property: opacity;
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
|
||||
.uni-top-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uni-bottom-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uni-center-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.uni-popup__wrapper {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.top {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transform: translateY(-500px);
|
||||
}
|
||||
|
||||
.bottom {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transform: translateY(500px);
|
||||
}
|
||||
|
||||
.center {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transform: scale(1.2);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.uni-popup__wrapper-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.content-ani {
|
||||
/* transition: transform 0.3s;
|
||||
*/
|
||||
transition-property: transform, opacity;
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
|
||||
|
||||
.uni-top-content {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.uni-bottom-content {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.uni-center-content {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<view class="uni-searchbar">
|
||||
<view :style="{borderRadius:radius+'px',backgroundColor: bgColor}" class="uni-searchbar__box" @click="searchClick">
|
||||
<!-- #ifdef MP-ALIPAY -->
|
||||
<view class="uni-searchbar__box-icon-search">
|
||||
<uni-icons color="#999999" size="18" type="search" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-ALIPAY -->
|
||||
<uni-icons color="#999999" class="uni-searchbar__box-icon-search" size="18" type="search" />
|
||||
<!-- #endif -->
|
||||
<input v-if="show" :focus="showSync" :placeholder="placeholder" :maxlength="maxlength" @confirm="confirm" class="uni-searchbar__box-search-input"
|
||||
confirm-type="search" type="text" v-model="searchVal" />
|
||||
<text v-else class="uni-searchbar__text-placeholder">{{ placeholder }}</text>
|
||||
<view v-if="show && (clearButton==='always'||clearButton==='auto'&&searchVal!=='')" class="uni-searchbar__box-icon-clear" @click="clear">
|
||||
<uni-icons color="#999999" class="" size="24" type="clear" />
|
||||
</view>
|
||||
</view>
|
||||
<text @click="cancel" class="uni-searchbar__cancel" v-if="cancelButton ==='always' || show && cancelButton ==='auto'">{{cancelText}}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniIcons from "../uni-icons/uni-icons.vue";
|
||||
export default {
|
||||
name: "UniSearchBar",
|
||||
components: {
|
||||
uniIcons
|
||||
},
|
||||
props: {
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "请输入搜索内容"
|
||||
},
|
||||
radius: {
|
||||
type: [Number, String],
|
||||
default: 5
|
||||
},
|
||||
clearButton: {
|
||||
type: String,
|
||||
default: "auto"
|
||||
},
|
||||
cancelButton: {
|
||||
type: String,
|
||||
default: "auto"
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: "#F8F8F8"
|
||||
},
|
||||
maxlength: {
|
||||
type: [Number, String],
|
||||
default: 100
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
showSync: false,
|
||||
searchVal: ""
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
searchVal() {
|
||||
this.$emit("input", {
|
||||
value: this.searchVal
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
searchClick() {
|
||||
if (this.show) {
|
||||
return
|
||||
}
|
||||
this.searchVal = ""
|
||||
this.show = true;
|
||||
this.$nextTick(() => {
|
||||
this.showSync = true;
|
||||
})
|
||||
},
|
||||
clear() {
|
||||
this.searchVal = ""
|
||||
},
|
||||
cancel() {
|
||||
this.$emit("cancel", {
|
||||
value: this.searchVal
|
||||
});
|
||||
this.searchVal = ""
|
||||
this.show = false
|
||||
this.showSync = false
|
||||
// #ifndef APP-PLUS
|
||||
uni.hideKeyboard()
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
plus.key.hideSoftKeybord()
|
||||
// #endif
|
||||
},
|
||||
confirm() {
|
||||
// #ifndef APP-PLUS
|
||||
uni.hideKeyboard();
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
plus.key.hideSoftKeybord()
|
||||
// #endif
|
||||
this.$emit("confirm", {
|
||||
value: this.searchVal
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$uni-searchbar-height: 36px;
|
||||
|
||||
.uni-searchbar {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
padding: $uni-spacing-col-base;
|
||||
background-color: $uni-bg-color;
|
||||
}
|
||||
|
||||
.uni-searchbar__box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
height: $uni-searchbar-height;
|
||||
padding: 5px 8px 5px 0px;
|
||||
border-width: 0.5px;
|
||||
border-style: solid;
|
||||
border-color: $uni-border-color;
|
||||
}
|
||||
|
||||
.uni-searchbar__box-icon-search {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
width: 32px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: $uni-text-color-placeholder;
|
||||
}
|
||||
|
||||
.uni-searchbar__box-search-input {
|
||||
flex: 1;
|
||||
font-size: $uni-font-size-base;
|
||||
color: $uni-text-color;
|
||||
}
|
||||
|
||||
.uni-searchbar__box-icon-clear {
|
||||
align-items: center;
|
||||
line-height: 24px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.uni-searchbar__text-placeholder {
|
||||
font-size: $uni-font-size-base;
|
||||
color: $uni-text-color-placeholder;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.uni-searchbar__cancel {
|
||||
padding-left: 10px;
|
||||
line-height: $uni-searchbar-height;
|
||||
font-size: 14px;
|
||||
color: $uni-text-color;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<view class="uni-section" nvue>
|
||||
<view v-if="type" class="uni-section__head">
|
||||
<view :class="type" class="uni-section__head-tag" />
|
||||
</view>
|
||||
<view class="uni-section__content">
|
||||
<text :class="{'distraction':!subTitle}" class="uni-section__content-title">{{ title }}</text>
|
||||
<text v-if="subTitle" class="uni-section__content-sub">{{ subTitle }}</text>
|
||||
</view>
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Section 标题栏
|
||||
* @description 标题栏
|
||||
* @property {String} type = [line|circle] 标题装饰类型
|
||||
* @value line 竖线
|
||||
* @value circle 圆形
|
||||
* @property {String} title 主标题
|
||||
* @property {String} subTitle 副标题
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniTitle',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
subTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
watch: {
|
||||
title(newVal) {
|
||||
if (uni.report && newVal !== '') {
|
||||
uni.report('title', newVal)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.uni-section {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
margin-top: 10px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
height: 50px;
|
||||
background-color: #f8f8f8;
|
||||
/* #ifdef APP-NVUE */
|
||||
border-bottom-color: #e5e5e5;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 0.5px;
|
||||
/* #endif */
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-section:after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
content: '';
|
||||
-webkit-transform: scaleY(.5);
|
||||
transform: scaleY(.5);
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.uni-section__head {
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.line {
|
||||
height: 15px;
|
||||
background-color: #c0c0c0;
|
||||
border-radius: 5px;
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-top-right-radius: 50px;
|
||||
border-top-left-radius: 50px;
|
||||
border-bottom-left-radius: 50px;
|
||||
border-bottom-right-radius: 50px;
|
||||
background-color: #c0c0c0;
|
||||
}
|
||||
|
||||
.uni-section__content {
|
||||
flex: 1;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.uni-section__content-title {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.distraction {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-section__content-sub {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<view :style="{ height: statusBarHeight }" class="uni-status-bar">
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
var statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
|
||||
export default {
|
||||
name: 'UniStatusBar',
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: statusBarHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.uni-status-bar {
|
||||
width: 750rpx;
|
||||
height: 20px;
|
||||
/* height: var(--status-bar-height);
|
||||
*/
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject" @click="change">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef APP-NVUE
|
||||
const animation = uni.requireNativePlugin('animation');
|
||||
// #endif
|
||||
/**
|
||||
* Transition 过渡动画
|
||||
* @description 简单过渡动画组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
|
||||
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
|
||||
* @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
|
||||
* @value fade 渐隐渐出过渡
|
||||
* @value slide-top 由上至下过渡
|
||||
* @value slide-right 由右至左过渡
|
||||
* @value slide-bottom 由下至上过渡
|
||||
* @value slide-left 由左至右过渡
|
||||
* @value zoom-in 由小到大过渡
|
||||
* @value zoom-out 由大到小过渡
|
||||
* @property {Number} duration 过渡动画持续时间
|
||||
* @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
|
||||
*/
|
||||
export default {
|
||||
name: 'uniTransition',
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
modeClass: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 300
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShow: false,
|
||||
transform: '',
|
||||
ani: {
|
||||
in: '',
|
||||
active: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
show: {
|
||||
handler(newVal) {
|
||||
if (newVal) {
|
||||
this.open()
|
||||
} else {
|
||||
this.close()
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
stylesObject() {
|
||||
let styles = {
|
||||
...this.styles,
|
||||
'transition-duration': this.duration / 1000 + 's'
|
||||
}
|
||||
let transfrom = ''
|
||||
for (let i in styles) {
|
||||
let line = this.toLine(i)
|
||||
transfrom += line + ':' + styles[i] + ';'
|
||||
}
|
||||
return transfrom
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// this.timer = null
|
||||
// this.nextTick = (time = 50) => new Promise(resolve => {
|
||||
// clearTimeout(this.timer)
|
||||
// this.timer = setTimeout(resolve, time)
|
||||
// return this.timer
|
||||
// });
|
||||
},
|
||||
methods: {
|
||||
change() {
|
||||
this.$emit('click', {
|
||||
detail: this.isShow
|
||||
})
|
||||
},
|
||||
open() {
|
||||
clearTimeout(this.timer)
|
||||
this.isShow = true
|
||||
this.transform = ''
|
||||
this.ani.in = ''
|
||||
for (let i in this.getTranfrom(false)) {
|
||||
if (i === 'opacity') {
|
||||
this.ani.in = 'fade-in'
|
||||
} else {
|
||||
this.transform += `${this.getTranfrom(false)[i]} `
|
||||
}
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this._animation(true)
|
||||
}, 50)
|
||||
})
|
||||
|
||||
},
|
||||
close(type) {
|
||||
clearTimeout(this.timer)
|
||||
this._animation(false)
|
||||
},
|
||||
_animation(type) {
|
||||
let styles = this.getTranfrom(type)
|
||||
// #ifdef APP-NVUE
|
||||
if (!this.$refs['ani']) return
|
||||
animation.transition(this.$refs['ani'].ref, {
|
||||
styles,
|
||||
duration: this.duration, //ms
|
||||
timingFunction: 'ease',
|
||||
needLayout: false,
|
||||
delay: 0 //ms
|
||||
}, () => {
|
||||
if (!type) {
|
||||
this.isShow = false
|
||||
}
|
||||
this.$emit('change', {
|
||||
detail: this.isShow
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.transform = ''
|
||||
for (let i in styles) {
|
||||
if (i === 'opacity') {
|
||||
this.ani.in = `fade-${type?'out':'in'}`
|
||||
} else {
|
||||
this.transform += `${styles[i]} `
|
||||
}
|
||||
}
|
||||
this.timer = setTimeout(() => {
|
||||
if (!type) {
|
||||
this.isShow = false
|
||||
}
|
||||
this.$emit('change', {
|
||||
detail: this.isShow
|
||||
})
|
||||
|
||||
}, this.duration)
|
||||
// #endif
|
||||
|
||||
},
|
||||
getTranfrom(type) {
|
||||
let styles = {
|
||||
transform: ''
|
||||
}
|
||||
this.modeClass.forEach((mode) => {
|
||||
switch (mode) {
|
||||
case 'fade':
|
||||
styles.opacity = type ? 1 : 0
|
||||
break;
|
||||
case 'slide-top':
|
||||
styles.transform += `translateY(${type?'0':'-100%'}) `
|
||||
break;
|
||||
case 'slide-right':
|
||||
styles.transform += `translateX(${type?'0':'100%'}) `
|
||||
break;
|
||||
case 'slide-bottom':
|
||||
styles.transform += `translateY(${type?'0':'100%'}) `
|
||||
break;
|
||||
case 'slide-left':
|
||||
styles.transform += `translateX(${type?'0':'-100%'}) `
|
||||
break;
|
||||
case 'zoom-in':
|
||||
styles.transform += `scale(${type?1:0.8}) `
|
||||
break;
|
||||
case 'zoom-out':
|
||||
styles.transform += `scale(${type?1:1.2}) `
|
||||
break;
|
||||
}
|
||||
})
|
||||
return styles
|
||||
},
|
||||
_modeClassArr(type) {
|
||||
let mode = this.modeClass
|
||||
if (typeof(mode) !== "string") {
|
||||
let modestr = ''
|
||||
mode.forEach((item) => {
|
||||
modestr += (item + '-' + type + ',')
|
||||
})
|
||||
return modestr.substr(0, modestr.length - 1)
|
||||
} else {
|
||||
return mode + '-' + type
|
||||
}
|
||||
},
|
||||
// getEl(el) {
|
||||
// console.log(el || el.ref || null);
|
||||
// return el || el.ref || null
|
||||
// },
|
||||
toLine(name) {
|
||||
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.uni-transition {
|
||||
transition-timing-function: ease;
|
||||
transition-duration: 0.3s;
|
||||
transition-property: transform, opacity;
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.fade-active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.slide-top-in {
|
||||
/* transition-property: transform, opacity; */
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
.slide-top-active {
|
||||
transform: translateY(0);
|
||||
/* opacity: 1; */
|
||||
}
|
||||
|
||||
.slide-right-in {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.slide-right-active {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.slide-bottom-in {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.slide-bottom-active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.slide-left-in {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.slide-left-active {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.zoom-in-in {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
|
||||
.zoom-out-active {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.zoom-out-in {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user