@ -1,5 +1,6 @@
|
||||
const ROOTPATH1 = "http://waimai.admin.service.cyjyyjy.com/sqx_fast/"; |
||||
const ROOTPATH = "http://waimai.admin.service.cyjyyjy.com/sqx_fast/"; |
||||
|
||||
const ROOTPATH1 = "http://192.168.0.111:8891/sqx_fast"; |
||||
const ROOTPATH = "https://bwc.xianmxkj.com/sqx_fast"; |
||||
module.exports = { |
||||
APIHOST: ROOTPATH, |
||||
APIHOST1: ROOTPATH1 |
||||
|
@ -1,151 +0,0 @@
|
||||
<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> |
@ -1,227 +0,0 @@
|
||||
<template> |
||||
<view class="uni-goods-nav"> |
||||
<!-- 底部占位 --> |
||||
<view class="uni-tab__seat" /> |
||||
<view class="uni-tab__cart-box flex"> |
||||
<view class="flex uni-tab__cart-sub-left"> |
||||
<view v-for="(item,index) in options" :key="index" class="flex uni-tab__cart-button-left uni-tab__shop-cart" @click="onClick(index,item)"> |
||||
<view class="uni-tab__icon"> |
||||
<uni-icons :type="item.icon" size="20" color="#646566"></uni-icons> |
||||
<!-- <image class="image" :src="item.icon" mode="widthFix" /> --> |
||||
</view> |
||||
<text class="uni-tab__text">{{ item.text }}</text> |
||||
<view class="flex uni-tab__dot-box"> |
||||
<text v-if="item.info" :class="{ 'uni-tab__dots': item.info > 9 }" class="uni-tab__dot " :style="{'backgroundColor':item.infoBackgroundColor?item.infoBackgroundColor:'#ff0000', |
||||
color:item.infoColor?item.infoColor:'#fff' |
||||
}">{{ item.info }}</text> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
<view :class="{'uni-tab__right':fill}" class="flex uni-tab__cart-sub-right "> |
||||
<view v-for="(item,index) in buttonGroup" :key="index" :style="{backgroundColor:item.backgroundColor,color:item.color}" |
||||
class="flex uni-tab__cart-button-right" @click="buttonClick(index,item)"><text :style="{color:item.color}" class="uni-tab__cart-button-right-text">{{ item.text }}</text></view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
/** |
||||
* GoodsNav 商品导航 |
||||
* @description 商品加入购物车、立即购买等 |
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=865 |
||||
* @property {Array} options 组件参数 |
||||
* @property {Array} buttonGroup 组件按钮组参数 |
||||
* @property {Boolean} fill = [true | false] 组件按钮组参数 |
||||
* @event {Function} click 左侧点击事件 |
||||
* @event {Function} buttonClick 右侧按钮组点击事件 |
||||
* @example <uni-goods-nav :fill="true" options="" buttonGroup="buttonGroup" @click="" @buttonClick="" /> |
||||
*/ |
||||
export default { |
||||
name: 'UniGoodsNav', |
||||
props: { |
||||
options: { |
||||
type: Array, |
||||
default () { |
||||
return [{ |
||||
icon: 'shop', |
||||
text: '店铺', |
||||
}, { |
||||
icon: 'cart', |
||||
text: '购物车' |
||||
}] |
||||
} |
||||
}, |
||||
buttonGroup: { |
||||
type: Array, |
||||
default () { |
||||
return [{ |
||||
text: '加入购物车', |
||||
backgroundColor: '#ffa200', |
||||
color: '#fff' |
||||
}, |
||||
{ |
||||
text: '立即购买', |
||||
backgroundColor: '#ff0000', |
||||
color: '#fff' |
||||
} |
||||
] |
||||
} |
||||
}, |
||||
fill: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
methods: { |
||||
onClick(index, item) { |
||||
this.$emit('click', { |
||||
index, |
||||
content: item, |
||||
|
||||
}) |
||||
}, |
||||
buttonClick(index, item) { |
||||
if (uni.report) { |
||||
uni.report(item.text, item.text) |
||||
} |
||||
this.$emit('buttonClick', { |
||||
index, |
||||
content: item |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.flex { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
flex-direction: row; |
||||
} |
||||
|
||||
.uni-goods-nav { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
flex: 1; |
||||
flex-direction: row; |
||||
} |
||||
|
||||
.uni-tab__cart-box { |
||||
flex: 1; |
||||
height: 50px; |
||||
background-color: #fff; |
||||
z-index: 900; |
||||
} |
||||
|
||||
.uni-tab__cart-sub-left { |
||||
padding: 0 5px; |
||||
} |
||||
|
||||
.uni-tab__cart-sub-right { |
||||
flex: 1; |
||||
} |
||||
|
||||
.uni-tab__right { |
||||
margin: 5px 0; |
||||
margin-right: 10px; |
||||
border-radius: 100px; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.uni-tab__cart-button-left { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
// flex: 1; |
||||
position: relative; |
||||
justify-content: center; |
||||
align-items: center; |
||||
flex-direction: column; |
||||
margin: 0 10px; |
||||
/* #ifdef H5 */ |
||||
cursor: pointer; |
||||
/* #endif */ |
||||
} |
||||
|
||||
.uni-tab__icon { |
||||
width: 18px; |
||||
height: 18px; |
||||
} |
||||
|
||||
.image { |
||||
width: 18px; |
||||
height: 18px; |
||||
} |
||||
|
||||
.uni-tab__text { |
||||
margin-top: 3px; |
||||
font-size: $uni-font-size-sm; |
||||
color: #646566; |
||||
} |
||||
|
||||
.uni-tab__cart-button-right { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
flex-direction: column; |
||||
/* #endif */ |
||||
flex: 1; |
||||
justify-content: center; |
||||
align-items: center; |
||||
/* #ifdef H5 */ |
||||
cursor: pointer; |
||||
/* #endif */ |
||||
} |
||||
|
||||
.uni-tab__cart-button-right-text { |
||||
font-size: $uni-font-size-base; |
||||
color: #fff; |
||||
} |
||||
|
||||
.uni-tab__cart-button-right:active { |
||||
opacity: 0.7; |
||||
} |
||||
|
||||
.uni-tab__dot-box { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
flex-direction: column; |
||||
/* #endif */ |
||||
position: absolute; |
||||
right: -2px; |
||||
top: 2px; |
||||
justify-content: center; |
||||
align-items: center; |
||||
// width: 0; |
||||
// height: 0; |
||||
} |
||||
|
||||
.uni-tab__dot { |
||||
// width: 30rpx; |
||||
// height: 30rpx; |
||||
padding: 0 4px; |
||||
line-height: 15px; |
||||
color: #ffffff; |
||||
text-align: center; |
||||
font-size: 12px; |
||||
background-color: #ff0000; |
||||
border-radius: 15px; |
||||
} |
||||
|
||||
.uni-tab__dots { |
||||
padding: 0 4px; |
||||
// width: auto; |
||||
border-radius: 15px; |
||||
} |
||||
|
||||
.uni-tab__color-y { |
||||
background-color: #ffa200; |
||||
} |
||||
|
||||
.uni-tab__color-r { |
||||
background-color: #ff0000; |
||||
} |
||||
</style> |
@ -1,132 +0,0 @@
|
||||
export default { |
||||
"pulldown": "\ue588", |
||||
"refreshempty": "\ue461", |
||||
"back": "\ue471", |
||||
"forward": "\ue470", |
||||
"more": "\ue507", |
||||
"more-filled": "\ue537", |
||||
"scan": "\ue612", |
||||
"qq": "\ue264", |
||||
"weibo": "\ue260", |
||||
"weixin": "\ue261", |
||||
"pengyouquan": "\ue262", |
||||
"loop": "\ue565", |
||||
"refresh": "\ue407", |
||||
"refresh-filled": "\ue437", |
||||
"arrowthindown": "\ue585", |
||||
"arrowthinleft": "\ue586", |
||||
"arrowthinright": "\ue587", |
||||
"arrowthinup": "\ue584", |
||||
"undo-filled": "\ue7d6", |
||||
"undo": "\ue406", |
||||
"redo": "\ue405", |
||||
"redo-filled": "\ue7d9", |
||||
"bars": "\ue563", |
||||
"chatboxes": "\ue203", |
||||
"camera": "\ue301", |
||||
"chatboxes-filled": "\ue233", |
||||
"camera-filled": "\ue7ef", |
||||
"cart-filled": "\ue7f4", |
||||
"cart": "\ue7f5", |
||||
"checkbox-filled": "\ue442", |
||||
"checkbox": "\ue7fa", |
||||
"arrowleft": "\ue582", |
||||
"arrowdown": "\ue581", |
||||
"arrowright": "\ue583", |
||||
"smallcircle-filled": "\ue801", |
||||
"arrowup": "\ue580", |
||||
"circle": "\ue411", |
||||
"eye-filled": "\ue568", |
||||
"eye-slash-filled": "\ue822", |
||||
"eye-slash": "\ue823", |
||||
"eye": "\ue824", |
||||
"flag-filled": "\ue825", |
||||
"flag": "\ue508", |
||||
"gear-filled": "\ue532", |
||||
"reload": "\ue462", |
||||
"gear": "\ue502", |
||||
"hand-thumbsdown-filled": "\ue83b", |
||||
"hand-thumbsdown": "\ue83c", |
||||
"hand-thumbsup-filled": "\ue83d", |
||||
"heart-filled": "\ue83e", |
||||
"hand-thumbsup": "\ue83f", |
||||
"heart": "\ue840", |
||||
"home": "\ue500", |
||||
"info": "\ue504", |
||||
"home-filled": "\ue530", |
||||
"info-filled": "\ue534", |
||||
"circle-filled": "\ue441", |
||||
"chat-filled": "\ue847", |
||||
"chat": "\ue263", |
||||
"mail-open-filled": "\ue84d", |
||||
"email-filled": "\ue231", |
||||
"mail-open": "\ue84e", |
||||
"email": "\ue201", |
||||
"checkmarkempty": "\ue472", |
||||
"list": "\ue562", |
||||
"locked-filled": "\ue856", |
||||
"locked": "\ue506", |
||||
"map-filled": "\ue85c", |
||||
"map-pin": "\ue85e", |
||||
"map-pin-ellipse": "\ue864", |
||||
"map": "\ue364", |
||||
"minus-filled": "\ue440", |
||||
"mic-filled": "\ue332", |
||||
"minus": "\ue410", |
||||
"micoff": "\ue360", |
||||
"mic": "\ue302", |
||||
"clear": "\ue434", |
||||
"smallcircle": "\ue868", |
||||
"close": "\ue404", |
||||
"closeempty": "\ue460", |
||||
"paperclip": "\ue567", |
||||
"paperplane": "\ue503", |
||||
"paperplane-filled": "\ue86e", |
||||
"person-filled": "\ue131", |
||||
"contact-filled": "\ue130", |
||||
"person": "\ue101", |
||||
"contact": "\ue100", |
||||
"images-filled": "\ue87a", |
||||
"phone": "\ue200", |
||||
"images": "\ue87b", |
||||
"image": "\ue363", |
||||
"image-filled": "\ue877", |
||||
"location-filled": "\ue333", |
||||
"location": "\ue303", |
||||
"plus-filled": "\ue439", |
||||
"plus": "\ue409", |
||||
"plusempty": "\ue468", |
||||
"help-filled": "\ue535", |
||||
"help": "\ue505", |
||||
"navigate-filled": "\ue884", |
||||
"navigate": "\ue501", |
||||
"mic-slash-filled": "\ue892", |
||||
"search": "\ue466", |
||||
"settings": "\ue560", |
||||
"sound": "\ue590", |
||||
"sound-filled": "\ue8a1", |
||||
"spinner-cycle": "\ue465", |
||||
"download-filled": "\ue8a4", |
||||
"personadd-filled": "\ue132", |
||||
"videocam-filled": "\ue8af", |
||||
"personadd": "\ue102", |
||||
"upload": "\ue402", |
||||
"upload-filled": "\ue8b1", |
||||
"starhalf": "\ue463", |
||||
"star-filled": "\ue438", |
||||
"star": "\ue408", |
||||
"trash": "\ue401", |
||||
"phone-filled": "\ue230", |
||||
"compose": "\ue400", |
||||
"videocam": "\ue300", |
||||
"trash-filled": "\ue8dc", |
||||
"download": "\ue403", |
||||
"chatbubble-filled": "\ue232", |
||||
"chatbubble": "\ue202", |
||||
"cloud-download": "\ue8e4", |
||||
"cloud-upload-filled": "\ue8e5", |
||||
"cloud-upload": "\ue8e6", |
||||
"cloud-download-filled": "\ue8e9", |
||||
"headphones":"\ue8bf", |
||||
"shop":"\ue609" |
||||
} |
@ -0,0 +1,15 @@
|
||||
## 1.1.3(2021-08-30) |
||||
- 修复 在vue3中to属性在发行应用的时候报错的bug |
||||
## 1.1.2(2021-07-30) |
||||
- 优化 vue3下事件警告的问题 |
||||
## 1.1.1(2021-07-21) |
||||
- 修复 与其他组件嵌套使用时,点击失效的Bug |
||||
## 1.1.0(2021-07-13) |
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
||||
## 1.0.17(2021-05-12) |
||||
- 新增 组件示例地址 |
||||
## 1.0.16(2021-02-05) |
||||
- 优化 组件引用关系,通过uni_modules引用组件 |
||||
## 1.0.15(2021-02-05) |
||||
- 调整为uni_modules目录规范 |
||||
- 修复 uni-list-chat 角标显示不正常的问题 |
@ -0,0 +1,107 @@
|
||||
<template> |
||||
<!-- #ifdef APP-NVUE --> |
||||
<cell> |
||||
<!-- #endif --> |
||||
<view class="uni-list-ad"> |
||||
<view v-if="borderShow" :class="{'uni-list--border':border,'uni-list-item--first':isFirstChild}"></view> |
||||
<ad style="width: 200px;height: 300px;border-width: 1px;border-color: red;border-style: solid;" adpid="1111111111" |
||||
unit-id="" appid="" apid="" type="feed" @error="aderror" @close="closeAd"></ad> |
||||
</view> |
||||
<!-- #ifdef APP-NVUE --> |
||||
</cell> |
||||
<!-- #endif --> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
// #ifdef APP-NVUE |
||||
const dom = uni.requireNativePlugin('dom'); |
||||
// #endif |
||||
export default { |
||||
name: 'UniListAd', |
||||
props: { |
||||
title: { |
||||
type: String, |
||||
default: '', |
||||
|
||||
} |
||||
}, |
||||
// inject: ['list'], |
||||
data() { |
||||
return { |
||||
isFirstChild: false, |
||||
border: false, |
||||
borderShow: true, |
||||
} |
||||
}, |
||||
|
||||
mounted() { |
||||
this.list = this.getForm() |
||||
if (this.list) { |
||||
if (!this.list.firstChildAppend) { |
||||
this.list.firstChildAppend = true |
||||
this.isFirstChild = true |
||||
} |
||||
this.border = this.list.border |
||||
} |
||||
}, |
||||
methods: { |
||||
/** |
||||
* 获取父元素实例 |
||||
*/ |
||||
getForm(name = 'uniList') { |
||||
let parent = this.$parent; |
||||
let parentName = parent.$options.name; |
||||
while (parentName !== name) { |
||||
parent = parent.$parent; |
||||
if (!parent) return false |
||||
parentName = parent.$options.name; |
||||
} |
||||
return parent; |
||||
}, |
||||
aderror(e) { |
||||
console.log("aderror: " + JSON.stringify(e.detail)); |
||||
}, |
||||
closeAd(e) { |
||||
this.borderShow = false |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.uni-list-ad { |
||||
position: relative; |
||||
border: 1px red solid; |
||||
} |
||||
|
||||
.uni-list--border { |
||||
position: relative; |
||||
padding-bottom: 1px; |
||||
/* #ifdef APP-PLUS */ |
||||
border-top-color: $uni-border-color; |
||||
border-top-style: solid; |
||||
border-top-width: 0.5px; |
||||
/* #endif */ |
||||
margin-left: $uni-spacing-row-lg; |
||||
} |
||||
|
||||
/* #ifndef APP-NVUE */ |
||||
.uni-list--border: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 */ |
||||
</style> |
@ -0,0 +1,58 @@
|
||||
/** |
||||
* 这里是 uni-list 组件内置的常用样式变量 |
||||
* 如果需要覆盖样式,这里提供了基本的组件样式变量,您可以尝试修改这里的变量,去完成样式替换,而不用去修改源码 |
||||
* |
||||
*/ |
||||
|
||||
// 背景色 |
||||
$background-color : #fff; |
||||
// 分割线颜色 |
||||
$divide-line-color : #e5e5e5; |
||||
|
||||
// 默认头像大小,如需要修改此值,注意同步修改 js 中的值 const avatarWidth = xx ,目前只支持方形头像 |
||||
// nvue 页面不支持修改头像大小 |
||||
$avatar-width : 45px ; |
||||
|
||||
// 头像边框 |
||||
$avatar-border-radius: 5px; |
||||
$avatar-border-color: #eee; |
||||
$avatar-border-width: 1px; |
||||
|
||||
// 标题文字样式 |
||||
$title-size : 16px; |
||||
$title-color : #3b4144; |
||||
$title-weight : normal; |
||||
|
||||
// 描述文字样式 |
||||
$note-size : 12px; |
||||
$note-color : #999; |
||||
$note-weight : normal; |
||||
|
||||
// 右侧额外内容默认样式 |
||||
$right-text-size : 12px; |
||||
$right-text-color : #999; |
||||
$right-text-weight : normal; |
||||
|
||||
// 角标样式 |
||||
// nvue 页面不支持修改圆点位置以及大小 |
||||
// 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动 |
||||
$badge-left: 0px; |
||||
$badge-top: 0px; |
||||
|
||||
// 显示圆点时,圆点大小 |
||||
$dot-width: 10px; |
||||
$dot-height: 10px; |
||||
|
||||
// 显示角标时,角标大小和字体大小 |
||||
$badge-size : 18px; |
||||
$badge-font : 12px; |
||||
// 显示角标时,角标前景色 |
||||
$badge-color : #fff; |
||||
// 显示角标时,角标背景色 |
||||
$badge-background-color : #ff5a5f; |
||||
// 显示角标时,角标左右间距 |
||||
$badge-space : 6px; |
||||
|
||||
// 状态样式 |
||||
// 选中颜色 |
||||
$hover : #f5f5f5; |
@ -0,0 +1,534 @@
|
||||
<template> |
||||
<!-- #ifdef APP-NVUE --> |
||||
<cell> |
||||
<!-- #endif --> |
||||
<view :hover-class="!clickable && !link ? '' : 'uni-list-chat--hover'" class="uni-list-chat" @click.stop="onClick"> |
||||
<view :class="{ 'uni-list--border': border, 'uni-list-chat--first': isFirstChild }"></view> |
||||
<view class="uni-list-chat__container"> |
||||
<view class="uni-list-chat__header-warp"> |
||||
<view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }"> |
||||
<image class="uni-list-chat__header-image" :src="avatar" mode="aspectFill"></image> |
||||
</view> |
||||
<!-- 头像组 --> |
||||
<view v-else class="uni-list-chat__header"> |
||||
<view v-for="(item, index) in avatarList" :key="index" class="uni-list-chat__header-box" :class="computedAvatar" |
||||
:style="{ width: imageWidth + 'px', height: imageWidth + 'px' }"> |
||||
<image class="uni-list-chat__header-image" :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }" :src="item.url" |
||||
mode="aspectFill"></image> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
<view v-if="badgeText && badgePositon === 'left'" class="uni-list-chat__badge uni-list-chat__badge-pos" :class="[isSingle]"> |
||||
<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text> |
||||
</view> |
||||
<view class="uni-list-chat__content"> |
||||
<view class="uni-list-chat__content-main"> |
||||
<text class="uni-list-chat__content-title uni-ellipsis">{{ title }}</text> |
||||
<text class="uni-list-chat__content-note uni-ellipsis">{{ note }}</text> |
||||
</view> |
||||
<view class="uni-list-chat__content-extra"> |
||||
<slot> |
||||
<text class="uni-list-chat__content-extra-text">{{ time }}</text> |
||||
<view v-if="badgeText && badgePositon === 'right'" class="uni-list-chat__badge" :class="[isSingle, badgePositon === 'right' ? 'uni-list-chat--right' : '']"> |
||||
<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text> |
||||
</view> |
||||
</slot> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
<!-- #ifdef APP-NVUE --> |
||||
</cell> |
||||
<!-- #endif --> |
||||
</template> |
||||
|
||||
<script> |
||||
// 头像大小 |
||||
const avatarWidth = 45; |
||||
|
||||
/** |
||||
* ListChat 聊天列表 |
||||
* @description 聊天列表,用于创建聊天类列表 |
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24 |
||||
* @property {String} title 标题 |
||||
* @property {String} note 描述 |
||||
* @property {Boolean} clickable = [true|false] 是否开启点击反馈,默认为false |
||||
* @property {String} badgeText 数字角标内容 |
||||
* @property {String} badgePositon = [left|right] 角标位置,默认为 right |
||||
* @property {String} link = [false|navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈,默认为false |
||||
* @value false 不开启 |
||||
* @value navigateTo 同 uni.navigateTo() |
||||
* @value redirectTo 同 uni.redirectTo() |
||||
* @value reLaunch 同 uni.reLaunch() |
||||
* @value switchTab 同 uni.switchTab() |
||||
* @property {String | PageURIString} to 跳转目标页面 |
||||
* @property {String} time 右侧时间显示 |
||||
* @property {Boolean} avatarCircle = [true|false] 是否显示圆形头像,默认为false |
||||
* @property {String} avatar 头像地址,avatarCircle 不填时生效 |
||||
* @property {Array} avatarList 头像组,格式为 [{url:''}] |
||||
* @event {Function} click 点击 uniListChat 触发事件 |
||||
*/ |
||||
export default { |
||||
name: 'UniListChat', |
||||
emits:['click'], |
||||
props: { |
||||
title: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
note: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
clickable: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
link: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
to: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
badgeText: { |
||||
type: [String, Number], |
||||
default: '' |
||||
}, |
||||
badgePositon: { |
||||
type: String, |
||||
default: 'right' |
||||
}, |
||||
time: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
avatarCircle: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
avatar: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
avatarList: { |
||||
type: Array, |
||||
default () { |
||||
return []; |
||||
} |
||||
} |
||||
}, |
||||
// inject: ['list'], |
||||
computed: { |
||||
isSingle() { |
||||
if (this.badgeText === 'dot') { |
||||
return 'uni-badge--dot'; |
||||
} else { |
||||
const badgeText = this.badgeText.toString(); |
||||
if (badgeText.length > 1) { |
||||
return 'uni-badge--complex'; |
||||
} else { |
||||
return 'uni-badge--single'; |
||||
} |
||||
} |
||||
}, |
||||
computedAvatar() { |
||||
if (this.avatarList.length > 4) { |
||||
this.imageWidth = avatarWidth * 0.31; |
||||
return 'avatarItem--3'; |
||||
} else if (this.avatarList.length > 1) { |
||||
this.imageWidth = avatarWidth * 0.47; |
||||
return 'avatarItem--2'; |
||||
} else { |
||||
this.imageWidth = avatarWidth; |
||||
return 'avatarItem--1'; |
||||
} |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
isFirstChild: false, |
||||
border: true, |
||||
// avatarList: 3, |
||||
imageWidth: 50 |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.list = this.getForm() |
||||
if (this.list) { |
||||
if (!this.list.firstChildAppend) { |
||||
this.list.firstChildAppend = true; |
||||
this.isFirstChild = true; |
||||
} |
||||
this.border = this.list.border; |
||||
} |
||||
}, |
||||
methods: { |
||||
/** |
||||
* 获取父元素实例 |
||||
*/ |
||||
getForm(name = 'uniList') { |
||||
let parent = this.$parent; |
||||
let parentName = parent.$options.name; |
||||
while (parentName !== name) { |
||||
parent = parent.$parent; |
||||
if (!parent) return false |
||||
parentName = parent.$options.name; |
||||
} |
||||
return parent; |
||||
}, |
||||
onClick() { |
||||
if (this.to !== '') { |
||||
this.openPage(); |
||||
return; |
||||
} |
||||
|
||||
if (this.clickable || this.link) { |
||||
this.$emit('click', { |
||||
data: {} |
||||
}); |
||||
} |
||||
}, |
||||
openPage() { |
||||
if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) { |
||||
this.pageApi(this.link); |
||||
} else { |
||||
this.pageApi('navigateTo'); |
||||
} |
||||
}, |
||||
pageApi(api) { |
||||
uni[api]({ |
||||
url: this.to, |
||||
success: res => { |
||||
this.$emit('click', { |
||||
data: res |
||||
}); |
||||
}, |
||||
fail: err => { |
||||
this.$emit('click', { |
||||
data: err |
||||
}); |
||||
console.error(err.errMsg); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
$background-color: #fff; |
||||
$divide-line-color: #e5e5e5; |
||||
$avatar-width: 45px; |
||||
$avatar-border-radius: 5px; |
||||
$avatar-border-color: #eee; |
||||
$avatar-border-width: 1px; |
||||
$title-size: 16px; |
||||
$title-color: #3b4144; |
||||
$title-weight: normal; |
||||
$note-size: 12px; |
||||
$note-color: #999; |
||||
$note-weight: normal; |
||||
$right-text-size: 12px; |
||||
$right-text-color: #999; |
||||
$right-text-weight: normal; |
||||
$badge-left: 0px; |
||||
$badge-top: 0px; |
||||
$dot-width: 10px; |
||||
$dot-height: 10px; |
||||
$badge-size: 18px; |
||||
$badge-font: 12px; |
||||
$badge-color: #fff; |
||||
$badge-background-color: #ff5a5f; |
||||
$badge-space: 6px; |
||||
$hover: #f5f5f5; |
||||
|
||||
.uni-list-chat { |
||||
font-size: $uni-font-size-lg; |
||||
position: relative; |
||||
flex-direction: column; |
||||
justify-content: space-between; |
||||
background-color: $background-color; |
||||
} |
||||
|
||||
// .uni-list-chat--disabled { |
||||
// opacity: 0.3; |
||||
// } |
||||
|
||||
.uni-list-chat--hover { |
||||
background-color: $hover; |
||||
} |
||||
|
||||
.uni-list--border { |
||||
position: relative; |
||||
margin-left: $uni-spacing-row-lg; |
||||
/* #ifdef APP-PLUS */ |
||||
border-top-color: $divide-line-color; |
||||
border-top-style: solid; |
||||
border-top-width: 0.5px; |
||||
/* #endif */ |
||||
} |
||||
|
||||
/* #ifndef APP-NVUE */ |
||||
.uni-list--border:after { |
||||
position: absolute; |
||||
top: 0; |
||||
right: 0; |
||||
left: 0; |
||||
height: 1px; |
||||
content: ''; |
||||
-webkit-transform: scaleY(0.5); |
||||
transform: scaleY(0.5); |
||||
background-color: $divide-line-color; |
||||
} |
||||
|
||||
.uni-list-item--first:after { |
||||
height: 0px; |
||||
} |
||||
|
||||
/* #endif */ |
||||
|
||||
.uni-list-chat--first { |
||||
border-top-width: 0px; |
||||
} |
||||
|
||||
.uni-ellipsis { |
||||
/* #ifndef APP-NVUE */ |
||||
overflow: hidden; |
||||
white-space: nowrap; |
||||
text-overflow: ellipsis; |
||||
/* #endif */ |
||||
/* #ifdef APP-NVUE */ |
||||
lines: 1; |
||||
/* #endif */ |
||||
} |
||||
|
||||
.uni-ellipsis-2 { |
||||
/* #ifndef APP-NVUE */ |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
display: -webkit-box; |
||||
-webkit-line-clamp: 2; |
||||
-webkit-box-orient: vertical; |
||||
/* #endif */ |
||||
|
||||
/* #ifdef APP-NVUE */ |
||||
lines: 2; |
||||
/* #endif */ |
||||
} |
||||
|
||||
.uni-list-chat__container { |
||||
position: relative; |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
flex-direction: row; |
||||
flex: 1; |
||||
padding: $uni-spacing-row-base $uni-spacing-row-lg; |
||||
position: relative; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.uni-list-chat__header-warp { |
||||
position: relative; |
||||
} |
||||
|
||||
.uni-list-chat__header { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
align-content: center; |
||||
/* #endif */ |
||||
flex-direction: row; |
||||
justify-content: center; |
||||
align-items: center; |
||||
flex-wrap: wrap-reverse; |
||||
/* #ifdef APP-NVUE */ |
||||
width: 50px; |
||||
height: 50px; |
||||
/* #endif */ |
||||
/* #ifndef APP-NVUE */ |
||||
width: $avatar-width; |
||||
height: $avatar-width; |
||||
/* #endif */ |
||||
|
||||
border-radius: $avatar-border-radius; |
||||
border-color: $avatar-border-color; |
||||
border-width: $avatar-border-width; |
||||
border-style: solid; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.uni-list-chat__header-box { |
||||
/* #ifndef APP-PLUS */ |
||||
box-sizing: border-box; |
||||
display: flex; |
||||
width: $avatar-width; |
||||
height: $avatar-width; |
||||
/* #endif */ |
||||
/* #ifdef APP-NVUE */ |
||||
width: 50px; |
||||
height: 50px; |
||||
/* #endif */ |
||||
overflow: hidden; |
||||
border-radius: 2px; |
||||
} |
||||
|
||||
.uni-list-chat__header-image { |
||||
margin: 1px; |
||||
/* #ifdef APP-NVUE */ |
||||
width: 50px; |
||||
height: 50px; |
||||
/* #endif */ |
||||
/* #ifndef APP-NVUE */ |
||||
width: $avatar-width; |
||||
height: $avatar-width; |
||||
/* #endif */ |
||||
} |
||||
|
||||
/* #ifndef APP-NVUE */ |
||||
.uni-list-chat__header-image { |
||||
display: block; |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
.avatarItem--1 { |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
.avatarItem--2 { |
||||
width: 47%; |
||||
height: 47%; |
||||
} |
||||
|
||||
.avatarItem--3 { |
||||
width: 32%; |
||||
height: 32%; |
||||
} |
||||
|
||||
/* #endif */ |
||||
.header--circle { |
||||
border-radius: 50%; |
||||
} |
||||
|
||||
.uni-list-chat__content { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
flex-direction: row; |
||||
flex: 1; |
||||
overflow: hidden; |
||||
padding: 2px 0; |
||||
} |
||||
|
||||
.uni-list-chat__content-main { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
flex-direction: column; |
||||
justify-content: space-between; |
||||
padding-left: $uni-spacing-row-base; |
||||
flex: 1; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.uni-list-chat__content-title { |
||||
font-size: $title-size; |
||||
color: $title-color; |
||||
font-weight: $title-weight; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.uni-list-chat__content-note { |
||||
margin-top: 3px; |
||||
color: $note-color; |
||||
font-size: $note-size; |
||||
font-weight: $title-weight; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.uni-list-chat__content-extra { |
||||
/* #ifndef APP-NVUE */ |
||||
flex-shrink: 0; |
||||
display: flex; |
||||
/* #endif */ |
||||
flex-direction: column; |
||||
justify-content: space-between; |
||||
align-items: flex-end; |
||||
margin-left: 5px; |
||||
} |
||||
|
||||
.uni-list-chat__content-extra-text { |
||||
color: $right-text-color; |
||||
font-size: $right-text-size; |
||||
font-weight: $right-text-weight; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.uni-list-chat__badge-pos { |
||||
position: absolute; |
||||
/* #ifdef APP-NVUE */ |
||||
left: 55px; |
||||
top: 3px; |
||||
/* #endif */ |
||||
/* #ifndef APP-NVUE */ |
||||
left: calc(#{$avatar-width} + 10px - #{$badge-space} + #{$badge-left}); |
||||
top: calc(#{$uni-spacing-row-base}/ 2 + 1px + #{$badge-top}); |
||||
/* #endif */ |
||||
} |
||||
|
||||
.uni-list-chat__badge { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
justify-content: center; |
||||
align-items: center; |
||||
border-radius: 100px; |
||||
background-color: $badge-background-color; |
||||
} |
||||
|
||||
.uni-list-chat__badge-text { |
||||
color: $badge-color; |
||||
font-size: $badge-font; |
||||
} |
||||
|
||||
.uni-badge--single { |
||||
/* #ifndef APP-NVUE */ |
||||
// left: calc(#{$avatar-width} + 7px + #{$badge-left}); |
||||
/* #endif */ |
||||
width: $badge-size; |
||||
height: $badge-size; |
||||
} |
||||
|
||||
.uni-badge--complex { |
||||
/* #ifdef APP-NVUE */ |
||||
left: 50px; |
||||
/* #endif */ |
||||
/* #ifndef APP-NVUE */ |
||||
width: auto; |
||||
/* #endif */ |
||||
height: $badge-size; |
||||
padding: 0 $badge-space; |
||||
} |
||||
|
||||
.uni-badge--dot { |
||||
/* #ifdef APP-NVUE */ |
||||
left: 60px; |
||||
top: 6px; |
||||
/* #endif */ |
||||
/* #ifndef APP-NVUE */ |
||||
left: calc(#{$avatar-width} + 15px - #{$dot-width}/ 2 + 1px + #{$badge-left}); |
||||
/* #endif */ |
||||
width: $dot-width; |
||||
height: $dot-height; |
||||
padding: 0; |
||||
} |
||||
|
||||
.uni-list-chat--right { |
||||
/* #ifdef APP-NVUE */ |
||||
left: 0; |
||||
/* #endif */ |
||||
} |
||||
</style> |
@ -0,0 +1,461 @@
|
||||
<template> |
||||
<!-- #ifdef APP-NVUE --> |
||||
<cell> |
||||
<!-- #endif --> |
||||
|
||||
<view :class="{ 'uni-list-item--disabled': disabled }" |
||||
:hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uni-list-item--hover'" |
||||
class="uni-list-item" @click="onClick"> |
||||
<view v-if="!isFirstChild" class="border--left" :class="{ 'uni-list--border': border }"></view> |
||||
<view class="uni-list-item__container" |
||||
:class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column' }"> |
||||
<slot name="header"> |
||||
<view class="uni-list-item__header"> |
||||
<view v-if="thumb" class="uni-list-item__icon"> |
||||
<image :src="thumb" class="uni-list-item__icon-img" :class="['uni-list--' + thumbSize]" /> |
||||
</view> |
||||
<view v-else-if="showExtraIcon" class="uni-list-item__icon"> |
||||
<uni-icons :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" /> |
||||
</view> |
||||
</view> |
||||
</slot> |
||||
<slot name="body"> |
||||
<view class="uni-list-item__content" |
||||
:class="{ 'uni-list-item__content--center': thumb || showExtraIcon || showBadge || showSwitch }"> |
||||
<text v-if="title" class="uni-list-item__content-title" |
||||
:class="[ellipsis !== 0 && ellipsis <= 2 ? 'uni-ellipsis-' + ellipsis : '']">{{ title }}</text> |
||||
<text v-if="note" class="uni-list-item__content-note">{{ note }}</text> |
||||
</view> |
||||
</slot> |
||||
<slot name="footer"> |
||||
<view v-if="rightText || showBadge || showSwitch" class="uni-list-item__extra" |
||||
:class="{ 'flex--justify': direction === 'column' }"> |
||||
<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" /> |
||||
</view> |
||||
</slot> |
||||
</view> |
||||
<uni-icons v-if="showArrow || link" :size="16" class="uni-icon-wrapper" color="#bbb" type="arrowright" /> |
||||
</view> |
||||
<!-- #ifdef APP-NVUE --> |
||||
</cell> |
||||
<!-- #endif --> |
||||
</template> |
||||
|
||||
<script> |
||||
/** |
||||
* ListItem 列表子组件 |
||||
* @description 列表子组件 |
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24 |
||||
* @property {String} title 标题 |
||||
* @property {String} note 描述 |
||||
* @property {String} thumb 左侧缩略图,若thumb有值,则不会显示扩展图标 |
||||
* @property {String} thumbSize = [lg|base|sm] 略缩图大小 |
||||
* @value lg 大图 |
||||
* @value base 一般 |
||||
* @value sm 小图 |
||||
* @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} clickable = [true|false] 是否开启点击反馈 |
||||
* @property {String} link = [navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈 |
||||
* @value navigateTo 同 uni.navigateTo() |
||||
* @value redirectTo 同 uni.redirectTo() |
||||
* @value reLaunch 同 uni.reLaunch() |
||||
* @value switchTab 同 uni.switchTab() |
||||
* @property {String | PageURIString} to 跳转目标页面 |
||||
* @property {Boolean} showBadge = [true|false] 是否显示数字角标 |
||||
* @property {Boolean} showSwitch = [true|false] 是否显示Switch |
||||
* @property {Boolean} switchChecked = [true|false] Switch是否被选中 |
||||
* @property {Boolean} showExtraIcon = [true|false] 左侧是否显示扩展图标 |
||||
* @property {Object} extraIcon 扩展图标参数,格式为 {color: '#4cd964',size: '22',type: 'spinner'} |
||||
* @property {String} direction = [row|column] 排版方向 |
||||
* @value row 水平排列 |
||||
* @value column 垂直排列 |
||||
* @event {Function} click 点击 uniListItem 触发事件 |
||||
* @event {Function} switchChange 点击切换 Switch 时触发 |
||||
*/ |
||||
export default { |
||||
name: 'UniListItem', |
||||
emits: ['click', 'switchChange'], |
||||
props: { |
||||
direction: { |
||||
type: String, |
||||
default: 'row' |
||||
}, |
||||
title: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
note: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
ellipsis: { |
||||
type: [Number], |
||||
default: 0 |
||||
}, |
||||
disabled: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
clickable: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
showArrow: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
link: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
to: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
showBadge: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
showSwitch: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
switchChecked: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
badgeText: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
badgeType: { |
||||
type: String, |
||||
default: 'success' |
||||
}, |
||||
rightText: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
thumb: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
thumbSize: { |
||||
type: String, |
||||
default: 'base' |
||||
}, |
||||
showExtraIcon: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
extraIcon: { |
||||
type: Object, |
||||
default () { |
||||
return { |
||||
type: 'contact', |
||||
color: '#000000', |
||||
size: 20 |
||||
}; |
||||
} |
||||
}, |
||||
border: { |
||||
type: Boolean, |
||||
default: true |
||||
} |
||||
}, |
||||
// inject: ['list'], |
||||
data() { |
||||
return { |
||||
isFirstChild: false |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.list = this.getForm() |
||||
// 判断是否存在 uni-list 组件 |
||||
if (this.list) { |
||||
if (!this.list.firstChildAppend) { |
||||
this.list.firstChildAppend = true; |
||||
this.isFirstChild = true; |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
/** |
||||
* 获取父元素实例 |
||||
*/ |
||||
getForm(name = 'uniList') { |
||||
let parent = this.$parent; |
||||
let parentName = parent.$options.name; |
||||
while (parentName !== name) { |
||||
parent = parent.$parent; |
||||
if (!parent) return false |
||||
parentName = parent.$options.name; |
||||
} |
||||
return parent; |
||||
}, |
||||
onClick() { |
||||
if (this.to !== '') { |
||||
this.openPage(); |
||||
return; |
||||
} |
||||
if (this.clickable || this.link) { |
||||
this.$emit('click', { |
||||
data: {} |
||||
}); |
||||
} |
||||
}, |
||||
onSwitchChange(e) { |
||||
this.$emit('switchChange', e.detail); |
||||
}, |
||||
openPage() { |
||||
if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) { |
||||
this.pageApi(this.link); |
||||
} else { |
||||
this.pageApi('navigateTo'); |
||||
} |
||||
}, |
||||
pageApi(api) { |
||||
let callback = { |
||||
url: this.to, |
||||
success: res => { |
||||
this.$emit('click', { |
||||
data: res |
||||
}); |
||||
}, |
||||
fail: err => { |
||||
this.$emit('click', { |
||||
data: err |
||||
}); |
||||
} |
||||
} |
||||
switch (api) { |
||||
case 'navigateTo': |
||||
uni.navigateTo(callback) |
||||
break |
||||
case 'redirectTo': |
||||
uni.redirectTo(callback) |
||||
break |
||||
case 'reLaunch': |
||||
uni.reLaunch(callback) |
||||
break |
||||
case 'switchTab': |
||||
uni.switchTab(callback) |
||||
break |
||||
default: |
||||
uni.navigateTo(callback) |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss"> |
||||
$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg; |
||||
|
||||
.uni-list-item { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
font-size: $uni-font-size-lg; |
||||
position: relative; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
background-color: #fff; |
||||
flex-direction: row; |
||||
/* #ifdef H5 */ |
||||
cursor: pointer; |
||||
/* #endif */ |
||||
} |
||||
|
||||
.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: $uni-spacing-row-lg; |
||||
flex: 1; |
||||
overflow: hidden; |
||||
// align-items: center; |
||||
} |
||||
|
||||
.container--right { |
||||
padding-right: 0; |
||||
} |
||||
|
||||
// .border--left { |
||||
// margin-left: $uni-spacing-row-lg; |
||||
// } |
||||
|
||||
.uni-list--border { |
||||
position: absolute; |
||||
top: 0; |
||||
right: 0; |
||||
left: 0; |
||||
/* #ifdef APP-NVUE */ |
||||
border-top-color: $uni-border-color; |
||||
border-top-style: solid; |
||||
border-top-width: 0.5px; |
||||
/* #endif */ |
||||
} |
||||
|
||||
/* #ifndef APP-NVUE */ |
||||
.uni-list--border:after { |
||||
position: absolute; |
||||
top: 0; |
||||
right: 0; |
||||
left: 0; |
||||
height: 1px; |
||||
content: ''; |
||||
-webkit-transform: scaleY(0.5); |
||||
transform: scaleY(0.5); |
||||
background-color: $uni-border-color; |
||||
} |
||||
|
||||
/* #endif */ |
||||
|
||||
.uni-list-item__content { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
padding-right: 8px; |
||||
flex: 1; |
||||
color: #3b4144; |
||||
// overflow: hidden; |
||||
flex-direction: column; |
||||
justify-content: space-between; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.uni-list-item__content--center { |
||||
justify-content: center; |
||||
} |
||||
|
||||
.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__header { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
flex-direction: row; |
||||
align-items: center; |
||||
} |
||||
|
||||
.uni-list-item__icon { |
||||
margin-right: 18rpx; |
||||
flex-direction: row; |
||||
justify-content: center; |
||||
align-items: center; |
||||
} |
||||
|
||||
.uni-list-item__icon-img { |
||||
/* #ifndef APP-NVUE */ |
||||
display: block; |
||||
/* #endif */ |
||||
height: $uni-img-size-base; |
||||
width: $uni-img-size-base; |
||||
margin-right: 10px; |
||||
} |
||||
|
||||
.uni-icon-wrapper { |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
align-items: center; |
||||
padding: 0 10px; |
||||
} |
||||
|
||||
.flex--direction { |
||||
flex-direction: column; |
||||
/* #ifndef APP-NVUE */ |
||||
align-items: initial; |
||||
/* #endif */ |
||||
} |
||||
|
||||
.flex--justify { |
||||
/* #ifndef APP-NVUE */ |
||||
justify-content: initial; |
||||
/* #endif */ |
||||
} |
||||
|
||||
.uni-list--lg { |
||||
height: $uni-img-size-lg; |
||||
width: $uni-img-size-lg; |
||||
} |
||||
|
||||
.uni-list--base { |
||||
height: $uni-img-size-base; |
||||
width: $uni-img-size-base; |
||||
} |
||||
|
||||
.uni-list--sm { |
||||
height: $uni-img-size-sm; |
||||
width: $uni-img-size-sm; |
||||
} |
||||
|
||||
.uni-list-item__extra-text { |
||||
color: $uni-text-color-grey; |
||||
font-size: $uni-font-size-sm; |
||||
} |
||||
|
||||
.uni-ellipsis-1 { |
||||
/* #ifndef APP-NVUE */ |
||||
overflow: hidden; |
||||
white-space: nowrap; |
||||
text-overflow: ellipsis; |
||||
/* #endif */ |
||||
/* #ifdef APP-NVUE */ |
||||
lines: 1; |
||||
/* #endif */ |
||||
} |
||||
|
||||
.uni-ellipsis-2 { |
||||
/* #ifndef APP-NVUE */ |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
display: -webkit-box; |
||||
-webkit-line-clamp: 2; |
||||
-webkit-box-orient: vertical; |
||||
/* #endif */ |
||||
|
||||
/* #ifdef APP-NVUE */ |
||||
lines: 2; |
||||
/* #endif */ |
||||
} |
||||
</style> |
@ -0,0 +1,106 @@
|
||||
<template> |
||||
<!-- #ifndef APP-NVUE --> |
||||
<view class="uni-list uni-border-top-bottom"> |
||||
<view v-if="border" class="uni-list--border-top"></view> |
||||
<slot /> |
||||
<view v-if="border" class="uni-list--border-bottom"></view> |
||||
</view> |
||||
<!-- #endif --> |
||||
<!-- #ifdef APP-NVUE --> |
||||
<list class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop" loadmoreoffset="15"><slot /></list> |
||||
<!-- #endif --> |
||||
</template> |
||||
|
||||
<script> |
||||
/** |
||||
* List 列表 |
||||
* @description 列表组件 |
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=24 |
||||
* @property {String} border = [true|false] 标题 |
||||
*/ |
||||
export default { |
||||
name: 'uniList', |
||||
'mp-weixin': { |
||||
options: { |
||||
multipleSlots: false |
||||
} |
||||
}, |
||||
props: { |
||||
enableBackToTop: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
scrollY: { |
||||
type: [Boolean, String], |
||||
default: false |
||||
}, |
||||
border: { |
||||
type: Boolean, |
||||
default: true |
||||
} |
||||
}, |
||||
// 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; |
||||
} |
||||
|
||||
.uni-list--border { |
||||
position: relative; |
||||
/* #ifdef APP-NVUE */ |
||||
border-top-color: $uni-border-color; |
||||
border-top-style: solid; |
||||
border-top-width: 0.5px; |
||||
border-bottom-color: $uni-border-color; |
||||
border-bottom-style: solid; |
||||
border-bottom-width: 0.5px; |
||||
/* #endif */ |
||||
z-index: -1; |
||||
} |
||||
|
||||
/* #ifndef APP-NVUE */ |
||||
|
||||
.uni-list--border-top { |
||||
position: absolute; |
||||
top: 0; |
||||
right: 0; |
||||
left: 0; |
||||
height: 1px; |
||||
-webkit-transform: scaleY(0.5); |
||||
transform: scaleY(0.5); |
||||
background-color: $uni-border-color; |
||||
z-index: 1; |
||||
} |
||||
|
||||
.uni-list--border-bottom { |
||||
position: absolute; |
||||
bottom: 0; |
||||
right: 0; |
||||
left: 0; |
||||
height: 1px; |
||||
-webkit-transform: scaleY(0.5); |
||||
transform: scaleY(0.5); |
||||
background-color: $uni-border-color; |
||||
} |
||||
|
||||
/* #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 |
||||
} |
@ -0,0 +1,91 @@
|
||||
{ |
||||
"id": "uni-list", |
||||
"displayName": "uni-list 列表", |
||||
"version": "1.1.3", |
||||
"description": "List 组件 ,帮助使用者快速构建列表。", |
||||
"keywords": [ |
||||
"", |
||||
"uni-ui", |
||||
"uniui", |
||||
"列表", |
||||
"", |
||||
"list" |
||||
], |
||||
"repository": "https://github.com/dcloudio/uni-ui", |
||||
"engines": { |
||||
"HBuilderX": "" |
||||
}, |
||||
"directories": { |
||||
"example": "../../temps/example_temps" |
||||
}, |
||||
"dcloudext": { |
||||
"category": [ |
||||
"前端组件", |
||||
"通用组件" |
||||
], |
||||
"sale": { |
||||
"regular": { |
||||
"price": "0.00" |
||||
}, |
||||
"sourcecode": { |
||||
"price": "0.00" |
||||
} |
||||
}, |
||||
"contact": { |
||||
"qq": "" |
||||
}, |
||||
"declaration": { |
||||
"ads": "无", |
||||
"data": "无", |
||||
"permissions": "无" |
||||
}, |
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
||||
}, |
||||
"uni_modules": { |
||||
"dependencies": [ |
||||
"uni-badge", |
||||
"uni-icons" |
||||
], |
||||
"encrypt": [], |
||||
"platforms": { |
||||
"cloud": { |
||||
"tcb": "y", |
||||
"aliyun": "y" |
||||
}, |
||||
"client": { |
||||
"App": { |
||||
"app-vue": "y", |
||||
"app-nvue": "y" |
||||
}, |
||||
"H5-mobile": { |
||||
"Safari": "y", |
||||
"Android Browser": "y", |
||||
"微信浏览器(Android)": "y", |
||||
"QQ浏览器(Android)": "y" |
||||
}, |
||||
"H5-pc": { |
||||
"Chrome": "y", |
||||
"IE": "y", |
||||
"Edge": "y", |
||||
"Firefox": "y", |
||||
"Safari": "y" |
||||
}, |
||||
"小程序": { |
||||
"微信": "y", |
||||
"阿里": "y", |
||||
"百度": "y", |
||||
"字节跳动": "y", |
||||
"QQ": "y" |
||||
}, |
||||
"快应用": { |
||||
"华为": "u", |
||||
"联盟": "u" |
||||
}, |
||||
"Vue": { |
||||
"vue2": "y", |
||||
"vue3": "u" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,347 @@
|
||||
|
||||
|
||||
## List 列表 |
||||
> **组件名:uni-list** |
||||
> 代码块: `uList`、`uListItem` |
||||
> 关联组件:`uni-list-item`、`uni-badge`、`uni-icons`、`uni-list-chat`、`uni-list-ad` |
||||
|
||||
|
||||
List 列表组件,包含基本列表样式、可扩展插槽机制、长列表性能优化、多端兼容。 |
||||
|
||||
在vue页面里,它默认使用页面级滚动。在app-nvue页面里,它默认使用原生list组件滚动。这样的长列表,在滚动出屏幕外后,系统会回收不可见区域的渲染内存资源,不会造成滚动越长手机越卡的问题。 |
||||
|
||||
uni-list组件是父容器,里面的核心是uni-list-item子组件,它代表列表中的一个可重复行,子组件可以无限循环。 |
||||
|
||||
uni-list-item有很多风格,uni-list-item组件通过内置的属性,满足一些常用的场景。当内置属性不满足需求时,可以通过扩展插槽来自定义列表内容。 |
||||
|
||||
内置属性可以覆盖的场景包括:导航列表、设置列表、小图标列表、通信录列表、聊天记录列表。 |
||||
|
||||
涉及很多大图或丰富内容的列表,比如类今日头条的新闻列表、类淘宝的电商列表,需要通过扩展插槽实现。 |
||||
|
||||
下文均有样例给出。 |
||||
|
||||
uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-load-more](https://ext.dcloud.net.cn/plugin?id=29) |
||||
|
||||
|
||||
### 安装方式 |
||||
|
||||
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 |
||||
|
||||
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) |
||||
|
||||
> **注意事项** |
||||
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 |
||||
> - 组件需要依赖 `sass` 插件 ,请自行手动安装 |
||||
> - 组件内部依赖 `'uni-icons'` 、`uni-badge` 组件 |
||||
> - `uni-list` 和 `uni-list-item` 需要配套使用,暂不支持单独使用 `uni-list-item` |
||||
> - 只有开启点击反馈后,会有点击选中效果 |
||||
> - 使用插槽时,可以完全自定义内容 |
||||
> - note 、rightText 属性暂时没做限制,不支持文字溢出隐藏,使用时应该控制长度显示或通过默认插槽自行扩展 |
||||
> - 支付宝小程序平台需要在支付宝小程序开发者工具里开启 component2 编译模式,开启方式: 详情 --> 项目配置 --> 启用 component2 编译 |
||||
> - 如果需要修改 `switch`、`badge` 样式,请使用插槽自定义 |
||||
> - 在 `HBuilderX` 低版本中,可能会出现组件显示 `undefined` 的问题,请升级最新的 `HBuilderX` 或者 `cli` |
||||
> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
||||
|
||||
|
||||
### 基本用法 |
||||
|
||||
- 设置 `title` 属性,可以显示列表标题 |
||||
- 设置 `disabled` 属性,可以禁用当前项 |
||||
|
||||
```html |
||||
<uni-list> |
||||
<uni-list-item title="列表文字" ></uni-list-item> |
||||
<uni-list-item :disabled="true" title="列表禁用状态" ></uni-list-item> |
||||
</uni-list> |
||||
|
||||
``` |
||||
|
||||
### 多行内容显示 |
||||
|
||||
- 设置 `note` 属性 ,可以在第二行显示描述文本信息 |
||||
|
||||
```html |
||||
<uni-list> |
||||
<uni-list-item title="列表文字" note="列表描述信息"></uni-list-item> |
||||
<uni-list-item :disabled="true" title="列表文字" note="列表禁用状态"></uni-list-item> |
||||
</uni-list> |
||||
|
||||
``` |
||||
|
||||
### 右侧显示角标、switch |
||||
|
||||
- 设置 `show-badge` 属性 ,可以显示角标内容 |
||||
- 设置 `show-switch` 属性,可以显示 switch 开关 |
||||
|
||||
```html |
||||
<uni-list> |
||||
<uni-list-item title="列表右侧显示角标" :show-badge="true" badge-text="12" ></uni-list-item> |
||||
<uni-list-item title="列表右侧显示 switch" :show-switch="true" @switchChange="switchChange" ></uni-list-item> |
||||
</uni-list> |
||||
|
||||
``` |
||||
|
||||
### 左侧显示略缩图、图标 |
||||
|
||||
- 设置 `thumb` 属性 ,可以在列表左侧显示略缩图 |
||||
- 设置 `show-extra-icon` 属性,并指定 `extra-icon` 可以在左侧显示图标 |
||||
|
||||
```html |
||||
<uni-list> |
||||
<uni-list-item title="列表左侧带略缩图" note="列表描述信息" thumb="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" |
||||
thumb-size="lg" rightText="右侧文字"></uni-list-item> |
||||
<uni-list-item :show-extra-icon="true" :extra-icon="extraIcon1" title="列表左侧带扩展图标" ></uni-list-item> |
||||
</uni-list> |
||||
``` |
||||
|
||||
### 开启点击反馈和右侧箭头 |
||||
- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件 |
||||
- 设置 `link` 属性,会自动开启点击反馈,并给列表右侧添加一个箭头 |
||||
- 设置 `to` 属性,可以跳转页面,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo` |
||||
|
||||
```html |
||||
|
||||
<uni-list> |
||||
<uni-list-item title="开启点击反馈" clickable @click="onClick" ></uni-list-item> |
||||
<uni-list-item title="默认 navigateTo 方式跳转页面" link to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item> |
||||
<uni-list-item title="reLaunch 方式跳转页面" link="reLaunch" to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item> |
||||
</uni-list> |
||||
|
||||
``` |
||||
|
||||
|
||||
### 聊天列表示例 |
||||
- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件 |
||||
- 设置 `link` 属性,会自动开启点击反馈,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo` |
||||
- 设置 `to` 属性,可以跳转页面 |
||||
- `time` 属性,通常会设置成时间显示,但是这个属性不仅仅可以设置时间,你可以传入任何文本,注意文本长度可能会影响显示 |
||||
- `avatar` 和 `avatarList` 属性同时只会有一个生效,同时设置的话,`avatarList` 属性的长度大于1 ,`avatar` 属性将失效 |
||||
- 可以通过默认插槽自定义列表右侧内容 |
||||
|
||||
```html |
||||
|
||||
<uni-list> |
||||
<uni-list :border="true"> |
||||
<!-- 显示圆形头像 --> |
||||
<uni-list-chat :avatar-circle="true" title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" ></uni-list-chat> |
||||
<!-- 右侧带角标 --> |
||||
<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-text="12"></uni-list-chat> |
||||
<!-- 头像显示圆点 --> |
||||
<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat> |
||||
<!-- 头像显示角标 --> |
||||
<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="99"></uni-list-chat> |
||||
<!-- 显示多头像 --> |
||||
<uni-list-chat title="uni-app" :avatar-list="avatarList" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat> |
||||
<!-- 自定义右侧内容 --> |
||||
<uni-list-chat title="uni-app" :avatar-list="avatarList" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"> |
||||
<view class="chat-custom-right"> |
||||
<text class="chat-custom-text">刚刚</text> |
||||
<!-- 需要使用 uni-icons 请自行引入 --> |
||||
<uni-icons type="star-filled" color="#999" size="18"></uni-icons> |
||||
</view> |
||||
</uni-list-chat> |
||||
</uni-list> |
||||
</uni-list> |
||||
|
||||
``` |
||||
|
||||
```javascript |
||||
|
||||
export default { |
||||
components: {}, |
||||
data() { |
||||
return { |
||||
avatarList: [{ |
||||
url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' |
||||
}, { |
||||
url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' |
||||
}, { |
||||
url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' |
||||
}] |
||||
} |
||||
} |
||||
} |
||||
|
||||
``` |
||||
|
||||
|
||||
```css |
||||
|
||||
.chat-custom-right { |
||||
flex: 1; |
||||
/* #ifndef APP-NVUE */ |
||||
display: flex; |
||||
/* #endif */ |
||||
flex-direction: column; |
||||
justify-content: space-between; |
||||
align-items: flex-end; |
||||
} |
||||
|
||||
.chat-custom-text { |
||||
font-size: 12px; |
||||
color: #999; |
||||
} |
||||
|
||||
``` |
||||
|
||||
## API |
||||
|
||||
### List Props |
||||
|
||||
属性名 |类型 |默认值 | 说明 |
||||
:-: |:-: |:-: | :-: |
||||
border |Boolean |true | 是否显示边框 |
||||
|
||||
|
||||
### ListItem Props |
||||
|
||||
属性名 |类型 |默认值 | 说明 |
||||
:-: |:-: |:-: | :-: |
||||
title |String |- | 标题 |
||||
note |String |- | 描述 |
||||
ellipsis |Number |0 | title 是否溢出隐藏,可选值,0:默认; 1:显示一行; 2:显示两行;【nvue 暂不支持】 |
||||
thumb |String |- | 左侧缩略图,若thumb有值,则不会显示扩展图标 |
||||
thumbSize |String |medium | 略缩图尺寸,可选值,lg:大图; medium:一般; sm:小图; |
||||
showBadge |Boolean |false | 是否显示数字角标 |
||||
badgeText |String |- | 数字角标内容 |
||||
badgeType |String |- | 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21) |
||||
rightText |String |- | 右侧文字内容 |
||||
disabled |Boolean |false | 是否禁用 |
||||
showArrow |Boolean |true | 是否显示箭头图标 |
||||
link |String |navigateTo | 新页面跳转方式,可选值见下表 |
||||
to |String |- | 新页面跳转地址,如填写此属性,click 会返回页面是否跳转成功 |
||||
clickable |Boolean |false | 是否开启点击反馈 |
||||
showSwitch |Boolean |false | 是否显示Switch |
||||
switchChecked |Boolean |false | Switch是否被选中 |
||||
showExtraIcon |Boolean |false | 左侧是否显示扩展图标 |
||||
extraIcon |Object |- | 扩展图标参数,格式为 ``{color: '#4cd964',size: '22',type: 'spinner'}``,参考 [uni-icons](https://ext.dcloud.net.cn/plugin?id=28) |
||||
direction | String |row | 排版方向,可选值,row:水平排列; column:垂直排列; 3个插槽是水平排还是垂直排,也受此属性控制 |
||||
|
||||
|
||||
#### Link Options |
||||
|
||||
属性名 | 说明 |
||||
:-: | :-: |
||||
navigateTo | 同 uni.navigateTo() |
||||
redirectTo | 同 uni.reLaunch() |
||||
reLaunch | 同 uni.reLaunch() |
||||
switchTab | 同 uni.switchTab() |
||||
|
||||
### ListItem Events |
||||
|
||||
事件称名 |说明 |返回参数 |
||||
:-: |:-: |:-: |
||||
click |点击 uniListItem 触发事件,需开启点击反馈 |- |
||||
switchChange |点击切换 Switch 时触发,需显示 switch |e={value:checked} |
||||
|
||||
|
||||
|
||||
### ListItem Slots |
||||
|
||||
名称 | 说明 |
||||
:-: | :-: |
||||
header | 左/上内容插槽,可完全自定义默认显示 |
||||
body | 中间内容插槽,可完全自定义中间内容 |
||||
footer | 右/下内容插槽,可完全自定义右侧内容 |
||||
|
||||
|
||||
> **通过插槽扩展** |
||||
> 需要注意的是当使用插槽时,内置样式将会失效,只保留排版样式,此时的样式需要开发者自己实现 |
||||
> 如果 `uni-list-item` 组件内置属性样式无法满足需求,可以使用插槽来自定义uni-list-item里的内容。 |
||||
> uni-list-item提供了3个可扩展的插槽:`header`、`body`、`footer` |
||||
> - 当 `direction` 属性为 `row` 时表示水平排列,此时 `header` 表示列表的左边部分,`body` 表示列表的中间部分,`footer` 表示列表的右边部分 |
||||
> - 当 `direction` 属性为 `column` 时表示垂直排列,此时 `header` 表示列表的上边部分,`body` 表示列表的中间部分,`footer` 表示列表的下边部分 |
||||
> 开发者可以只用1个插槽,也可以3个一起使用。在插槽中可自主编写view标签,实现自己所需的效果。 |
||||
|
||||
|
||||
**示例** |
||||
|
||||
```html |
||||
<uni-list> |
||||
<uni-list-item title="自定义右侧插槽" note="列表描述信息" link> |
||||
<template slot="header"> |
||||
<image class="slot-image" src="/static/logo.png" mode="widthFix"></image> |
||||
</template> |
||||
</uni-list-item> |
||||
<uni-list-item> |
||||
<!-- 自定义 header --> |
||||
<view slot="header" class="slot-box"><image class="slot-image" src="/static/logo.png" mode="widthFix"></image></view> |
||||
<!-- 自定义 body --> |
||||
<text slot="body" class="slot-box slot-text">自定义插槽</text> |
||||
<!-- 自定义 footer--> |
||||
<template slot="footer"> |
||||
<image class="slot-image" src="/static/logo.png" mode="widthFix"></image> |
||||
</template> |
||||
</uni-list-item> |
||||
</uni-list> |
||||
``` |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### ListItemChat Props |
||||
|
||||
属性名 |类型 |默认值 | 说明 |
||||
:-: |:-: |:-: | :-: |
||||
title |String |- | 标题 |
||||
note |String |- | 描述 |
||||
clickable |Boolean |false | 是否开启点击反馈 |
||||
badgeText |String |- | 数字角标内容,设置为 `dot` 将显示圆点 |
||||
badgePositon |String |right | 角标位置 |
||||
link |String |navigateTo | 是否展示右侧箭头并开启点击反馈,可选值见下表 |
||||
clickable |Boolean |false | 是否开启点击反馈 |
||||
to |String |- | 跳转页面地址,如填写此属性,click 会返回页面是否跳转成功 |
||||
time |String |- | 右侧时间显示 |
||||
avatarCircle |Boolean |false | 是否显示圆形头像 |
||||
avatar |String |- | 头像地址,avatarCircle 不填时生效 |
||||
avatarList |Array |- | 头像组,格式为 [{url:''}] |
||||
|
||||
#### Link Options |
||||
|
||||
属性名 | 说明 |
||||
:-: | :-: |
||||
navigateTo | 同 uni.navigateTo() |
||||
redirectTo | 同 uni.reLaunch() |
||||
reLaunch | 同 uni.reLaunch() |
||||
switchTab | 同 uni.switchTab() |
||||
|
||||
### ListItemChat Slots |
||||
|
||||
名称 | 说明 |
||||
:- | :- |
||||
default | 自定义列表右侧内容(包括时间和角标显示) |
||||
|
||||
### ListItemChat Events |
||||
事件称名 | 说明 | 返回参数 |
||||
:-: | :-: | :-: |
||||
@click | 点击 uniListChat 触发事件 | {data:{}} ,如有 to 属性,会返回页面跳转信息 |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 基于uni-list扩展的页面模板 |
||||
|
||||
通过扩展插槽,可实现多种常见样式的列表 |
||||
|
||||
**新闻列表类** |
||||
|
||||
1. 云端一体混合布局:[https://ext.dcloud.net.cn/plugin?id=2546](https://ext.dcloud.net.cn/plugin?id=2546) |
||||
2. 云端一体垂直布局,大图模式:[https://ext.dcloud.net.cn/plugin?id=2583](https://ext.dcloud.net.cn/plugin?id=2583) |
||||
3. 云端一体垂直布局,多行图文混排:[https://ext.dcloud.net.cn/plugin?id=2584](https://ext.dcloud.net.cn/plugin?id=2584) |
||||
4. 云端一体垂直布局,多图模式:[https://ext.dcloud.net.cn/plugin?id=2585](https://ext.dcloud.net.cn/plugin?id=2585) |
||||
5. 云端一体水平布局,左图右文:[https://ext.dcloud.net.cn/plugin?id=2586](https://ext.dcloud.net.cn/plugin?id=2586) |
||||
6. 云端一体水平布局,左文右图:[https://ext.dcloud.net.cn/plugin?id=2587](https://ext.dcloud.net.cn/plugin?id=2587) |
||||
7. 云端一体垂直布局,无图模式,主标题+副标题:[https://ext.dcloud.net.cn/plugin?id=2588](https://ext.dcloud.net.cn/plugin?id=2588) |
||||
|
||||
**商品列表类** |
||||
|
||||
1. 云端一体列表/宫格视图互切:[https://ext.dcloud.net.cn/plugin?id=2651](https://ext.dcloud.net.cn/plugin?id=2651) |
||||
2. 云端一体列表(宫格模式):[https://ext.dcloud.net.cn/plugin?id=2671](https://ext.dcloud.net.cn/plugin?id=2671) |
||||
3. 云端一体列表(列表模式):[https://ext.dcloud.net.cn/plugin?id=2672](https://ext.dcloud.net.cn/plugin?id=2672) |
||||
|
||||
## 组件示例 |
||||
|
||||
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/list/list](https://hellouniapp.dcloud.net.cn/pages/extUI/list/list) |
@ -1,194 +0,0 @@
|
||||
<template> |
||||
<view class="uni-load-more"> |
||||
<view class="uni-load-more__img" v-show="status === 'loading' && showIcon"> |
||||
<view class="load1"> |
||||
<view :style="{background:color}"></view> |
||||
<view :style="{background:color}"></view> |
||||
<view :style="{background:color}"></view> |
||||
<view :style="{background:color}"></view> |
||||
</view> |
||||
<view class="load2"> |
||||
<view :style="{background:color}"></view> |
||||
<view :style="{background:color}"></view> |
||||
<view :style="{background:color}"></view> |
||||
<view :style="{background:color}"></view> |
||||
</view> |
||||
<view class="load3"> |
||||
<view :style="{background:color}"></view> |
||||
<view :style="{background:color}"></view> |
||||
<view :style="{background:color}"></view> |
||||
<view :style="{background:color}"></view> |
||||
</view> |
||||
</view> |
||||
<text class="uni-load-more__text" :style="{color:color}">{{status === 'more' ? contentText.contentdown : (status === 'loading' ? contentText.contentrefresh : contentText.contentnomore)}}</text> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
name: "uni-load-more", |
||||
props: { |
||||
status: { |
||||
//上拉的状态:more-loading前;loading-loading中;noMore-没有更多了 |
||||
type: String, |
||||
default: 'more' |
||||
}, |
||||
showIcon: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
color: { |
||||
type: String, |
||||
default: "#777777" |
||||
}, |
||||
contentText: { |
||||
type: Object, |
||||
default () { |
||||
return { |
||||
contentdown: "上拉显示更多", |
||||
contentrefresh: "正在加载...", |
||||
contentnomore: "没有更多数据了" |
||||
}; |
||||
} |
||||
} |
||||
}, |
||||
data() { |
||||
return {} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
@charset "UTF-8"; |
||||
|
||||
.uni-load-more { |
||||
display: flex; |
||||
flex-direction: row; |
||||
height: 80upx; |
||||
align-items: center; |
||||
justify-content: center |
||||
} |
||||
|
||||
.uni-load-more__text { |
||||
font-size: 28upx; |
||||
color: #999 |
||||
} |
||||
|
||||
.uni-load-more__img { |
||||
height: 24px; |
||||
width: 24px; |
||||
margin-right: 10px |
||||
} |
||||
|
||||
.uni-load-more__img>view { |
||||
position: absolute |
||||
} |
||||
|
||||
.uni-load-more__img>view view { |
||||
width: 6px; |
||||
height: 2px; |
||||
border-top-left-radius: 1px; |
||||
border-bottom-left-radius: 1px; |
||||
background: #999; |
||||
position: absolute; |
||||
opacity: .2; |
||||
transform-origin: 50%; |
||||
animation: load 1.56s ease infinite |
||||
} |
||||
|
||||
.uni-load-more__img>view view:nth-child(1) { |
||||
transform: rotate(90deg); |
||||
top: 2px; |
||||
left: 9px |
||||
} |
||||
|
||||
.uni-load-more__img>view view:nth-child(2) { |
||||
transform: rotate(180deg); |
||||
top: 11px; |
||||
right: 0 |
||||
} |
||||
|
||||
.uni-load-more__img>view view:nth-child(3) { |
||||
transform: rotate(270deg); |
||||
bottom: 2px; |
||||
left: 9px |
||||
} |
||||
|
||||
.uni-load-more__img>view view:nth-child(4) { |
||||
top: 11px; |
||||
left: 0 |
||||
} |
||||
|
||||
.load1, |
||||
.load2, |
||||
.load3 { |
||||
height: 24px; |
||||
width: 24px |
||||
} |
||||
|
||||
.load2 { |
||||
transform: rotate(30deg) |
||||
} |
||||
|
||||
.load3 { |
||||
transform: rotate(60deg) |
||||
} |
||||
|
||||
.load1 view:nth-child(1) { |
||||
animation-delay: 0s |
||||
} |
||||
|
||||
.load2 view:nth-child(1) { |
||||
animation-delay: .13s |
||||
} |
||||
|
||||
.load3 view:nth-child(1) { |
||||
animation-delay: .26s |
||||
} |
||||
|
||||
.load1 view:nth-child(2) { |
||||
animation-delay: .39s |
||||
} |
||||
|
||||
.load2 view:nth-child(2) { |
||||
animation-delay: .52s |
||||
} |
||||
|
||||
.load3 view:nth-child(2) { |
||||
animation-delay: .65s |
||||
} |
||||
|
||||
.load1 view:nth-child(3) { |
||||
animation-delay: .78s |
||||
} |
||||
|
||||
.load2 view:nth-child(3) { |
||||
animation-delay: .91s |
||||
} |
||||
|
||||
.load3 view:nth-child(3) { |
||||
animation-delay: 1.04s |
||||
} |
||||
|
||||
.load1 view:nth-child(4) { |
||||
animation-delay: 1.17s |
||||
} |
||||
|
||||
.load2 view:nth-child(4) { |
||||
animation-delay: 1.3s |
||||
} |
||||
|
||||
.load3 view:nth-child(4) { |
||||
animation-delay: 1.43s |
||||
} |
||||
|
||||
@-webkit-keyframes load { |
||||
0% { |
||||
opacity: 1 |
||||
} |
||||
|
||||
100% { |
||||
opacity: .2 |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,964 @@
|
||||
<template> |
||||
<view class="page"> |
||||
<view class="bill"> |
||||
<swiper class="swiper" autoplay="1500" :indicator-dots="true" :circular='true' |
||||
indicator-active-color="#ffffff" indicator-color="#cccccc"> |
||||
<swiper-item class="swiper-wrap" v-for="(item,index) in banners" :key='index'> |
||||
<image :src="item" mode="aspectFill"></image> |
||||
</swiper-item> |
||||
</swiper> |
||||
<!-- <image src="../../static/img/home/xiangqing.png"></image> --> |
||||
</view> |
||||
<view class="billtextbox"> |
||||
<view class="billtext"> |
||||
<view class="left"> |
||||
<image src="../../static/img/home/huangguan.png"></image> |
||||
<p>番茄会员满18元返18元</p> |
||||
</view> |
||||
<view class="middel"> |
||||
</view> |
||||
<view class="right"> |
||||
<view class="right a">限时</view> |
||||
<view class="right b">抢购</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
|
||||
|
||||
<view class="shop"> |
||||
<view class="shoptop"> |
||||
<view class="shoptext"> |
||||
<view class="left" style="float: left;"> |
||||
<image src="../../static/img/home/shangjia.png"></image> |
||||
</view> |
||||
<view class="right"> |
||||
<view class="shop-name-box"> |
||||
<image v-if="info.classify == 2" class="item-Logo" mode="aspectFill" |
||||
src="/static/img/home/storeLogo.png"></image> |
||||
<image v-if="info.classify == 1" class="item-Logo" mode="aspectFill" |
||||
src="/static/img/my/eleicon.png"></image> |
||||
<text>{{info.merchantName}}</text> |
||||
</view> |
||||
<view>活动结束时间:{{info.endTime}}</view> |
||||
<!-- <view>门店地址:</view> --> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
<view class="line"></view> |
||||
<view class="bottom"> |
||||
<view class="text"> {{info.classify == 1 ? '饿了么' : '美团' }}会员满{{info.memberPrice}}减{{info.memberMoney}} </view> |
||||
<view class="text" style="margin-left: 8rpx;">{{info.classify == 1 ? '饿了么' : '美团' }}非会员满{{info.price}}减{{info.money}} </view> |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="welfare"> |
||||
<view class="content"> |
||||
<view class="top" style="background-color: #0C0C0C;border-radius: 8px 8px 0 0;" v-if="member == 0"> |
||||
<view style="display: flex;"> |
||||
<view style="margin-left: 20px;">番茄会员满18元返18元</view> |
||||
<view class="button" @tap="goPageLogin('/pages/my/myVIP')">开通会员</view> |
||||
</view> |
||||
</view> |
||||
<view class="bottom"> |
||||
<view class="bottomcontent" style="display: flex;align-items: center;"> |
||||
<view class="circle"></view> |
||||
<view class="jieshao"> |
||||
<view style="font-size: 14px;font-family: PingFang SC;font-weight: 500;color: #000000;"> |
||||
进入番茄饭团福利群</view> |
||||
<view style="font-size: 11px;font-family: PingFang SC;font-weight: 500;color: #000000;"> |
||||
添加客服微信进入番茄饭团福利群</view> |
||||
</view> |
||||
<view class="add">添加</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
|
||||
</view> |
||||
|
||||
|
||||
<view class="footers"> |
||||
<view @click="kefu" style="24px;24px"> |
||||
<image src="../../static/img/home/kefuxin.png" mode="widthFix" style="width: 24px;height: 24px;"> |
||||
</image> |
||||
</view> |
||||
<view class="payinfo" @click="btns"> |
||||
<view>立即抢单</view> |
||||
</view> |
||||
<view class="payinfo" style="border-radius: 0px 16px 16px 0px;"> |
||||
<view>复制店名</view> |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="procedure">订单返现流程规则</view> |
||||
|
||||
<view class="procedurepictrue"> |
||||
<view class="item"> |
||||
<image src="../../static/img/home/qianggou.png"></image> |
||||
<view>抢购订单</view> |
||||
</view> |
||||
<view class="item" > |
||||
<image src="../../static/img/home/waimai.png" style="margin-left: 20px;"></image> |
||||
<view>外卖平台下单</view> |
||||
</view> |
||||
<view class="item"> |
||||
<image src="../../static/img/home/haoping.png"></image> |
||||
<view>好评上传</view> |
||||
</view> |
||||
<view class="item"> |
||||
<image src="../../static/img/home/fanli.png"></image> |
||||
<view>返利到账</view> |
||||
</view> |
||||
</view> |
||||
|
||||
</view> |
||||
|
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
import shmilyDragImage from '@/components/shmily-drag-image/shmily-drag-image.vue' |
||||
export default { |
||||
components: { |
||||
shmilyDragImage |
||||
}, |
||||
data() { |
||||
return { |
||||
// 页面信息 |
||||
info: {}, |
||||
items: [{ |
||||
title: "抢购订单", |
||||
}, |
||||
{ |
||||
title: "外卖平台下单", |
||||
}, |
||||
{ |
||||
title: "好评上传", |
||||
}, |
||||
{ |
||||
title: "返利到账", |
||||
}, |
||||
], |
||||
banners: [], |
||||
imageList: [], |
||||
isJieDanUser: false, |
||||
activeSteps: -1, |
||||
orderId: '', |
||||
goodsId: '', |
||||
latitude: '', |
||||
longitude: '', |
||||
isMyOrder: false, |
||||
isLogin: false, |
||||
recommendList1: [{ |
||||
iconImg: '../../static/img/home/qiangdan.png', |
||||
title: '立即抢单' |
||||
}, |
||||
{ |
||||
iconImg: '../../static/img/home/wmpt.png', |
||||
title: '外卖平台下单' |
||||
}, |
||||
{ |
||||
iconImg: '../../static/img/home/uoload.png', |
||||
title: '订单上传' |
||||
}, |
||||
{ |
||||
iconImg: '../../static/img/home/pinjian.png', |
||||
title: '评鉴上传' |
||||
} |
||||
], |
||||
recommendList: [{ |
||||
iconImg: '../../static/img/home/star.png', |
||||
title: '' |
||||
}, |
||||
{ |
||||
iconImg: '../../static/img/home/peitu.png', |
||||
title: '' |
||||
}, |
||||
{ |
||||
iconImg: '../../static/img/home/wenzi.png', |
||||
title: '' |
||||
} |
||||
], |
||||
btnType: '立即抢单', |
||||
status: 1, |
||||
id: 0, |
||||
arr: [], |
||||
showModal: true |
||||
} |
||||
}, |
||||
onLoad(e) { |
||||
this.goodsId = e.goodsId; |
||||
this.latitude = e.latitude; |
||||
this.longitude = e.longitude; |
||||
let token = this.$queue.getData('token'); |
||||
let userId = this.$queue.getData('userId'); |
||||
this.member = this.$queue.getData('member'); |
||||
// if (!token) { |
||||
// this.goLogin(); |
||||
// } |
||||
|
||||
// 订单审核提醒 202 |
||||
// 最新活动通知 204 |
||||
// 点评提醒 205 |
||||
// 活动反馈推送提醒 209 |
||||
let that = this; |
||||
that.$Request.getT('/common/type/202').then(res => { //订单审核提醒 |
||||
if (res.code == 0) { |
||||
if (res.data && res.data.value) { |
||||
that.arr.push(res.data.value) |
||||
} |
||||
} |
||||
}) |
||||
that.$Request.getT('/common/type/204').then(res => { //最新活动通知 |
||||
if (res.code == 0) { |
||||
if (res.data && res.data.value) { |
||||
that.arr.push(res.data.value) |
||||
} |
||||
} |
||||
}) |
||||
that.$Request.getT('/common/type/205').then(res => { //点评提醒 |
||||
if (res.code == 0) { |
||||
if (res.data && res.data.value) { |
||||
that.arr.push(res.data.value) |
||||
} |
||||
} |
||||
}) |
||||
}, |
||||
onShow() { |
||||
if (this.goodsId != '') { |
||||
this.initHelpOrder(this.goodsId); |
||||
} |
||||
|
||||
let userId = this.$queue.getData('userId'); |
||||
// if (userId) { |
||||
// //订阅 |
||||
// if(this.showModal) { |
||||
// this.openMsg() |
||||
// } |
||||
// } |
||||
}, |
||||
methods: { |
||||
// 开启订阅消息 |
||||
openMsg() { |
||||
var that = this |
||||
wx.getSetting({ |
||||
withSubscriptions: true, //是否获取用户订阅消息的订阅状态,默认false不返回 |
||||
success(ret) { |
||||
// console.log(ret,'------------------') |
||||
// console.log(Object.keys(ret.subscriptionsSetting.itemSettings).length) |
||||
// if (JSON.stringify(ret.subscriptionsSetting.itemSettings).indexOf('accept')!=-1) { |
||||
if (ret.subscriptionsSetting.itemSettings) { |
||||
uni.setStorageSync('sendorderMsg', true) |
||||
uni.openSetting({ // 打开设置页 |
||||
success(rea) { |
||||
console.log(rea.authSetting) |
||||
} |
||||
}); |
||||
} else { // 用户没有点击“总是保持以上,不再询问”则每次都会调起订阅消息 |
||||
uni.setStorageSync('sendorderMsg', false) |
||||
uni.showModal({ |
||||
title: '提示', |
||||
content: '为了更好的体验,请绑定消息推送', |
||||
confirmText: '确定', |
||||
cancelText: '取消', |
||||
success: function(res) { |
||||
if (res.confirm) { |
||||
uni.requestSubscribeMessage({ |
||||
tmplIds: that.arr, |
||||
success(re) { |
||||
// console.log(re,'**********') |
||||
var datas = JSON.stringify(re); |
||||
if (datas.indexOf("accept") != -1) { |
||||
console.log(re) |
||||
} |
||||
}, |
||||
fail: (res) => { |
||||
console.log(res) |
||||
} |
||||
}) |
||||
that.showModal = false |
||||
} else if (res.cancel) { |
||||
that.showModal = true |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
}) |
||||
}, |
||||
fensiImage() { |
||||
if (uni.getStorageSync('sendorderMsg')) { |
||||
uni.requestSubscribeMessage({ |
||||
tmplIds: this.arr, |
||||
success(re) { |
||||
// console.log(re,'**********') |
||||
var datas = JSON.stringify(re); |
||||
if (datas.indexOf("accept") != -1) { |
||||
console.log(re) |
||||
} |
||||
}, |
||||
fail: (res) => { |
||||
console.log(res) |
||||
} |
||||
}) |
||||
} |
||||
let fensiImage = this.$queue.getData('fensiImage'); |
||||
//#ifndef H5 |
||||
uni.navigateTo({ |
||||
url: '/pages/public/webview?url=' + fensiImage |
||||
}); |
||||
//#endif |
||||
//#ifdef H5 |
||||
window.location.href = fensiImage; |
||||
//#endif |
||||
}, |
||||
goShareUser() { |
||||
uni.navigateTo({ |
||||
url: '/pages/my/shareFriends' |
||||
}); |
||||
}, |
||||
navigate(href, e) { |
||||
// #ifdef H5 |
||||
window.location.href = href; |
||||
//#endif |
||||
|
||||
//#ifdef APP-PLUS |
||||
setTimeout(function() { |
||||
plus.runtime.openURL(href); |
||||
}, 500); |
||||
// #endif |
||||
}, |
||||
navigation(latitude, longitude, name) { |
||||
// #ifdef APP-PLUS |
||||
let url = ""; |
||||
if (plus.os.name == "Android") { //判断是安卓端 |
||||
plus.nativeUI.actionSheet({ //选择菜单 |
||||
title: "选择地图应用", |
||||
cancel: "取消", |
||||
buttons: [{ |
||||
title: "腾讯地图" |
||||
}, { |
||||
title: "百度地图" |
||||
}, { |
||||
title: "高德地图" |
||||
}] |
||||
}, function(e) { |
||||
switch (e.index) { |
||||
//下面是拼接url,不同系统以及不同地图都有不同的拼接字段 |
||||
case 1: |
||||
//注意referer=xxx的xxx替换成你在腾讯地图开发平台申请的key |
||||
url = `qqmap://map/geocoder?coord=${latitude},${longitude}&referer=xxx`; |
||||
break; |
||||
case 2: |
||||
url = |
||||
`baidumap://map/marker?location=${latitude},${longitude}&title=${name}&coord_type=gcj02&src=andr.baidu.openAPIdemo`; |
||||
break; |
||||
case 3: |
||||
url = |
||||
`androidamap://viewMap?sourceApplication=appname&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
if (url != "") { |
||||
url = encodeURI(url); |
||||
//plus.runtime.openURL(url,function(e){})调起手机APP应用 |
||||
plus.runtime.openURL(url, function(e) { |
||||
plus.nativeUI.alert("本机未安装指定的地图应用"); |
||||
}); |
||||
} |
||||
}) |
||||
} else { |
||||
// iOS上获取本机是否安装了百度高德地图,需要在manifest里配置 |
||||
// 在manifest.json文件app-plus->distribute->apple->urlschemewhitelist节点下添加 |
||||
//(如urlschemewhitelist:["iosamap","baidumap"]) |
||||
plus.nativeUI.actionSheet({ |
||||
title: "选择地图应用", |
||||
cancel: "取消", |
||||
buttons: [{ |
||||
title: "腾讯地图" |
||||
}, { |
||||
title: "百度地图" |
||||
}, { |
||||
title: "高德地图" |
||||
}] |
||||
}, function(e) { |
||||
switch (e.index) { |
||||
case 1: |
||||
url = `qqmap://map/geocoder?coord=${latitude},${longitude}&referer=xxx`; |
||||
break; |
||||
case 2: |
||||
url = |
||||
`baidumap://map/marker?location=${latitude},${longitude}&title=${name}&content=${name}&src=ios.baidu.openAPIdemo&coord_type=gcj02`; |
||||
break; |
||||
case 3: |
||||
url = |
||||
`iosamap://viewMap?sourceApplication=applicationName&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
if (url != "") { |
||||
url = encodeURI(url); |
||||
plus.runtime.openURL(url, function(e) { |
||||
plus.nativeUI.alert("本机未安装指定的地图应用"); |
||||
}); |
||||
} |
||||
}) |
||||
} |
||||
// #endif |
||||
// #ifdef MP-WEIXIN |
||||
uni.openLocation({ |
||||
latitude: Number(latitude), |
||||
longitude: Number(longitude), |
||||
success: function() { |
||||
console.log('success'); |
||||
} |
||||
}); |
||||
// #endif |
||||
}, |
||||
goShop() { |
||||
if (this.info.classify == 2) { //美团 |
||||
// #ifdef MP-WEIXIN |
||||
uni.navigateToMiniProgram({ |
||||
appId: 'wx2c348cf579062e56', |
||||
path: this.info.url, |
||||
fail(res) { |
||||
console.error(res) |
||||
} |
||||
}) |
||||
// #endif |
||||
} else if (this.info.classify == 1) { //饿了么 |
||||
// #ifdef MP-WEIXIN |
||||
uni.navigateToMiniProgram({ |
||||
appId: 'wxece3a9a4c82f58c9', |
||||
path: this.info.url, |
||||
fail(res) { |
||||
console.error(res) |
||||
} |
||||
}) |
||||
// #endif |
||||
} |
||||
}, |
||||
initHelpOrder(goodsId) { |
||||
this.$queue.showLoading('加载中...'); |
||||
let that = this; |
||||
let userId = this.$queue.getData('userId') ? this.$queue.getData('userId') : 0; |
||||
this.$Request.getT('/wm/selectGoodsDetails?goodsId=' + goodsId + '&userId=' + userId + '&latitude=' + this |
||||
.latitude + '&longitude=' + this.longitude).then(res => { |
||||
if (res.code == 0) { |
||||
let image = res.goods.img.split(","); |
||||
|
||||
if (Date.parse(res.goods.endTime.replace('-', '/').replace('-', '/')) < Date.parse( |
||||
new Date())) { |
||||
console.log('这个已经过期了') |
||||
this.status = 99; |
||||
} else { |
||||
this.status = res.status; |
||||
} |
||||
|
||||
this.banners = image; |
||||
if (res.orders) { |
||||
this.orderId = res.orders.orderId; |
||||
} |
||||
res.goods.distance = this.setMorKm(res.goods.distance); |
||||
this.info = res.goods; |
||||
uni.hideLoading(); |
||||
} else { |
||||
this.$queue.showToast(res.msg); |
||||
setTimeout(d => { |
||||
uni.hideLoading(); |
||||
uni.navigateBack(); |
||||
}, 1000); |
||||
} |
||||
}); |
||||
}, |
||||
setMorKm(m) { |
||||
var n = '' |
||||
if (m) { |
||||
if (m >= 1000) { |
||||
n = (m / 1000).toFixed(0) + 'km' |
||||
} else { |
||||
n = parseInt(m) + 'm' |
||||
} |
||||
} else { |
||||
n = '0m' |
||||
} |
||||
return n |
||||
}, |
||||
// 联系 |
||||
kefu() { |
||||
if (uni.getStorageSync('sendorderMsg')) { |
||||
uni.requestSubscribeMessage({ |
||||
tmplIds: this.arr, |
||||
success(re) { |
||||
// console.log(re,'**********') |
||||
var datas = JSON.stringify(re); |
||||
if (datas.indexOf("accept") != -1) { |
||||
console.log(re) |
||||
} |
||||
}, |
||||
fail: (res) => { |
||||
console.log(res) |
||||
} |
||||
}) |
||||
} |
||||
uni.navigateTo({ |
||||
url: '/pages/my/customer' |
||||
}); |
||||
}, |
||||
// 立即下单 打开美团外卖 |
||||
btns() { |
||||
if (uni.getStorageSync('sendorderMsg')) { |
||||
uni.requestSubscribeMessage({ |
||||
tmplIds: this.arr, |
||||
success(re) { |
||||
// console.log(re,'**********') |
||||
var datas = JSON.stringify(re); |
||||
if (datas.indexOf("accept") != -1) { |
||||
console.log(re) |
||||
} |
||||
}, |
||||
fail: (res) => { |
||||
console.log(res) |
||||
} |
||||
}) |
||||
} |
||||
this.$queue.showLoading('抢单中...'); |
||||
let userId = this.$queue.getData('userId'); |
||||
this.$Request.postT('/wm/insertOrders?goodsId=' + this.goodsId + '&userId=' + userId).then(res => { |
||||
if (res.code == 0) { |
||||
this.$queue.showToast('抢单成功!'); |
||||
this.initHelpOrder(this.goodsId); |
||||
setTimeout(d => { |
||||
if (this.info.classify == 2) { //美团 |
||||
// #ifdef MP-WEIXIN |
||||
uni.navigateToMiniProgram({ |
||||
appId: 'wx2c348cf579062e56', |
||||
path: this.info.url, |
||||
fail(res) { |
||||
console.error(res) |
||||
} |
||||
}) |
||||
// #endif |
||||
} else if (this.info.classify == 1) { //饿了么 |
||||
// #ifdef MP-WEIXIN |
||||
uni.navigateToMiniProgram({ |
||||
appId: 'wxece3a9a4c82f58c9', |
||||
path: this.info.url, |
||||
fail(res) { |
||||
console.error(res) |
||||
} |
||||
}) |
||||
// #endif |
||||
} |
||||
}, 500); |
||||
} else { |
||||
uni.hideLoading(); |
||||
this.$queue.showToast(res.msg); |
||||
} |
||||
}); |
||||
}, |
||||
// 放弃任务 |
||||
fangqi(id) { |
||||
if (uni.getStorageSync('sendorderMsg')) { |
||||
uni.requestSubscribeMessage({ |
||||
tmplIds: this.arr, |
||||
success(re) { |
||||
// console.log(re,'**********') |
||||
var datas = JSON.stringify(re); |
||||
if (datas.indexOf("accept") != -1) { |
||||
console.log(re) |
||||
} |
||||
}, |
||||
fail: (res) => { |
||||
console.log(res) |
||||
} |
||||
}) |
||||
} |
||||
uni.showModal({ |
||||
title: '温馨提示', |
||||
content: '您是否要放弃当前任务?', |
||||
showCancel: true, |
||||
cancelText: '取消', |
||||
confirmText: '确认', |
||||
success: d => { |
||||
var that = this; |
||||
if (d.confirm) { |
||||
console.log('用户点击确定'); |
||||
that.$queue.showLoading('提交中...'); |
||||
that.$Request.postT('/wm/abandonOrders?orderId=' + id).then(res => { |
||||
if (res.code === 0) { |
||||
that.$queue.showToast('已放弃当前任务!'); |
||||
that.initHelpOrder(that.goodsId); |
||||
uni.hideLoading(); |
||||
} else { |
||||
that.$queue.showToast(res.msg); |
||||
uni.hideLoading(); |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
// 上传凭证 |
||||
shangchuan(id) { |
||||
if (uni.getStorageSync('sendorderMsg')) { |
||||
uni.requestSubscribeMessage({ |
||||
tmplIds: this.arr, |
||||
success(re) { |
||||
// console.log(re,'**********') |
||||
var datas = JSON.stringify(re); |
||||
if (datas.indexOf("accept") != -1) { |
||||
console.log(re) |
||||
} |
||||
}, |
||||
fail: (res) => { |
||||
console.log(res) |
||||
} |
||||
}) |
||||
} |
||||
uni.navigateTo({ |
||||
url: '/pages/order/release?orderId=' + id |
||||
}); |
||||
}, |
||||
callContact(phone) { |
||||
if (uni.getStorageSync('sendorderMsg')) { |
||||
uni.requestSubscribeMessage({ |
||||
tmplIds: this.arr, |
||||
success(re) { |
||||
// console.log(re,'**********') |
||||
var datas = JSON.stringify(re); |
||||
if (datas.indexOf("accept") != -1) { |
||||
console.log(re) |
||||
} |
||||
}, |
||||
fail: (res) => { |
||||
console.log(res) |
||||
} |
||||
}) |
||||
} |
||||
uni.makePhoneCall({ |
||||
phoneNumber: phone |
||||
}); |
||||
}, |
||||
goLogin() { |
||||
this.$queue.setData('href', '/pages/index/taskDetail?helpOrderId=' + this.helpOrderId); |
||||
uni.navigateTo({ |
||||
url: '/pages/public/login' |
||||
}); |
||||
}, |
||||
goPageLogin(url) { |
||||
let token = this.$queue.getData('token'); |
||||
if (token) { |
||||
if (uni.getStorageSync('sendMyMsg')) { |
||||
uni.requestSubscribeMessage({ |
||||
tmplIds: this.arr, |
||||
success(re) { |
||||
// console.log(re,'**********') |
||||
var datas = JSON.stringify(re); |
||||
if (datas.indexOf("accept") != -1) { |
||||
console.log(re) |
||||
} |
||||
}, |
||||
fail: (res) => { |
||||
console.log(res) |
||||
} |
||||
}) |
||||
} |
||||
console.log('是否有token') |
||||
uni.navigateTo({ |
||||
url |
||||
}) |
||||
} else { |
||||
this.goLogin(); |
||||
} |
||||
}, |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss"> |
||||
page { |
||||
width: 100%; |
||||
margin: 0; |
||||
padding: 0; |
||||
background-color: #F6F6F6; |
||||
padding-bottom: 164rpx; |
||||
} |
||||
.bill{ |
||||
width: 100%; |
||||
height: 426rpx; |
||||
.swiper{ |
||||
width: 100%; |
||||
height: 426rpx; |
||||
image{ |
||||
width: 100%; |
||||
display: block; |
||||
} |
||||
} |
||||
} |
||||
// .bill image { |
||||
// width: 100%; |
||||
// height: 208px; |
||||
// display: block; |
||||
// } |
||||
|
||||
.billtextbox { |
||||
width: 100%; |
||||
height: 60px; |
||||
display: flex; |
||||
align-items: center; |
||||
background: linear-gradient(48deg, #FF5656 0%, #FF9F74 100%); |
||||
} |
||||
|
||||
.billtext { |
||||
width: 100%; |
||||
margin: 0 16px; |
||||
} |
||||
|
||||
|
||||
|
||||
.billtext .left { |
||||
width: 50%; |
||||
height: 23px; |
||||
background-color: #000000; |
||||
font-size: 14px; |
||||
font-family: PingFang SC; |
||||
color: #FAD19C; |
||||
float: left; |
||||
margin-top: 3px; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
margin-top: 10px; |
||||
} |
||||
|
||||
.billtext .left image { |
||||
width: 12px; |
||||
height: 12px; |
||||
float: left; |
||||
margin-top: 2px; |
||||
margin-right: 2px; |
||||
} |
||||
|
||||
.middel { |
||||
width: 0px; |
||||
height: 31px; |
||||
border: 1px solid #FFFFFF; |
||||
float: left; |
||||
margin: 0 7px; |
||||
margin-top: 6rpx; |
||||
} |
||||
|
||||
.billtext .right { |
||||
font-size: 15px; |
||||
font-family: PingFang SC; |
||||
font-weight: 400; |
||||
color: #FFFFFF; |
||||
} |
||||
|
||||
.text2 { |
||||
float: left; |
||||
width: 50%; |
||||
} |
||||
|
||||
.shop { |
||||
|
||||
margin: 0 16px; |
||||
height: 152px; |
||||
margin-top: 20rpx; |
||||
background-color: #FFFFFF; |
||||
border-radius: 8px; |
||||
} |
||||
|
||||
.shoptop { |
||||
height: 94px; |
||||
width: 90%; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
.shoptext { |
||||
height: 57px; |
||||
padding-top: 20px; |
||||
} |
||||
|
||||
.shoptext image { |
||||
width: 65px; |
||||
height: 65px; |
||||
|
||||
} |
||||
|
||||
.shoptext .right { |
||||
float: left; |
||||
margin-left: 10rpx; |
||||
.shop-name-box{ |
||||
display: flex; |
||||
align-items: center; |
||||
margin-bottom: 10rpx; |
||||
image{ |
||||
width: 40rpx; |
||||
height: 40rpx; |
||||
margin-right: 8rpx; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.shop .bottom { |
||||
height: 70px; |
||||
width: 90%; |
||||
margin: 0 auto; |
||||
display: flex; |
||||
margin-top: 30rpx; |
||||
} |
||||
|
||||
.shop .bottom .text { |
||||
font-size: 12px; |
||||
font-family: PingFang SC; |
||||
font-weight: 500; |
||||
color: #FF4848; |
||||
} |
||||
|
||||
.line { |
||||
width: 316px; |
||||
height: 1px; |
||||
border: 1px solid rgba(112, 112, 112, 0.10980392156862745); |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
|
||||
|
||||
.welfare { |
||||
margin: 0 16px; |
||||
// height: 138px; |
||||
margin-top: 16px; |
||||
} |
||||
|
||||
.welfare .top { |
||||
color: #FAD19C; |
||||
display: flex; |
||||
height: 38px; |
||||
align-items: center; |
||||
|
||||
} |
||||
|
||||
.welfare .button { |
||||
margin-left: 70px; |
||||
width: 100px; |
||||
height: 24px; |
||||
background: #FAD19C; |
||||
border-radius: 12px; |
||||
font-size: 11px; |
||||
font-family: PingFang SC; |
||||
color: #000000; |
||||
padding-top:5px; |
||||
padding-left: 25px; |
||||
} |
||||
|
||||
.content .bottom { |
||||
height: 100px; |
||||
display: flex; |
||||
background-color: #FFFFFF; |
||||
} |
||||
|
||||
.bottom .circle { |
||||
width: 50px; |
||||
height: 50px; |
||||
background: #FF4848; |
||||
border-radius: 50%; |
||||
margin-left: 10rpx; |
||||
} |
||||
|
||||
.bottom .jieshao { |
||||
margin-top: 5px; |
||||
margin-left: 10px; |
||||
} |
||||
|
||||
.bottom .add { |
||||
width: 48px; |
||||
height: 19px; |
||||
background: linear-gradient(141deg, #FF4848 0%, #FF2929 100%); |
||||
opacity: 1; |
||||
border-radius: 10px; |
||||
font-size: 12px; |
||||
font-family: PingFang SC; |
||||
font-weight: 500; |
||||
color: #FFFFFF; |
||||
padding-left: 12px; |
||||
padding-top: 2px; |
||||
margin-left: 50px; |
||||
margin-top: 10px; |
||||
} |
||||
|
||||
// 底部按钮 |
||||
.footers { |
||||
width: 100%; |
||||
height: 124rpx; |
||||
background: #FFFFFF; |
||||
position: fixed; |
||||
bottom: 0; |
||||
padding: 0 20rpx; |
||||
z-index: 10; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
|
||||
.payinfo { |
||||
width: 152px; |
||||
height: 64rpx; |
||||
background: linear-gradient(127deg, #FF8A6B 0%, #FF2929 100%); |
||||
opacity: 1; |
||||
border-radius: 17px 0px 0px 15px; |
||||
font-size: 12px; |
||||
font-weight: 500; |
||||
color: #FFFFFF; |
||||
line-height: 32px; |
||||
text-align: center; |
||||
} |
||||
|
||||
.payinfo1 { |
||||
width: 25%; |
||||
display: inline-block; |
||||
} |
||||
|
||||
.tui-button-primar { |
||||
width: 60%; |
||||
height: 78upx; |
||||
line-height: 78upx; |
||||
opacity: 1; |
||||
background: #ffc705; |
||||
border-radius: 16rpx; |
||||
} |
||||
} |
||||
|
||||
.procedure { |
||||
font-size: 32rpx; |
||||
font-weight: 600; |
||||
color: #000000; |
||||
margin-top: 36rpx; |
||||
margin-bottom: 16rpx; |
||||
padding-left: 64rpx; |
||||
} |
||||
|
||||
.procedurepictrue { |
||||
height: 130rpx; |
||||
background-color: #FFFFFF; |
||||
border-radius: 8rpx; |
||||
margin: 0 46rpx 20rpx; |
||||
display: flex; |
||||
justify-content: space-around; |
||||
} |
||||
|
||||
.procedurepictrue image{ |
||||
width: 46rpx; |
||||
height: 60rpx; |
||||
margin-top: 20rpx; |
||||
margin-left: 20rpx ; |
||||
} |
||||
|
||||
.procedurepictrue .item{ |
||||
font-size: 24rpx; |
||||
font-weight: 600; |
||||
} |
||||
|
||||
|
||||
</style> |
@ -1,306 +1,236 @@
|
||||
<template> |
||||
<view class="page" style="background: #FFFFFF;"> |
||||
<view> |
||||
<view class="feedback-title"> |
||||
<text>问题和意见</text> |
||||
<text @tap="chooseMsg">快速键入</text> |
||||
<view class="content"> |
||||
<view class="title">请选择问题反馈类型:</view> |
||||
<view class="choicebox"> |
||||
<view class="choices "> |
||||
<view style="float: left;margin-right: 10px;" v-for="(item,index) in choicelist" class="a" |
||||
:key="index" :class="{changeStyle:changeSelectStyle == index}" @click="changeStyle(index)"> |
||||
{{item.name}} |
||||
</view> |
||||
</view> |
||||
</view> |
||||
<view style="height: 0px;border: 1px solid rgba(112, 112, 112, 0.10980392156862745);"> |
||||
</view> |
||||
<view> |
||||
<textarea auto-height placeholder="请填写15字以上的内容描述,我们将尽快给您回复" v-model="text" |
||||
placeholder-style="font-size: 12px;font-family: PingFang SC;font-weight: 400;color: #999999;" /> |
||||
</view> |
||||
</view> |
||||
|
||||
<!-- <text @tap="chooseMsg">快速键入</text> --> |
||||
</view> |
||||
<view class="feedback-body"><textarea placeholder="请详细描述你的问题和意见..." v-model="sendDate.content" class="feedback-textare" /></view> |
||||
<!-- <view class="feedback-body"><textarea placeholder="请详细描述你的问题和意见..." v-model="sendDate.content" class="feedback-textare" /></view> |
||||
<view class="feedback-title"><text>QQ/邮箱</text></view> |
||||
<view class="feedback-body"><input class="feedback-input" v-model="sendDate.contact" placeholder="方便我们联系你 " /></view> |
||||
<view class="feedback-body"><input class="feedback-input" v-model="sendDate.contact" placeholder="方便我们联系你 " /></view> --> |
||||
<!-- <view class="feedback-title feedback-star-view"> |
||||
<text>应用评分</text> |
||||
<view class="feedback-star-view"> |
||||
<text class="feedback-star" v-for="(value, key) in stars" :key="key" :class="key < sendDate.score ? 'active' : ''" @tap="chooseStar(value)"></text> |
||||
</view> |
||||
</view> --> |
||||
<button type="primary" style="background: #ffc705;margin-top: 32upx;" class="feedback-submit" @tap="send">提交</button> |
||||
<view type="primary" class="button" @tap="send">提交</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
msgContents: ['界面显示错乱', '启动缓慢,卡出翔了', 'UI无法直视,丑哭了', '偶发性崩溃'], |
||||
stars: [1, 2, 3, 4, 5], |
||||
imageList: [], |
||||
sendDate: { |
||||
score: 5, |
||||
content: '', |
||||
contact: '' |
||||
} |
||||
}; |
||||
}, |
||||
onLoad() { |
||||
let deviceInfo = { |
||||
appid: plus.runtime.appid, |
||||
imei: plus.device.imei, //设备标识 |
||||
p: plus.os.name === 'Android' ? 'a' : 'i', //平台类型,i表示iOS平台,a表示Android平台。 |
||||
md: plus.device.model, //设备型号 |
||||
app_version: plus.runtime.version, |
||||
plus_version: plus.runtime.innerVersion, //基座版本号 |
||||
os: plus.os.version, |
||||
net: '' + plus.networkinfo.getCurrentType() |
||||
}; |
||||
this.sendDate = Object.assign(deviceInfo, this.sendDate); |
||||
}, |
||||
methods: { |
||||
close(e) { |
||||
this.imageList.splice(e, 1); |
||||
}, |
||||
chooseMsg() { |
||||
//快速输入 |
||||
uni.showActionSheet({ |
||||
itemList: this.msgContents, |
||||
success: res => { |
||||
this.sendDate.content = this.msgContents[res.tapIndex]; |
||||
} |
||||
}); |
||||
}, |
||||
chooseImg() { |
||||
//选择图片 |
||||
uni.chooseImage({ |
||||
sourceType: ['camera', 'album'], |
||||
sizeType: 'compressed', |
||||
count: 8 - this.imageList.length, |
||||
success: res => { |
||||
this.imageList = this.imageList.concat(res.tempFilePaths); |
||||
} |
||||
}); |
||||
}, |
||||
chooseStar(e) { |
||||
//点击评星 |
||||
this.sendDate.score = e; |
||||
}, |
||||
previewImage() { |
||||
//预览图片 |
||||
uni.previewImage({ |
||||
urls: this.imageList |
||||
}); |
||||
}, |
||||
send() { |
||||
//发送反馈 |
||||
console.log(JSON.stringify(this.sendDate)); |
||||
export default { |
||||
data() { |
||||
return { |
||||
msgContents: ['界面显示错乱', '启动缓慢,卡出翔了', 'UI无法直视,丑哭了', '偶发性崩溃'], |
||||
stars: [1, 2, 3, 4, 5], |
||||
imageList: [], |
||||
sendDate: { |
||||
score: 5, |
||||
content: '', |
||||
contact: '' |
||||
}, |
||||
text: '', |
||||
choicelist: [{ |
||||
"name": "其他反馈" |
||||
}, |
||||
{ |
||||
"name": "优化建议" |
||||
}, |
||||
|
||||
if (!this.sendDate.content) { |
||||
uni.showToast({ |
||||
icon: 'none', |
||||
title: '请输入反馈内容' |
||||
}); |
||||
return; |
||||
} |
||||
if (!this.sendDate.contact) { |
||||
uni.showToast({ |
||||
icon: 'none', |
||||
title: '请填写QQ或邮箱' |
||||
], |
||||
changeSelectStyle: '', |
||||
isshow: true |
||||
}; |
||||
}, |
||||
// onLoad() { |
||||
// let deviceInfo = { |
||||
// appid: plus.runtime.appid, |
||||
// imei: plus.device.imei, //设备标识 |
||||
// p: plus.os.name === 'Android' ? 'a' : 'i', //平台类型,i表示iOS平台,a表示Android平台。 |
||||
// md: plus.device.model, //设备型号 |
||||
// app_version: plus.runtime.version, |
||||
// plus_version: plus.runtime.innerVersion, //基座版本号 |
||||
// os: plus.os.version, |
||||
// net: '' + plus.networkinfo.getCurrentType() |
||||
// }; |
||||
// this.sendDate = Object.assign(deviceInfo, this.sendDate); |
||||
// }, |
||||
methods: { |
||||
close(e) { |
||||
this.imageList.splice(e, 1); |
||||
}, |
||||
changeStyle(index) { |
||||
this.changeSelectStyle = index; |
||||
}, |
||||
chooseMsg() { |
||||
//快速输入 |
||||
uni.showActionSheet({ |
||||
itemList: this.msgContents, |
||||
success: res => { |
||||
this.sendDate.content = this.msgContents[res.tapIndex]; |
||||
} |
||||
}); |
||||
return; |
||||
} |
||||
// uni.report('意见反馈', this.sendDate); |
||||
this.$queue.showLoading('加载中...'); |
||||
this.$Request |
||||
.postJson('/message/add', { |
||||
state: 2, |
||||
title: this.sendDate.contact, |
||||
content: JSON.stringify(this.sendDate) |
||||
}) |
||||
.then(res => { |
||||
if (res.code === 0) { |
||||
uni.showToast({ |
||||
title: '反馈成功' |
||||
}); |
||||
setTimeout(function() { |
||||
uni.navigateBack(); |
||||
}, 1000); |
||||
} else { |
||||
uni.hideLoading(); |
||||
uni.showModal({ |
||||
showCancel: false, |
||||
title: '反馈失败', |
||||
content: res.msg |
||||
}); |
||||
}, |
||||
chooseImg() { |
||||
//选择图片 |
||||
uni.chooseImage({ |
||||
sourceType: ['camera', 'album'], |
||||
sizeType: 'compressed', |
||||
count: 8 - this.imageList.length, |
||||
success: res => { |
||||
this.imageList = this.imageList.concat(res.tempFilePaths); |
||||
} |
||||
}); |
||||
}, |
||||
chooseStar(e) { |
||||
//点击评星 |
||||
this.sendDate.score = e; |
||||
}, |
||||
previewImage() { |
||||
//预览图片 |
||||
uni.previewImage({ |
||||
urls: this.imageList |
||||
}); |
||||
}, |
||||
send() { |
||||
//发送反馈 |
||||
console.log(JSON.stringify(this.sendDate)); |
||||
|
||||
if (!this.sendDate.content) { |
||||
uni.showToast({ |
||||
icon: 'none', |
||||
title: '请输入反馈内容' |
||||
}); |
||||
return; |
||||
} |
||||
if (!this.sendDate.contact) { |
||||
uni.showToast({ |
||||
icon: 'none', |
||||
title: '请填写QQ或邮箱' |
||||
}); |
||||
return; |
||||
} |
||||
// uni.report('意见反馈', this.sendDate); |
||||
this.$queue.showLoading('加载中...'); |
||||
this.$Request |
||||
.postJson('/message/add', { |
||||
state: 2, |
||||
title: this.sendDate.contact, |
||||
content: JSON.stringify(this.sendDate) |
||||
}) |
||||
.then(res => { |
||||
if (res.code === 0) { |
||||
uni.showToast({ |
||||
title: '反馈成功' |
||||
}); |
||||
setTimeout(function() { |
||||
uni.navigateBack(); |
||||
}, 1000); |
||||
} else { |
||||
uni.hideLoading(); |
||||
uni.showModal({ |
||||
showCancel: false, |
||||
title: '反馈失败', |
||||
content: res.msg |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
}; |
||||
</script> |
||||
|
||||
<style> |
||||
@font-face { |
||||
font-family: uniicons; |
||||
font-weight: normal; |
||||
font-style: normal; |
||||
src: url('https://img-cdn-qiniu.dcloud.net.cn/fonts/uni.ttf') format('truetype'); |
||||
} |
||||
page { |
||||
background-color: #FFFFFF; |
||||
} |
||||
view { |
||||
font-size: 28upx; |
||||
} |
||||
.input-view { |
||||
font-size: 28upx; |
||||
} |
||||
.close-view { |
||||
text-align: center; |
||||
line-height: 14px; |
||||
height: 16px; |
||||
width: 16px; |
||||
border-radius: 50%; |
||||
background: #ff5053; |
||||
color: #ffffff; |
||||
position: absolute; |
||||
top: -6px; |
||||
right: -4px; |
||||
font-size: 12px; |
||||
} |
||||
/* 上传 */ |
||||
.uni-uploader { |
||||
flex: 1; |
||||
flex-direction: column; |
||||
} |
||||
.uni-uploader-head { |
||||
display: flex; |
||||
flex-direction: row; |
||||
justify-content: space-between; |
||||
} |
||||
.uni-uploader-info { |
||||
color: #b2b2b2; |
||||
} |
||||
.uni-uploader-body { |
||||
margin-top: 16upx; |
||||
} |
||||
.uni-uploader__files { |
||||
display: flex; |
||||
flex-direction: row; |
||||
flex-wrap: wrap; |
||||
} |
||||
.uni-uploader__file { |
||||
margin: 10upx; |
||||
width: 210upx; |
||||
height: 210upx; |
||||
} |
||||
.uni-uploader__img { |
||||
display: block; |
||||
width: 210upx; |
||||
height: 210upx; |
||||
} |
||||
.uni-uploader__input-box { |
||||
position: relative; |
||||
margin: 10upx; |
||||
width: 208upx; |
||||
height: 208upx; |
||||
border: 2upx solid #d9d9d9; |
||||
} |
||||
.uni-uploader__input-box:before, |
||||
.uni-uploader__input-box:after { |
||||
content: ' '; |
||||
position: absolute; |
||||
top: 50%; |
||||
left: 50%; |
||||
-webkit-transform: translate(-50%, -50%); |
||||
transform: translate(-50%, -50%); |
||||
background-color: #d9d9d9; |
||||
} |
||||
.uni-uploader__input-box:before { |
||||
width: 4upx; |
||||
height: 79upx; |
||||
} |
||||
.uni-uploader__input-box:after { |
||||
width: 79upx; |
||||
height: 4upx; |
||||
} |
||||
.uni-uploader__input-box:active { |
||||
border-color: #999999; |
||||
} |
||||
.uni-uploader__input-box:active:before, |
||||
.uni-uploader__input-box:active:after { |
||||
background-color: #999999; |
||||
} |
||||
.uni-uploader__input { |
||||
position: absolute; |
||||
z-index: 1; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
opacity: 0; |
||||
} |
||||
page { |
||||
background-color: #F6F6F6; |
||||
} |
||||
|
||||
.feedback-title { |
||||
height: 200px; |
||||
background: #FFFFFF; |
||||
opacity: 1; |
||||
border-radius: 6px; |
||||
margin: 0 16px; |
||||
margin-top: 16px; |
||||
} |
||||
|
||||
/*问题反馈*/ |
||||
.feedback-title { |
||||
display: flex; |
||||
flex-direction: row; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
padding: 20upx; |
||||
color: #8f8f94; |
||||
font-size: 28upx; |
||||
} |
||||
.feedback-star-view.feedback-title { |
||||
justify-content: flex-start; |
||||
margin: 0; |
||||
} |
||||
.feedback-quick { |
||||
position: relative; |
||||
padding-right: 40upx; |
||||
} |
||||
.feedback-quick:after { |
||||
font-family: uniicons; |
||||
font-size: 40upx; |
||||
content: '\e581'; |
||||
position: absolute; |
||||
right: 0; |
||||
top: 50%; |
||||
color: #bbb; |
||||
-webkit-transform: translateY(-50%); |
||||
transform: translateY(-50%); |
||||
} |
||||
.feedback-body { |
||||
font-size: 32upx; |
||||
padding: 16upx; |
||||
margin: 16upx; |
||||
border-radius: 16upx; |
||||
background: #F8F8F8; |
||||
} |
||||
.feedback-textare { |
||||
height: 200upx; |
||||
font-size: 34upx; |
||||
line-height: 50upx; |
||||
width: 100%; |
||||
box-sizing: border-box; |
||||
padding: 20upx 30upx 0; |
||||
} |
||||
.feedback-input { |
||||
font-size: 32upx; |
||||
height: 60upx; |
||||
padding: 15upx 20upx; |
||||
line-height: 60upx; |
||||
} |
||||
.feedback-uploader { |
||||
padding: 22upx 20upx; |
||||
} |
||||
.feedback-star { |
||||
font-family: uniicons; |
||||
font-size: 40upx; |
||||
margin-left: 6upx; |
||||
} |
||||
.feedback-star-view { |
||||
margin-left: 20upx; |
||||
} |
||||
.feedback-star:after { |
||||
content: '\e408'; |
||||
} |
||||
.feedback-star.active { |
||||
color: #ffb400; |
||||
} |
||||
.feedback-star.active:after { |
||||
content: '\e438'; |
||||
} |
||||
.feedback-submit { |
||||
background: #007aff; |
||||
color: #ffffff; |
||||
margin: 20upx; |
||||
} |
||||
.feedback-title .content { |
||||
margin: 0 16px; |
||||
} |
||||
|
||||
.feedback-title .title { |
||||
padding-top: 12px; |
||||
margin-bottom: 8rpx; |
||||
font-size: 14px; |
||||
font-family: PingFang SC; |
||||
font-weight: 400; |
||||
color: #000000; |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
.feedback-submit { |
||||
background: #007aff; |
||||
color: #ffffff; |
||||
margin: 20upx; |
||||
} |
||||
|
||||
.choicebox { |
||||
height: 32px; |
||||
} |
||||
|
||||
.choices { |
||||
padding-top: 10px; |
||||
margin-bottom: 8px; |
||||
} |
||||
|
||||
.a { |
||||
background: #F5F5F5; |
||||
border: 1px solid #999999; |
||||
opacity: 1; |
||||
border-radius: 2px; |
||||
color: #999999; |
||||
} |
||||
|
||||
.button { |
||||
width: 120px; |
||||
height: 24px; |
||||
background: linear-gradient(141deg, #FF4848 0%, #FF2929 100%); |
||||
opacity: 1; |
||||
border-radius: 12px; |
||||
font-size: 11px; |
||||
font-family: PingFang SC; |
||||
font-weight: 400; |
||||
color: #FFFFFF; |
||||
padding-top: 4px; |
||||
padding-left: 50px; |
||||
margin: 0 auto; |
||||
margin-top: 10px; |
||||
} |
||||
|
||||
.changeStyle { |
||||
background: #F8E3DF; |
||||
border: 1px solid #FF6A6A; |
||||
opacity: 1; |
||||
border-radius: 2px; |
||||
color: #FF7171; |
||||
} |
||||
</style> |
||||
|
@ -1,116 +0,0 @@
|
||||
<template> |
||||
<view class="container"> |
||||
<view class="list-cell b-b" @click="navTo('/pages/member/zhifubao')" hover-class="cell-hover" |
||||
:hover-stay-time="50"> |
||||
<text class="cell-tit">支付宝账号</text> |
||||
<text class="right cuIcon-right"></text> |
||||
</view> |
||||
<view class="list-cell b-b" @click="navTo('/pages/member/mimi')" hover-class="cell-hover" |
||||
:hover-stay-time="50"> |
||||
<text class="cell-tit">隐私政策</text> |
||||
<text class="right cuIcon-right"></text> |
||||
</view> |
||||
<view class="list-cell b-b" @click="navTo('/pages/member/xieyi')" hover-class="cell-hover" |
||||
:hover-stay-time="50"> |
||||
<text class="cell-tit">用户协议</text> |
||||
<text class="right cuIcon-right"></text> |
||||
</view> |
||||
<view class="list-cell b-b" @click="navTo('/pages/member/feedback')" hover-class="cell-hover" |
||||
:hover-stay-time="50"> |
||||
<text class="cell-tit">意见反馈</text> |
||||
<text class="right cuIcon-right"></text> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return {}; |
||||
}, |
||||
onShow() { |
||||
|
||||
}, |
||||
methods: { |
||||
navTo(url) { |
||||
let token = this.$queue.getData("token"); |
||||
if (token) { |
||||
uni.navigateTo({ |
||||
url: url |
||||
}); |
||||
} else { |
||||
uni.navigateTo({ |
||||
url: '/pages/public/login' |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='scss'> |
||||
page { |
||||
background: $page-color-base; |
||||
} |
||||
|
||||
.right-txt { |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
.list-cell { |
||||
display: flex; |
||||
align-items: baseline; |
||||
padding: 20upx $page-row-spacing; |
||||
line-height: 60upx; |
||||
position: relative; |
||||
background: #fff; |
||||
justify-content: center; |
||||
|
||||
&.log-out-btn { |
||||
margin-top: 40upx; |
||||
|
||||
.cell-tit { |
||||
color: $uni-color-primary; |
||||
text-align: center; |
||||
margin-right: 0; |
||||
} |
||||
|
||||
} |
||||
|
||||
&.cell-hover { |
||||
background: #fafafa; |
||||
} |
||||
|
||||
&.b-b:after { |
||||
left: 32upx; |
||||
} |
||||
|
||||
&.m-t { |
||||
margin-top: 18upx; |
||||
} |
||||
|
||||
.cell-more { |
||||
align-self: baseline; |
||||
font-size: $font-lg; |
||||
color: $font-color-light; |
||||
margin-left: 12upx; |
||||
} |
||||
|
||||
.cell-tit { |
||||
flex: 1; |
||||
font-size: $font-base + 2upx; |
||||
color: $font-color-dark; |
||||
margin-right: 12upx; |
||||
} |
||||
|
||||
.cell-tip { |
||||
font-size: $font-base; |
||||
color: $font-color-light; |
||||
} |
||||
|
||||
switch { |
||||
transform: translateX(8px) scale(.84); |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,68 @@
|
||||
<template> |
||||
<view class="container"> |
||||
<view class="top"> |
||||
|
||||
<u-cell-group> |
||||
<u-cell-item icon="share" title="支付宝绑定" :arrow="true" value="绑定支付宝" @click="navTo('/pages/my/zhifubao')"></u-cell-item> |
||||
<u-cell-item icon="fingerprint" title="隐私政策" :arrow="true" @click="navTo('/pages/member/mimi')"></u-cell-item> |
||||
<u-cell-item icon="order" title="用户协议" :arrow="true" @click="navTo('/pages/member/xieyi')"></u-cell-item> |
||||
<u-cell-item icon="question-circle" title="意见反馈" :arrow="true" @click="navTo('/pages/member/feedback')"></u-cell-item> |
||||
</u-cell-group> |
||||
</view> |
||||
<button>退出登录</button> |
||||
|
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return {}; |
||||
}, |
||||
onShow() { |
||||
|
||||
}, |
||||
methods: { |
||||
navTo(url) { |
||||
let token = this.$queue.getData("token"); |
||||
if (token) { |
||||
uni.navigateTo({ |
||||
url: url |
||||
}); |
||||
} else { |
||||
uni.navigateTo({ |
||||
url: '/pages/public/login' |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang='scss'> |
||||
page { |
||||
background: #F6F6F6; |
||||
} |
||||
|
||||
.top { |
||||
margin: 0 16px; |
||||
background: #FFFFFF; |
||||
opacity: 1; |
||||
border-radius: 6px; |
||||
margin-top: 16px; |
||||
} |
||||
|
||||
|
||||
|
||||
button { |
||||
width: 152px; |
||||
height: 32px; |
||||
background: linear-gradient(141deg, #FF4848 0%, #FF2929 100%); |
||||
border-radius: 16px; |
||||
font-size: 12px; |
||||
font-family: PingFang SC; |
||||
font-weight: 400; |
||||
color: #FFFFFF; |
||||
margin-top: 10px; |
||||
} |
||||
</style> |
@ -0,0 +1,53 @@
|
||||
<template> |
||||
<view> |
||||
<view class="menu"> |
||||
<view class="tips">支付宝账号</view> |
||||
<input class="uni-input" type="number" placeholder="请输入支付宝账号" style="margin-top: 5px;"/> |
||||
|
||||
|
||||
|
||||
<view class="tips" style="margin-top: 10px;">姓名</view> |
||||
<input class="uni-input" type="number" placeholder="请输入真实姓名" style="margin-top: 5px;"/> |
||||
</view> |
||||
|
||||
<button>确认提交</button> |
||||
</view> |
||||
|
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
|
||||
} |
||||
}, |
||||
methods: { |
||||
|
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
.menu { |
||||
background-color: #FFFFFF; |
||||
margin: 0 16px; |
||||
padding-top: 10px; |
||||
} |
||||
|
||||
input { |
||||
border-bottom: 1px solid rgba(112, 112, 112, 0.10980392156862745); |
||||
|
||||
} |
||||
|
||||
button { |
||||
width: 152px; |
||||
height: 32px; |
||||
background: linear-gradient(141deg, #FF4848 0%, #FF2929 100%); |
||||
font-size: 12px; |
||||
font-family: PingFang SC; |
||||
border-radius: 16px; |
||||
margin-top: 42px; |
||||
color: #FFFFFF; |
||||
} |
||||
</style> |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 522 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 403 B |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 591 B |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 192 KiB |
After Width: | Height: | Size: 769 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 499 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 721 B |
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 702 B |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 865 B |
After Width: | Height: | Size: 778 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 970 B |
After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1014 B |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 993 B |
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,21 @@
|
||||
MIT License |
||||
|
||||
Copyright (c) 2020 www.uviewui.com |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
@ -0,0 +1,106 @@
|
||||
<p align="center"> |
||||
<img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;"> |
||||
</p> |
||||
<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView</h3> |
||||
<h3 align="center">多平台快速开发的UI框架</h3> |
||||
|
||||
|
||||
## 说明 |
||||
|
||||
uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水 |
||||
|
||||
## 特性 |
||||
|
||||
- 兼容安卓,iOS,微信小程序,H5,QQ小程序,百度小程序,支付宝小程序,头条小程序 |
||||
- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用 |
||||
- 众多贴心的JS利器,让您飞镖在手,召之即来,百步穿杨 |
||||
- 众多的常用页面和布局,让您专注逻辑,事半功倍 |
||||
- 详尽的文档支持,现代化的演示效果 |
||||
- 按需引入,精简打包体积 |
||||
|
||||
|
||||
## 安装 |
||||
|
||||
```bash |
||||
# npm方式安装 |
||||
npm i uview-ui |
||||
``` |
||||
|
||||
## 快速上手 |
||||
|
||||
1. `main.js`引入uView库 |
||||
```js |
||||
// main.js |
||||
import uView from 'uview-ui'; |
||||
Vue.use(uView); |
||||
``` |
||||
|
||||
2. `App.vue`引入基础样式(注意style标签需声明scss属性支持) |
||||
```css |
||||
/* App.vue */ |
||||
<style lang="scss"> |
||||
@import "uview-ui/index.scss"; |
||||
</style> |
||||
``` |
||||
|
||||
3. `uni.scss`引入全局scss变量文件 |
||||
```css |
||||
/* uni.scss */ |
||||
@import "uview-ui/theme.scss"; |
||||
``` |
||||
|
||||
4. `pages.json`配置easycom规则(按需引入) |
||||
|
||||
```js |
||||
// pages.json |
||||
{ |
||||
"easycom": { |
||||
// npm安装的方式不需要前面的"@/",下载安装的方式需要"@/" |
||||
// npm安装方式 |
||||
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue" |
||||
// 下载安装方式 |
||||
// "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue" |
||||
}, |
||||
// 此为本身已有的内容 |
||||
"pages": [ |
||||
// ...... |
||||
] |
||||
} |
||||
``` |
||||
|
||||
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 |
||||
|
||||
## 使用方法 |
||||
配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。 |
||||
|
||||
```html |
||||
<template> |
||||
<u-button>按钮</u-button> |
||||
</template> |
||||
``` |
||||
|
||||
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容 |
||||
|
||||
## 链接 |
||||
|
||||
- [官方文档](https://uviewui.com/) |
||||
- [更新日志](https://uviewui.com/components/changelog.html) |
||||
- [升级指南](https://uviewui.com/components/changelog.html) |
||||
- [关于我们](https://uviewui.com/cooperation/about.html) |
||||
|
||||
## 预览 |
||||
|
||||
您可以通过**微信**扫码,查看最佳的演示效果。 |
||||
<br> |
||||
<br> |
||||
<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" > |
||||
|
||||
<!-- ## 捐赠uView的研发 |
||||
|
||||
uView文档和源码全部开源免费,如果您认为uView帮到了您的开发工作,您可以捐赠uView的研发工作,捐赠无门槛,哪怕是一杯可乐也好(相信这比打赏主播更有意义)。 |
||||
|
||||
<img src="https://uviewui.com/common/wechat.png" width="220" > |
||||
<img style="margin-left: 100px;" src="https://uviewui.com/common/alipay.png" width="220" > |
||||
--> |
||||
## 版权信息 |
||||
uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。 |
@ -0,0 +1,190 @@
|
||||
<template> |
||||
<u-popup mode="bottom" :border-radius="borderRadius" :popup="false" v-model="value" :maskCloseAble="maskCloseAble" |
||||
length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="popupClose" :z-index="uZIndex"> |
||||
<view class="u-tips u-border-bottom" v-if="tips.text" :style="[tipsStyle]"> |
||||
{{tips.text}} |
||||
</view> |
||||
<block v-for="(item, index) in list" :key="index"> |
||||
<view |
||||
@touchmove.stop.prevent |
||||
@tap="itemClick(index)" |
||||
:style="[itemStyle(index)]" |
||||
class="u-action-sheet-item u-line-1" |
||||
:class="[index < list.length - 1 ? 'u-border-bottom' : '']" |
||||
:hover-stay-time="150" |
||||
> |
||||
<text>{{item.text}}</text> |
||||
<text class="u-action-sheet-item__subtext u-line-1" v-if="item.subText">{{item.subText}}</text> |
||||
</view> |
||||
</block> |
||||
<view class="u-gab" v-if="cancelBtn"> |
||||
</view> |
||||
<view @touchmove.stop.prevent class="u-actionsheet-cancel u-action-sheet-item" hover-class="u-hover-class" |
||||
:hover-stay-time="150" v-if="cancelBtn" @tap="close">{{cancelText}}</view> |
||||
</u-popup> |
||||
</template> |
||||
|
||||
<script> |
||||
/** |
||||
* actionSheet 操作菜单 |
||||
* @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。 |
||||
* @tutorial https://www.uviewui.com/components/actionSheet.html |
||||
* @property {Array<Object>} list 按钮的文字数组,见官方文档示例 |
||||
* @property {Object} tips 顶部的提示文字,见官方文档示例 |
||||
* @property {String} cancel-text 取消按钮的提示文字 |
||||
* @property {Boolean} cancel-btn 是否显示底部的取消按钮(默认true) |
||||
* @property {Number String} border-radius 弹出部分顶部左右的圆角值,单位rpx(默认0) |
||||
* @property {Boolean} mask-close-able 点击遮罩是否可以关闭(默认true) |
||||
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false) |
||||
* @property {Number String} z-index z-index值(默认1075) |
||||
* @property {String} cancel-text 取消按钮的提示文字 |
||||
* @event {Function} click 点击ActionSheet列表项时触发 |
||||
* @event {Function} close 点击取消按钮时触发 |
||||
* @example <u-action-sheet :list="list" @click="click" v-model="show"></u-action-sheet> |
||||
*/ |
||||
export default { |
||||
name: "u-action-sheet", |
||||
props: { |
||||
// 点击遮罩是否可以关闭actionsheet |
||||
maskCloseAble: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 按钮的文字数组,可以自定义颜色和字体大小,字体单位为rpx |
||||
list: { |
||||
type: Array, |
||||
default () { |
||||
// 如下 |
||||
// return [{ |
||||
// text: '确定', |
||||
// color: '', |
||||
// fontSize: '' |
||||
// }] |
||||
return []; |
||||
} |
||||
}, |
||||
// 顶部的提示文字 |
||||
tips: { |
||||
type: Object, |
||||
default () { |
||||
return { |
||||
text: '', |
||||
color: '', |
||||
fontSize: '26' |
||||
} |
||||
} |
||||
}, |
||||
// 底部的取消按钮 |
||||
cancelBtn: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 是否开启底部安全区适配,开启的话,会在iPhoneX机型底部添加一定的内边距 |
||||
safeAreaInsetBottom: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 通过双向绑定控制组件的弹出与收起 |
||||
value: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 弹出的顶部圆角值 |
||||
borderRadius: { |
||||
type: [String, Number], |
||||
default: 0 |
||||
}, |
||||
// 弹出的z-index值 |
||||
zIndex: { |
||||
type: [String, Number], |
||||
default: 0 |
||||
}, |
||||
// 取消按钮的文字提示 |
||||
cancelText: { |
||||
type: String, |
||||
default: '取消' |
||||
} |
||||
}, |
||||
computed: { |
||||
// 顶部提示的样式 |
||||
tipsStyle() { |
||||
let style = {}; |
||||
if (this.tips.color) style.color = this.tips.color; |
||||
if (this.tips.fontSize) style.fontSize = this.tips.fontSize + 'rpx'; |
||||
return style; |
||||
}, |
||||
// 操作项目的样式 |
||||
itemStyle() { |
||||
return (index) => { |
||||
let style = {}; |
||||
if (this.list[index].color) style.color = this.list[index].color; |
||||
if (this.list[index].fontSize) style.fontSize = this.list[index].fontSize + 'rpx'; |
||||
// 选项被禁用的样式 |
||||
if (this.list[index].disabled) style.color = '#c0c4cc'; |
||||
return style; |
||||
} |
||||
}, |
||||
uZIndex() { |
||||
// 如果用户有传递z-index值,优先使用 |
||||
return this.zIndex ? this.zIndex : this.$u.zIndex.popup; |
||||
} |
||||
}, |
||||
methods: { |
||||
// 点击取消按钮 |
||||
close() { |
||||
// 发送input事件,并不会作用于父组件,而是要设置组件内部通过props传递的value参数 |
||||
// 这是一个vue发送事件的特殊用法 |
||||
this.popupClose(); |
||||
this.$emit('close'); |
||||
}, |
||||
// 弹窗关闭 |
||||
popupClose() { |
||||
this.$emit('input', false); |
||||
}, |
||||
// 点击某一个item |
||||
itemClick(index) { |
||||
// disabled的项禁止点击 |
||||
if(this.list[index].disabled) return; |
||||
this.$emit('click', index); |
||||
this.$emit('input', false); |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
@import "../../libs/css/style.components.scss"; |
||||
|
||||
.u-tips { |
||||
font-size: 26rpx; |
||||
text-align: center; |
||||
padding: 34rpx 0; |
||||
line-height: 1; |
||||
color: $u-tips-color; |
||||
} |
||||
|
||||
.u-action-sheet-item { |
||||
@include vue-flex;; |
||||
line-height: 1; |
||||
justify-content: center; |
||||
align-items: center; |
||||
font-size: 32rpx; |
||||
padding: 34rpx 0; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.u-action-sheet-item__subtext { |
||||
font-size: 24rpx; |
||||
color: $u-tips-color; |
||||
margin-top: 20rpx; |
||||
} |
||||
|
||||
.u-gab { |
||||
height: 12rpx; |
||||
background-color: rgb(234, 234, 236); |
||||
} |
||||
|
||||
.u-actionsheet-cancel { |
||||
color: $u-main-color; |
||||
} |
||||
</style> |
@ -0,0 +1,256 @@
|
||||
<template> |
||||
<view class="u-alert-tips" v-if="show" :class="[ |
||||
!show ? 'u-close-alert-tips': '', |
||||
type ? 'u-alert-tips--bg--' + type + '-light' : '', |
||||
type ? 'u-alert-tips--border--' + type + '-disabled' : '', |
||||
]" :style="{ |
||||
backgroundColor: bgColor, |
||||
borderColor: borderColor |
||||
}"> |
||||
<view class="u-icon-wrap"> |
||||
<u-icon v-if="showIcon" :name="uIcon" :size="description ? 40 : 32" class="u-icon" :color="uIconType" :custom-style="iconStyle"></u-icon> |
||||
</view> |
||||
<view class="u-alert-content" @tap.stop="click"> |
||||
<view class="u-alert-title" :style="[uTitleStyle]"> |
||||
{{title}} |
||||
</view> |
||||
<view v-if="description" class="u-alert-desc" :style="[descStyle]"> |
||||
{{description}} |
||||
</view> |
||||
</view> |
||||
<view class="u-icon-wrap"> |
||||
<u-icon @click="close" v-if="closeAble && !closeText" hoverClass="u-type-error-hover-color" name="close" color="#c0c4cc" |
||||
:size="22" class="u-close-icon" :style="{ |
||||
top: description ? '18rpx' : '24rpx' |
||||
}"></u-icon> |
||||
</view> |
||||
<text v-if="closeAble && closeText" class="u-close-text" :style="{ |
||||
top: description ? '18rpx' : '24rpx' |
||||
}">{{closeText}}</text> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
/** |
||||
* alertTips 警告提示 |
||||
* @description 警告提示,展现需要关注的信息 |
||||
* @tutorial https://uviewui.com/components/alertTips.html |
||||
* @property {String} title 显示的标题文字 |
||||
* @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选 |
||||
* @property {String} type 关闭按钮(默认为叉号icon图标) |
||||
* @property {String} icon 图标名称 |
||||
* @property {Object} icon-style 图标的样式,对象形式 |
||||
* @property {Object} title-style 标题的样式,对象形式 |
||||
* @property {Object} desc-style 描述的样式,对象形式 |
||||
* @property {String} close-able 用文字替代关闭图标,close-able为true时有效 |
||||
* @property {Boolean} show-icon 是否显示左边的辅助图标 |
||||
* @property {Boolean} show 显示或隐藏组件 |
||||
* @event {Function} click 点击组件时触发 |
||||
* @event {Function} close 点击关闭按钮时触发 |
||||
*/ |
||||
export default { |
||||
name: 'u-alert-tips', |
||||
props: { |
||||
// 显示文字 |
||||
title: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 主题,success/warning/info/error |
||||
type: { |
||||
type: String, |
||||
default: 'warning' |
||||
}, |
||||
// 辅助性文字 |
||||
description: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 是否可关闭 |
||||
closeAble: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 关闭按钮自定义文本 |
||||
closeText: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 是否显示图标 |
||||
showIcon: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 文字颜色,如果定义了color值,icon会失效 |
||||
color: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 背景颜色 |
||||
bgColor: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 边框颜色 |
||||
borderColor: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 是否显示 |
||||
show: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 左边显示的icon |
||||
icon: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// icon的样式 |
||||
iconStyle: { |
||||
type: Object, |
||||
default() { |
||||
return {} |
||||
} |
||||
}, |
||||
// 标题的样式 |
||||
titleStyle: { |
||||
type: Object, |
||||
default() { |
||||
return {} |
||||
} |
||||
}, |
||||
// 描述文字的样式 |
||||
descStyle: { |
||||
type: Object, |
||||
default() { |
||||
return {} |
||||
} |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
} |
||||
}, |
||||
computed: { |
||||
uTitleStyle() { |
||||
let style = {}; |
||||
// 如果有描述文字的话,标题进行加粗 |
||||
style.fontWeight = this.description ? 500 : 'normal'; |
||||
// 将用户传入样式对象和style合并,传入的优先级比style高,同属性会被覆盖 |
||||
return this.$u.deepMerge(style, this.titleStyle); |
||||
}, |
||||
uIcon() { |
||||
// 如果有设置icon名称就使用,否则根据type主题,推定一个默认的图标 |
||||
return this.icon ? this.icon : this.$u.type2icon(this.type); |
||||
}, |
||||
uIconType() { |
||||
// 如果有设置图标的样式,优先使用,没有的话,则用type的样式 |
||||
return Object.keys(this.iconStyle).length ? '' : this.type; |
||||
} |
||||
}, |
||||
methods: { |
||||
// 点击内容 |
||||
click() { |
||||
this.$emit('click'); |
||||
}, |
||||
// 点击关闭按钮 |
||||
close() { |
||||
this.$emit('close'); |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
@import "../../libs/css/style.components.scss"; |
||||
|
||||
.u-alert-tips { |
||||
@include vue-flex; |
||||
align-items: center; |
||||
padding: 16rpx 30rpx; |
||||
border-radius: 8rpx; |
||||
position: relative; |
||||
transition: all 0.3s linear; |
||||
border: 1px solid #fff; |
||||
|
||||
&--bg--primary-light { |
||||
background-color: $u-type-primary-light; |
||||
} |
||||
|
||||
&--bg--info-light { |
||||
background-color: $u-type-info-light; |
||||
} |
||||
|
||||
&--bg--success-light { |
||||
background-color: $u-type-success-light; |
||||
} |
||||
|
||||
&--bg--warning-light { |
||||
background-color: $u-type-warning-light; |
||||
} |
||||
|
||||
&--bg--error-light { |
||||
background-color: $u-type-error-light; |
||||
} |
||||
|
||||
&--border--primary-disabled { |
||||
border-color: $u-type-primary-disabled; |
||||
} |
||||
|
||||
&--border--success-disabled { |
||||
border-color: $u-type-success-disabled; |
||||
} |
||||
|
||||
&--border--error-disabled { |
||||
border-color: $u-type-error-disabled; |
||||
} |
||||
|
||||
&--border--warning-disabled { |
||||
border-color: $u-type-warning-disabled; |
||||
} |
||||
|
||||
&--border--info-disabled { |
||||
border-color: $u-type-info-disabled; |
||||
} |
||||
} |
||||
|
||||
.u-close-alert-tips { |
||||
opacity: 0; |
||||
visibility: hidden; |
||||
} |
||||
|
||||
.u-icon { |
||||
margin-right: 16rpx; |
||||
} |
||||
|
||||
.u-alert-title { |
||||
font-size: 28rpx; |
||||
color: $u-main-color; |
||||
} |
||||
|
||||
.u-alert-desc { |
||||
font-size: 26rpx; |
||||
text-align: left; |
||||
color: $u-content-color; |
||||
} |
||||
|
||||
.u-close-icon { |
||||
position: absolute; |
||||
top: 20rpx; |
||||
right: 20rpx; |
||||
} |
||||
|
||||
.u-close-hover { |
||||
color: red; |
||||
} |
||||
|
||||
.u-close-text { |
||||
font-size: 24rpx; |
||||
color: $u-tips-color; |
||||
position: absolute; |
||||
top: 20rpx; |
||||
right: 20rpx; |
||||
line-height: 1; |
||||
} |
||||
</style> |
@ -0,0 +1,290 @@
|
||||
<template> |
||||
<view class="content"> |
||||
<view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }"> |
||||
<canvas |
||||
class="cropper" |
||||
:disable-scroll="true" |
||||
@touchstart="touchStart" |
||||
@touchmove="touchMove" |
||||
@touchend="touchEnd" |
||||
:style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }" |
||||
canvas-id="cropper" |
||||
id="cropper" |
||||
></canvas> |
||||
<canvas |
||||
class="cropper" |
||||
:disable-scroll="true" |
||||
:style="{ |
||||
position: 'fixed', |
||||
top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`, |
||||
left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`, |
||||
width: `${cropperOpt.width * cropperOpt.pixelRatio}px`, |
||||
height: `${cropperOpt.height * cropperOpt.pixelRatio}` |
||||
}" |
||||
canvas-id="targetId" |
||||
id="targetId" |
||||
></canvas> |
||||
</view> |
||||
<view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }"> |
||||
<!-- #ifdef H5 --> |
||||
<view class="upload" @tap="uploadTap">选择图片</view> |
||||
<!-- #endif --> |
||||
<!-- #ifndef H5 --> |
||||
<view class="upload" @tap="uploadTap">重新选择</view> |
||||
<!-- #endif --> |
||||
<view class="getCropperImage" @tap="getCropperImage(false)">确定</view> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
import WeCropper from './weCropper.js'; |
||||
export default { |
||||
props: { |
||||
// 裁剪矩形框的样式,其中可包含的属性为lineWidth-边框宽度(单位rpx),color: 边框颜色, |
||||
// mask-遮罩颜色,一般设置为一个rgba的透明度,如"rgba(0, 0, 0, 0.35)" |
||||
boundStyle: { |
||||
type: Object, |
||||
default() { |
||||
return { |
||||
lineWidth: 4, |
||||
borderColor: 'rgb(245, 245, 245)', |
||||
mask: 'rgba(0, 0, 0, 0.35)' |
||||
}; |
||||
} |
||||
} |
||||
// // 裁剪框宽度,单位rpx |
||||
// rectWidth: { |
||||
// type: [String, Number], |
||||
// default: 400 |
||||
// }, |
||||
// // 裁剪框高度,单位rpx |
||||
// rectHeight: { |
||||
// type: [String, Number], |
||||
// default: 400 |
||||
// }, |
||||
// // 输出图片宽度,单位rpx |
||||
// destWidth: { |
||||
// type: [String, Number], |
||||
// default: 400 |
||||
// }, |
||||
// // 输出图片高度,单位rpx |
||||
// destHeight: { |
||||
// type: [String, Number], |
||||
// default: 400 |
||||
// }, |
||||
// // 输出的图片类型,如果发现裁剪的图片很大,可能是因为设置为了"png",改成"jpg"即可 |
||||
// fileType: { |
||||
// type: String, |
||||
// default: 'jpg', |
||||
// }, |
||||
// // 生成的图片质量 |
||||
// // H5上无效,目前不考虑使用此参数 |
||||
// quality: { |
||||
// type: [Number, String], |
||||
// default: 1 |
||||
// } |
||||
}, |
||||
data() { |
||||
return { |
||||
// 底部导航的高度 |
||||
bottomNavHeight: 50, |
||||
originWidth: 200, |
||||
width: 0, |
||||
height: 0, |
||||
cropperOpt: { |
||||
id: 'cropper', |
||||
targetId: 'targetCropper', |
||||
pixelRatio: 1, |
||||
width: 0, |
||||
height: 0, |
||||
scale: 2.5, |
||||
zoom: 8, |
||||
cut: { |
||||
x: (this.width - this.originWidth) / 2, |
||||
y: (this.height - this.originWidth) / 2, |
||||
width: this.originWidth, |
||||
height: this.originWidth |
||||
}, |
||||
boundStyle: { |
||||
lineWidth: uni.upx2px(this.boundStyle.lineWidth), |
||||
mask: this.boundStyle.mask, |
||||
color: this.boundStyle.borderColor |
||||
} |
||||
}, |
||||
// 裁剪框和输出图片的尺寸,高度默认等于宽度 |
||||
// 输出图片宽度,单位px |
||||
destWidth: 200, |
||||
// 裁剪框宽度,单位px |
||||
rectWidth: 200, |
||||
// 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可 |
||||
fileType: 'jpg', |
||||
src: '', // 选择的图片路径,用于在点击确定时,判断是否选择了图片 |
||||
}; |
||||
}, |
||||
onLoad(option) { |
||||
let rectInfo = uni.getSystemInfoSync(); |
||||
this.width = rectInfo.windowWidth; |
||||
this.height = rectInfo.windowHeight - this.bottomNavHeight; |
||||
this.cropperOpt.width = this.width; |
||||
this.cropperOpt.height = this.height; |
||||
this.cropperOpt.pixelRatio = rectInfo.pixelRatio; |
||||
|
||||
if (option.destWidth) this.destWidth = option.destWidth; |
||||
if (option.rectWidth) { |
||||
let rectWidth = Number(option.rectWidth); |
||||
this.cropperOpt.cut = { |
||||
x: (this.width - rectWidth) / 2, |
||||
y: (this.height - rectWidth) / 2, |
||||
width: rectWidth, |
||||
height: rectWidth |
||||
}; |
||||
} |
||||
this.rectWidth = option.rectWidth; |
||||
if (option.fileType) this.fileType = option.fileType; |
||||
// 初始化 |
||||
this.cropper = new WeCropper(this.cropperOpt) |
||||
.on('ready', ctx => { |
||||
// wecropper is ready for work! |
||||
}) |
||||
.on('beforeImageLoad', ctx => { |
||||
// before picture loaded, i can do something |
||||
}) |
||||
.on('imageLoad', ctx => { |
||||
// picture loaded |
||||
}) |
||||
.on('beforeDraw', (ctx, instance) => { |
||||
// before canvas draw,i can do something |
||||
}); |
||||
// 设置导航栏样式,以免用户在page.json中没有设置为黑色背景 |
||||
uni.setNavigationBarColor({ |
||||
frontColor: '#ffffff', |
||||
backgroundColor: '#000000' |
||||
}); |
||||
uni.chooseImage({ |
||||
count: 1, // 默认9 |
||||
sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有 |
||||
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 |
||||
success: res => { |
||||
this.src = res.tempFilePaths[0]; |
||||
// 获取裁剪图片资源后,给data添加src属性及其值 |
||||
this.cropper.pushOrign(this.src); |
||||
} |
||||
}); |
||||
}, |
||||
methods: { |
||||
touchStart(e) { |
||||
this.cropper.touchStart(e); |
||||
}, |
||||
touchMove(e) { |
||||
this.cropper.touchMove(e); |
||||
}, |
||||
touchEnd(e) { |
||||
this.cropper.touchEnd(e); |
||||
}, |
||||
getCropperImage(isPre = false) { |
||||
if(!this.src) return this.$u.toast('请先选择图片再裁剪'); |
||||
|
||||
let cropper_opt = { |
||||
destHeight: Number(this.destWidth), // uni.canvasToTempFilePath要求这些参数为数值 |
||||
destWidth: Number(this.destWidth), |
||||
fileType: this.fileType |
||||
}; |
||||
this.cropper.getCropperImage(cropper_opt, (path, err) => { |
||||
if (err) { |
||||
uni.showModal({ |
||||
title: '温馨提示', |
||||
content: err.message |
||||
}); |
||||
} else { |
||||
if (isPre) { |
||||
uni.previewImage({ |
||||
current: '', // 当前显示图片的 http 链接 |
||||
urls: [path] // 需要预览的图片 http 链接列表 |
||||
}); |
||||
} else { |
||||
uni.$emit('uAvatarCropper', path); |
||||
this.$u.route({ |
||||
type: 'back' |
||||
}); |
||||
} |
||||
} |
||||
}); |
||||
}, |
||||
uploadTap() { |
||||
const self = this; |
||||
uni.chooseImage({ |
||||
count: 1, // 默认9 |
||||
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 |
||||
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 |
||||
success: (res) => { |
||||
self.src = res.tempFilePaths[0]; |
||||
// 获取裁剪图片资源后,给data添加src属性及其值 |
||||
|
||||
self.cropper.pushOrign(this.src); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
@import '../../libs/css/style.components.scss'; |
||||
|
||||
.content { |
||||
background: rgba(255, 255, 255, 1); |
||||
} |
||||
|
||||
.cropper { |
||||
position: absolute; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
z-index: 11; |
||||
} |
||||
|
||||
.cropper-buttons { |
||||
background-color: #000000; |
||||
color: #eee; |
||||
} |
||||
|
||||
.cropper-wrapper { |
||||
position: relative; |
||||
@include vue-flex; |
||||
flex-direction: row; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
width: 100%; |
||||
background-color: #000; |
||||
} |
||||
|
||||
.cropper-buttons { |
||||
width: 100vw; |
||||
@include vue-flex; |
||||
flex-direction: row; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
position: fixed; |
||||
bottom: 0; |
||||
left: 0; |
||||
font-size: 28rpx; |
||||
} |
||||
|
||||
.cropper-buttons .upload, |
||||
.cropper-buttons .getCropperImage { |
||||
width: 50%; |
||||
text-align: center; |
||||
} |
||||
|
||||
.cropper-buttons .upload { |
||||
text-align: left; |
||||
padding-left: 50rpx; |
||||
} |
||||
|
||||
.cropper-buttons .getCropperImage { |
||||
text-align: right; |
||||
padding-right: 50rpx; |
||||
} |
||||
</style> |
@ -0,0 +1,244 @@
|
||||
<template> |
||||
<view class="u-avatar" :style="[wrapStyle]" @tap="click"> |
||||
<image |
||||
@error="loadError" |
||||
:style="[imgStyle]" |
||||
class="u-avatar__img" |
||||
v-if="!uText && avatar" |
||||
:src="avatar" |
||||
:mode="imgMode" |
||||
></image> |
||||
<text class="u-line-1" v-else-if="uText" :style="{ |
||||
fontSize: '38rpx' |
||||
}">{{uText}}</text> |
||||
<slot v-else></slot> |
||||
<view class="u-avatar__sex" v-if="showSex" :class="['u-avatar__sex--' + sexIcon]" :style="[uSexStyle]"> |
||||
<u-icon :name="sexIcon" size="20"></u-icon> |
||||
</view> |
||||
<view class="u-avatar__level" v-if="showLevel" :style="[uLevelStyle]"> |
||||
<u-icon :name="levelIcon" size="20"></u-icon> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
let base64Avatar = "data:image/jpg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMraHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjREMEQwRkY0RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjREMEQwRkY1RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEQwRDBGRjJGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEQwRDBGRjNGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx//wAARCADIAMgDAREAAhEBAxEB/8QAcQABAQEAAwEBAAAAAAAAAAAAAAUEAQMGAgcBAQAAAAAAAAAAAAAAAAAAAAAQAAIBAwICBgkDBQAAAAAAAAABAhEDBCEFMVFBYXGREiKBscHRMkJSEyOh4XLxYjNDFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A/fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHbHFyZ/Dam+yLA+Z2L0Pjtyj2poD4AAAAAAAAAAAAAAAAAAAAAAAAKWFs9y6lcvvwQeqj8z9wFaziY1n/HbUX9XF97A7QAGXI23EvJ1goyfzR0YEfN269jeZ+a03pNe0DIAAAAAAAAAAAAAAAAAAAACvtO3RcVkXlWutuL9YFYAAAAAOJRjKLjJVi9GmB5/csH/mu1h/in8PU+QGMAAAAAAAAAAAAAAAAAAaMDG/6MmMH8C80+xAelSSVFolwQAAAAAAAHVlWI37ErUulaPk+hgeYnCUJuElSUXRrrQHAAAAAAAAAAAAAAAAABa2Oz4bM7r4zdF2ICmAAAAAAAAAg7zZ8GX41wuJP0rRgYAAAAAAAAAAAAAAAAAD0m2R8ODaXU33tsDSAAAAAAAAAlb9HyWZcnJd9PcBHAAAAAAAAAAAAAAAAAPS7e64Vn+KA0AAAAAAAAAJm+v8Ftf3ewCKAAAAAAAAAAAAAAAAAX9muqeGo9NttP06+0DcAAAAAAAAAjb7dTu2ra+VOT9P8AQCWAAAAAAAAAAAAAAAAAUNmyPt5Ltv4bui/kuAF0AAAAAAADiUlGLlJ0SVW+oDzOXfd/Ind6JPRdS0QHSAAAAAAAAAAAAAAAAAE2nVaNcGB6Lbs6OTao9LsF51z60BrAAAAAABJ3jOVHjW3r/sa9QEgAAAAAAAAAAAAAAAAAAAPu1duWriuW34ZR4MC9hbnZyEoy8l36XwfYBsAAADaSq9EuLAlZ+7xSdrGdW9Hc5dgEdtt1erfFgAAAAAAAAAAAAAAAAADVjbblX6NR8MH80tEBRs7HYivyzlN8lovaBPzduvY0m6eK10TXtAyAarO55lpJK54orolr+4GqO/Xaea1FvqbXvA+Z77kNeW3GPbV+4DJfzcm/pcm3H6Vou5AdAFLC2ed2Pjv1txa8sV8T6wOL+yZEKu1JXFy4MDBOE4ScZxcZLinoB8gAAAAAAAAAAAB242LeyJ+C3GvN9C7QLmJtePYpKS+5c+p8F2IDYAANJqj1T4oCfk7Nj3G5Wn9qXJax7gJ93Z82D8sVNc4v30A6Xg5i42Z+iLfqARwcyT0sz9MWvWBps7LlTf5Grce9/oBTxdtxseklHxT+uWr9AGoAB138ezfj4bsFJdD6V2MCPm7RdtJzs1uW1xXzL3gTgAAAAAAAAADRhYc8q74I6RWs5ckB6GxYtWLat21SK731sDsAAAAAAAAAAAAAAAASt021NO/YjrxuQXT1oCOAAAAAAABzGLlJRSq26JAelwsWONYjbXxcZvmwO8AAAAAAAAAAAAAAAAAAef3TEWPkVivx3NY9T6UBiAAAAAABo2+VmGXblddIJ8eivRUD0oAAAAAAAAAAAAAAAAAAAYt4tKeFKVNYNSXfRgefAAAAAAAAr7VuSSWPedKaW5v1MCsAAAAAAAAAAAAAAAAAAIe6bj96Ts2n+JPzSXzP3ATgAAAAAAAAFbbt1UUrOQ9FpC4/UwK6aaqtU+DAAAAAAAAAAAAAAA4lKMIuUmoxWrb4ARNx3R3q2rLpa4Sl0y/YCcAAAAAAAAAAANmFud7G8r89r6X0dgFvGzLGRGtuWvTF6NAdwAAAAAAAAAAAy5W442PVN+K59EePp5ARMvOv5MvO6QXCC4AZwAAAAAAAAAAAAAcxlKLUotprg1owN+PvORborq+7Hnwl3gUbO74VzRydt8pKn68ANcJwmqwkpLmnUDkAAAAfNy9atqtyagut0AxXt5xIV8Fbj6lRd7Am5G65V6qUvtwfyx94GMAAAAAAAAAAAAAAAAAAAOU2nVOj5gdsc3LiqRvTpyqwOxbnnrhdfpSfrQB7pnv/AGvuS9gHXPMy5/Fem1yq0v0A6W29XqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//Z"; |
||||
/** |
||||
* avatar 头像 |
||||
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。 |
||||
* @tutorial https://www.uviewui.com/components/avatar.html |
||||
* @property {String} bg-color 背景颜色,一般显示文字时用(默认#ffffff) |
||||
* @property {String} src 头像路径,如加载失败,将会显示默认头像 |
||||
* @property {String Number} size 头像尺寸,可以为指定字符串(large, default, mini),或者数值,单位rpx(默认default) |
||||
* @property {String} mode 显示类型,见上方说明(默认circle) |
||||
* @property {String} sex-icon 性别图标,man-男,woman-女(默认man) |
||||
* @property {String} level-icon 等级图标(默认level) |
||||
* @property {String} sex-bg-color 性别图标背景颜色 |
||||
* @property {String} level-bg-color 等级图标背景颜色 |
||||
* @property {String} show-sex 是否显示性别图标(默认false) |
||||
* @property {String} show-level 是否显示等级图标(默认false) |
||||
* @property {String} img-mode 头像图片的裁剪类型,与uni的image组件的mode参数一致,如效果达不到需求,可尝试传widthFix值(默认aspectFill) |
||||
* @property {String} index 用户传递的标识符值,如果是列表循环,可穿v-for的index值 |
||||
* @event {Function} click 头像被点击 |
||||
* @example <u-avatar :src="src"></u-avatar> |
||||
*/ |
||||
export default { |
||||
name: 'u-avatar', |
||||
props: { |
||||
// 背景颜色 |
||||
bgColor: { |
||||
type: String, |
||||
default: 'transparent' |
||||
}, |
||||
// 头像路径 |
||||
src: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 尺寸,large-大,default-中等,mini-小,如果为数值,则单位为rpx |
||||
// 宽度等于高度 |
||||
size: { |
||||
type: [String, Number], |
||||
default: 'default' |
||||
}, |
||||
// 头像模型,square-带圆角方形,circle-圆形 |
||||
mode: { |
||||
type: String, |
||||
default: 'circle' |
||||
}, |
||||
// 文字内容 |
||||
text: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 图片的裁剪模型 |
||||
imgMode: { |
||||
type: String, |
||||
default: 'aspectFill' |
||||
}, |
||||
// 标识符 |
||||
index: { |
||||
type: [String, Number], |
||||
default: '' |
||||
}, |
||||
// 右上角性别角标,man-男,woman-女 |
||||
sexIcon: { |
||||
type: String, |
||||
default: 'man' |
||||
}, |
||||
// 右下角的等级图标 |
||||
levelIcon: { |
||||
type: String, |
||||
default: 'level' |
||||
}, |
||||
// 右下角等级图标背景颜色 |
||||
levelBgColor: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 右上角性别图标的背景颜色 |
||||
sexBgColor: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 是否显示性别图标 |
||||
showSex: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 是否显示等级图标 |
||||
showLevel: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
error: false, |
||||
// 头像的地址,因为如果加载错误,需要赋值为默认图片,props值无法修改,所以需要一个中间值 |
||||
avatar: this.src ? this.src : base64Avatar, |
||||
} |
||||
}, |
||||
watch: { |
||||
src(n) { |
||||
// 用户可能会在头像加载失败时,再次修改头像值,所以需要重新赋值 |
||||
if(!n) { |
||||
// 如果传入null或者'',或者undefined,显示默认头像 |
||||
this.avatar = base64Avatar; |
||||
this.error = true; |
||||
} else { |
||||
this.avatar = n; |
||||
this.error = false; |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
wrapStyle() { |
||||
let style = {}; |
||||
style.height = this.size == 'large' ? '120rpx' : this.size == 'default' ? |
||||
'90rpx' : this.size == 'mini' ? '70rpx' : this.size + 'rpx'; |
||||
style.width = style.height; |
||||
style.flex = `0 0 ${style.height}`; |
||||
style.backgroundColor = this.bgColor; |
||||
style.borderRadius = this.mode == 'circle' ? '500px' : '5px'; |
||||
if(this.text) style.padding = `0 6rpx`; |
||||
return style; |
||||
}, |
||||
imgStyle() { |
||||
let style = {}; |
||||
style.borderRadius = this.mode == 'circle' ? '500px' : '5px'; |
||||
return style; |
||||
}, |
||||
// 取字符串的第一个字符 |
||||
uText() { |
||||
return String(this.text)[0]; |
||||
}, |
||||
// 性别图标的自定义样式 |
||||
uSexStyle() { |
||||
let style = {}; |
||||
if(this.sexBgColor) style.backgroundColor = this.sexBgColor; |
||||
return style; |
||||
}, |
||||
// 等级图标的自定义样式 |
||||
uLevelStyle() { |
||||
let style = {}; |
||||
if(this.levelBgColor) style.backgroundColor = this.levelBgColor; |
||||
return style; |
||||
} |
||||
}, |
||||
methods: { |
||||
// 图片加载错误时,显示默认头像 |
||||
loadError() { |
||||
this.error = true; |
||||
this.avatar = base64Avatar; |
||||
}, |
||||
click() { |
||||
this.$emit('click', this.index); |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
@import "../../libs/css/style.components.scss"; |
||||
|
||||
.u-avatar { |
||||
/* #ifndef APP-NVUE */ |
||||
display: inline-flex; |
||||
/* #endif */ |
||||
align-items: center; |
||||
justify-content: center; |
||||
font-size: 28rpx; |
||||
color: $u-content-color; |
||||
border-radius: 10px; |
||||
position: relative; |
||||
|
||||
&__img { |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
&__sex { |
||||
position: absolute; |
||||
width: 32rpx; |
||||
color: #ffffff; |
||||
height: 32rpx; |
||||
@include vue-flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
border-radius: 100rpx; |
||||
top: 5%; |
||||
z-index: 1; |
||||
right: -7%; |
||||
border: 1px #ffffff solid; |
||||
|
||||
&--man { |
||||
background-color: $u-type-primary; |
||||
} |
||||
|
||||
&--woman { |
||||
background-color: $u-type-error; |
||||
} |
||||
|
||||
&--none { |
||||
background-color: $u-type-warning; |
||||
} |
||||
} |
||||
|
||||
&__level { |
||||
position: absolute; |
||||
width: 32rpx; |
||||
color: #ffffff; |
||||
height: 32rpx; |
||||
@include vue-flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
border-radius: 100rpx; |
||||
bottom: 5%; |
||||
z-index: 1; |
||||
right: -7%; |
||||
border: 1px #ffffff solid; |
||||
background-color: $u-type-warning; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,153 @@
|
||||
<template> |
||||
<view @tap="backToTop" class="u-back-top" :class="['u-back-top--mode--' + mode]" :style="[{ |
||||
bottom: bottom + 'rpx', |
||||
right: right + 'rpx', |
||||
borderRadius: mode == 'circle' ? '10000rpx' : '8rpx', |
||||
zIndex: uZIndex, |
||||
opacity: opacity |
||||
}, customStyle]"> |
||||
<view class="u-back-top__content" v-if="!$slots.default && !$slots.$default"> |
||||
<u-icon @click="backToTop" :name="icon" :custom-style="iconStyle"></u-icon> |
||||
<view class="u-back-top__content__tips"> |
||||
{{tips}} |
||||
</view> |
||||
</view> |
||||
<slot v-else /> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
name: 'u-back-top', |
||||
props: { |
||||
// 返回顶部的形状,circle-圆形,square-方形 |
||||
mode: { |
||||
type: String, |
||||
default: 'circle' |
||||
}, |
||||
// 自定义图标 |
||||
icon: { |
||||
type: String, |
||||
default: 'arrow-upward' |
||||
}, |
||||
// 提示文字 |
||||
tips: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 返回顶部滚动时间 |
||||
duration: { |
||||
type: [Number, String], |
||||
default: 100 |
||||
}, |
||||
// 滚动距离 |
||||
scrollTop: { |
||||
type: [Number, String], |
||||
default: 0 |
||||
}, |
||||
// 距离顶部多少距离显示,单位rpx |
||||
top: { |
||||
type: [Number, String], |
||||
default: 400 |
||||
}, |
||||
// 返回顶部按钮到底部的距离,单位rpx |
||||
bottom: { |
||||
type: [Number, String], |
||||
default: 200 |
||||
}, |
||||
// 返回顶部按钮到右边的距离,单位rpx |
||||
right: { |
||||
type: [Number, String], |
||||
default: 40 |
||||
}, |
||||
// 层级 |
||||
zIndex: { |
||||
type: [Number, String], |
||||
default: '9' |
||||
}, |
||||
// 图标的样式,对象形式 |
||||
iconStyle: { |
||||
type: Object, |
||||
default() { |
||||
return { |
||||
color: '#909399', |
||||
fontSize: '38rpx' |
||||
} |
||||
} |
||||
}, |
||||
// 整个组件的样式 |
||||
customStyle: { |
||||
type: Object, |
||||
default() { |
||||
return {} |
||||
} |
||||
} |
||||
}, |
||||
watch: { |
||||
showBackTop(nVal, oVal) { |
||||
// 当组件的显示与隐藏状态发生跳变时,修改组件的层级和不透明度 |
||||
// 让组件有显示和消失的动画效果,如果用v-if控制组件状态,将无设置动画效果 |
||||
if(nVal) { |
||||
this.uZIndex = this.zIndex; |
||||
this.opacity = 1; |
||||
} else { |
||||
this.uZIndex = -1; |
||||
this.opacity = 0; |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
showBackTop() { |
||||
// 由于scrollTop为页面的滚动距离,默认为px单位,这里将用于传入的top(rpx)值 |
||||
// 转为px用于比较,如果滚动条到顶的距离大于设定的距离,就显示返回顶部的按钮 |
||||
return this.scrollTop > uni.upx2px(this.top); |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
// 不透明度,为了让组件有一个显示和隐藏的过渡动画 |
||||
opacity: 0, |
||||
// 组件的z-index值,隐藏时设置为-1,就会看不到 |
||||
uZIndex: -1 |
||||
} |
||||
}, |
||||
methods: { |
||||
backToTop() { |
||||
uni.pageScrollTo({ |
||||
scrollTop: 0, |
||||
duration: this.duration |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
@import "../../libs/css/style.components.scss"; |
||||
|
||||
.u-back-top { |
||||
width: 80rpx; |
||||
height: 80rpx; |
||||
position: fixed; |
||||
z-index: 9; |
||||
@include vue-flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
background-color: #E1E1E1; |
||||
color: $u-content-color; |
||||
align-items: center; |
||||
transition: opacity 0.4s; |
||||
|
||||
&__content { |
||||
@include vue-flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
|
||||
&__tips { |
||||
font-size: 24rpx; |
||||
transform: scale(0.8); |
||||
line-height: 1; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,216 @@
|
||||
<template> |
||||
<view v-if="show" class="u-badge" :class="[ |
||||
isDot ? 'u-badge-dot' : '', |
||||
size == 'mini' ? 'u-badge-mini' : '', |
||||
type ? 'u-badge--bg--' + type : '' |
||||
]" :style="[{ |
||||
top: offset[0] + 'rpx', |
||||
right: offset[1] + 'rpx', |
||||
fontSize: fontSize + 'rpx', |
||||
position: absolute ? 'absolute' : 'static', |
||||
color: color, |
||||
backgroundColor: bgColor |
||||
}, boxStyle]" |
||||
> |
||||
{{showText}} |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
/** |
||||
* badge 角标 |
||||
* @description 本组件一般用于展示头像的地方,如个人中心,或者评论列表页的用户头像展示等场所。 |
||||
* @tutorial https://www.uviewui.com/components/badge.html |
||||
* @property {String Number} count 展示的数字,大于 overflowCount 时显示为 ${overflowCount}+,为0且show-zero为false时隐藏 |
||||
* @property {Boolean} is-dot 不展示数字,只有一个小点(默认false) |
||||
* @property {Boolean} absolute 组件是否绝对定位,为true时,offset参数才有效(默认true) |
||||
* @property {String Number} overflow-count 展示封顶的数字值(默认99) |
||||
* @property {String} type 使用预设的背景颜色(默认error) |
||||
* @property {Boolean} show-zero 当数值为 0 时,是否展示 Badge(默认false) |
||||
* @property {String} size Badge的尺寸,设为mini会得到小一号的Badge(默认default) |
||||
* @property {Array} offset 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,单位rpx。absolute为true时有效(默认[20, 20]) |
||||
* @property {String} color 字体颜色(默认#ffffff) |
||||
* @property {String} bgColor 背景颜色,优先级比type高,如设置,type参数会失效 |
||||
* @property {Boolean} is-center 组件中心点是否和父组件右上角重合,优先级比offset高,如设置,offset参数会失效(默认false) |
||||
* @example <u-badge type="error" count="7"></u-badge> |
||||
*/ |
||||
export default { |
||||
name: 'u-badge', |
||||
props: { |
||||
// primary,warning,success,error,info |
||||
type: { |
||||
type: String, |
||||
default: 'error' |
||||
}, |
||||
// default, mini |
||||
size: { |
||||
type: String, |
||||
default: 'default' |
||||
}, |
||||
//是否是圆点 |
||||
isDot: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 显示的数值内容 |
||||
count: { |
||||
type: [Number, String], |
||||
}, |
||||
// 展示封顶的数字值 |
||||
overflowCount: { |
||||
type: Number, |
||||
default: 99 |
||||
}, |
||||
// 当数值为 0 时,是否展示 Badge |
||||
showZero: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 位置偏移 |
||||
offset: { |
||||
type: Array, |
||||
default: () => { |
||||
return [20, 20] |
||||
} |
||||
}, |
||||
// 是否开启绝对定位,开启了offset才会起作用 |
||||
absolute: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 字体大小 |
||||
fontSize: { |
||||
type: [String, Number], |
||||
default: '24' |
||||
}, |
||||
// 字体演示 |
||||
color: { |
||||
type: String, |
||||
default: '#ffffff' |
||||
}, |
||||
// badge的背景颜色 |
||||
bgColor: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 是否让badge组件的中心点和父组件右上角重合,配置的话,offset将会失效 |
||||
isCenter: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
computed: { |
||||
// 是否将badge中心与父组件右上角重合 |
||||
boxStyle() { |
||||
let style = {}; |
||||
if(this.isCenter) { |
||||
style.top = 0; |
||||
style.right = 0; |
||||
// Y轴-50%,意味着badge向上移动了badge自身高度一半,X轴50%,意味着向右移动了自身宽度一半 |
||||
style.transform = "translateY(-50%) translateX(50%)"; |
||||
} else { |
||||
style.top = this.offset[0] + 'rpx'; |
||||
style.right = this.offset[1] + 'rpx'; |
||||
style.transform = "translateY(0) translateX(0)"; |
||||
} |
||||
// 如果尺寸为mini,后接上scal() |
||||
if(this.size == 'mini') { |
||||
style.transform = style.transform + " scale(0.8)"; |
||||
} |
||||
return style; |
||||
}, |
||||
// isDot类型时,不显示文字 |
||||
showText() { |
||||
if(this.isDot) return ''; |
||||
else { |
||||
if(this.count > this.overflowCount) return `${this.overflowCount}+`; |
||||
else return this.count; |
||||
} |
||||
}, |
||||
// 是否显示组件 |
||||
show() { |
||||
// 如果count的值为0,并且showZero设置为false,不显示组件 |
||||
if(this.count == 0 && this.showZero == false) return false; |
||||
else return true; |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
@import "../../libs/css/style.components.scss"; |
||||
|
||||
.u-badge { |
||||
/* #ifndef APP-NVUE */ |
||||
display: inline-flex; |
||||
/* #endif */ |
||||
justify-content: center; |
||||
align-items: center; |
||||
line-height: 24rpx; |
||||
padding: 4rpx 8rpx; |
||||
border-radius: 100rpx; |
||||
z-index: 9; |
||||
|
||||
&--bg--primary { |
||||
background-color: $u-type-primary; |
||||
} |
||||
|
||||
&--bg--error { |
||||
background-color: $u-type-error; |
||||
} |
||||
|
||||
&--bg--success { |
||||
background-color: $u-type-success; |
||||
} |
||||
|
||||
&--bg--info { |
||||
background-color: $u-type-info; |
||||
} |
||||
|
||||
&--bg--warning { |
||||
background-color: $u-type-warning; |
||||
} |
||||
} |
||||
|
||||
.u-badge-dot { |
||||
height: 16rpx; |
||||
width: 16rpx; |
||||
border-radius: 100rpx; |
||||
line-height: 1; |
||||
} |
||||
|
||||
.u-badge-mini { |
||||
transform: scale(0.8); |
||||
transform-origin: center center; |
||||
} |
||||
|
||||
// .u-primary { |
||||
// background: $u-type-primary; |
||||
// color: #fff; |
||||
// } |
||||
|
||||
// .u-error { |
||||
// background: $u-type-error; |
||||
// color: #fff; |
||||
// } |
||||
|
||||
// .u-warning { |
||||
// background: $u-type-warning; |
||||
// color: #fff; |
||||
// } |
||||
|
||||
// .u-success { |
||||
// background: $u-type-success; |
||||
// color: #fff; |
||||
// } |
||||
|
||||
// .u-black { |
||||
// background: #585858; |
||||
// color: #fff; |
||||
// } |
||||
|
||||
.u-info { |
||||
background-color: $u-type-info; |
||||
color: #fff; |
||||
} |
||||
</style> |
@ -0,0 +1,596 @@
|
||||
<template> |
||||
<button |
||||
id="u-wave-btn" |
||||
class="u-btn u-line-1 u-fix-ios-appearance" |
||||
:class="[ |
||||
'u-size-' + size, |
||||
plain ? 'u-btn--' + type + '--plain' : '', |
||||
loading ? 'u-loading' : '', |
||||
shape == 'circle' ? 'u-round-circle' : '', |
||||
hairLine ? showHairLineBorder : 'u-btn--bold-border', |
||||
'u-btn--' + type, |
||||
disabled ? `u-btn--${type}--disabled` : '', |
||||
]" |
||||
:hover-start-time="Number(hoverStartTime)" |
||||
:hover-stay-time="Number(hoverStayTime)" |
||||
:disabled="disabled" |
||||
:form-type="formType" |
||||
:open-type="openType" |
||||
:app-parameter="appParameter" |
||||
:hover-stop-propagation="hoverStopPropagation" |
||||
:send-message-title="sendMessageTitle" |
||||
send-message-path="sendMessagePath" |
||||
:lang="lang" |
||||
:data-name="dataName" |
||||
:session-from="sessionFrom" |
||||
:send-message-img="sendMessageImg" |
||||
:show-message-card="showMessageCard" |
||||
@getphonenumber="getphonenumber" |
||||
@getuserinfo="getuserinfo" |
||||
@error="error" |
||||
@opensetting="opensetting" |
||||
@launchapp="launchapp" |
||||
:style="[customStyle, { |
||||
overflow: ripple ? 'hidden' : 'visible' |
||||
}]" |
||||
@tap.stop="click($event)" |
||||
:hover-class="getHoverClass" |
||||
:loading="loading" |
||||
> |
||||
<slot></slot> |
||||
<view |
||||
v-if="ripple" |
||||
class="u-wave-ripple" |
||||
:class="[waveActive ? 'u-wave-active' : '']" |
||||
:style="{ |
||||
top: rippleTop + 'px', |
||||
left: rippleLeft + 'px', |
||||
width: fields.targetWidth + 'px', |
||||
height: fields.targetWidth + 'px', |
||||
'background-color': rippleBgColor || 'rgba(0, 0, 0, 0.15)' |
||||
}" |
||||
></view> |
||||
</button> |
||||
</template> |
||||
|
||||
<script> |
||||
/** |
||||
* button 按钮 |
||||
* @description Button 按钮 |
||||
* @tutorial https://www.uviewui.com/components/button.html |
||||
* @property {String} size 按钮的大小 |
||||
* @property {Boolean} ripple 是否开启点击水波纹效果 |
||||
* @property {String} ripple-bg-color 水波纹的背景色,ripple为true时有效 |
||||
* @property {String} type 按钮的样式类型 |
||||
* @property {Boolean} plain 按钮是否镂空,背景色透明 |
||||
* @property {Boolean} disabled 是否禁用 |
||||
* @property {Boolean} hair-line 是否显示按钮的细边框(默认true) |
||||
* @property {Boolean} shape 按钮外观形状,见文档说明 |
||||
* @property {Boolean} loading 按钮名称前是否带 loading 图标(App-nvue 平台,在 ios 上为雪花,Android上为圆圈) |
||||
* @property {String} form-type 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件 |
||||
* @property {String} open-type 开放能力 |
||||
* @property {String} data-name 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取 |
||||
* @property {String} hover-class 指定按钮按下去的样式类。当 hover-class="none" 时,没有点击态效果(App-nvue 平台暂不支持) |
||||
* @property {Number} hover-start-time 按住后多久出现点击态,单位毫秒 |
||||
* @property {Number} hover-stay-time 手指松开后点击态保留时间,单位毫秒 |
||||
* @property {Object} custom-style 对按钮的自定义样式,对象形式,见文档说明 |
||||
* @event {Function} click 按钮点击 |
||||
* @event {Function} getphonenumber open-type="getPhoneNumber"时有效 |
||||
* @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,从返回参数的detail中获取到的值同uni.getUserInfo |
||||
* @event {Function} error 当使用开放能力时,发生错误的回调 |
||||
* @event {Function} opensetting 在打开授权设置页并关闭后回调 |
||||
* @event {Function} launchapp 打开 APP 成功的回调 |
||||
* @example <u-button>月落</u-button> |
||||
*/ |
||||
export default { |
||||
name: 'u-button', |
||||
props: { |
||||
// 是否细边框 |
||||
hairLine: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 按钮的预置样式,default,primary,error,warning,success |
||||
type: { |
||||
type: String, |
||||
default: 'default' |
||||
}, |
||||
// 按钮尺寸,default,medium,mini |
||||
size: { |
||||
type: String, |
||||
default: 'default' |
||||
}, |
||||
// 按钮形状,circle(两边为半圆),square(带圆角) |
||||
shape: { |
||||
type: String, |
||||
default: 'square' |
||||
}, |
||||
// 按钮是否镂空 |
||||
plain: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 是否禁止状态 |
||||
disabled: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 是否加载中 |
||||
loading: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 开放能力,具体请看uniapp稳定关于button组件部分说明 |
||||
// https://uniapp.dcloud.io/component/button |
||||
openType: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件 |
||||
// 取值为submit(提交表单),reset(重置表单) |
||||
formType: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 |
||||
// 只微信小程序、QQ小程序有效 |
||||
appParameter: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效 |
||||
hoverStopPropagation: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效 |
||||
lang: { |
||||
type: String, |
||||
default: 'en' |
||||
}, |
||||
// 会话来源,open-type="contact"时有效。只微信小程序有效 |
||||
sessionFrom: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 会话内消息卡片标题,open-type="contact"时有效 |
||||
// 默认当前标题,只微信小程序有效 |
||||
sendMessageTitle: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效 |
||||
// 默认当前分享路径,只微信小程序有效 |
||||
sendMessagePath: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 会话内消息卡片图片,open-type="contact"时有效 |
||||
// 默认当前页面截图,只微信小程序有效 |
||||
sendMessageImg: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示, |
||||
// 用户点击后可以快速发送小程序消息,open-type="contact"时有效 |
||||
showMessageCard: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 手指按(触摸)按钮时按钮时的背景颜色 |
||||
hoverBgColor: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 水波纹的背景颜色 |
||||
rippleBgColor: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 是否开启水波纹效果 |
||||
ripple: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 按下的类名 |
||||
hoverClass: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 自定义样式,对象形式 |
||||
customStyle: { |
||||
type: Object, |
||||
default() { |
||||
return {}; |
||||
} |
||||
}, |
||||
// 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取 |
||||
dataName: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 节流,一定时间内只能触发一次 |
||||
throttleTime: { |
||||
type: [String, Number], |
||||
default: 1000 |
||||
}, |
||||
// 按住后多久出现点击态,单位毫秒 |
||||
hoverStartTime: { |
||||
type: [String, Number], |
||||
default: 20 |
||||
}, |
||||
// 手指松开后点击态保留时间,单位毫秒 |
||||
hoverStayTime: { |
||||
type: [String, Number], |
||||
default: 150 |
||||
}, |
||||
}, |
||||
computed: { |
||||
// 当没有传bgColor变量时,按钮按下去的颜色类名 |
||||
getHoverClass() { |
||||
// 如果开启水波纹效果,则不启用hover-class效果 |
||||
if (this.loading || this.disabled || this.ripple || this.hoverClass) return ''; |
||||
let hoverClass = ''; |
||||
hoverClass = this.plain ? 'u-' + this.type + '-plain-hover' : 'u-' + this.type + '-hover'; |
||||
return hoverClass; |
||||
}, |
||||
// 在'primary', 'success', 'error', 'warning'类型下,不显示边框,否则会造成四角有毛刺现象 |
||||
showHairLineBorder() { |
||||
if (['primary', 'success', 'error', 'warning'].indexOf(this.type) >= 0 && !this.plain) { |
||||
return ''; |
||||
} else { |
||||
return 'u-hairline-border'; |
||||
} |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
rippleTop: 0, // 水波纹的起点Y坐标到按钮上边界的距离 |
||||
rippleLeft: 0, // 水波纹起点X坐标到按钮左边界的距离 |
||||
fields: {}, // 波纹按钮节点信息 |
||||
waveActive: false // 激活水波纹 |
||||
}; |
||||
}, |
||||
methods: { |
||||
// 按钮点击 |
||||
click(e) { |
||||
// 进行节流控制,每this.throttle毫秒内,只在开始处执行 |
||||
this.$u.throttle(() => { |
||||
// 如果按钮时disabled和loading状态,不触发水波纹效果 |
||||
if (this.loading === true || this.disabled === true) return; |
||||
// 是否开启水波纹效果 |
||||
if (this.ripple) { |
||||
// 每次点击时,移除上一次的类,再次添加,才能触发动画效果 |
||||
this.waveActive = false; |
||||
this.$nextTick(function() { |
||||
this.getWaveQuery(e); |
||||
}); |
||||
} |
||||
this.$emit('click', e); |
||||
}, this.throttleTime); |
||||
}, |
||||
// 查询按钮的节点信息 |
||||
getWaveQuery(e) { |
||||
this.getElQuery().then(res => { |
||||
// 查询返回的是一个数组节点 |
||||
let data = res[0]; |
||||
// 查询不到节点信息,不操作 |
||||
if (!data.width || !data.width) return; |
||||
// 水波纹的最终形态是一个正方形(通过border-radius让其变为一个圆形),这里要保证正方形的边长等于按钮的最长边 |
||||
// 最终的方形(变换后的圆形)才能覆盖整个按钮 |
||||
data.targetWidth = data.height > data.width ? data.height : data.width; |
||||
if (!data.targetWidth) return; |
||||
this.fields = data; |
||||
let touchesX = '', |
||||
touchesY = ''; |
||||
// #ifdef MP-BAIDU |
||||
touchesX = e.changedTouches[0].clientX; |
||||
touchesY = e.changedTouches[0].clientY; |
||||
// #endif |
||||
// #ifdef MP-ALIPAY |
||||
touchesX = e.detail.clientX; |
||||
touchesY = e.detail.clientY; |
||||
// #endif |
||||
// #ifndef MP-BAIDU || MP-ALIPAY |
||||
touchesX = e.touches[0].clientX; |
||||
touchesY = e.touches[0].clientY; |
||||
// #endif |
||||
// 获取触摸点相对于按钮上边和左边的x和y坐标,原理是通过屏幕的触摸点(touchesY),减去按钮的上边界data.top |
||||
// 但是由于`transform-origin`默认是center,所以这里再减去半径才是水波纹view应该的位置 |
||||
// 总的来说,就是把水波纹的矩形(变换后的圆形)的中心点,移动到我们的触摸点位置 |
||||
this.rippleTop = touchesY - data.top - data.targetWidth / 2; |
||||
this.rippleLeft = touchesX - data.left - data.targetWidth / 2; |
||||
this.$nextTick(() => { |
||||
this.waveActive = true; |
||||
}); |
||||
}); |
||||
}, |
||||
// 获取节点信息 |
||||
getElQuery() { |
||||
return new Promise(resolve => { |
||||
let queryInfo = ''; |
||||
// 获取元素节点信息,请查看uniapp相关文档 |
||||
// https://uniapp.dcloud.io/api/ui/nodes-info?id=nodesrefboundingclientrect |
||||
queryInfo = uni.createSelectorQuery().in(this); |
||||
//#ifdef MP-ALIPAY |
||||
queryInfo = uni.createSelectorQuery(); |
||||
//#endif |
||||
queryInfo.select('.u-btn').boundingClientRect(); |
||||
queryInfo.exec(data => { |
||||
resolve(data); |
||||
}); |
||||
}); |
||||
}, |
||||
// 下面为对接uniapp官方按钮开放能力事件回调的对接 |
||||
getphonenumber(res) { |
||||
this.$emit('getphonenumber', res); |
||||
}, |
||||
getuserinfo(res) { |
||||
this.$emit('getuserinfo', res); |
||||
}, |
||||
error(res) { |
||||
this.$emit('error', res); |
||||
}, |
||||
opensetting(res) { |
||||
this.$emit('opensetting', res); |
||||
}, |
||||
launchapp(res) { |
||||
this.$emit('launchapp', res); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
@import '../../libs/css/style.components.scss'; |
||||
.u-btn::after { |
||||
border: none; |
||||
} |
||||
|
||||
.u-btn { |
||||
position: relative; |
||||
border: 0; |
||||
//border-radius: 10rpx; |
||||
/* #ifndef APP-NVUE */ |
||||
display: inline-flex; |
||||
/* #endif */ |
||||
// 避免边框某些场景可能被“裁剪”,不能设置为hidden |
||||
overflow: visible; |
||||
line-height: 1; |
||||
@include vue-flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
cursor: pointer; |
||||
padding: 0 40rpx; |
||||
z-index: 1; |
||||
box-sizing: border-box; |
||||
transition: all 0.15s; |
||||
|
||||
&--bold-border { |
||||
border: 1px solid #ffffff; |
||||
} |
||||
|
||||
&--default { |
||||
color: $u-content-color; |
||||
border-color: #c0c4cc; |
||||
background-color: #ffffff; |
||||
} |
||||
|
||||
&--primary { |
||||
color: #ffffff; |
||||
border-color: $u-type-primary; |
||||
background-color: $u-type-primary; |
||||
} |
||||
|
||||
&--success { |
||||
color: #ffffff; |
||||
border-color: $u-type-success; |
||||
background-color: $u-type-success; |
||||
} |
||||
|
||||
&--error { |
||||
color: #ffffff; |
||||
border-color: $u-type-error; |
||||
background-color: $u-type-error; |
||||
} |
||||
|
||||
&--warning { |
||||
color: #ffffff; |
||||
border-color: $u-type-warning; |
||||
background-color: $u-type-warning; |
||||
} |
||||
|
||||
&--default--disabled { |
||||
color: #ffffff; |
||||
border-color: #e4e7ed; |
||||
background-color: #ffffff; |
||||
} |
||||
|
||||
&--primary--disabled { |
||||
color: #ffffff!important; |
||||
border-color: $u-type-primary-disabled!important; |
||||
background-color: $u-type-primary-disabled!important; |
||||
} |
||||
|
||||
&--success--disabled { |
||||
color: #ffffff!important; |
||||
border-color: $u-type-success-disabled!important; |
||||
background-color: $u-type-success-disabled!important; |
||||
} |
||||
|
||||
&--error--disabled { |
||||
color: #ffffff!important; |
||||
border-color: $u-type-error-disabled!important; |
||||
background-color: $u-type-error-disabled!important; |
||||
} |
||||
|
||||
&--warning--disabled { |
||||
color: #ffffff!important; |
||||
border-color: $u-type-warning-disabled!important; |
||||
background-color: $u-type-warning-disabled!important; |
||||
} |
||||
|
||||
&--primary--plain { |
||||
color: $u-type-primary!important; |
||||
border-color: $u-type-primary-disabled!important; |
||||
background-color: $u-type-primary-light!important; |
||||
} |
||||
|
||||
&--success--plain { |
||||
color: $u-type-success!important; |
||||
border-color: $u-type-success-disabled!important; |
||||
background-color: $u-type-success-light!important; |
||||
} |
||||
|
||||
&--error--plain { |
||||
color: $u-type-error!important; |
||||
border-color: $u-type-error-disabled!important; |
||||
background-color: $u-type-error-light!important; |
||||
} |
||||
|
||||
&--warning--plain { |
||||
color: $u-type-warning!important; |
||||
border-color: $u-type-warning-disabled!important; |
||||
background-color: $u-type-warning-light!important; |
||||
} |
||||
} |
||||
|
||||
.u-hairline-border:after { |
||||
content: ' '; |
||||
position: absolute; |
||||
pointer-events: none; |
||||
// 设置为border-box,意味着下面的scale缩小为0.5,实际上缩小的是伪元素的内容(border-box意味着内容不含border) |
||||
box-sizing: border-box; |
||||
// 中心点作为变形(scale())的原点 |
||||
-webkit-transform-origin: 0 0; |
||||
transform-origin: 0 0; |
||||
left: 0; |
||||
top: 0; |
||||
width: 199.8%; |
||||
height: 199.7%; |
||||
-webkit-transform: scale(0.5, 0.5); |
||||
transform: scale(0.5, 0.5); |
||||
border: 1px solid currentColor; |
||||
z-index: 1; |
||||
} |
||||
|
||||
.u-wave-ripple { |
||||
z-index: 0; |
||||
position: absolute; |
||||
border-radius: 100%; |
||||
background-clip: padding-box; |
||||
pointer-events: none; |
||||
user-select: none; |
||||
transform: scale(0); |
||||
opacity: 1; |
||||
transform-origin: center; |
||||
} |
||||
|
||||
.u-wave-ripple.u-wave-active { |
||||
opacity: 0; |
||||
transform: scale(2); |
||||
transition: opacity 1s linear, transform 0.4s linear; |
||||
} |
||||
|
||||
.u-round-circle { |
||||
border-radius: 100rpx; |
||||
} |
||||
|
||||
.u-round-circle::after { |
||||
border-radius: 100rpx; |
||||
} |
||||
|
||||
.u-loading::after { |
||||
background-color: hsla(0, 0%, 100%, 0.35); |
||||
} |
||||
|
||||
.u-size-default { |
||||
font-size: 30rpx; |
||||
height: 80rpx; |
||||
line-height: 80rpx; |
||||
} |
||||
|
||||
.u-size-medium { |
||||
/* #ifndef APP-NVUE */ |
||||
display: inline-flex; |
||||
/* #endif */ |
||||
width: auto; |
||||
font-size: 26rpx; |
||||
height: 70rpx; |
||||
line-height: 70rpx; |
||||
padding: 0 80rpx; |
||||
} |
||||
|
||||
.u-size-mini { |
||||
/* #ifndef APP-NVUE */ |
||||
display: inline-flex; |
||||
/* #endif */ |
||||
width: auto; |
||||
font-size: 22rpx; |
||||
padding-top: 1px; |
||||
height: 50rpx; |
||||
line-height: 50rpx; |
||||
padding: 0 20rpx; |
||||
} |
||||
|
||||
.u-primary-plain-hover { |
||||
color: #ffffff !important; |
||||
background: $u-type-primary-dark !important; |
||||
} |
||||
|
||||
.u-default-plain-hover { |
||||
color: $u-type-primary-dark !important; |
||||
background: $u-type-primary-light !important; |
||||
} |
||||
|
||||
.u-success-plain-hover { |
||||
color: #ffffff !important; |
||||
background: $u-type-success-dark !important; |
||||
} |
||||
|
||||
.u-warning-plain-hover { |
||||
color: #ffffff !important; |
||||
background: $u-type-warning-dark !important; |
||||
} |
||||
|
||||
.u-error-plain-hover { |
||||
color: #ffffff !important; |
||||
background: $u-type-error-dark !important; |
||||
} |
||||
|
||||
.u-info-plain-hover { |
||||
color: #ffffff !important; |
||||
background: $u-type-info-dark !important; |
||||
} |
||||
|
||||
.u-default-hover { |
||||
color: $u-type-primary-dark !important; |
||||
border-color: $u-type-primary-dark !important; |
||||
background-color: $u-type-primary-light !important; |
||||
} |
||||
|
||||
.u-primary-hover { |
||||
background: $u-type-primary-dark !important; |
||||
color: #fff; |
||||
} |
||||
|
||||
.u-success-hover { |
||||
background: $u-type-success-dark !important; |
||||
color: #fff; |
||||
} |
||||
|
||||
.u-info-hover { |
||||
background: $u-type-info-dark !important; |
||||
color: #fff; |
||||
} |
||||
|
||||
.u-warning-hover { |
||||
background: $u-type-warning-dark !important; |
||||
color: #fff; |
||||
} |
||||
|
||||
.u-error-hover { |
||||
background: $u-type-error-dark !important; |
||||
color: #fff; |
||||
} |
||||
</style> |
@ -0,0 +1,639 @@
|
||||
<template> |
||||
<u-popup closeable :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto" |
||||
:safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex" :border-radius="borderRadius" :closeable="closeable"> |
||||
<view class="u-calendar"> |
||||
<view class="u-calendar__header"> |
||||
<view class="u-calendar__header__text" v-if="!$slots['tooltip']"> |
||||
{{toolTip}} |
||||
</view> |
||||
<slot v-else name="tooltip" /> |
||||
</view> |
||||
<view class="u-calendar__action u-flex u-row-center"> |
||||
<view class="u-calendar__action__icon"> |
||||
<u-icon v-if="changeYear" name="arrow-left-double" :color="yearArrowColor" @click="changeYearHandler(0)"></u-icon> |
||||
</view> |
||||
<view class="u-calendar__action__icon"> |
||||
<u-icon v-if="changeMonth" name="arrow-left" :color="monthArrowColor" @click="changeMonthHandler(0)"></u-icon> |
||||
</view> |
||||
<view class="u-calendar__action__text">{{ showTitle }}</view> |
||||
<view class="u-calendar__action__icon"> |
||||
<u-icon v-if="changeMonth" name="arrow-right" :color="monthArrowColor" @click="changeMonthHandler(1)"></u-icon> |
||||
</view> |
||||
<view class="u-calendar__action__icon"> |
||||
<u-icon v-if="changeYear" name="arrow-right-double" :color="yearArrowColor" @click="changeYearHandler(1)"></u-icon> |
||||
</view> |
||||
</view> |
||||
<view class="u-calendar__week-day"> |
||||
<view class="u-calendar__week-day__text" v-for="(item, index) in weekDayZh" :key="index">{{item}}</view> |
||||
</view> |
||||
<view class="u-calendar__content"> |
||||
<!-- 前置空白部分 --> |
||||
<block v-for="(item, index) in weekdayArr" :key="index"> |
||||
<view class="u-calendar__content__item"></view> |
||||
</block> |
||||
<view class="u-calendar__content__item" :class="{ |
||||
'u-hover-class':openDisAbled(year,month,index+1), |
||||
'u-calendar__content--start-date': (mode == 'range' && startDate==`${year}-${month}-${index+1}`) || mode== 'date', |
||||
'u-calendar__content--end-date':(mode== 'range' && endDate==`${year}-${month}-${index+1}`) || mode == 'date' |
||||
}" :style="{backgroundColor: getColor(index,1)}" v-for="(item, index) in daysArr" :key="index" |
||||
@tap="dateClick(index)"> |
||||
<view class="u-calendar__content__item__inner" :style="{color: getColor(index,2)}"> |
||||
<view>{{ index + 1 }}</view> |
||||
</view> |
||||
<view class="u-calendar__content__item__tips" :style="{color:activeColor}" v-if="mode== 'range' && startDate==`${year}-${month}-${index+1}` && startDate!=endDate">{{startText}}</view> |
||||
<view class="u-calendar__content__item__tips" :style="{color:activeColor}" v-if="mode== 'range' && endDate==`${year}-${month}-${index+1}`">{{endText}}</view> |
||||
</view> |
||||
<view class="u-calendar__content__bg-month">{{month}}</view> |
||||
</view> |
||||
<view class="u-calendar__bottom"> |
||||
<view class="u-calendar__bottom__choose"> |
||||
<text>{{mode == 'date' ? activeDate : startDate}}</text> |
||||
<text v-if="endDate">至{{endDate}}</text> |
||||
</view> |
||||
<view class="u-calendar__bottom__btn"> |
||||
<u-button :type="btnType" shape="circle" size="default" @click="btnFix(false)">确定</u-button> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</u-popup> |
||||
</template> |
||||
<script> |
||||
/** |
||||
* calendar 日历 |
||||
* @description 此组件用于单个选择日期,范围选择日期等,日历被包裹在底部弹起的容器中。 |
||||
* @tutorial http://uviewui.com/components/calendar.html |
||||
* @property {String} mode 选择日期的模式,date-为单个日期,range-为选择日期范围 |
||||
* @property {Boolean} v-model 布尔值变量,用于控制日历的弹出与收起 |
||||
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false) |
||||
* @property {Boolean} change-year 是否显示顶部的切换年份方向的按钮(默认true) |
||||
* @property {Boolean} change-month 是否显示顶部的切换月份方向的按钮(默认true) |
||||
* @property {String Number} max-year 可切换的最大年份(默认2050) |
||||
* @property {String Number} min-year 可切换的最小年份(默认1950) |
||||
* @property {String Number} min-date 最小可选日期(默认1950-01-01) |
||||
* @property {String Number} max-date 最大可选日期(默认当前日期) |
||||
* @property {String Number} 弹窗顶部左右两边的圆角值,单位rpx(默认20) |
||||
* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭日历(默认true) |
||||
* @property {String} month-arrow-color 月份切换按钮箭头颜色(默认#606266) |
||||
* @property {String} year-arrow-color 年份切换按钮箭头颜色(默认#909399) |
||||
* @property {String} color 日期字体的默认颜色(默认#303133) |
||||
* @property {String} active-bg-color 起始/结束日期按钮的背景色(默认#2979ff) |
||||
* @property {String Number} z-index 弹出时的z-index值(默认10075) |
||||
* @property {String} active-color 起始/结束日期按钮的字体颜色(默认#ffffff) |
||||
* @property {String} range-bg-color 起始/结束日期之间的区域的背景颜色(默认rgba(41,121,255,0.13)) |
||||
* @property {String} range-color 选择范围内字体颜色(默认#2979ff) |
||||
* @property {String} start-text 起始日期底部的提示文字(默认 '开始') |
||||
* @property {String} end-text 结束日期底部的提示文字(默认 '结束') |
||||
* @property {String} btn-type 底部确定按钮的主题(默认 'primary') |
||||
* @property {String} toolTip 顶部提示文字,如设置名为tooltip的slot,此参数将失效(默认 '选择日期') |
||||
* @property {Boolean} closeable 是否显示右上角的关闭图标(默认true) |
||||
* @example <u-calendar v-model="show" :mode="mode"></u-calendar> |
||||
*/ |
||||
|
||||
export default { |
||||
name: 'u-calendar', |
||||
props: { |
||||
safeAreaInsetBottom: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 是否允许通过点击遮罩关闭Picker |
||||
maskCloseAble: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 通过双向绑定控制组件的弹出与收起 |
||||
value: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 弹出的z-index值 |
||||
zIndex: { |
||||
type: [String, Number], |
||||
default: 0 |
||||
}, |
||||
// 是否允许切换年份 |
||||
changeYear: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 是否允许切换月份 |
||||
changeMonth: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// date-单个日期选择,range-开始日期+结束日期选择 |
||||
mode: { |
||||
type: String, |
||||
default: 'date' |
||||
}, |
||||
// 可切换的最大年份 |
||||
maxYear: { |
||||
type: [Number, String], |
||||
default: 2050 |
||||
}, |
||||
// 可切换的最小年份 |
||||
minYear: { |
||||
type: [Number, String], |
||||
default: 1950 |
||||
}, |
||||
// 最小可选日期(不在范围内日期禁用不可选) |
||||
minDate: { |
||||
type: [Number, String], |
||||
default: '1950-01-01' |
||||
}, |
||||
/** |
||||
* 最大可选日期 |
||||
* 默认最大值为今天,之后的日期不可选 |
||||
* 2030-12-31 |
||||
* */ |
||||
maxDate: { |
||||
type: [Number, String], |
||||
default: '' |
||||
}, |
||||
// 弹窗顶部左右两边的圆角值 |
||||
borderRadius: { |
||||
type: [String, Number], |
||||
default: 20 |
||||
}, |
||||
// 月份切换按钮箭头颜色 |
||||
monthArrowColor: { |
||||
type: String, |
||||
default: '#606266' |
||||
}, |
||||
// 年份切换按钮箭头颜色 |
||||
yearArrowColor: { |
||||
type: String, |
||||
default: '#909399' |
||||
}, |
||||
// 默认日期字体颜色 |
||||
color: { |
||||
type: String, |
||||
default: '#303133' |
||||
}, |
||||
// 选中|起始结束日期背景色 |
||||
activeBgColor: { |
||||
type: String, |
||||
default: '#2979ff' |
||||
}, |
||||
// 选中|起始结束日期字体颜色 |
||||
activeColor: { |
||||
type: String, |
||||
default: '#ffffff' |
||||
}, |
||||
// 范围内日期背景色 |
||||
rangeBgColor: { |
||||
type: String, |
||||
default: 'rgba(41,121,255,0.13)' |
||||
}, |
||||
// 范围内日期字体颜色 |
||||
rangeColor: { |
||||
type: String, |
||||
default: '#2979ff' |
||||
}, |
||||
// mode=range时生效,起始日期自定义文案 |
||||
startText: { |
||||
type: String, |
||||
default: '开始' |
||||
}, |
||||
// mode=range时生效,结束日期自定义文案 |
||||
endText: { |
||||
type: String, |
||||
default: '结束' |
||||
}, |
||||
//按钮样式类型 |
||||
btnType: { |
||||
type: String, |
||||
default: 'primary' |
||||
}, |
||||
// 当前选中日期带选中效果 |
||||
isActiveCurrent: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 切换年月是否触发事件 mode=date时生效 |
||||
isChange: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 是否显示右上角的关闭图标 |
||||
closeable: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 顶部的提示文字 |
||||
toolTip: { |
||||
type: String, |
||||
default: '选择日期' |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
// 星期几,值为1-7 |
||||
weekday: 1, |
||||
weekdayArr:[], |
||||
// 当前月有多少天 |
||||
days: 0, |
||||
daysArr:[], |
||||
showTitle: '', |
||||
year: 2020, |
||||
month: 0, |
||||
day: 0, |
||||
startYear: 0, |
||||
startMonth: 0, |
||||
startDay: 0, |
||||
endYear: 0, |
||||
endMonth: 0, |
||||
endDay: 0, |
||||
today: '', |
||||
activeDate: '', |
||||
startDate: '', |
||||
endDate: '', |
||||
isStart: true, |
||||
min: null, |
||||
max: null, |
||||
weekDayZh: ['日', '一', '二', '三', '四', '五', '六'] |
||||
}; |
||||
}, |
||||
computed: { |
||||
dataChange() { |
||||
return `${this.mode}-${this.minDate}-${this.maxDate}`; |
||||
}, |
||||
uZIndex() { |
||||
// 如果用户有传递z-index值,优先使用 |
||||
return this.zIndex ? this.zIndex : this.$u.zIndex.popup; |
||||
} |
||||
}, |
||||
watch: { |
||||
dataChange(val) { |
||||
this.init() |
||||
} |
||||
}, |
||||
created() { |
||||
this.init() |
||||
}, |
||||
methods: { |
||||
getColor(index, type) { |
||||
let color = type == 1 ? '' : this.color; |
||||
let day = index + 1 |
||||
let date = `${this.year}-${this.month}-${day}` |
||||
let timestamp = new Date(date.replace(/\-/g, '/')).getTime(); |
||||
let start = this.startDate.replace(/\-/g, '/') |
||||
let end = this.endDate.replace(/\-/g, '/') |
||||
if ((this.isActiveCurrent && this.activeDate == date) || this.startDate == date || this.endDate == date) { |
||||
color = type == 1 ? this.activeBgColor : this.activeColor; |
||||
} else if (this.endDate && timestamp > new Date(start).getTime() && timestamp < new Date(end).getTime()) { |
||||
color = type == 1 ? this.rangeBgColor : this.rangeColor; |
||||
} |
||||
return color; |
||||
}, |
||||
init() { |
||||
let now = new Date(); |
||||
this.year = now.getFullYear(); |
||||
this.month = now.getMonth() + 1; |
||||
this.day = now.getDate(); |
||||
this.today = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`; |
||||
this.activeDate = this.today; |
||||
this.min = this.initDate(this.minDate); |
||||
this.max = this.initDate(this.maxDate || this.today); |
||||
this.startDate = ""; |
||||
this.startYear = 0; |
||||
this.startMonth = 0; |
||||
this.startDay = 0; |
||||
this.endYear = 0; |
||||
this.endMonth = 0; |
||||
this.endDay = 0; |
||||
this.endDate = ""; |
||||
this.isStart = true; |
||||
this.changeData(); |
||||
}, |
||||
//日期处理 |
||||
initDate(date) { |
||||
let fdate = date.split('-'); |
||||
return { |
||||
year: Number(fdate[0] || 1920), |
||||
month: Number(fdate[1] || 1), |
||||
day: Number(fdate[2] || 1) |
||||
} |
||||
}, |
||||
openDisAbled: function(year, month, day) { |
||||
let bool = true; |
||||
let date = `${year}/${month}/${day}`; |
||||
// let today = this.today.replace(/\-/g, '/'); |
||||
let min = `${this.min.year}/${this.min.month}/${this.min.day}`; |
||||
let max = `${this.max.year}/${this.max.month}/${this.max.day}`; |
||||
let timestamp = new Date(date).getTime(); |
||||
if (timestamp >= new Date(min).getTime() && timestamp <= new Date(max).getTime()) { |
||||
bool = false; |
||||
} |
||||
return bool; |
||||
}, |
||||
generateArray: function(start, end) { |
||||
return Array.from(new Array(end + 1).keys()).slice(start); |
||||
}, |
||||
formatNum: function(num) { |
||||
return num < 10 ? '0' + num : num + ''; |
||||
}, |
||||
//一个月有多少天 |
||||
getMonthDay(year, month) { |
||||
let days = new Date(year, month, 0).getDate(); |
||||
return days; |
||||
}, |
||||
getWeekday(year, month) { |
||||
let date = new Date(`${year}/${month}/01 00:00:00`); |
||||
return date.getDay(); |
||||
}, |
||||
checkRange(year) { |
||||
let overstep = false; |
||||
if (year < this.minYear || year > this.maxYear) { |
||||
uni.showToast({ |
||||
title: "日期超出范围啦~", |
||||
icon: 'none' |
||||
}) |
||||
overstep = true; |
||||
} |
||||
return overstep; |
||||
}, |
||||
changeMonthHandler(isAdd) { |
||||
if (isAdd) { |
||||
let month = this.month + 1; |
||||
let year = month > 12 ? this.year + 1 : this.year; |
||||
if (!this.checkRange(year)) { |
||||
this.month = month > 12 ? 1 : month; |
||||
this.year = year; |
||||
this.changeData(); |
||||
} |
||||
|
||||
} else { |
||||
let month = this.month - 1; |
||||
let year = month < 1 ? this.year - 1 : this.year; |
||||
if (!this.checkRange(year)) { |
||||
this.month = month < 1 ? 12 : month; |
||||
this.year = year; |
||||
this.changeData(); |
||||
} |
||||
} |
||||
}, |
||||
changeYearHandler(isAdd) { |
||||
let year = isAdd ? this.year + 1 : this.year - 1; |
||||
if (!this.checkRange(year)) { |
||||
this.year = year; |
||||
this.changeData(); |
||||
} |
||||
}, |
||||
changeData() { |
||||
this.days = this.getMonthDay(this.year, this.month); |
||||
this.daysArr=this.generateArray(1,this.days) |
||||
this.weekday = this.getWeekday(this.year, this.month); |
||||
this.weekdayArr=this.generateArray(1,this.weekday) |
||||
this.showTitle = `${this.year}年${this.month}月`; |
||||
if (this.isChange && this.mode == 'date') { |
||||
this.btnFix(true); |
||||
} |
||||
}, |
||||
dateClick: function(day) { |
||||
day += 1; |
||||
if (!this.openDisAbled(this.year, this.month, day)) { |
||||
this.day = day; |
||||
let date = `${this.year}-${this.month}-${day}`; |
||||
if (this.mode == 'date') { |
||||
this.activeDate = date; |
||||
} else { |
||||
let compare = new Date(date.replace(/\-/g, '/')).getTime() < new Date(this.startDate.replace(/\-/g, '/')).getTime() |
||||
if (this.isStart || compare) { |
||||
this.startDate = date; |
||||
this.startYear = this.year; |
||||
this.startMonth = this.month; |
||||
this.startDay = this.day; |
||||
this.endYear = 0; |
||||
this.endMonth = 0; |
||||
this.endDay = 0; |
||||
this.endDate = ""; |
||||
this.activeDate = ""; |
||||
this.isStart = false; |
||||
} else { |
||||
this.endDate = date; |
||||
this.endYear = this.year; |
||||
this.endMonth = this.month; |
||||
this.endDay = this.day; |
||||
this.isStart = true; |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
close() { |
||||
// 修改通过v-model绑定的父组件变量的值为false,从而隐藏日历弹窗 |
||||
this.$emit('input', false); |
||||
}, |
||||
getWeekText(date) { |
||||
date = new Date(`${date.replace(/\-/g, '/')} 00:00:00`); |
||||
let week = date.getDay(); |
||||
return '星期' + ['日', '一', '二', '三', '四', '五', '六'][week]; |
||||
}, |
||||
btnFix(show) { |
||||
if (!show) { |
||||
this.close(); |
||||
} |
||||
if (this.mode == 'date') { |
||||
let arr = this.activeDate.split('-') |
||||
let year = this.isChange ? this.year : Number(arr[0]); |
||||
let month = this.isChange ? this.month : Number(arr[1]); |
||||
let day = this.isChange ? this.day : Number(arr[2]); |
||||
//当前月有多少天 |
||||
let days = this.getMonthDay(year, month); |
||||
let result = `${year}-${this.formatNum(month)}-${this.formatNum(day)}`; |
||||
let weekText = this.getWeekText(result); |
||||
let isToday = false; |
||||
if (`${year}-${month}-${day}` == this.today) { |
||||
//今天 |
||||
isToday = true; |
||||
} |
||||
this.$emit('change', { |
||||
year: year, |
||||
month: month, |
||||
day: day, |
||||
days: days, |
||||
result: result, |
||||
week: weekText, |
||||
isToday: isToday, |
||||
// switch: show //是否是切换年月操作 |
||||
}); |
||||
} else { |
||||
if (!this.startDate || !this.endDate) return; |
||||
let startMonth = this.formatNum(this.startMonth); |
||||
let startDay = this.formatNum(this.startDay); |
||||
let startDate = `${this.startYear}-${startMonth}-${startDay}`; |
||||
let startWeek = this.getWeekText(startDate) |
||||
|
||||
let endMonth = this.formatNum(this.endMonth); |
||||
let endDay = this.formatNum(this.endDay); |
||||
let endDate = `${this.endYear}-${endMonth}-${endDay}`; |
||||
let endWeek = this.getWeekText(endDate); |
||||
this.$emit('change', { |
||||
startYear: this.startYear, |
||||
startMonth: this.startMonth, |
||||
startDay: this.startDay, |
||||
startDate: startDate, |
||||
startWeek: startWeek, |
||||
endYear: this.endYear, |
||||
endMonth: this.endMonth, |
||||
endDay: this.endDay, |
||||
endDate: endDate, |
||||
endWeek: endWeek |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
@import "../../libs/css/style.components.scss"; |
||||
|
||||
.u-calendar { |
||||
color: $u-content-color; |
||||
|
||||
&__header { |
||||
width: 100%; |
||||
box-sizing: border-box; |
||||
font-size: 30rpx; |
||||
background-color: #fff; |
||||
color: $u-main-color; |
||||
|
||||
&__text { |
||||
margin-top: 30rpx; |
||||
padding: 0 60rpx; |
||||
@include vue-flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
} |
||||
} |
||||
|
||||
&__action { |
||||
padding: 40rpx 0 40rpx 0; |
||||
|
||||
&__icon { |
||||
margin: 0 16rpx; |
||||
} |
||||
|
||||
&__text { |
||||
padding: 0 16rpx; |
||||
color: $u-main-color; |
||||
font-size: 32rpx; |
||||
line-height: 32rpx; |
||||
font-weight: bold; |
||||
} |
||||
} |
||||
|
||||
&__week-day { |
||||
@include vue-flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
padding: 6px 0; |
||||
overflow: hidden; |
||||
|
||||
&__text { |
||||
flex: 1; |
||||
text-align: center; |
||||
} |
||||
} |
||||
|
||||
&__content { |
||||
width: 100%; |
||||
@include vue-flex; |
||||
flex-wrap: wrap; |
||||
padding: 6px 0; |
||||
box-sizing: border-box; |
||||
background-color: #fff; |
||||
position: relative; |
||||
|
||||
&--end-date { |
||||
border-top-right-radius: 8rpx; |
||||
border-bottom-right-radius: 8rpx; |
||||
} |
||||
|
||||
&--start-date { |
||||
border-top-left-radius: 8rpx; |
||||
border-bottom-left-radius: 8rpx; |
||||
} |
||||
|
||||
&__item { |
||||
width: 14.2857%; |
||||
@include vue-flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
padding: 6px 0; |
||||
overflow: hidden; |
||||
position: relative; |
||||
z-index: 2; |
||||
|
||||
&__inner { |
||||
height: 84rpx; |
||||
@include vue-flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
flex-direction: column; |
||||
font-size: 32rpx; |
||||
position: relative; |
||||
border-radius: 50%; |
||||
|
||||
&__desc { |
||||
width: 100%; |
||||
font-size: 24rpx; |
||||
line-height: 24rpx; |
||||
transform: scale(0.75); |
||||
transform-origin: center center; |
||||
position: absolute; |
||||
left: 0; |
||||
text-align: center; |
||||
bottom: 2rpx; |
||||
} |
||||
} |
||||
|
||||
&__tips { |
||||
width: 100%; |
||||
font-size: 24rpx; |
||||
line-height: 24rpx; |
||||
position: absolute; |
||||
left: 0; |
||||
transform: scale(0.8); |
||||
transform-origin: center center; |
||||
text-align: center; |
||||
bottom: 8rpx; |
||||
z-index: 2; |
||||
} |
||||
} |
||||
|
||||
&__bg-month { |
||||
position: absolute; |
||||
font-size: 130px; |
||||
line-height: 130px; |
||||
left: 50%; |
||||
top: 50%; |
||||
transform: translate(-50%, -50%); |
||||
color: #e4e7ed; |
||||
z-index: 1; |
||||
} |
||||
} |
||||
|
||||
&__bottom { |
||||
width: 100%; |
||||
@include vue-flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
flex-direction: column; |
||||
background-color: #fff; |
||||
padding: 0 40rpx 30rpx; |
||||
box-sizing: border-box; |
||||
font-size: 24rpx; |
||||
color: $u-tips-color; |
||||
|
||||
&__choose { |
||||
height: 50rpx; |
||||
} |
||||
|
||||
&__btn { |
||||
width: 100%; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,257 @@
|
||||
<template> |
||||
<view class="u-keyboard" @touchmove.stop.prevent="() => {}"> |
||||
<view class="u-keyboard-grids"> |
||||
<block> |
||||
<view class="u-keyboard-grids-item" v-for="(group, i) in abc ? EngKeyBoardList : areaList" :key="i"> |
||||
<view :hover-stay-time="100" @tap="carInputClick(i, j)" hover-class="u-carinput-hover" class="u-keyboard-grids-btn" |
||||
v-for="(item, j) in group" :key="j"> |
||||
{{ item }} |
||||
</view> |
||||
</view> |
||||
<view @touchstart="backspaceClick" @touchend="clearTimer" :hover-stay-time="100" class="u-keyboard-back" |
||||
hover-class="u-hover-class"> |
||||
<u-icon :size="38" name="backspace" :bold="true"></u-icon> |
||||
</view> |
||||
<view :hover-stay-time="100" class="u-keyboard-change" hover-class="u-carinput-hover" @tap="changeCarInputMode"> |
||||
<text class="zh" :class="[!abc ? 'active' : 'inactive']">中</text> |
||||
/ |
||||
<text class="en" :class="[abc ? 'active' : 'inactive']">英</text> |
||||
</view> |
||||
</block> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
name: "u-keyboard", |
||||
props: { |
||||
// 是否打乱键盘按键的顺序 |
||||
random: { |
||||
type: Boolean, |
||||
default: false |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
// 车牌输入时,abc=true为输入车牌号码,bac=false为输入省份中文简称 |
||||
abc: false |
||||
}; |
||||
}, |
||||
computed: { |
||||
areaList() { |
||||
let data = [ |
||||
'京', |
||||
'沪', |
||||
'粤', |
||||
'津', |
||||
'冀', |
||||
'豫', |
||||
'云', |
||||
'辽', |
||||
'黑', |
||||
'湘', |
||||
'皖', |
||||
'鲁', |
||||
'苏', |
||||
'浙', |
||||
'赣', |
||||
'鄂', |
||||
'桂', |
||||
'甘', |
||||
'晋', |
||||
'陕', |
||||
'蒙', |
||||
'吉', |
||||
'闽', |
||||
'贵', |
||||
'渝', |
||||
'川', |
||||
'青', |
||||
'琼', |
||||
'宁', |
||||
'挂', |
||||
'藏', |
||||
'港', |
||||
'澳', |
||||
'新', |
||||
'使', |
||||
'学' |
||||
]; |
||||
let tmp = []; |
||||
// 打乱顺序 |
||||
if (this.random) data = this.$u.randomArray(data); |
||||
// 切割成二维数组 |
||||
tmp[0] = data.slice(0, 10); |
||||
tmp[1] = data.slice(10, 20); |
||||
tmp[2] = data.slice(20, 30); |
||||
tmp[3] = data.slice(30, 36); |
||||
return tmp; |
||||
}, |
||||
EngKeyBoardList() { |
||||
let data = [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
0, |
||||
'Q', |
||||
'W', |
||||
'E', |
||||
'R', |
||||
'T', |
||||
'Y', |
||||
'U', |
||||
'I', |
||||
'O', |
||||
'P', |
||||
'A', |
||||
'S', |
||||
'D', |
||||
'F', |
||||
'G', |
||||
'H', |
||||
'J', |
||||
'K', |
||||
'L', |
||||
'Z', |
||||
'X', |
||||
'C', |
||||
'V', |
||||
'B', |
||||
'N', |
||||
'M' |
||||
]; |
||||
let tmp = []; |
||||
if (this.random) data = this.$u.randomArray(data); |
||||
tmp[0] = data.slice(0, 10); |
||||
tmp[1] = data.slice(10, 20); |
||||
tmp[2] = data.slice(20, 30); |
||||
tmp[3] = data.slice(30, 36); |
||||
return tmp; |
||||
} |
||||
}, |
||||
methods: { |
||||
// 点击键盘按钮 |
||||
carInputClick(i, j) { |
||||
let value = ''; |
||||
// 不同模式,获取不同数组的值 |
||||
if (this.abc) value = this.EngKeyBoardList[i][j]; |
||||
else value = this.areaList[i][j]; |
||||
this.$emit('change', value); |
||||
}, |
||||
// 修改汽车牌键盘的输入模式,中文|英文 |
||||
changeCarInputMode() { |
||||
this.abc = !this.abc; |
||||
}, |
||||
// 点击退格键 |
||||
backspaceClick() { |
||||
this.$emit('backspace'); |
||||
clearInterval(this.timer); //再次清空定时器,防止重复注册定时器 |
||||
this.timer = null; |
||||
this.timer = setInterval(() => { |
||||
this.$emit('backspace'); |
||||
}, 250); |
||||
}, |
||||
clearTimer() { |
||||
clearInterval(this.timer); |
||||
this.timer = null; |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
@import "../../libs/css/style.components.scss"; |
||||
|
||||
.u-keyboard-grids { |
||||
background: rgb(215, 215, 217); |
||||
padding: 24rpx 0; |
||||
position: relative; |
||||
} |
||||
|
||||
.u-keyboard-grids-item { |
||||
@include vue-flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
|
||||
.u-keyboard-grids-btn { |
||||
text-decoration: none; |
||||
width: 62rpx; |
||||
flex: 0 0 64rpx; |
||||
height: 80rpx; |
||||
/* #ifndef APP-NVUE */ |
||||
display: inline-flex; |
||||
/* #endif */ |
||||
font-size: 36rpx; |
||||
text-align: center; |
||||
line-height: 80rpx; |
||||
background-color: #fff; |
||||
margin: 8rpx 5rpx; |
||||
border-radius: 8rpx; |
||||
box-shadow: 0 2rpx 0rpx #888992; |
||||
font-weight: 500; |
||||
justify-content: center; |
||||
} |
||||
|
||||
.u-carinput-hover { |
||||
background-color: rgb(185, 188, 195) !important; |
||||
} |
||||
|
||||
.u-keyboard-back { |
||||
position: absolute; |
||||
width: 96rpx; |
||||
right: 22rpx; |
||||
bottom: 32rpx; |
||||
height: 80rpx; |
||||
background-color: rgb(185, 188, 195); |
||||
@include vue-flex; |
||||
align-items: center; |
||||
border-radius: 8rpx; |
||||
justify-content: center; |
||||
box-shadow: 0 2rpx 0rpx #888992; |
||||
} |
||||
|
||||
.u-keyboard-change { |
||||
font-size: 24rpx; |
||||
box-shadow: 0 2rpx 0rpx #888992; |
||||
position: absolute; |
||||
width: 96rpx; |
||||
left: 22rpx; |
||||
line-height: 1; |
||||
bottom: 32rpx; |
||||
height: 80rpx; |
||||
background-color: #ffffff; |
||||
@include vue-flex; |
||||
align-items: center; |
||||
border-radius: 8rpx; |
||||
justify-content: center; |
||||
} |
||||
|
||||
.u-keyboard-change .inactive.zh { |
||||
transform: scale(0.85) translateY(-10rpx); |
||||
} |
||||
|
||||
.u-keyboard-change .inactive.en { |
||||
transform: scale(0.85) translateY(10rpx); |
||||
} |
||||
|
||||
.u-keyboard-change .active { |
||||
color: rgb(237, 112, 64); |
||||
font-size: 30rpx; |
||||
} |
||||
|
||||
.u-keyboard-change .zh { |
||||
transform: translateY(-10rpx); |
||||
} |
||||
|
||||
.u-keyboard-change .en { |
||||
transform: translateY(10rpx); |
||||
} |
||||
</style> |
@ -0,0 +1,299 @@
|
||||
<template> |
||||
<view |
||||
class="u-card" |
||||
@tap.stop="click" |
||||
:class="{ 'u-border': border, 'u-card-full': full, 'u-card--border': borderRadius > 0 }" |
||||
:style="{ |
||||
borderRadius: borderRadius + 'rpx', |
||||
margin: margin, |
||||
boxShadow: boxShadow |
||||
}" |
||||
> |
||||
<view |
||||
v-if="showHead" |
||||
class="u-card__head" |
||||
:style="[{padding: padding + 'rpx'}, headStyle]" |
||||
:class="{ |
||||
'u-border-bottom': headBorderBottom |
||||
}" |
||||
@tap="headClick" |
||||
> |
||||
<view v-if="!$slots.head" class="u-flex u-row-between"> |
||||
<view class="u-card__head--left u-flex u-line-1" v-if="title"> |
||||
<image |
||||
:src="thumb" |
||||
class="u-card__head--left__thumb" |
||||
mode="aspectfull" |
||||
v-if="thumb" |
||||
:style="{ |
||||
height: thumbWidth + 'rpx', |
||||
width: thumbWidth + 'rpx', |
||||
borderRadius: thumbCircle ? '100rpx' : '6rpx' |
||||
}" |
||||
></image> |
||||
<text |
||||
class="u-card__head--left__title u-line-1" |
||||
:style="{ |
||||
fontSize: titleSize + 'rpx', |
||||
color: titleColor |
||||
}" |
||||
> |
||||
{{ title }} |
||||
</text> |
||||
</view> |
||||
<view class="u-card__head--right u-line-1" v-if="subTitle"> |
||||
<text |
||||
class="u-card__head__title__text" |
||||
:style="{ |
||||
fontSize: subTitleSize + 'rpx', |
||||
color: subTitleColor |
||||
}" |
||||
> |
||||
{{ subTitle }} |
||||
</text> |
||||
</view> |
||||
</view> |
||||
<slot name="head" v-else /> |
||||
</view> |
||||
<view @tap="bodyClick" class="u-card__body" :style="[{padding: padding + 'rpx'}, bodyStyle]"><slot name="body" /></view> |
||||
<view |
||||
v-if="showFoot" |
||||
class="u-card__foot" |
||||
@tap="footClick" |
||||
:style="[{padding: $slots.foot ? padding + 'rpx' : 0}, footStyle]" |
||||
:class="{ |
||||
'u-border-top': footBorderTop |
||||
}" |
||||
> |
||||
<slot name="foot" /> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
/** |
||||
* card 卡片 |
||||
* @description 卡片组件一般用于多个列表条目,且风格统一的场景 |
||||
* @tutorial https://www.uviewui.com/components/card.html |
||||
* @property {Boolean} full 卡片与屏幕两侧是否留空隙(默认false) |
||||
* @property {String} title 头部左边的标题 |
||||
* @property {String} title-color 标题颜色(默认#303133) |
||||
* @property {String | Number} title-size 标题字体大小,单位rpx(默认30) |
||||
* @property {String} sub-title 头部右边的副标题 |
||||
* @property {String} sub-title-color 副标题颜色(默认#909399) |
||||
* @property {String | Number} sub-title-size 副标题字体大小(默认26) |
||||
* @property {Boolean} border 是否显示边框(默认true) |
||||
* @property {String | Number} index 用于标识点击了第几个卡片 |
||||
* @property {String} box-shadow 卡片外围阴影,字符串形式(默认none) |
||||
* @property {String} margin 卡片与屏幕两边和上下元素的间距,需带单位,如"30rpx 20rpx"(默认30rpx) |
||||
* @property {String | Number} border-radius 卡片整体的圆角值,单位rpx(默认16) |
||||
* @property {Object} head-style 头部自定义样式,对象形式 |
||||
* @property {Object} body-style 中部自定义样式,对象形式 |
||||
* @property {Object} foot-style 底部自定义样式,对象形式 |
||||
* @property {Boolean} head-border-bottom 是否显示头部的下边框(默认true) |
||||
* @property {Boolean} foot-border-top 是否显示底部的上边框(默认true) |
||||
* @property {Boolean} show-head 是否显示头部(默认true) |
||||
* @property {Boolean} show-head 是否显示尾部(默认true) |
||||
* @property {String} thumb 缩略图路径,如设置将显示在标题的左边,不建议使用相对路径 |
||||
* @property {String | Number} thumb-width 缩略图的宽度,高等于宽,单位rpx(默认60) |
||||
* @property {Boolean} thumb-circle 缩略图是否为圆形(默认false) |
||||
* @event {Function} click 整个卡片任意位置被点击时触发 |
||||
* @event {Function} head-click 卡片头部被点击时触发 |
||||
* @event {Function} body-click 卡片主体部分被点击时触发 |
||||
* @event {Function} foot-click 卡片底部部分被点击时触发 |
||||
* @example <u-card padding="30" title="card"></u-card> |
||||
*/ |
||||
export default { |
||||
name: 'u-card', |
||||
props: { |
||||
// 与屏幕两侧是否留空隙 |
||||
full: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 标题 |
||||
title: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 标题颜色 |
||||
titleColor: { |
||||
type: String, |
||||
default: '#303133' |
||||
}, |
||||
// 标题字体大小,单位rpx |
||||
titleSize: { |
||||
type: [Number, String], |
||||
default: '30' |
||||
}, |
||||
// 副标题 |
||||
subTitle: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 副标题颜色 |
||||
subTitleColor: { |
||||
type: String, |
||||
default: '#909399' |
||||
}, |
||||
// 副标题字体大小,单位rpx |
||||
subTitleSize: { |
||||
type: [Number, String], |
||||
default: '26' |
||||
}, |
||||
// 是否显示外部边框,只对full=false时有效(卡片与边框有空隙时) |
||||
border: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 用于标识点击了第几个 |
||||
index: { |
||||
type: [Number, String, Object], |
||||
default: '' |
||||
}, |
||||
// 用于隔开上下左右的边距,带单位的写法,如:"30rpx 30rpx","20rpx 20rpx 30rpx 30rpx" |
||||
margin: { |
||||
type: String, |
||||
default: '30rpx' |
||||
}, |
||||
// card卡片的圆角 |
||||
borderRadius: { |
||||
type: [Number, String], |
||||
default: '16' |
||||
}, |
||||
// 头部自定义样式,对象形式 |
||||
headStyle: { |
||||
type: Object, |
||||
default() { |
||||
return {}; |
||||
} |
||||
}, |
||||
// 主体自定义样式,对象形式 |
||||
bodyStyle: { |
||||
type: Object, |
||||
default() { |
||||
return {}; |
||||
} |
||||
}, |
||||
// 底部自定义样式,对象形式 |
||||
footStyle: { |
||||
type: Object, |
||||
default() { |
||||
return {}; |
||||
} |
||||
}, |
||||
// 头部是否下边框 |
||||
headBorderBottom: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 底部是否有上边框 |
||||
footBorderTop: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 标题左边的缩略图 |
||||
thumb: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 缩略图宽高,单位rpx |
||||
thumbWidth: { |
||||
type: [String, Number], |
||||
default: '60' |
||||
}, |
||||
// 缩略图是否为圆形 |
||||
thumbCircle: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
// 给head,body,foot的内边距 |
||||
padding: { |
||||
type: [String, Number], |
||||
default: '30' |
||||
}, |
||||
// 是否显示头部 |
||||
showHead: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 是否显示尾部 |
||||
showFoot: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 卡片外围阴影,字符串形式 |
||||
boxShadow: { |
||||
type: String, |
||||
default: 'none' |
||||
} |
||||
}, |
||||
data() { |
||||
return {}; |
||||
}, |
||||
methods: { |
||||
click() { |
||||
this.$emit('click', this.index); |
||||
}, |
||||
headClick() { |
||||
this.$emit('head-click', this.index); |
||||
}, |
||||
bodyClick() { |
||||
this.$emit('body-click', this.index); |
||||
}, |
||||
footClick() { |
||||
this.$emit('foot-click', this.index); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
@import "../../libs/css/style.components.scss"; |
||||
|
||||
.u-card { |
||||
position: relative; |
||||
overflow: hidden; |
||||
font-size: 28rpx; |
||||
background-color: #ffffff; |
||||
box-sizing: border-box; |
||||
|
||||
&-full { |
||||
// 如果是与屏幕之间不留空隙,应该设置左右边距为0 |
||||
margin-left: 0 !important; |
||||
margin-right: 0 !important; |
||||
width: 100%; |
||||
} |
||||
|
||||
&--border:after { |
||||
border-radius: 16rpx; |
||||
} |
||||
|
||||
&__head { |
||||
&--left { |
||||
color: $u-main-color; |
||||
|
||||
&__thumb { |
||||
margin-right: 16rpx; |
||||
} |
||||
|
||||
&__title { |
||||
max-width: 400rpx; |
||||
} |
||||
} |
||||
|
||||
&--right { |
||||
color: $u-tips-color; |
||||
margin-left: 6rpx; |
||||
} |
||||
} |
||||
|
||||
&__body { |
||||
color: $u-content-color; |
||||
} |
||||
|
||||
&__foot { |
||||
color: $u-tips-color; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,70 @@
|
||||
<template> |
||||
<view class="u-cell-box"> |
||||
<view class="u-cell-title" v-if="title" :style="[titleStyle]"> |
||||
{{title}} |
||||
</view> |
||||
<view class="u-cell-item-box" :class="{'u-border-bottom u-border-top': border}"> |
||||
<slot /> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
/** |
||||
* cellGroup 单元格父组件Group |
||||
* @description cell单元格一般用于一组列表的情况,比如个人中心页,设置页等。搭配u-cell-item |
||||
* @tutorial https://www.uviewui.com/components/cell.html |
||||
* @property {String} title 分组标题 |
||||
* @property {Boolean} border 是否显示外边框(默认true) |
||||
* @property {Object} title-style 分组标题的的样式,对象形式,如{'font-size': '24rpx'} 或 {'fontSize': '24rpx'} |
||||
* @example <u-cell-group title="设置喜好"> |
||||
*/ |
||||
export default { |
||||
name: "u-cell-group", |
||||
props: { |
||||
// 分组标题 |
||||
title: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 是否显示分组list上下边框 |
||||
border: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 分组标题的样式,对象形式,注意驼峰属性写法 |
||||
// 类似 {'font-size': '24rpx'} 和 {'fontSize': '24rpx'} |
||||
titleStyle: { |
||||
type: Object, |
||||
default () { |
||||
return {}; |
||||
} |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
index: 0, |
||||
} |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
@import "../../libs/css/style.components.scss"; |
||||
|
||||
.u-cell-box { |
||||
width: 100%; |
||||
} |
||||
|
||||
.u-cell-title { |
||||
padding: 30rpx 32rpx 10rpx 32rpx; |
||||
font-size: 30rpx; |
||||
text-align: left; |
||||
color: $u-tips-color; |
||||
} |
||||
|
||||
.u-cell-item-box { |
||||
background-color: #FFFFFF; |
||||
flex-direction: row; |
||||
} |
||||
</style> |