mirror of
https://github.com/ialley-workshop-open/uni-halo.git
synced 2026-06-12 13:19:31 +08:00
v1.0.0-beta 源码正式开源
This commit is contained in:
@@ -0,0 +1,328 @@
|
||||
<template>
|
||||
<view class="tm-quickIndex " :style="{
|
||||
height: activeHeight_watch + 'px'
|
||||
}">
|
||||
<view :style="{
|
||||
height: activeHeight_watch + 'px'
|
||||
}">
|
||||
<tm-loadding v-if="loadding" label="处理中..."></tm-loadding>
|
||||
<scroll-view scroll-y :class="[black_tmeme?'grey-darken-4':'white']" :style="{
|
||||
height: activeHeight_watch + 'px',
|
||||
}" @scroll="scrollIn" :scroll-into-view="guid+'_'+(isScroll?'':active_value)">
|
||||
<view v-for="(item,index) in dataList" :key="index" :id="guid+'_'+index" class="tm-quickIndex-item">
|
||||
|
||||
<view :class="[black_tmeme?'grey-darken-5':'grey-lighten-4 text']" class=" text-size-s text-weight-b px-32 py-12">{{item.title}}</view>
|
||||
<view>
|
||||
|
||||
<view v-for="(item2,index2) in item.children" :key="index2">
|
||||
|
||||
<slot name="cell" :data="{prevent:index,children:index2,total:item.children.length,item:item2,title:item2[rangKey],color:color_tmeme,black:black_tmeme}">
|
||||
<view :class="[index2!==item.children.length-1?'border-grey-lighten-4-b-1 ':'',black_tmeme?'bk':'']" class="mx-32 py-24 flex-start" @click="changeIndex(index,index2,item2)">
|
||||
<view v-if="item2['icon']" style="width: 48rpx;height: 48rpx;" class="mr-24 rounded flex-center overflow">
|
||||
<tm-icons :size="48" :name="item2['icon']"></tm-icons>
|
||||
</view>
|
||||
<view class="text-size-n">
|
||||
{{item2[rangKey]}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view class="tm-quickIndex-index flex-center flex-col pr-16" :style="{
|
||||
height: activeHeight_watch + 'px'
|
||||
}">
|
||||
<view v-if="showtips"
|
||||
:class="[`text-${color_tmeme}`,black_tmeme?'bk':'']"
|
||||
class="tm-quickIndex-index-Tips absolute rounded shadow-10 flex-center white text-size-g text-weight-b">
|
||||
{{ returnIndexStr(scrollIndx) }}
|
||||
</view>
|
||||
<!-- <view v-if="scrollInBarIndex"
|
||||
:class="[`text-${color}`]"
|
||||
class="tm-quickIndex-index-Tips absolute rounded shadow-10 flex-center white text-size-g text-weight-b">
|
||||
{{returnIndexStr(scrollIndx)}} :class="[scrollIndx==index?`text-${color} text-weight-b`:'']"
|
||||
</view> -->
|
||||
<view v-if="activeHeight_watch>0" @touchend.stop.prevent="indexMove($event,'end')" @touchmove.stop.prevent="indexMove($event,'scroll')"
|
||||
class="tm-quickIndex-index-Bk round-24 shadow-3 " :class="[black_tmeme?'grey-darken-5 bk':'white']">
|
||||
<view @click.stop="acitveItemClick($event,index)"
|
||||
class="tm-quickIndex-index-item text-size-xxs flex-center px-2"
|
||||
|
||||
v-for="(item,index) in dataList" :key="index">
|
||||
{{
|
||||
returnIndexStr(index)
|
||||
}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 快速索引
|
||||
* @property {Array} list = [] 默认:[],列表数据,格式:[{title:"汽车品牌",children:[{title:"宝马"},{title:"奔驰"}]}]
|
||||
* @property {String} rang-key = [] 默认:'title',列表对象key,
|
||||
* @property {String | Number} height = [] 默认:0,高度,默认为0时,自动使用屏幕的高度。
|
||||
* @property {Number} value = [] 默认:0,当前滚动的索引位置,推荐使用v-model或者value.sync
|
||||
* @property {String} color = [] 默认:primary,主题色。
|
||||
* @property {Function} change 点击列表项时产生的事件,返回参数:{prent:父Index,children:子index,data:项数据。}
|
||||
* @example <tm-quickIndex :list='[{title:"汽车品牌",children:[{title:"宝马"},{title:"奔驰"}]}]'></tm-quickIndex>
|
||||
* 如果 不提供index索引字符将截取title第一个字符作为索引。如果title第一个没有将使用自建的数字索引。
|
||||
*/
|
||||
|
||||
import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
|
||||
import tmLoadding from "@/tm-vuetify/components/tm-loadding/tm-loadding.vue"
|
||||
export default {
|
||||
components:{tmIcons,tmLoadding},
|
||||
name: 'tm-quickIndex',
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'input'
|
||||
},
|
||||
props: {
|
||||
// 高度,默认为0时,自动使用屏幕的高度。
|
||||
height: {
|
||||
type: String | Number,
|
||||
default: 0
|
||||
},
|
||||
// 当前滚动的位置。
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
// 当前滚动的位置。
|
||||
color: {
|
||||
type: String,
|
||||
default: "primary"
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
rangKey: {
|
||||
type: String,
|
||||
default: "title"
|
||||
},
|
||||
black: {
|
||||
type: String|Boolean,
|
||||
default: null
|
||||
},
|
||||
// 跟随主题色的改变而改变。
|
||||
fllowTheme:{
|
||||
type:Boolean|String,
|
||||
default:true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: function() {
|
||||
|
||||
this.active = this.value;
|
||||
this.isScroll=false;
|
||||
this.scrollIndx = this.value;
|
||||
},
|
||||
list:{
|
||||
deep:true,
|
||||
handler(){
|
||||
this.dataList = this.list;
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
black_tmeme: function() {
|
||||
if (this.black !== null) return this.black;
|
||||
return this.$tm.vx.state().tmVuetify.black;
|
||||
},
|
||||
color_tmeme:function(){
|
||||
if(this.$tm.vx.state().tmVuetify.color!==null&&this.$tm.vx.state().tmVuetify.color && this.fllowTheme){
|
||||
return this.$tm.vx.state().tmVuetify.color;
|
||||
}
|
||||
return this.color;
|
||||
},
|
||||
active: {
|
||||
get: function() {
|
||||
return this.active_value;
|
||||
},
|
||||
set: async function(val) {
|
||||
this.active_value = val;
|
||||
this.$emit('input', val);
|
||||
this.$emit('update:value', val);
|
||||
let t = this;
|
||||
this.showtips = true;
|
||||
let idx = 5655555
|
||||
clearTimeout(idx)
|
||||
idx = setTimeout(function(){
|
||||
t.showtips = false;
|
||||
},500)
|
||||
|
||||
}
|
||||
},
|
||||
activeHeight_watch: {
|
||||
get: function() {
|
||||
return this.activeHeight;
|
||||
},
|
||||
set: function(val) {
|
||||
this.activeHeight = val;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
minTop:0,
|
||||
activeHeight: 0,
|
||||
guid: "",
|
||||
active_value: 0,
|
||||
listBound: [],
|
||||
nowIndex: 0,
|
||||
showtips: false,
|
||||
isScroll: true,
|
||||
quinkBar: null,
|
||||
scrollIndx: 0,
|
||||
scrollInBarIndex: false,
|
||||
dataList:[],
|
||||
loadding:true
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
this.guid = uni.$tm.guid();
|
||||
let t = this;
|
||||
this.activeHeight_watch = uni.upx2px(this.height);
|
||||
this.loadding=true;
|
||||
await uni.$tm.sleep(50)
|
||||
this.dataList = [...this.list];
|
||||
|
||||
this.$nextTick(async function() {
|
||||
if (!this.activeHeight_watch) {
|
||||
let sysinfo = uni.getSystemInfoSync();
|
||||
this.activeHeight_watch = sysinfo.windowHeight;
|
||||
|
||||
}
|
||||
let df = await this.$Querey(".tm-quickIndex",this).catch(e=>{});
|
||||
|
||||
this.minTop = df[0].top;
|
||||
let indexbar = await t.$Querey(".tm-quickIndex-index-Bk", t).catch(e => {})
|
||||
t.quinkBar = indexbar[0]
|
||||
await uni.$tm.sleep(100)
|
||||
t.active = t.value;
|
||||
uni.createSelectorQuery().in(t).selectAll('.tm-quickIndex-item')
|
||||
.boundingClientRect(res => {
|
||||
res.forEach(item => {
|
||||
t.listBound.push(item.top)
|
||||
})
|
||||
t.loadding=false;
|
||||
}).exec()
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
returnIndexStr(index){
|
||||
let item = this.list[index];
|
||||
if(!item || typeof item === 'undefined') return;
|
||||
if(item['index']&& typeof item['index'] !=='undefined'){
|
||||
|
||||
return item['index'];
|
||||
}else{
|
||||
if(item[this.rangKey][0]&& typeof item[this.rangKey][0] !=='undefined'){
|
||||
return item[this.rangKey][0];
|
||||
}
|
||||
}
|
||||
return index+1
|
||||
|
||||
},
|
||||
scrollIn(e) {
|
||||
let t = this;
|
||||
let y = e.detail.scrollTop;
|
||||
this.isScroll = true;
|
||||
|
||||
function chatIndex(min) {
|
||||
let index = 0;
|
||||
|
||||
for (let i = 0; i < t.listBound.length; i++) {
|
||||
if (t.listBound[i] >= min + t.minTop+1) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
this.nowIndex = chatIndex(y) - 1;
|
||||
|
||||
},
|
||||
changeIndex(prentindex, childrenindex, item) {
|
||||
this.$emit('change', {
|
||||
prent: prentindex,
|
||||
children: childrenindex,
|
||||
data: item
|
||||
})
|
||||
},
|
||||
async acitveItemClick(e, indx) {
|
||||
this.isScroll = false;
|
||||
if (this.list.length <= 0) return;
|
||||
this.active = indx;
|
||||
},
|
||||
async indexMove(e, type) {
|
||||
let t = this;
|
||||
if (this.list.length <= 0) return;
|
||||
if (e.changedTouches.length > 1) return;
|
||||
let y = e.changedTouches[0].clientY;
|
||||
let itemHeight = uni.upx2px(40);
|
||||
let ClickTop = e.target.offsetTop;
|
||||
let index = 0;
|
||||
if (y <= this.quinkBar.top) {
|
||||
index = 0;
|
||||
} else if (y >= this.quinkBar.bottom) {
|
||||
index = this.list.length - 1;
|
||||
} else {
|
||||
let xy = y - this.quinkBar.top
|
||||
index = Math.floor(xy / itemHeight);
|
||||
}
|
||||
if(index>=this.list.length-1) index = this.list.length-1
|
||||
if(index<=0) index = 0;
|
||||
this.isScroll = false;
|
||||
|
||||
if(this.scrollIndx!==index){
|
||||
this.scrollIndx = index
|
||||
}
|
||||
if(this.active!==index){
|
||||
this.active = index;
|
||||
}
|
||||
if (type == 'end') {
|
||||
t.scrollInBarIndex = false;
|
||||
} else {
|
||||
t.scrollInBarIndex = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tm-quickIndex {
|
||||
position: relative;
|
||||
|
||||
.tm-quickIndex-index {
|
||||
position: absolute;
|
||||
right: 0upx;
|
||||
top: 0;
|
||||
|
||||
.tm-quickIndex-index-item {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
// background: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.tm-quickIndex-index-Tips {
|
||||
right: 160rpx;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user