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,272 @@
|
||||
<template>
|
||||
<view class="tm-dragList ">
|
||||
<view :style="{height:h*list.length+'px',width:w+'px'}" class="relative"
|
||||
:class="[disabled?'opacity-7':'']">
|
||||
<view class="fulled-height overflow" :class="[bgColor,black_tmeme?'grey-darken-4 bk':'',
|
||||
'absolute',
|
||||
'tm-dragList-item','shadow-'+(nowMove_index==index?16:0),'flex-between']" v-for="(item,index) in listData"
|
||||
:key="index" :style="{
|
||||
transition: nowMove_index==index||endDrage?'all 0s':'all 0.25s',
|
||||
top: item.top+'px',
|
||||
height:h+'px',width:w+'px',zIndex:nowMove_index==index?5:0}">
|
||||
<view class=" flex-start fulled" :class="[black_tmeme?'border-grey-darken-5-b-1':'border-b-1']"
|
||||
:style="{height:(h-1)+'px'}"
|
||||
>
|
||||
<view v-if="item['icon']" class="flex-shrink pl-32 fulled-height flex-center">
|
||||
<tm-icons :black="black_tmeme" :color="item['color']||'black'" :fllowTheme="fllowTheme" dense
|
||||
:name="item['icon']" :size="40"></tm-icons>
|
||||
|
||||
</view>
|
||||
<view class="pl-32 text-size-n" :class="[black_tmeme?'bk':'']">{{item.text}}</view>
|
||||
</view>
|
||||
<view
|
||||
:style="{height:(h-1)+'px',width: '100rpx'}"
|
||||
@touchstart="m_start($event,index)"
|
||||
@mousedown="m_start($event,index)"
|
||||
@touchmove.stop.prevent="m_move($event,index)"
|
||||
@mousemove.stop.prevent="m_move($event,index)"
|
||||
@touchend="m_end($event,index)"
|
||||
@mouseup="m_end($event,index)"
|
||||
class="flex-shrink flex-end " :class="[black_tmeme?'border-grey-darken-5-b-1':'border-b-1']">
|
||||
<text class="iconfont icon-menu pr-32 text-size-n"
|
||||
:class="[black_tmeme?' bk text-grey-darken-2':'text-grey']"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 拖放排序
|
||||
* @property {String | Boolean} black = [true|false] 默认:null,是否开启暗黑模式
|
||||
* @property {String | Boolean} disabled = [true|false] 默认:false,是否禁用,禁用后无法操作。
|
||||
* @property {Number} width = [] 默认:0,组件的宽度,rpx,可不提供,默认为父组件的宽度。
|
||||
* @property {Number} height = [] 默认:120,列表项目的高度,rpx,
|
||||
* @property {String} bgColor = [] 默认:white,项目的背景色
|
||||
* @property {String} right-icon = [] 默认:'',项目右边可拖动的图标
|
||||
* @property {String} rang-key = [] 默认:'text',列表项目读取文本的key
|
||||
* @property {String} list = [] 默认:[],列表数据[{text: "菜单选项",icon: 'icon-menu',color:'red'}]
|
||||
* @param {Function} change 拖动排序后,触发,返回新的排序后list数据。
|
||||
*/
|
||||
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
|
||||
export default {
|
||||
name: "tm-dragList",
|
||||
components: {
|
||||
tmIcons
|
||||
},
|
||||
props: {
|
||||
disabled: {
|
||||
type: String | Boolean,
|
||||
default: false
|
||||
},
|
||||
// 跟随主题色的改变而改变。
|
||||
fllowTheme: {
|
||||
type: Boolean | String,
|
||||
default: true
|
||||
},
|
||||
// 是否开启暗黑模式
|
||||
black: {
|
||||
type: String | Boolean,
|
||||
default: null
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 120
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
rangKey: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
rightIcon: {
|
||||
type: String,
|
||||
default: "icon-menu"
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: "white"
|
||||
},
|
||||
|
||||
},
|
||||
destroyed() {
|
||||
clearTimeout(999)
|
||||
},
|
||||
watch: {
|
||||
list: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.jishunTopData();
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
w: 0,
|
||||
h: 0,
|
||||
totalH: 0,
|
||||
y: 0,
|
||||
|
||||
new_index: null, //即将被替换的索引(实质性被替换)
|
||||
nowMove_index: null, //现在正在移动的索引
|
||||
listData: [], //被处理过的数据。
|
||||
new_item: [], //虚拟列表,内部排列好,但未在页面中渲染。
|
||||
endDrage: false,
|
||||
Drage__id: '', //正在被拖动的id;
|
||||
h_top: 0,
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
black_tmeme: function() {
|
||||
if (this.black !== null) return this.black;
|
||||
return this.$tm.vx.state().tmVuetify.black;
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
let t = this;
|
||||
this.jishunTopData();
|
||||
},
|
||||
methods: {
|
||||
jishunTopData() {
|
||||
this.$nextTick(async function() {
|
||||
this.listData = [];
|
||||
|
||||
let p = await this.$Querey(".tm-dragList", this).catch(e => {})
|
||||
this.w = uni.upx2px(this.width) || p[0].width;
|
||||
this.h = uni.upx2px(this.height)
|
||||
|
||||
this.totalH = this.h * this.list.length
|
||||
let list = [];
|
||||
for (let i = 0; i < this.list.length; i++) {
|
||||
let p = this.list[i];
|
||||
p['top'] = i * this.h;
|
||||
p['i'] = i;
|
||||
p['__id'] = uni.$tm.guid();
|
||||
this.listData.push(p)
|
||||
}
|
||||
this.new_item = [...this.listData];
|
||||
|
||||
})
|
||||
},
|
||||
m_start(event, index) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
if (this.disabled) return;
|
||||
|
||||
this.nowMove_index = index;
|
||||
|
||||
this.endDrage = false;
|
||||
this.new_item = [...this.listData];
|
||||
if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
|
||||
var touch = event.changedTouches[0];
|
||||
this.y = touch.pageY - event.currentTarget.offsetTop - this.listData[index].top
|
||||
} else {
|
||||
this.y = event.pageY - event.currentTarget.offsetTop - this.listData[index].top
|
||||
}
|
||||
|
||||
// #ifdef MP
|
||||
uni.vibrateShort({})
|
||||
// #endif
|
||||
},
|
||||
m_move(event, index) {
|
||||
if (this.disabled) return;
|
||||
let t = this
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
if (t.nowMove_index == null) return;
|
||||
//当前元素的top位置。
|
||||
let ch = 0;
|
||||
if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
|
||||
var touch = event.changedTouches[0];
|
||||
ch = touch.pageY - t.y
|
||||
|
||||
} else {
|
||||
ch = event.pageY - t.y
|
||||
}
|
||||
|
||||
t.listData.splice(index, 1, {
|
||||
...t.listData[index],
|
||||
top: ch
|
||||
})
|
||||
const currenit_index = index;
|
||||
const currentSort = t.listData[currenit_index].i;
|
||||
const currenit_id = t.listData[currenit_index].__id;
|
||||
|
||||
// 计算当前移动的index.
|
||||
let moveIndex = Math.round(ch / t.h);
|
||||
|
||||
moveIndex = moveIndex < 0 ? 0 : moveIndex;
|
||||
moveIndex = moveIndex > t.listData.length - 1 ? t.listData.length - 1 : moveIndex;
|
||||
|
||||
moveIndex = Math.abs(moveIndex)
|
||||
|
||||
index = moveIndex;
|
||||
let elList = [...t.listData]
|
||||
for (let i = 0; i < elList.length; i++) {
|
||||
if (currentSort < moveIndex) {
|
||||
if (elList[i].i > currentSort && elList[i].i <= moveIndex) {
|
||||
elList[i].i -= 1;
|
||||
};
|
||||
} else if (currentSort > moveIndex) {
|
||||
if (elList[i].i < currentSort && elList[i].i >= moveIndex) {
|
||||
elList[i].i += 1;
|
||||
};
|
||||
}
|
||||
};
|
||||
elList[currenit_index].i = moveIndex;
|
||||
elList = elList.map(im => {
|
||||
if (im.__id != currenit_id) {
|
||||
im.top = im.i * t.h;
|
||||
}
|
||||
|
||||
return im;
|
||||
})
|
||||
t.listData = elList;
|
||||
t.new_index = moveIndex;
|
||||
// #ifdef MP
|
||||
uni.vibrateShort({})
|
||||
// #endif
|
||||
|
||||
|
||||
},
|
||||
m_end(event, index) {
|
||||
if (this.disabled) return;
|
||||
let t = this;
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
this.nowMove_index = null;
|
||||
this.endDrage = true;
|
||||
if (this.new_index == null) return;
|
||||
let elList = t.listData
|
||||
elList = elList.map(im => {
|
||||
im.top = im.i * t.h;
|
||||
return im;
|
||||
})
|
||||
elList.sort((a,b)=>a.i-b.i)
|
||||
t.listData = [...elList]
|
||||
this.moveChange();
|
||||
},
|
||||
|
||||
moveChange(e, index) {
|
||||
if (this.disabled) return;
|
||||
//change后修改的数据 。
|
||||
this.$emit('change', this.listData);
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user