一、支付组件使用uview-ui
效果:
组件:Pay.vue 代码:
<template>
<!--去付款-->
<u-popup v-model="showPay" mode="bottom" border-radius="20" class="upay" :mask-close-able="false">
<view class="pay-alert">
<view class="pay-con">
<view class="ht">选择支付方式</view>
<radio-group @change="radioChange">
<view class="item row-between">
<view class="fl row-center"><u-icon size="42" color="#48B36E" class="ic" name="weixin-circle-fill"></u-icon><text>微信支付</text></view>
<radio value="apipay" color="#E41436"></radio>
</view>
<view class="item row-between">
<view class="fl row-center"><u-icon size="42" color="#05B4FD" class="ic" name="zhifubao-circle-fill"></u-icon><text>支付宝支付</text></view>
<radio value="wechat" color="#E41436"></radio>
</view>
</radio-group>
</view>
<view class="hm row-between">
<view class="btn row-center" @tap="closePay">暂不支付</view>
<view class="btn row-center red">立即支付</view>
</view>
</view>
</u-popup>
</template>
<script>
export default{
name:'Pay',
props:{
showPay:{
type:Boolean,
default:false
}
},
data(){
return{
}
},
methods:{
closePay(){
this.$emit("closePay")
},
radioChange(v){
console.log(v.target.value)
}
}
}
</script>
<style lang="scss" scoped>
.upay{ margin:auto; max-width:540px;}
.pay-alert{
.pay-con{ padding:0 35rpx;
.ht{ font-weight:bold; color:#333; padding:35rpx 0;}
.item{ height:110rpx; border-top:1px solid #f8f8f8;
.fl{
.ic{margin:6rpx 15rpx 0 0;}
}
radio{ transform: scale(0.7); transform-origin: right}
}
}
.hm{
.btn{ height:110rpx; color:#333; background:#f2f2f2; font-weight:bold; flex:1; &.red{ background:$u-type-primary; color: #fff; } }
}
}
</style>
使用支付组件:
<template>
<view>
<view @tap="showPay=true">立即付款</view>
<Pay :showPay="showPay" v-on:closePay="closePay"></Pay>
</view>
</template>
<script>
import Pay from '@/components/Pay/Pay.vue'
export default{
components:{ Pay },
data(){
return{
showPay:false
}
},
onLoad(){
},
methods:{
//关闭支付
closePay(){
this.showPay = false
}
}
}
</script>
<style lang="scss" scoped>
</style>
二、物流组件
效果图:
logistics.vue 代码:
<template>
<view>
<!--物流-->
<view class="logistics">
<view class="goods row">
<view class="image"><image src="/static/img/1.jpg" mode="aspectFill"></image></view>
<view class="text">
<view class="txt">物流公司:圆通快递</view>
<view class="txt">运单编号:888999166546546</view>
</view>
</view>
<view class="logis-time">
<view class="item cur">
<view class="icon"></view>
<view class="text">
<view class="tit">商家正在通知快递公司揽件</view>
<view class="time">2019/05/08 12:12:22</view>
</view>
</view>
<view class="item">
<view class="icon"></view>
<view class="text">
<view class="tit">您的包裹已出库</view>
<view class="time">2019/05/08 12:12:22</view>
</view>
</view>
<view class="item">
<view class="icon"></view>
<view class="text">
<view class="tit">您的订单正在等待配货</view>
<view class="time">2019/05/08 12:12:22</view>
</view>
</view>
<view class="item">
<view class="icon"></view>
<view class="text">
<view class="tit">您的订单开始处理</view>
<view class="time">2019/05/08 12:12:22</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default{
data(){
return{
}
},
onLoad(){
},
methods:{
}
}
</script>
<style> page{ background:#f4f4f4;} </style>
<style lang="scss" scoped>
.logistics{ padding:25rpx;
.goods{padding:25rpx; background:#fff; overflow: hidden; border-radius:20rpx;
.image{ width:180rpx; height:180rpx; border-radius:10rpx; overflow:hidden;}
.text{ flex:1; height:180rpx; overflow: hidden; margin-left:25rpx;
.txt{ padding-top:15rpx;}
}
}
.logis-time{padding:25rpx 40rpx 30rpx 60rpx; background:#fff; margin-top:25rpx; overflow: hidden; border-radius:20rpx;
.item{ position: relative; padding-bottom:60rpx; padding-left:60rpx;
&:after{ width:1px; height:100%; background:#eee; position: absolute; left:10rpx; top:0; content:'';}
&:nth-child(1):after{ top:20rpx;}
&:last-child:after{ height:20rpx;}
.icon{ width:20rpx; height:20rpx; background:#fff; z-index:1; position:absolute; left:0; top:10rpx; border-radius:50%; border:1px solid #eee;}
.text{
.tit{ font-size:32rpx; padding-bottom:12rpx; color:#bfbfbf;}
.time{ color:#bfbfbf; font-size:26rpx;}
}
&.cur{
.icon{ background:$u-type-primary; left:-8rpx; border:10rpx solid #FCE6EA; width:35rpx; height:35rpx;}
.tit{ color:#333;}
.time{ color:#888;}
}
}
}
}
</style>
三、订单样式swiper+tab
效果图:
orderList.vue 代码:
<template>
<view>
<!-- #ifdef H5 -->
<Header type="public" title="我的订单"></Header>
<!-- #endif -->
<!--TAB切换-->
<view class="tab">
<view class="tab-con fixed row-between">
<view class="item row-center" :class="tabIndex==index?'on':''" v-for="(item,index) in tab" :key="index" @tap="changeTab(index)"><text>{{item.label}}</text></view>
<view class="tab-line" :style="'transform:translateX('+translateX+'px)'"></view>
</view>
</view>
<!--订单列表-->
<swiper :current="tabIndex" @change="swiperChange">
<swiper-item v-for="(item,index) in tab" :key="index">
<view class="orderList">
<view class="item">
<view class="ht row-between" @tap="util.goPage('/pages/usersub/order/detail?orderId=1')">
<view class="name line1">店铺名称名称</view>
<view class="status">等待买家付款</view>
</view>
<view class="goods row" @tap="util.goPage('/pages/usersub/order/detail?orderId=1')">
<view class="image"><image src="/static/img/p.png" mode="aspectFill"></image></view>
<view class="text">
<view class="title line1">商品名称展示这里是商品名称</view>
<view class="spec">复颜玻灵酸15片</view>
<view class="price row-between"><text>¥59.9</text><view class="nul"><label>X 1</label></view></view>
</view>
</view>
<view class="total row-between">
<text>共一件商品</text>
<view class="sf">实付款:<label>¥39.9</label></view>
</view>
<view class="btns">
<view class="btn row-center">取消订单</view>
<view class="btn row-center red">去付款</view>
</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
export default{
data(){
return{
tabIndex:0, //当前index
tabWidth:0, //tab宽
lineWidth:0, //线条宽
translateX:0,//线当前位置
tab:[
{label:'全部',value:1},
{label:'待付款',value:2},
{label:'待发货',value:3},
{label:'待收货',value:4},
{label:'已完成',value:5},
],
}
},
async mounted(){
let that = this;
const dom1 = await this.util.getDom('tab-con');
this.tabWidth = dom1.width;
const dom2 = await this.util.getDom('tab-line');
this.lineWidth = dom2.width;
this.transTabX();
},
onLoad(){
},
methods:{
//tab滚动
transTabX(){
let itemW = this.tabIndex * (this.tabWidth / this.tab.length);
this.translateX = itemW + ((this.tabWidth / this.tab.length - this.lineWidth) / 2)
},
//切换
changeTab(index){
this.tabIndex = index;
this.transTabX()
},
swiperChange(e){
this.tabIndex = e.detail.current;
this.transTabX()
}
}
}
</script>
<style> page{ background:#f4f4f4;} </style>
<style lang="scss" scoped>
.tab{ height:110rpx;
.tab-con{
.item{flex:1; text-align: center; height:110rpx;
&.on{ color:$u-type-primary; }
}
.tab-line{ height:5rpx; width:40rpx; transition:all 0.4s ease; position:absolute; bottom:20rpx; left:0; content:''; background:$u-type-primary;}
}
}
.orderList{ padding:0 20rpx;
.item{ background:#fff; border-radius:20rpx; padding:28rpx; padding-top:0; margin-top:20rpx; overflow:hidden;
.ht{ height:100rpx;
.name{ max-width:60%; font-size:33rpx; font-weight:bold; color:#333;}
.status{ color:#999; &.red{ color:$u-type-primary;} }
}
.goods{padding:20rpx 0; overflow: hidden; border-bottom:1px solid #f9f9f9;
.image{ width:180rpx; height:180rpx; border-radius:10rpx; overflow:hidden;}
.text{ flex:1; height:180rpx; display:flex; justify-content: space-between; flex-direction: column; overflow: hidden; margin-left:25rpx;
.title{ font-size:32rpx;}
.spec{ color:#999; margin-top:-20rpx;}
.price{ text{ font-size:32rpx; font-weight:bold;} .num{ font-size:32rpx; label{ font-size:23rpx; margin-right:8rpx;} } }
}
}
.total{ padding-top:20rpx; .sf{ label{ font-size:33rpx; color:$u-type-primary; } } }
.btns{ margin-top:25rpx; display:flex; justify-content: flex-end;
.btn{ color:#666; border:1px solid #eee; margin-left:40rpx; border-radius:70rpx; width:200rpx; height:70rpx;
&.red{ background: linear-gradient(-45deg, #FA143A, #E41436); color:#fff; border-color:linear-gradient(-45deg, #FA143A, #E41436); }
}
}
}
}
</style>
//获取元素长宽高
getDom(className){
return new Promise((resolve, reject) => {
let obj = uni.createSelectorQuery().select('.'+className)
obj.boundingClientRect(function (data) {
resolve(data)
}).exec();
})
},
四、uniapp H5端页面切换向上回弹效果(转)
/components/page-animation/index.css
/* #ifdef H5 */
uni-page {
opacity: 0;
}
uni-page.animation-before {
/* 在页面上使用 transform 会导致页面内的 fixed 定位渲染为 absolute,需要在动画完成后移除 */
transform: translateY(20px);
}
uni-page.animation-leave {
transition: all .3s ease;
}
uni-page.animation-enter {
transition: all .3s ease;
}
uni-page.animation-show {
opacity: 1;
}
uni-page.animation-after {
/* 在页面上使用 transform 会导致页面内的 fixed 定位渲染为 absolute,需要在动画完成后移除 */
transform: translateY(0);
}
/* #endif */
/components/page-animation/index.vue
<script>
import './index.css'
export default {
// #ifdef H5
onLaunch: function() {
this.show()
this.$router.beforeEach((to, from, next) => {
this.hide(next)
})
this.$router.afterEach(() => {
setTimeout(this.show, 50)
})
},
methods: {
hide(callback) {
const classList = document.querySelector('uni-page').classList
classList.add('animation-before', 'animation-leave')
classList.remove('animation-show')
setTimeout(() => {
classList.remove('animation-before', 'animation-leave')
callback && callback()
}, 300)
},
show() {
const classList = document.querySelector('uni-page').classList
classList.add('animation-before')
setTimeout(() => {
classList.add('animation-enter', 'animation-after', 'animation-show')
setTimeout(() => {
classList.remove('animation-before', 'animation-after', 'animation-enter')
}, 300)
}, 20)
}
},
// #endif
}
</script>
在app.vue中使用
<script>
import pageAnimation from './components/page-animation'
export default {
mixins: [pageAnimation],
onLaunch: function() {
},
onShow: function() {
},
onHide: function() {
},
......
五、TAB切换组件形式
效果图
components/Tab/tab.vue
<template>
<!--TAB切换-->
<view class="tab">
<view class="tab-con fixed row-between">
<view class="item row-center" :class="cur==index?'on':''" v-for="(item,index) in options" :key="index" @tap="changeTab(index)"><text>{{item.label}}</text></view>
<view class="tab-line" :style="'transform:translateX('+translateX+'px)'"></view>
</view>
</view>
</template>
<script>
export default{
name:'Tab',
props:{
curIndex:{
type:Number,
default:0
},
options:{
type:Array,
default:[]
},
},
data(){
return{
cur:0, //当前index
tabWidth:0, //tab宽
lineWidth:0, //线条宽
translateX:0,//线当前位置
}
},
watch:{
curIndex(v){
this.transTabX(v)
}
},
async mounted(){
this.$nextTick(()=>{
this.getDom();
})
},
methods:{
//获取元素宽
async getDom(){
const query = uni.createSelectorQuery().in(this);
query.select('.tab-con').fields({ size: true})
query.select('.tab-line').fields({ size: true})
query.exec((data) => {
this.tabWidth = data[0].width
this.lineWidth = data[1].width
this.transTabX(this.curIndex)
});
},
//tab滚动
transTabX(cur){
this.cur = cur;
let itemW = cur * (this.tabWidth / this.options.length);
this.translateX = itemW + ((this.tabWidth / this.options.length - this.lineWidth) / 2)
},
//切换
changeTab(index){
this.cur = index;
this.transTabX(index)
this.$emit('changeTab',index)
},
}
}
</script>
<style lang="scss" scoped>
.tab{ height:110rpx;
.tab-con{
.item{flex:1; text-align: center; height:110rpx; font-size:28rpx;
&.on{ color:$u-type-primary; }
}
.tab-line{ height:5rpx; width:40rpx; transition:all 0.4s ease; position:absolute; bottom:20rpx; left:0; content:''; background:$u-type-primary;}
}
}
</style>
调用tab组件:
<template>
<view class="appcon column">
<!--TAB切换-->
<Tab :options="tabList" :curIndex="curIndex" @changeTab="changeTab"></Tab>
<!--订单列表-->
<swiper class="swiper" :current="curIndex" @change="swiperChange">
<swiper-item v-for="(item,index) in tabList" :key="index">
<order-item></order-item>
</swiper-item>
</swiper>
</view>
</template>
<script>
import Tab from '@/components/Tab/Tab.vue'
import OrderItem from '@/components/order-item/order-item.vue'
export default{
components:{Tab, OrderItem },
data(){
return{
curIndex:0, //当前tabIndex
tabList:[ //订单状态
{label:'全部',value:1},
{label:'待付款',value:2},
{label:'待发货',value:3},
{label:'待收货',value:4},
{label:'已完成',value:5},
],
}
},
methods:{
//tab切换
changeTab(index){
this.curIndex = index;
},
//swiper切换
swiperChange(e){
this.curIndex = e.target.current
}
}
}
</script>
<style> page{ background:#f4f4f4; height:100%;} </style>
<style lang="scss" scoped>
.swiper{ flex:1; }
</style>
六、图片上传样式
效果图
代码
<template>
<view>
<view class="uploads">
<view class="up-item">
<image src="/static/img/p.png"></image>
<view class="close row-center">
<u-icon name="close" size="28" class="ico" color="#fff"></u-icon>
</view>
</view>
<view class="up-item">
<image src="/static/img/p.png"></image>
<view class="close row-center">
<u-icon name="close" size="28" class="ico" color="#fff"></u-icon>
</view>
</view>
<view class="up-item up column-center">
<view class="camera"><image src="/static/icon_camera.png"></image></view>
<view>
<text>上传凭证</text>
<text>(最多3张)</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default{
data(){
return{
}
},
onLoad(){
},
methods:{
}
}
</script>
<style> page{ background:#f4f4f4;} </style>
<style lang="scss" scoped>
.uploads{ display:flex; flex-wrap: wrap; margin-left:-25rpx;
.up-item{ width:200rpx; height:200rpx; border:1px dashed #ddd; border-radius:10rpx; position:relative; margin:25rpx 0 0 25rpx;
.close{position: absolute; right:0; top:0; border-radius:0 0 0 10rpx; background:rgba(0,0,0,0.6); width:40rpx; height:40rpx; .ico{transform: scale(0.6);} }
&.up{
.camera{ width:48rpx; height:37rpx; margin-bottom:18rpx;}
text{ display: block; font-size:24rpx; color:#a8a8a8; line-height:35rpx;}
}
}
}
</style>