Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
295 lines
7.2 KiB
Vue
295 lines
7.2 KiB
Vue
<template>
|
||
<tm-sheet
|
||
v-if="tabsSwiper || (!tabsSwiper && isShowRender)"
|
||
:transprent="props.transprent"
|
||
:color="props.color"
|
||
:followTheme="props.followTheme"
|
||
:followDark="props.followDark"
|
||
:dark="props.dark"
|
||
:round="props.round"
|
||
:shadow="props.shadow"
|
||
:outlined="props.outlined"
|
||
:border="props.border"
|
||
:borderStyle="props.borderStyle"
|
||
:borderDirection="props.borderDirection"
|
||
:text="props.text"
|
||
:linear="props.linear"
|
||
:linearDeep="props.linearDeep"
|
||
:_style="props._style"
|
||
:_class="props._class"
|
||
:eventPenetrationEnabled="true"
|
||
:margin="[0, 0]"
|
||
:padding="[0, 0]"
|
||
:width="_width"
|
||
:height="_height"
|
||
>
|
||
<view
|
||
v-if="sc_top < -30 && reFresh != 0 && !tabsSwiperDisAbledPull"
|
||
:style="{
|
||
top: (reFresh == 2 ? -refreshJuli / 2 : -sc_top - 30) + 'px',
|
||
width: _width + 'rpx'
|
||
}"
|
||
class="zIndex-17 absolute l-0 flex flex-row flex-row-center-center"
|
||
>
|
||
<view class="pr-32">
|
||
<tm-icon v-if="sc_top > refreshJuli && reFresh != 2" name="tmicon-long-arrow-down"></tm-icon>
|
||
<tm-icon v-if="sc_top <= refreshJuli && reFresh != 2" name="tmicon-long-arrow-up"></tm-icon>
|
||
<tm-icon v-if="reFresh == 2" spin name="tmicon-shuaxin"></tm-icon>
|
||
</view>
|
||
<view>
|
||
<tm-text v-if="sc_top > refreshJuli" _class="text-align-center" label="下拉刷新"></tm-text>
|
||
<tm-text v-if="sc_top <= refreshJuli" _class="text-align-center" label="松开立即刷新"></tm-text>
|
||
<tm-text _class="text-align-center" label="更新于今日8:30"></tm-text>
|
||
</view>
|
||
</view>
|
||
<scroll-view
|
||
@scrolltolower="onScrollBootom"
|
||
@scroll="onScroll"
|
||
:scroll-y="_height ? true : false"
|
||
enable-flex
|
||
class="flex-col"
|
||
:style="[{ width: _width + 'rpx' }, _height ? { height: _height + 'rpx' } : '']"
|
||
>
|
||
<view
|
||
@touchStart="onScrollStart"
|
||
@touchend="onScrollEnd"
|
||
v-if="isShowRender"
|
||
:style="{ transform: `translateY(${reFresh == 2 ? -refreshJuli : 0}px)` }"
|
||
class="flex contentx"
|
||
>
|
||
<slot></slot>
|
||
</view>
|
||
</scroll-view>
|
||
</tm-sheet>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
/**
|
||
* 选项卡面板
|
||
* @description 不可以单独使用,必须放置在tm-tabs组件中使用。
|
||
*/
|
||
import tmSheet from '../tm-sheet/tm-sheet.vue'
|
||
import tmTabs from '../tm-tabs/tm-tabs.vue'
|
||
import tmIcon from '../tm-icon/tm-icon.vue'
|
||
import tmText from '../tm-text/tm-text.vue'
|
||
import { tabsobj } from '../tm-tabs/interface'
|
||
import { Ref, ref, computed, watch, onUnmounted, inject, ComputedRef, getCurrentInstance, ComponentInternalInstance, PropType, onMounted } from 'vue'
|
||
import { custom_props } from '../../tool/lib/minxs'
|
||
const tabs = ref<InstanceType<typeof tmTabs> | null>(null)
|
||
const proxy = getCurrentInstance()?.proxy ?? null
|
||
const props = defineProps({
|
||
...custom_props,
|
||
transprent: {
|
||
type: [Boolean, String],
|
||
default: false
|
||
},
|
||
color: {
|
||
type: String,
|
||
default: 'white'
|
||
},
|
||
//是否显示红点,与count不能同时出现
|
||
dot: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
count: {
|
||
type: [String, Number],
|
||
default: ''
|
||
},
|
||
//红点颜色
|
||
dotColor: {
|
||
type: String,
|
||
default: 'red'
|
||
},
|
||
name: {
|
||
type: [String, Number],
|
||
default: '',
|
||
required: true
|
||
},
|
||
title: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
icon: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
pullFun: {
|
||
type: [Function] as PropType<(type: 'top' | 'bottom') => boolean>,
|
||
default: () => {
|
||
return (type: 'top' | 'bottom') => {
|
||
return true
|
||
}
|
||
}
|
||
}
|
||
})
|
||
|
||
//---scroll下拉刷新---------
|
||
//0未初始化/松手可能未被触发,没有达到刷新的条件(即被中止了),1下拉手势中还未放开手。2松开手触发下拉刷新,3复位刷新完成
|
||
type reFreshType = 0 | 1 | 2 | 3
|
||
const sc_top = ref(0)
|
||
const refreshJuli = -100 //达到120才能被刷新
|
||
const reFresh: Ref<reFreshType> = ref(0)
|
||
const isyesResh = ref(false) //是否达到了规定刷新条件。
|
||
const isUpToogle = ref(true) //手指是否放开。
|
||
|
||
//---------------
|
||
|
||
const _pname = computed(() => String(props.name))
|
||
//父级方法。
|
||
let parent: any = proxy?.$parent
|
||
while (parent) {
|
||
if (parent?.tmTabsId == 'tmTabsId' || !parent) {
|
||
break
|
||
} else {
|
||
parent = parent?.$parent ?? null
|
||
}
|
||
}
|
||
|
||
if (typeof _pname.value != 'undefined' && _pname.value != '') {
|
||
parent?.pushKey({
|
||
key: _pname.value,
|
||
title: props.title,
|
||
icon: props.icon,
|
||
dot: props.dot,
|
||
count: props.count,
|
||
dotColor: props.dotColor
|
||
})
|
||
}
|
||
|
||
const _width = inject(
|
||
'tabsWidth',
|
||
computed(() => 0)
|
||
)
|
||
const _height = inject(
|
||
'tabsheight',
|
||
computed(() => 0)
|
||
)
|
||
const tabsActiveName: ComputedRef<string | number | undefined> = inject(
|
||
'tabsActiveName',
|
||
computed(() => undefined)
|
||
)
|
||
const tabsActiveCacheTabse = inject(
|
||
'tabsActiveCacheTabse',
|
||
computed<Array<tabsobj>>(() => {
|
||
return []
|
||
})
|
||
)
|
||
const tabsSwiper = inject(
|
||
'tabsSwiper',
|
||
computed(() => false)
|
||
)
|
||
const tabsSwiperIsMoveing = inject(
|
||
'tabsSwiperIsMoveing',
|
||
computed(() => false)
|
||
)
|
||
const tabsSwiperDisAbledPull = inject(
|
||
'tabsSwiperDisAbledPull',
|
||
computed(() => true)
|
||
)
|
||
|
||
const activeIndex = inject(
|
||
'tabsActiveactiveIndex',
|
||
computed(() => 0)
|
||
)
|
||
// const selfIndex = computed(()=>tabsActiveCacheTabse.value.findIndex(el=>el.key==tabsActiveName.value))
|
||
const selfIndex = computed(() => tabsActiveCacheTabse.value.findIndex((el) => el.key == _pname.value))
|
||
|
||
const isShowRender = computed(() => {
|
||
if (tabsSwiper.value == false) {
|
||
return selfIndex.value == activeIndex.value
|
||
}
|
||
return selfIndex.value >= activeIndex.value - 1 && selfIndex.value <= activeIndex.value + 1
|
||
})
|
||
|
||
watch([() => props.title, () => props.icon, () => props.dot, () => props.dotColor, () => props.count], () => {
|
||
parent?.setTitle({
|
||
key: _pname.value,
|
||
title: props.title,
|
||
icon: props.icon,
|
||
dot: props.dot,
|
||
count: props.count,
|
||
dotColor: props.dotColor
|
||
})
|
||
})
|
||
onUnmounted(() => {
|
||
parent?.unbindKey(_pname.value)
|
||
})
|
||
|
||
//=====
|
||
function onScroll(e: any) {
|
||
// 切换页面中不允许下拉。
|
||
if (tabsSwiperIsMoveing.value) return
|
||
if (reFresh.value == 2 && isUpToogle.value) return
|
||
if (sc_top.value <= refreshJuli) {
|
||
isyesResh.value = true
|
||
} else {
|
||
isyesResh.value = false
|
||
}
|
||
|
||
sc_top.value = e.detail.scrollTop
|
||
reFresh.value = 1
|
||
}
|
||
function onScrollStart() {
|
||
// 切换页面中不允许下拉。
|
||
if (tabsSwiperIsMoveing.value) return
|
||
isUpToogle.value = false
|
||
}
|
||
async function onScrollEnd() {
|
||
// 切换页面中不允许下拉。
|
||
if (tabsSwiperIsMoveing.value) return
|
||
isUpToogle.value = true
|
||
if (reFresh.value == 2) return
|
||
if (isyesResh.value) {
|
||
let p = await funPull('top')
|
||
if (p) {
|
||
reFresh.value = 0
|
||
} else {
|
||
isUpToogle.value = false
|
||
}
|
||
} else {
|
||
reFresh.value = 0
|
||
}
|
||
}
|
||
async function onScrollBootom() {
|
||
// 切换页面中不允许下拉。
|
||
if (tabsSwiperIsMoveing.value) return
|
||
isUpToogle.value = true
|
||
if (reFresh.value == 2) return
|
||
if (isyesResh.value) {
|
||
let p = await funPull('bottom')
|
||
if (p) {
|
||
reFresh.value = 0
|
||
} else {
|
||
isUpToogle.value = false
|
||
}
|
||
} else {
|
||
reFresh.value = 0
|
||
}
|
||
}
|
||
async function funPull(type: 'top' | 'bottom') {
|
||
if (typeof props.pullFun === 'function') {
|
||
uni.showLoading({
|
||
title: '...',
|
||
mask: true
|
||
})
|
||
let p = await props.pullFun(type)
|
||
if (typeof p === 'function') {
|
||
p = await p(type)
|
||
}
|
||
uni.hideLoading()
|
||
return p
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.contentx {
|
||
transition-duration: 0.5s;
|
||
transition-timing-function: ease;
|
||
transition-delay: 0s;
|
||
transform: translateY(0px);
|
||
transition-property: transform, top;
|
||
}
|
||
</style>
|