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,415 @@
|
||||
<template>
|
||||
<view class="tm-switchList fulled overflow border-b-1" :class="[black_tmeme?'grey-darken-4 bk':bgColor]"
|
||||
:style="{height:height+'rpx'}">
|
||||
<movable-area :style="{height:height+'rpx',width:w+'px'}">
|
||||
|
||||
<movable-view :disabled="disabled" :animation="showright" :x="activeOn"
|
||||
:style="{height:height+'rpx',width:(w-i_w)+'px'}" inertia @change="onChange" direction="horizontal">
|
||||
<view :style="{width:(w-i_w)+'px'}" :class="[disabled?'gray-100':'']"
|
||||
class="fulled fulled-height flex-between relative">
|
||||
<view @click="click" @touchend="move_action_end" @touchstart="move_action_start"
|
||||
:style="{width:(w+i_w)+'px',left:-(w)+'px'}" class=" fulled-height flex-shrink absolute">
|
||||
<view class="fulled-height " :style="{width:(w)+'px',marginLeft:(w-i_w)+'px'}">
|
||||
<view class="fulled fulled-height flex-start overflow ">
|
||||
<view v-if="icon" class=" d-inline-block">
|
||||
<view class="overflow flex-end" style="width: 102rpx;height: 80rpx;">
|
||||
<view v-if="dotObj.dot!==null" class="absolute fulled-height fulled" style="z-index: 10;">
|
||||
<tm-badges :dot="dotObj.dot" :label="dotObj.label" :icon="dotObj.icon"
|
||||
:offset="[5,10]"></tm-badges>
|
||||
</view>
|
||||
<view class=" flex-center overflow flex-shrink round-4" style="width: 80rpx;height: 80rpx;">
|
||||
|
||||
<slot name="left" :hdata="{width:80,height:80}">
|
||||
<tm-images :round="4" :src="iconName" :width="80" :height="80" v-if="vtype==false"></tm-images>
|
||||
<view v-if="vtype==true" class="round-4 flex-center "
|
||||
:class="[color_tmeme,black_tmeme?'bk':'']"
|
||||
style="width: 80rpx;height: 80rpx;">
|
||||
|
||||
<text :style="{fontSize: iconSize+'rpx'}"
|
||||
:class="[prefx_computed,iconName]"></text>
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="d-inline-block overflow px-32 "
|
||||
:style="{width: `calc(100% - ${icon?164:0}rpx)`,height:height+'rpx'}">
|
||||
<view class="fulled-height flex-between overflow">
|
||||
<view :style="{width: `calc(100% - ${icon?160:150}rpx)`}">
|
||||
<slot name="default">
|
||||
<view class="text-size-n text-overflow ">{{title}}</view>
|
||||
<view v-if="label" class="text-size-s text-grey text-overflow pt-4">
|
||||
{{label}}
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
<view class="flex-end fulled-height relative">
|
||||
<view class=" absolute flex-shrink" style="z-index: 9;">
|
||||
<slot name="right">
|
||||
<view v-if="rightLabel"
|
||||
class="text-size-s text-grey text-align-right nowrap">{{rightLabel}}
|
||||
</view>
|
||||
<view v-if="rightIcon" class="flex-end nowrap pt-10">
|
||||
<tm-icons :fllowTheme="fllowTheme" :color="color_tmeme"
|
||||
:name="rightIcon"></tm-icons>
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view @click="click" @touchend="move_action_end" @touchstart="move_action_start"
|
||||
:style="{width:w+'px'}" class="fulled fulled-height flex-end absolute">
|
||||
<block v-if="showright">
|
||||
<view @click.stop="actionsClick(index,item)" v-for="(item,index) in actions" :key="index"
|
||||
:style="{width:(item.width||itemWidth)+'rpx'}" :class="[item['color']||'white']"
|
||||
class=" fulled-height flex-center text-size-n flex-shrink">{{item.text}}</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</movable-view>
|
||||
</movable-area>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 滑动单元格
|
||||
* @property {String | Boolean} black = [true|false] 默认:null,是否开启暗黑模式
|
||||
* @property {String | Boolean} disabled = [true|false] 默认:false,是否禁用,禁用后无法操作。
|
||||
* @property {String | Boolean} on = [true|false] 默认:false,是否打开操作栏
|
||||
* @property {Number} width = [] 默认:0,单元格的宽度,rpx,可不提供,默认为父组件的宽度
|
||||
* @property {Number} height = [] 默认:120,单元格的高度度,rpx,
|
||||
* @property {Number} item-width = [] 默认:140,底部操作按钮的宽度,rpx,
|
||||
* @property {Number} icon-size = [] 默认:40,项目左边的图标大小,rpx,
|
||||
* @property {String} color = [] 默认:primary,主题颜色名称
|
||||
* @property {String} bgColor = [] 默认:white,项目的背景色
|
||||
* @property {String} icon = [] 默认:'',项目左边的图标
|
||||
* @property {String} right-icon = [] 默认:'',项目右边的图标
|
||||
* @property {String} right-label = [] 默认:'',项目右边的文字
|
||||
* @property {String} title = [] 默认:'',项目的标题
|
||||
* @property {String} label = [] 默认:'',项目的详细信息文字
|
||||
* @property {String|Boolean|Number} dot = [] 默认:false,是否显示左边图标的角标.Boolean类型时,显示dot。String类型时显示图标,Number类型时显示数字角标。
|
||||
* @property {String} actions = [] 默认:[],底部的操作按钮格式:{text: "删除列表",width: 190,color: 'red'}
|
||||
* @param {Function} click 点击项目时触发
|
||||
* @param {Function} actionsClick 点击操作按钮时触发,{index:index,item:item}
|
||||
*/
|
||||
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
|
||||
import tmBadges from '@/tm-vuetify/components/tm-badges/tm-badges.vue';
|
||||
import tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue';
|
||||
export default {
|
||||
name: "tm-switchList",
|
||||
components: {
|
||||
tmIcons,
|
||||
tmBadges,tmImages
|
||||
},
|
||||
props: {
|
||||
width: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 140
|
||||
},
|
||||
itemWidth: {
|
||||
type: Number,
|
||||
default: 180
|
||||
},
|
||||
on: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: 'primary'
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: 'white'
|
||||
},
|
||||
// 跟随主题色的改变而改变。
|
||||
fllowTheme: {
|
||||
type: Boolean | String,
|
||||
default: true
|
||||
},
|
||||
// 是否开启暗黑模式
|
||||
black: {
|
||||
type: String | Boolean,
|
||||
default: null
|
||||
},
|
||||
disabled: {
|
||||
type: String | Boolean,
|
||||
default: false
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
iconSize: {
|
||||
type: Number | String,
|
||||
default: 40
|
||||
},
|
||||
rightIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
rightLabel: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '标题'
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
dot: {
|
||||
type: String | Boolean | Number,
|
||||
default: false
|
||||
},
|
||||
actions: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
x: 0,
|
||||
old_x: 0,
|
||||
w: 0,
|
||||
h: 0,
|
||||
i_w: 0,
|
||||
showright: false,
|
||||
isopnen: 0,
|
||||
timidId: 88656,
|
||||
isDrageUp: false,
|
||||
is_js_cha_old_x: true,
|
||||
cha_old_x: 0,
|
||||
last_len: 0, //最后一次的距离差,
|
||||
last_dir: 0 //最后一次的方向。原因在于滑动时,可能断点
|
||||
};
|
||||
},
|
||||
watch:{
|
||||
on:function(){
|
||||
if(this.on==true){
|
||||
this.$nextTick(function(){
|
||||
this.activeOn = 0
|
||||
})
|
||||
}else if(this.on==false){
|
||||
this.$nextTick(function(){
|
||||
this.activeOn = this.i_w;
|
||||
})
|
||||
}
|
||||
},
|
||||
actions:function () {
|
||||
this.initsWH();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
vtype: function() {
|
||||
if (this.icon[0] == "." ||
|
||||
this.icon[0] == "/" ||
|
||||
this.icon.substring(0, 4) == 'http' ||
|
||||
this.icon.substring(0, 5) == 'https' ||
|
||||
this.icon.substring(0, 3) == 'ftp'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
iconName: function() {
|
||||
return this.icon;
|
||||
},
|
||||
prefx_computed(){
|
||||
let prefix = this.icon.split('-')[0];
|
||||
if(prefix=='icon') return 'iconfont';
|
||||
if(prefix=='mdi') return 'mdi';
|
||||
|
||||
return prefix;
|
||||
},
|
||||
dotObj: function() {
|
||||
if (typeof this.dot === 'number' && this.dot) {
|
||||
return {
|
||||
dot: false,
|
||||
label: this.dot,
|
||||
icon: ''
|
||||
};
|
||||
}
|
||||
if (typeof this.dot === 'string' && this.dot) {
|
||||
|
||||
if(this.dot.indexOf('-')>0){
|
||||
return {
|
||||
dot: false,
|
||||
label: 0,
|
||||
icon: this.dot
|
||||
};
|
||||
}else{
|
||||
|
||||
return {
|
||||
dot: false,
|
||||
label: this.dot,
|
||||
icon: ''
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
if (typeof this.dot === 'boolean' && this.dot) {
|
||||
return {
|
||||
dot: true,
|
||||
label: 0,
|
||||
icon: ''
|
||||
};
|
||||
}
|
||||
return {
|
||||
dot: null,
|
||||
label: 0,
|
||||
icon: ''
|
||||
};
|
||||
},
|
||||
activeOn: {
|
||||
get: function() {
|
||||
if (this.disabled) return this.i_w;
|
||||
return this.isopnen;
|
||||
},
|
||||
set: function(val) {
|
||||
this.isopnen = val
|
||||
|
||||
}
|
||||
},
|
||||
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;
|
||||
},
|
||||
|
||||
},
|
||||
async mounted() {
|
||||
this.initsWH();
|
||||
},
|
||||
methods: {
|
||||
initsWH(){
|
||||
let t = this;
|
||||
let iitemw = uni.upx2px(this.itemWidth);
|
||||
let total = 0;
|
||||
for (let i = 0; i < this.actions.length; i++) {
|
||||
if (this.actions[i]['width']) {
|
||||
total += uni.upx2px(this.actions[i]['width'])
|
||||
} else {
|
||||
total += iitemw
|
||||
}
|
||||
}
|
||||
|
||||
this.$nextTick(async function() {
|
||||
|
||||
let p = await this.$Querey(".tm-switchList", this,30).catch(e => {})
|
||||
this.w = uni.upx2px(this.width) || p[0].width
|
||||
this.i_w = total
|
||||
this.x = this.on ? 0 : this.i_w;
|
||||
this.isopnen = this.on ? 0 : this.i_w;
|
||||
setTimeout(function() {
|
||||
t.showright = true;
|
||||
}, 50)
|
||||
})
|
||||
},
|
||||
move_action_start(e) {
|
||||
if (this.activeOn)
|
||||
this.isDrageUp = false;
|
||||
this.is_js_cha_old_x = true
|
||||
|
||||
},
|
||||
async move_action_end(e) {
|
||||
this.isDrageUp = true;
|
||||
let t = this;
|
||||
await uni.$tm.sleep(50)
|
||||
//t.last_len移动的距离。
|
||||
//t.last_dir 负为左。正为右
|
||||
//左方向。需要达到一定的距离差才会执行
|
||||
//以免误触。
|
||||
if (t.last_dir < 0) {
|
||||
|
||||
// console.log('左');
|
||||
// 如果此时,已经在左边。如果还继续往左拉,就是复位到左边。而不是右边。
|
||||
if (t.activeOn == 0) {
|
||||
t.activeOn = 20;
|
||||
await uni.$tm.sleep(200)
|
||||
t.activeOn = 0;
|
||||
return;
|
||||
}
|
||||
if (t.last_len > 20) {
|
||||
t.activeOn = t.i_w + 10;
|
||||
t.$nextTick(function() {
|
||||
t.activeOn = 0;
|
||||
})
|
||||
} else if (t.last_len <= 20) {
|
||||
t.activeOn = t.x - 10
|
||||
t.$nextTick(function() {
|
||||
t.activeOn = t.i_w;
|
||||
})
|
||||
}
|
||||
//右方向
|
||||
} else if (t.last_dir > 0) {
|
||||
// console.log('右');
|
||||
t.activeOn = t.i_w + 10
|
||||
await uni.$tm.sleep(10)
|
||||
t.$nextTick(function() {
|
||||
|
||||
t.activeOn = t.i_w;
|
||||
})
|
||||
}
|
||||
},
|
||||
actionsClick(index, item) {
|
||||
if (this.disabled) return;
|
||||
this.$emit('actionsClick', {
|
||||
index: index,
|
||||
item: item
|
||||
});
|
||||
},
|
||||
click(e) {
|
||||
this.activeOn = this.i_w;
|
||||
if (this.disabled) return;
|
||||
this.$emit('click', e)
|
||||
|
||||
},
|
||||
onChange: function(e) {
|
||||
let t = this;
|
||||
let pos_x = e.detail.x;
|
||||
this.last_dir = pos_x - this.x; //上一次移动到下一次移动的距离。正为右,负为反方向左。
|
||||
if (this.is_js_cha_old_x == true && this.isDrageUp == false) {
|
||||
this.cha_old_x = pos_x;
|
||||
this.is_js_cha_old_x = false;
|
||||
// console.log('按下', pos_x);
|
||||
}
|
||||
if (this.isDrageUp == true && this.is_js_cha_old_x == false) {
|
||||
this.$nextTick(function() {
|
||||
this.is_js_cha_old_x = true;
|
||||
this.last_len = Math.floor(Math.abs(this.cha_old_x - pos_x)); //从第一次移动到结束时的移动距离。
|
||||
// console.log('松开', this.last_len);
|
||||
})
|
||||
}
|
||||
t.x = pos_x;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user