|
@@ -1,35 +1,65 @@
|
|
|
<template>
|
|
|
- <view class="fs-popover">
|
|
|
- <view class="fs-popover-refer" @click="handleClickRefer">
|
|
|
- <slot name="refer"></slot>
|
|
|
- </view>
|
|
|
- <view class="fs-popover-action" v-if="actionVisible" :class="['fs-popover-' + placement]" @click="handleClose">
|
|
|
+ <view class="fs-popover" :style="{ 'z-index': zIndex }">
|
|
|
+ <view class="fs-popover-refer" @click="handleClickRefer"><slot name="refer"></slot></view>
|
|
|
+ <view
|
|
|
+ class="fs-popover-action"
|
|
|
+ v-if="actionVisible"
|
|
|
+ :class="['fs-popover-' + placement]"
|
|
|
+ :style="{ 'z-index': zIndex }"
|
|
|
+ @click="handleClose"
|
|
|
+ >
|
|
|
<view class="fs-popover-arrow"></view>
|
|
|
<slot>
|
|
|
- <view class="fs-popover-action-item line1" v-for="(item, index) in actions" :key="index" @click="handleClickAction(item)">{{item.text}}</view>
|
|
|
+ <view
|
|
|
+ class="fs-popover-action-item line1"
|
|
|
+ :class="{ 'fs-popover-active': item[valueKey] && item[valueKey] === modelValue[valueKey] }"
|
|
|
+ v-for="(item, index) in actions"
|
|
|
+ :key="index"
|
|
|
+ @click="handleClickAction(item)"
|
|
|
+ >
|
|
|
+ {{ item.text }}
|
|
|
+ </view>
|
|
|
</slot>
|
|
|
</view>
|
|
|
-
|
|
|
- <fs-mask v-model="actionVisible" :z-index="100" bgColor="rgba(0,0,0,0)"></fs-mask>
|
|
|
+
|
|
|
+ <fs-mask v-model="actionVisible" :z-index="1" bgColor="rgba(0,0,0,0)"></fs-mask>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
export default {
|
|
|
- name:"fs-popover",
|
|
|
+ name: 'fs-popover'
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, onMounted } from 'vue'
|
|
|
+import { ref, onMounted, watch } from 'vue'
|
|
|
import utils from '@/utils/utils'
|
|
|
|
|
|
const props = defineProps({
|
|
|
+ modelValue: [Object],
|
|
|
+ valueKey: {
|
|
|
+ type: String,
|
|
|
+ default: 'id'
|
|
|
+ },
|
|
|
placement: {
|
|
|
type: String,
|
|
|
default: 'bottom',
|
|
|
validator(value) {
|
|
|
- return ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end','left', 'left-start', 'left-end','right', 'right-start', 'right-end'].includes(value)
|
|
|
+ return [
|
|
|
+ 'top',
|
|
|
+ 'top-start',
|
|
|
+ 'top-end',
|
|
|
+ 'bottom',
|
|
|
+ 'bottom-start',
|
|
|
+ 'bottom-end',
|
|
|
+ 'left',
|
|
|
+ 'left-start',
|
|
|
+ 'left-end',
|
|
|
+ 'right',
|
|
|
+ 'right-start',
|
|
|
+ 'right-end'
|
|
|
+ ].includes(value)
|
|
|
}
|
|
|
},
|
|
|
actions: Array,
|
|
@@ -41,17 +71,24 @@ const props = defineProps({
|
|
|
type: String,
|
|
|
default: '#666'
|
|
|
},
|
|
|
+ activeColor: {
|
|
|
+ type: String,
|
|
|
+ default: '#165DFF'
|
|
|
+ },
|
|
|
borderColor: {
|
|
|
type: String,
|
|
|
default: '#E8EAF2'
|
|
|
},
|
|
|
- zIndex: {
|
|
|
- type: Number,
|
|
|
- default: 99
|
|
|
+ width: {
|
|
|
+ type: String,
|
|
|
+ default: 'auto'
|
|
|
+ },
|
|
|
+ actionWidth: {
|
|
|
+ type: String,
|
|
|
+ default: 'auto'
|
|
|
}
|
|
|
})
|
|
|
-const emits = defineEmits(['clickAction'])
|
|
|
-
|
|
|
+const emits = defineEmits(['clickAction', 'visibleChange', 'update:modelValue'])
|
|
|
const uuid = utils.uuid()
|
|
|
|
|
|
const actionVisible = ref(false)
|
|
@@ -59,17 +96,25 @@ const handleClickRefer = () => {
|
|
|
uni.$emit('popoverClose', { uuid: uuid })
|
|
|
actionVisible.value = !actionVisible.value
|
|
|
}
|
|
|
+watch(actionVisible, () => {
|
|
|
+ emits('visibleChange')
|
|
|
+})
|
|
|
|
|
|
const handleClickAction = item => {
|
|
|
+ emits('update:modelValue', item)
|
|
|
emits('clickAction', item)
|
|
|
}
|
|
|
const handleClose = () => {
|
|
|
actionVisible.value = false
|
|
|
}
|
|
|
|
|
|
+const zIndex = ref(10)
|
|
|
uni.$on('popoverClose', res => {
|
|
|
if (uuid !== res.uuid) {
|
|
|
+ zIndex.value = 10
|
|
|
handleClose()
|
|
|
+ } else {
|
|
|
+ zIndex.value = 20
|
|
|
}
|
|
|
})
|
|
|
|
|
@@ -81,194 +126,203 @@ defineExpose({
|
|
|
<style lang="scss" scoped>
|
|
|
$margin: 20rpx;
|
|
|
$arrowOffset: 30rpx;
|
|
|
+$arrowSize: 24rpx;
|
|
|
|
|
|
-.fs-popover{
|
|
|
- display: inline-block;
|
|
|
+.fs-popover {
|
|
|
position: relative;
|
|
|
- z-index: v-bind(zIndex);
|
|
|
-
|
|
|
- &-action{
|
|
|
+ display: inline-block;
|
|
|
+ width: v-bind(width);
|
|
|
+
|
|
|
+ &-action {
|
|
|
position: absolute;
|
|
|
min-width: 260rpx;
|
|
|
- z-index: calc(v-bind(zIndex) + 1);
|
|
|
+ max-width: 100%;
|
|
|
+ width: v-bind(actionWidth);
|
|
|
background-color: v-bind(bgColor);
|
|
|
- transition: opacity .15s,transform .15s;
|
|
|
+ transition: opacity 0.15s, transform 0.15s;
|
|
|
border-radius: 12rpx;
|
|
|
padding: 0 30rpx;
|
|
|
color: v-bind(textColor);
|
|
|
-
|
|
|
- &-item{
|
|
|
+ border: 2rpx solid v-bind(borderColor);
|
|
|
+
|
|
|
+ &-item {
|
|
|
padding: 20rpx;
|
|
|
- & + &{
|
|
|
+ & + & {
|
|
|
border-top: 2rpx solid v-bind(borderColor);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- &-arrow{
|
|
|
+
|
|
|
+ &-active {
|
|
|
+ color: v-bind(activeColor);
|
|
|
+ }
|
|
|
+
|
|
|
+ &-arrow {
|
|
|
position: absolute;
|
|
|
- width: 0;
|
|
|
- height: 0;
|
|
|
- border-color: transparent;
|
|
|
- border-style: solid;
|
|
|
- border-width: 12rpx;
|
|
|
+ width: $arrowSize;
|
|
|
+ height: $arrowSize;
|
|
|
+ transform: rotate(45deg);
|
|
|
+ z-index: 1000;
|
|
|
+ background-color: v-bind(bgColor);
|
|
|
+ border: 2rpx solid transparent;
|
|
|
+ margin-top: -$arrowSize / 2;
|
|
|
+ margin-left: -$arrowSize / 2;
|
|
|
}
|
|
|
-
|
|
|
- &-top{
|
|
|
+
|
|
|
+ &-top {
|
|
|
left: 50%;
|
|
|
bottom: 100%;
|
|
|
transform: translateX(-50%);
|
|
|
margin-bottom: $margin;
|
|
|
- .fs-popover-arrow{
|
|
|
- border-bottom-width: 0;
|
|
|
- border-top-color: v-bind(bgColor);
|
|
|
- bottom: 0;
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-bottom-color: v-bind(borderColor);
|
|
|
+ border-right-color: v-bind(borderColor);
|
|
|
+ bottom: -$arrowSize / 2;
|
|
|
left: 50%;
|
|
|
- transform: translate(-50%, 100%);
|
|
|
}
|
|
|
}
|
|
|
- &-top-start{
|
|
|
+ &-top-start {
|
|
|
left: 0;
|
|
|
bottom: 100%;
|
|
|
margin-bottom: $margin;
|
|
|
- .fs-popover-arrow{
|
|
|
- border-bottom-width: 0;
|
|
|
- border-top-color: v-bind(bgColor);
|
|
|
- bottom: 0;
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-bottom-color: v-bind(borderColor);
|
|
|
+ border-right-color: v-bind(borderColor);
|
|
|
+ bottom: -$arrowSize / 2;
|
|
|
left: $arrowOffset;
|
|
|
- transform: translateY(100%);
|
|
|
+ margin-left: 0;
|
|
|
}
|
|
|
}
|
|
|
- &-top-end{
|
|
|
+ &-top-end {
|
|
|
right: 0;
|
|
|
bottom: 100%;
|
|
|
margin-bottom: $margin;
|
|
|
- .fs-popover-arrow{
|
|
|
- border-bottom-width: 0;
|
|
|
- border-top-color: v-bind(bgColor);
|
|
|
- bottom: 0;
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-bottom-color: v-bind(borderColor);
|
|
|
+ border-right-color: v-bind(borderColor);
|
|
|
+ bottom: -$arrowSize / 2;
|
|
|
right: $arrowOffset;
|
|
|
- transform: translateY(100%);
|
|
|
+ margin-left: 0;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- &-bottom{
|
|
|
+
|
|
|
+ &-bottom {
|
|
|
left: 50%;
|
|
|
top: 100%;
|
|
|
transform: translateX(-50%);
|
|
|
margin-top: $margin;
|
|
|
-
|
|
|
- .fs-popover-arrow{
|
|
|
- border-top-width: 0;
|
|
|
- border-bottom-color: v-bind(bgColor);
|
|
|
+
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-top-color: v-bind(borderColor);
|
|
|
+ border-left-color: v-bind(borderColor);
|
|
|
top: 0;
|
|
|
left: 50%;
|
|
|
- transform: translate(-50%, -100%);
|
|
|
}
|
|
|
}
|
|
|
- &-bottom-start{
|
|
|
+ &-bottom-start {
|
|
|
left: 0;
|
|
|
top: 100%;
|
|
|
margin-top: $margin;
|
|
|
-
|
|
|
- .fs-popover-arrow{
|
|
|
- border-top-width: 0;
|
|
|
- border-bottom-color: v-bind(bgColor);
|
|
|
+
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-top-color: v-bind(borderColor);
|
|
|
+ border-left-color: v-bind(borderColor);
|
|
|
top: 0;
|
|
|
left: $arrowOffset;
|
|
|
- transform: translateY(-100%);
|
|
|
+ margin-left: 0;
|
|
|
}
|
|
|
}
|
|
|
- &-bottom-end{
|
|
|
+ &-bottom-end {
|
|
|
right: 0;
|
|
|
top: 100%;
|
|
|
margin-top: $margin;
|
|
|
-
|
|
|
- .fs-popover-arrow{
|
|
|
- border-top-width: 0;
|
|
|
- border-bottom-color: v-bind(bgColor);
|
|
|
+
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-top-color: v-bind(borderColor);
|
|
|
+ border-left-color: v-bind(borderColor);
|
|
|
top: 0;
|
|
|
right: $arrowOffset;
|
|
|
- transform: translateY(-100%);
|
|
|
+ margin-left: 0;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- &-left{
|
|
|
+
|
|
|
+ &-left {
|
|
|
left: -$margin;
|
|
|
top: 50%;
|
|
|
transform: translate(-100%, -50%);
|
|
|
- .fs-popover-arrow{
|
|
|
- border-right-width: 0;
|
|
|
- border-left-color: v-bind(bgColor);
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-bottom-color: v-bind(borderColor);
|
|
|
+ border-right-color: v-bind(borderColor);
|
|
|
top: 50%;
|
|
|
- right: 0;
|
|
|
- transform: translate(100%, -50%);
|
|
|
+ right: -$arrowSize / 2;
|
|
|
+ transform: rotate(-45deg);
|
|
|
}
|
|
|
}
|
|
|
- &-left-start{
|
|
|
+ &-left-start {
|
|
|
left: -$margin;
|
|
|
top: 0;
|
|
|
transform: translateX(-100%);
|
|
|
-
|
|
|
- .fs-popover-arrow{
|
|
|
- border-right-width: 0;
|
|
|
- border-left-color: v-bind(bgColor);
|
|
|
+
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-bottom-color: v-bind(borderColor);
|
|
|
+ border-right-color: v-bind(borderColor);
|
|
|
top: $arrowOffset;
|
|
|
- right: 0;
|
|
|
- transform: translateX(100%);
|
|
|
+ right: -$arrowSize / 2;
|
|
|
+ transform: rotate(-45deg);
|
|
|
+ margin-top: 0;
|
|
|
}
|
|
|
}
|
|
|
- &-left-end{
|
|
|
+ &-left-end {
|
|
|
left: -$margin;
|
|
|
bottom: 0;
|
|
|
transform: translateX(-100%);
|
|
|
-
|
|
|
- .fs-popover-arrow{
|
|
|
- border-right-width: 0;
|
|
|
- border-left-color: v-bind(bgColor);
|
|
|
+
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-bottom-color: v-bind(borderColor);
|
|
|
+ border-right-color: v-bind(borderColor);
|
|
|
bottom: $arrowOffset;
|
|
|
- right: 0;
|
|
|
- transform: translateX(100%);
|
|
|
+ right: -$arrowSize / 2;
|
|
|
+ transform: rotate(-45deg);
|
|
|
+ margin-top: 0;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- &-right{
|
|
|
+
|
|
|
+ &-right {
|
|
|
left: 100%;
|
|
|
- top: 0;
|
|
|
+ top: 50%;
|
|
|
transform: translateY(-50%);
|
|
|
margin-left: $margin;
|
|
|
-
|
|
|
- .fs-popover-arrow{
|
|
|
- border-left-width: 0;
|
|
|
- border-right-color: v-bind(bgColor);
|
|
|
+
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-bottom-color: v-bind(borderColor);
|
|
|
+ border-left-color: v-bind(borderColor);
|
|
|
top: 50%;
|
|
|
left: 0;
|
|
|
- transform: translateX(-50%);
|
|
|
}
|
|
|
}
|
|
|
- &-right-start{
|
|
|
+ &-right-start {
|
|
|
left: 100%;
|
|
|
top: 0;
|
|
|
margin-left: $margin;
|
|
|
- .fs-popover-arrow{
|
|
|
- border-left-width: 0;
|
|
|
- border-right-color: v-bind(bgColor);
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-bottom-color: v-bind(borderColor);
|
|
|
+ border-left-color: v-bind(borderColor);
|
|
|
top: $arrowOffset;
|
|
|
left: 0;
|
|
|
- transform: translateX(-100%);
|
|
|
+ margin-top: 0;
|
|
|
}
|
|
|
}
|
|
|
- &-right-end{
|
|
|
+ &-right-end {
|
|
|
left: 100%;
|
|
|
bottom: 0;
|
|
|
margin-left: $margin;
|
|
|
- .fs-popover-arrow{
|
|
|
- border-left-width: 0;
|
|
|
- border-right-color: v-bind(bgColor);
|
|
|
+ .fs-popover-arrow {
|
|
|
+ border-bottom-color: v-bind(borderColor);
|
|
|
+ border-left-color: v-bind(borderColor);
|
|
|
left: 0;
|
|
|
bottom: $arrowOffset;
|
|
|
- transform: translateX(-100%);
|
|
|
+ margin-top: 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|