189 lines
3.9 KiB
Vue
189 lines
3.9 KiB
Vue
<template>
|
|
<div class="mobile-button-group" :class="{ 'sticky': sticky }">
|
|
<!-- 移动端按钮组 -->
|
|
<div v-if="isMobile" class="mobile-buttons">
|
|
<!-- 主要操作按钮 -->
|
|
<div class="primary-actions" v-if="primaryButtons.length > 0">
|
|
<el-button
|
|
v-for="btn in primaryButtons"
|
|
:key="btn.key || btn.label"
|
|
:type="btn.type || 'primary'"
|
|
:size="btn.size || 'medium'"
|
|
:icon="btn.icon"
|
|
:disabled="btn.disabled"
|
|
:loading="btn.loading"
|
|
@click="handleClick(btn)"
|
|
class="action-btn"
|
|
>
|
|
{{ btn.label }}
|
|
</el-button>
|
|
</div>
|
|
|
|
<!-- 更多操作下拉菜单 -->
|
|
<el-dropdown
|
|
v-if="moreButtons.length > 0"
|
|
trigger="click"
|
|
placement="top-end"
|
|
@command="handleCommand"
|
|
>
|
|
<el-button
|
|
type="default"
|
|
size="medium"
|
|
icon="el-icon-more"
|
|
class="more-btn"
|
|
>
|
|
更多
|
|
</el-button>
|
|
<el-dropdown-menu slot="dropdown">
|
|
<el-dropdown-item
|
|
v-for="btn in moreButtons"
|
|
:key="btn.key || btn.label"
|
|
:command="btn.key || btn.label"
|
|
:disabled="btn.disabled"
|
|
:divided="btn.divided"
|
|
>
|
|
<i :class="btn.icon" v-if="btn.icon"></i>
|
|
{{ btn.label }}
|
|
</el-dropdown-item>
|
|
</el-dropdown-menu>
|
|
</el-dropdown>
|
|
</div>
|
|
|
|
<!-- 桌面端按钮组 -->
|
|
<div v-else class="desktop-buttons">
|
|
<slot>
|
|
<el-button
|
|
v-for="btn in allButtons"
|
|
:key="btn.key || btn.label"
|
|
:type="btn.type || 'default'"
|
|
:size="btn.size || 'mini'"
|
|
:icon="btn.icon"
|
|
:disabled="btn.disabled"
|
|
:loading="btn.loading"
|
|
:plain="btn.plain"
|
|
@click="handleClick(btn)"
|
|
>
|
|
{{ btn.label }}
|
|
</el-button>
|
|
</slot>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters } from 'vuex'
|
|
|
|
export default {
|
|
name: 'MobileButtonGroup',
|
|
props: {
|
|
buttons: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
primaryCount: {
|
|
type: Number,
|
|
default: 2
|
|
},
|
|
sticky: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
},
|
|
computed: {
|
|
...mapGetters(['device']),
|
|
isMobile() {
|
|
return this.device === 'mobile' || window.innerWidth < 768
|
|
},
|
|
allButtons() {
|
|
return this.buttons || []
|
|
},
|
|
primaryButtons() {
|
|
return this.allButtons.slice(0, this.primaryCount).filter(btn => !btn.hide)
|
|
},
|
|
moreButtons() {
|
|
return this.allButtons.slice(this.primaryCount).filter(btn => !btn.hide)
|
|
}
|
|
},
|
|
methods: {
|
|
handleClick(btn) {
|
|
if (btn.handler) {
|
|
btn.handler()
|
|
}
|
|
this.$emit('button-click', btn)
|
|
},
|
|
handleCommand(command) {
|
|
const btn = this.moreButtons.find(b => (b.key || b.label) === command)
|
|
if (btn) {
|
|
this.handleClick(btn)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.mobile-button-group {
|
|
width: 100%;
|
|
|
|
&.sticky {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 100;
|
|
background: #fff;
|
|
padding: 12px;
|
|
margin: -12px -12px 12px -12px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
}
|
|
}
|
|
|
|
.mobile-buttons {
|
|
display: flex;
|
|
gap: 12px;
|
|
padding: 12px;
|
|
background: #fff;
|
|
border-bottom: 1px solid #e4e7ed;
|
|
|
|
.primary-actions {
|
|
flex: 1;
|
|
display: flex;
|
|
gap: 12px;
|
|
|
|
.action-btn {
|
|
flex: 1;
|
|
height: 44px;
|
|
font-size: 15px;
|
|
border-radius: 8px;
|
|
}
|
|
}
|
|
|
|
.more-btn {
|
|
flex-shrink: 0;
|
|
width: 60px;
|
|
height: 44px;
|
|
padding: 0;
|
|
border-radius: 8px;
|
|
}
|
|
}
|
|
|
|
.desktop-buttons {
|
|
display: flex;
|
|
gap: 10px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
// 桌面端隐藏移动端组件
|
|
@media (min-width: 769px) {
|
|
.mobile-buttons {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
// 移动端隐藏桌面端组件
|
|
@media (max-width: 768px) {
|
|
.desktop-buttons {
|
|
display: none;
|
|
}
|
|
}
|
|
</style>
|
|
|