From 1e61215b48e59e94c1ed98e4ef956227d689d6bc Mon Sep 17 00:00:00 2001 From: quanyawei <401863037@qq.com> Date: Mon, 06 Nov 2023 08:48:39 +0800 Subject: [PATCH] fix:小程序订阅消息 --- uni_modules/uview-ui/components/u-index-list/u-index-list.vue | 440 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 440 insertions(+), 0 deletions(-) diff --git a/uni_modules/uview-ui/components/u-index-list/u-index-list.vue b/uni_modules/uview-ui/components/u-index-list/u-index-list.vue new file mode 100644 index 0000000..d712618 --- /dev/null +++ b/uni_modules/uview-ui/components/u-index-list/u-index-list.vue @@ -0,0 +1,440 @@ +<template> + <view class="u-index-list"> + <!-- #ifdef APP-NVUE --> + <list + :scrollTop="scrollTop" + enable-back-to-top + :offset-accuracy="1" + :style="{ + maxHeight: $u.addUnit(scrollViewHeight) + }" + @scroll="scrollHandler" + ref="uList" + > + <cell + v-if="$slots.header" + ref="header" + > + <slot name="header" /> + </cell> + <slot /> + <cell v-if="$slots.footer"> + <slot name="footer" /> + </cell> + </list> + <!-- #endif --> + <!-- #ifndef APP-NVUE --> + <scroll-view + :scrollTop="scrollTop" + :scrollIntoView="scrollIntoView" + :offset-accuracy="1" + :style="{ + maxHeight: $u.addUnit(scrollViewHeight) + }" + scroll-y + @scroll="scrollHandler" + ref="uList" + > + <view v-if="$slots.header"> + <slot name="header" /> + </view> + <slot /> + <view v-if="$slots.footer"> + <slot name="footer" /> + </view> + </scroll-view> + <!-- #endif --> + <view + class="u-index-list__letter" + ref="u-index-list__letter" + :style="{ top: $u.addUnit(letterInfo.top || 100) }" + @touchstart="touchStart" + @touchmove.stop.prevent="touchMove" + @touchend.stop.prevent="touchEnd" + @touchcancel.stop.prevent="touchEnd" + > + <view + class="u-index-list__letter__item" + v-for="(item, index) in uIndexList" + :key="index" + :style="{ + backgroundColor: activeIndex === index ? activeColor : 'transparent' + }" + > + <text + class="u-index-list__letter__item__index" + :style="{color: activeIndex === index ? '#fff' : inactiveColor}" + >{{ item }}</text> + </view> + </view> + <u-transition + mode="fade" + :show="touching" + :customStyle="{ + position: 'fixed', + right: '50px', + top: $u.addUnit(indicatorTop), + zIndex: 2 + }" + > + <view + class="u-index-list__indicator" + :class="['u-index-list__indicator--show']" + :style="{ + height: $u.addUnit(indicatorHeight), + width: $u.addUnit(indicatorHeight) + }" + > + <text class="u-index-list__indicator__text">{{ uIndexList[activeIndex] }}</text> + </view> + </u-transition> + </view> +</template> + +<script> + const indexList = () => { + const indexList = []; + const charCodeOfA = 'A'.charCodeAt(0); + for (let i = 0; i < 26; i++) { + indexList.push(String.fromCharCode(charCodeOfA + i)); + } + return indexList; + } + import props from './props.js'; + // #ifdef APP-NVUE + // ������weex������������KPI���������������������������������������������������������������������������dom��������������������� + const dom = uni.requireNativePlugin('dom') + // #endif + /** + * IndexList ������������ + * @description ������������������������������������ + * @tutorial https://uviewui.com/components/indexList.html + * @property {String} inactiveColor ������������������������������ ( ������ '#606266' ) + * @property {String} activeColor ��������������������������� ( ������ '#5677fc' ) + * @property {Array} indexList ��������������������������������� + * @property {Boolean} sticky ������������������������������ ( ������ true ) + * @property {String | Number} customNavHeight ��������������������������� ( ������ 0 ) + * */ + export default { + name: 'u-index-list', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + // #ifdef MP-WEIXIN + // ���������������������������������������������������Vue������������������������������������flex������ + options: { + virtualHost: true + }, + // #endif + data() { + return { + // ������������������������������������ + activeIndex: -1, + touchmoveIndex: 1, + // ��������������������� + letterInfo: { + height: 0, + itemHeight: 0, + top: 0 + }, + // ������������������������������������������������������������������������������������������������������������������������������������ + indicatorHeight: 50, + // ������������������������top��������������������������������������������� + // indicatorTop: 0 + // ��������������������������������� + touching: false, + // ���������������top��� + scrollTop: 0, + // scroll-view��������� + scrollViewHeight: 0, + // ������������ + sys: uni.$u.sys(), + scrolling: false, + scrollIntoView: '', + } + }, + computed: { + // ������������������������indexList������������������������������������������������A-Z������ + uIndexList() { + return this.indexList.length ? this.indexList : indexList() + }, + // ������������������������top��������������������������������������������� + indicatorTop() { + const { + top, + itemHeight + } = this.letterInfo + return Math.floor(top + itemHeight * this.activeIndex + itemHeight / 2 - this.indicatorHeight / 2) + } + }, + watch: { + // ������������������������������������������������ + uIndexList: { + immediate: true, + handler() { + uni.$u.sleep().then(() => { + this.setIndexListLetterInfo() + }) + } + } + }, + created() { + this.children = [] + this.anchors = [] + this.init() + }, + mounted() { + this.setIndexListLetterInfo() + }, + methods: { + init() { + // ��������������������������������������������� + //������this.customNavHeight���������this.scrollViewHeight���������maxHeight + //���������u-index-list������������tabbar���������,scroll-view������������������������������ + this.scrollViewHeight = this.sys.windowHeight - this.customNavHeight + }, + // ��������������������� + touchStart(e) { + // ��������������������� + const touchStart = e.changedTouches[0] + if (!touchStart) return + this.touching = true + const { + pageY + } = touchStart + // ������������������������������������������������������������������������ + const currentIndex = this.getIndexListLetter(pageY) + this.setValueForTouch(currentIndex) + }, + // ������������������������������������ + touchMove(e) { + // ��������������������� + let touchMove = e.changedTouches[0] + if (!touchMove) return; + + // ������������������������������������������������ touching ��� false ��������������� indicator ������ + if (!this.touching) { + this.touching = true + } + const { + pageY + } = touchMove + const currentIndex = this.getIndexListLetter(pageY) + this.setValueForTouch(currentIndex) + }, + // ������������ + touchEnd(e) { + // ���������������������������������������������������������������������������������������������������������������u-transition���show��������������� + uni.$u.sleep(300).then(() => { + this.touching = false + }) + }, + // ������������������������������������������������������������ + getIndexListLetterRect() { + return new Promise(resolve => { + // ������������������������������dom������ + // #ifndef APP-NVUE + this.$uGetRect('.u-index-list__letter').then(size => { + resolve(size) + }) + // #endif + + // #ifdef APP-NVUE + const ref = this.$refs['u-index-list__letter'] + dom.getComponentRect(ref, res => { + resolve(res.size) + }) + // #endif + }) + }, + // ������indexList��������������������� + setIndexListLetterInfo() { + this.getIndexListLetterRect().then(size => { + const { + height + } = size + const sys = uni.$u.sys() + const windowHeight = sys.windowHeight + let customNavHeight = 0 + // ��������������������������������������������������������������������������������������������������� + if (this.customNavHeight == 0) { + // #ifdef H5 + customNavHeight = sys.windowTop + // #endif + // #ifndef H5 + // ������H5���������������������������������������������windowHeight��������������������������������������������������������������������������� + customNavHeight = -(sys.statusBarHeight + 44) + // #endif + } else { + customNavHeight = uni.$u.getPx(this.customNavHeight) + } + this.letterInfo = { + height, + // ������������������������������������������������������������������������������������������������������������������������ + top: (windowHeight - height) / 2 + customNavHeight / 2, + itemHeight: Math.floor(height / this.uIndexList.length) + } + }) + }, + // ������������������������������������ + getIndexListLetter(pageY) { + const { + top, + height, + itemHeight + } = this.letterInfo + // ���H5���pageY���������������������������uni-app���������������H5���������������������������H5��������������������������������� + // #ifdef H5 + pageY += uni.$u.sys().windowTop + // #endif + // ��������������������������������������������������������������������������������������������������������������������������������� + if (pageY < top) { + return 0 + } else if (pageY >= top + height) { + // ��������������������������������������� + return this.uIndexList.length - 1 + } else { + // ���������������Y������������������������������������top������������������������������������������������������������������������������������ + return Math.floor((pageY - top) / itemHeight); + } + }, + // ������������������������������������������ + setValueForTouch(currentIndex) { + // ������������������������������������������������������������������������������������������������ + if (currentIndex === this.activeIndex) return + this.activeIndex = currentIndex + // #ifndef APP-NVUE || MP-WEIXIN + // ������nvue������������anchor���item������u-index-item���������������������index-item������������ + this.scrollIntoView = `u-index-item-${this.uIndexList[currentIndex].charCodeAt(0)}` + // #endif + // #ifdef MP-WEIXIN + // ���������������������scroll-view���scroll-into-view���������������slot���������������id���������������������������scrollTop��������������������������� + this.scrollTop = this.children[currentIndex].top + // #endif + // #ifdef APP-NVUE + // ���nvue������������cell���header������������������������������������������header(anchor)������������ + const anchor = `u-index-anchor-${this.uIndexList[currentIndex]}` + dom.scrollToElement(this.anchors[currentIndex].$refs[anchor], { + offset: 0, + animated: false + }) + // #endif + }, + getHeaderRect() { + // ������header slot������������������list���������������������������������������top������ + return new Promise(resolve => { + dom.getComponentRect(this.$refs.header, res => { + resolve(res.size) + }) + }) + }, + // scroll-view��������������� + async scrollHandler(e) { + if (this.touching || this.scrolling) return + // ������������������������������������������������������������������������������ + this.scrolling = true + uni.$u.sleep(10).then(() => { + this.scrolling = false + }) + let scrollTop = 0 + const len = this.children.length + let children = this.children + const anchors = this.anchors + // #ifdef APP-NVUE + // nvue��������������������������������������������������������� + scrollTop = Math.abs(e.contentOffset.y) + // ������header slot��������������� + const header = await this.getHeaderRect() + // item���top���������nvue������������������anchor���top������������nvue������index-item���top + let top = header.height + // ������list������������������cell���top������������������header slot���������item���������height���������������������nvue������������������ + children = this.children.map((item, index) => { + const child = { + height: item.height, + top + } + // ���������������������������item������������������ + top += item.height + anchors[index].height + return child + }) + // #endif + // #ifndef APP-NVUE + // ���nvue������detail��������������������� + scrollTop = e.detail.scrollTop + // #endif + for (let i = 0; i < len; i++) { + const item = children[i], + nextItem = children[i + 1] + // ������������������������������������item���top��������������������������������������������� + if (scrollTop <= children[0].top || scrollTop >= children[len - 1].top + children[len - + 1].height) { + this.activeIndex = -1 + break + } else if (!nextItem) { + // ���������������������item��������������������������������������� + this.activeIndex = len - 1 + break + } else if (scrollTop > item.top && scrollTop < nextItem.top) { + this.activeIndex = i + break + } + } + }, + }, + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-index-list { + + &__letter { + position: fixed; + right: 0; + text-align: center; + z-index: 3; + padding: 0 6px; + + &__item { + width: 16px; + height: 16px; + border-radius: 100px; + margin: 1px 0; + @include flex; + align-items: center; + justify-content: center; + + &--active { + background-color: $u-primary; + } + + &__index { + font-size: 12px; + text-align: center; + line-height: 12px; + } + } + } + + &__indicator { + width: 50px; + height: 50px; + border-radius: 100px 100px 0 100px; + text-align: center; + color: #ffffff; + background-color: #c9c9c9; + transform: rotate(-45deg); + @include flex; + justify-content: center; + align-items: center; + + &__text { + font-size: 28px; + line-height: 28px; + font-weight: bold; + color: #fff; + transform: rotate(45deg); + text-align: center; + } + } + } +</style> -- Gitblit v1.8.0