299 lines
6.7 KiB
Vue
299 lines
6.7 KiB
Vue
<!-- PageBottom.vue -->
|
||
<template>
|
||
<view class="pageBottom" :style="{ position: position, bottom: isSubmit ? '60rpx' : '0' }">
|
||
<view class="uni-flex uni-row buttons">
|
||
<view class="flex-item " v-for="(item, index) in toolbar" :key="index" style="padding: 1ch;width: 100%;">
|
||
<!-- 更多按钮:todo 1.按钮权限控制;2.动态宽度; -->
|
||
<!-- type: 'primary' 蓝色(不同终端默认颜色不同),'default' 白色,'warn'红色 如想在多端统一颜色,请改用default,然后自行写样式 -->
|
||
<!-- style: 支持自定义样式 -->
|
||
<button :type="item.type && ['primary','default','warn'].includes(item.type) ? item.type : 'default'"
|
||
@click="handleClick(item,index)" :style="item.style || ''" :loading="buttonStates[index]"
|
||
:disabled="buttonStates[index]">
|
||
{{ item.label }}{{ item.disable }}
|
||
</button>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
propsToAttrMap
|
||
} from '@vue/shared';
|
||
|
||
export default {
|
||
name: 'bottomBtnGroup',
|
||
// 接收的 props
|
||
props: {
|
||
/// 头工具栏
|
||
toolbar: {
|
||
type: Array,
|
||
default () {
|
||
return [{
|
||
label: "新增",
|
||
type: "primary",
|
||
event: function(done) {
|
||
//方式1: 接收 done 回调 在业务结束时手动触发回调
|
||
setTimeout(() => {
|
||
console.log("延时5秒 新增方法完成")
|
||
done(); //
|
||
}, 5000);
|
||
}
|
||
},
|
||
{
|
||
label: "删除",
|
||
type: "default",
|
||
event: function(done) {
|
||
setTimeout(() => {
|
||
console.log("延时5秒 删除方法完成")
|
||
done();
|
||
}, 5000);
|
||
}
|
||
},
|
||
{
|
||
label: "取消",
|
||
type: "primary",
|
||
event: function() {
|
||
//方式2:
|
||
return new Promise(resolve => {
|
||
console.log("取消方法完成")
|
||
setTimeout(resolve, 5000);
|
||
});
|
||
}
|
||
},
|
||
]
|
||
}
|
||
},
|
||
//背景是否是白色
|
||
backgroundWhite: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
//是否是提交表单的样式
|
||
isSubmit: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
//按钮是否可点击的状态
|
||
disable: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
position: {
|
||
type: String,
|
||
default: 'fixed'
|
||
}
|
||
},
|
||
created() {
|
||
// 初始化每个按钮的loading状态
|
||
this.initButtonStates();
|
||
},
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
// 存储按钮的loading状态(与toolbar对应)
|
||
buttonStates: []
|
||
|
||
};
|
||
},
|
||
watch: {
|
||
// 监听toolbar变化,重新初始化状态(适用于动态更新按钮列表的场景)
|
||
toolbar: {
|
||
handler() {
|
||
this.initButtonStates();
|
||
},
|
||
deep: true
|
||
}
|
||
},
|
||
|
||
// 方法
|
||
methods: {
|
||
// 初始化按钮状态(为每个按钮添加loading属性)
|
||
initButtonStates() {
|
||
this.toolbar.map((item, index) => {
|
||
//this.buttonStates.push(false)//vue3生效
|
||
// 响应式更新
|
||
this.$set(this.buttonStates, index, false); //vue2生效
|
||
});
|
||
},
|
||
async handleClick(item, index) {
|
||
try {
|
||
this.$set(this.buttonStates, index, true);
|
||
this.$modal.loading("请等待...")
|
||
//方式1:注意:此处约定 item.event() 返回一个Promise 否则loding状态不生效
|
||
//return new Promise(resolve => setTimeout(resolve, 5000));
|
||
//方式2:把 resolve/reject 作为“完成信号”传给业务函数,像调用方法传递done 方法,在业务处理结后调用
|
||
await new Promise((resolve, reject) => {
|
||
// 把 resolve/reject 作为“完成信号”传给业务函数
|
||
item.event(resolve, reject);
|
||
});
|
||
} catch (error) {
|
||
console.error('catch 按钮事件执行出错:', error);
|
||
} finally {
|
||
// 响应式更新
|
||
console.info('finally 按钮事件执行');
|
||
this.$set(this.buttonStates, index, false);
|
||
this.$modal.closeLoading()
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.pageBottom {
|
||
left: 0;
|
||
bottom: 0;
|
||
z-index: 30;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
flex-direction: column;
|
||
width: 100%;
|
||
padding: 20rpx 0 20rpx;
|
||
|
||
.button {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
width: 686rpx;
|
||
height: 72rpx;
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
color: #ffffff;
|
||
border-radius: 16rpx;
|
||
//background: rgb(22, 93, 255);
|
||
}
|
||
|
||
.backgroundWhite {
|
||
background: #fff;
|
||
color: #165dff;
|
||
border: 2rpx solid rgb(22, 93, 255);
|
||
}
|
||
|
||
.buttons {
|
||
display: flex;
|
||
justify-content: center;
|
||
width: 100%;
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
padding: 24rpx 0 60rpx;
|
||
background-color: #fff;
|
||
//background-color: #165DFF;
|
||
|
||
.buttonOne {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 90rpx;
|
||
width: 664rpx;
|
||
box-sizing: border-box;
|
||
//background: rgb(22, 93, 255);
|
||
border-radius: 16rpx;
|
||
color: #FFFFFF;
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.buttonLeft {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 90rpx;
|
||
width: 332rpx;
|
||
box-sizing: border-box;
|
||
background: rgb(22, 93, 255);
|
||
border-radius: 16rpx;
|
||
color: #FFFFFF;
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.buttonRight {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 90rpx;
|
||
width: 332rpx;
|
||
border-radius: 16rpx;
|
||
background: rgb(22, 93, 255);
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
color: #FFFFFF;
|
||
margin-left: 22rpx;
|
||
}
|
||
}
|
||
|
||
.thirdbuttons {
|
||
display: flex;
|
||
justify-content: center;
|
||
width: 100%;
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
padding: 10rpx 0 60rpx;
|
||
background-color: #fff;
|
||
|
||
.buttonLeft {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 72rpx;
|
||
width: 232rpx;
|
||
box-sizing: border-box;
|
||
border: 2rpx solid rgb(22, 93, 255);
|
||
border-radius: 16rpx;
|
||
background: rgb(255, 255, 255);
|
||
color: #165DFF;
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.buttonMid {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 72rpx;
|
||
width: 232rpx;
|
||
box-sizing: border-box;
|
||
border: 2rpx solid rgb(22, 93, 255);
|
||
border-radius: 16rpx;
|
||
background: rgb(255, 255, 255);
|
||
color: #165DFF;
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
margin-left: 10rpx;
|
||
}
|
||
|
||
.buttonRight {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 72rpx;
|
||
width: 232rpx;
|
||
border-radius: 16rpx;
|
||
background: rgb(22, 93, 255);
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
color: #FFFFFF;
|
||
margin-left: 10rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.contentWhite {
|
||
content: '';
|
||
position: fixed;
|
||
left: 0;
|
||
bottom: 0;
|
||
width: 100%;
|
||
height: 240rpx;
|
||
background: linear-gradient(to bottom,
|
||
#f3ece400 0%,
|
||
#F2F3F5 100%);
|
||
pointer-events: none;
|
||
}
|
||
</style> |