移动端touch事件
<template>
<div class="systemListPage">
<div class="search">
<el-input v-model="paramsData.keywords" @input="searchList" placeholder="输入拼音首字母/名字,搜索应用" clearable class="input">
<span slot="prefix">
<img src="@/assets/common/fangdajing.png" />
</span>
</el-input>
</div>
<transition-group class="container" name="flip-list" tag="ul">
<div
id="draggable-list"
class="systemList draggable-item"
:ref="'lists' + key"
draggable="true"
@touchstart="touchstart(key, $event, item)"
@touchmove="touchmove($event, item, key)"
@touchend="touchend($event)"
:data-item="item.app_name"
:key="item.app_id"
v-for="(item, key) in list"
@click.stop="goSystem(item, key)"
@dragenter="dragenter(item, $event)"
@dragstart="dragstart(item)"
@dragover="dragover($event)"
@dragend="touchend($event)"
>
<div :class="(attribute.length > 0 || func.length > 0) && activeIndex == key ? 'item' : 'otheritem'" :style="{ backgroundColor: JSON.parse(item.app_api_show).style.bgc }">
<span class="title"> {{ item.app_name }}</span>
<div class="topItem" v-if="attribute.length > 0 && activeIndex == key">
<div class="attr-list">
<div class="attr-item" v-for="item in attribute" :key="item.id">
<div class="number" @click.stop="handleClickAttrib(item)">{{ Number(item.keyFunc) }}</div>
<div class="title">{{ item.valueFunc }}</div>
</div>
</div>
</div>
<div class="bottomItem" v-if="func.length > 0 && activeIndex == key">
<div class="big_box">
<span class="tj">统计列表</span>
<div class="func-list" @click="handleClickFunc(ele)" v-for="ele in func" :key="ele.id">
<div class="func-item">
<div class="pic">
<img src="@/assets/common/bookmark.png" />
</div>
<div class="title">{{ ele.funcName }}</div>
</div>
</div>
</div>
</div>
</div>
<span class="name"> {{ item.app_info }}</span>
</div>
</transition-group>
</div>
</template>
<script>
import { getApplyProperty, getApplicationList, getByApp } from "@/api/applicationList.js";
import { mapMutations, mapGetters } from "vuex";
import { appPersonal } from "@/api/applicationList";
import { loginOA } from "@/api/userInfo";
export default {
name: "systemList",
data() {
return {
list: [],
draggingItem: null,
lastItem: null,
appId: "",
attributeParameter: {
funcld: "",
},
attribute: [],
func: [],
activeIndex: null,
paramsData: {
page: 1,
size: 10,
keywords: "",
type: "2",
},
personal_app: [],
newData: "",
reorderedItems: [],
dragging: null,
dragStartPosition: { x: 0, y: 0 },
ismove: false,
};
},
created() {
this.getApplicationList();
},
computed: {
...mapGetters(["token"]),
},
methods: {
searchList(val) {
this.paramsData.keywords = val;
this.getApplicationList();
},
...mapMutations("sx_system", ["setTreeData", "setEerTreeData"]),
async getApplicationList() {
const {
data: { data },
} = await getApplicationList(this.paramsData);
const arr = data.list.sort((a, b) => a.sort - b.sort);
this.list = arr;
},
async getApplyProperty() {
const { data } = await getApplyProperty(this.attributeParameter);
this.attribute = data.data;
},
async getByApp() {
const {
data: { data },
} = await getByApp(this.attributeParameter);
this.func = data;
},
async goSystem(item, key) {
try {
if (item.app_api) {
this.setTreeData(JSON.parse(item.app_api));
}
this.attributeParameter.appId = item.id;
this.getByApp();
this.getApplyProperty();
if (item.app_type === 1) {
this.activeIndex = key;
this.$emit("showmaskingFlag");
} else if (item.app_type === 99) {
const { data } = await loginOA({ app_id: item.id });
if (data.code === 1) {
window.location.href = `${data.data.url}`;
}
} else {
window.location.href = `${JSON.parse(item.app_api_show).url}?Api-Auth=${this.token}&target_url=${JSON.parse(item.app_api_show).target_url}`;
}
} catch (error) {
console.log(error);
}
},
handleClickAttrib(item) {
this.$router.push({
path: `${item.attrUrl}${item.keyFunc}`,
});
},
handleClickFunc(item) {
const hrefFlag = item.funcUrl.includes("http");
if (hrefFlag) {
window.location.href = `${item.funcUrl}?Api-Auth=${this.token}&type=close_menu`;
} else {
this.setEerTreeData(JSON.parse(item.appApi));
console.log("setTreeData-->", JSON.parse(item.appApi));
this.$router.push({
path: `${item.funcUrl}`,
});
}
},
dragstart(item) {
this.draggingItem = item;
},
touchstart(index, event, item) {
if (!this.ismove) {
this.draggingItem = item;
this.dragging = index;
this.dragStartPosition = { x: event.touches[0].clientX, y: event.touches[0].clientY };
this.ismove = false;
}
},
dragenter(item, e) {
this.newData = item;
this.ismove = true;
e.preventDefault();
},
async touchmove(event, item, index) {
this.ismove = true;
if (this.dragging === null) return;
const touch = event.touches[0];
this.list.forEach(async (item, index) => {
if (index === this.dragging) return;
const element = this.$el.querySelector(`.draggable-item[data-item="${item.app_name}"]`);
if (!element) return;
const rect = element.getBoundingClientRect();
if (touch.clientX >= rect.left && touch.clientX <= rect.right && touch.clientY >= rect.top && touch.clientY <= rect.bottom) {
this.newData = item;
event.preventDefault();
}
});
},
async touchend() {
if (this.ismove) {
this.dragging = null;
if (this.draggingItem !== this.newData) {
let oldIndex = this.list.indexOf(this.draggingItem);
let newIndex = this.list.indexOf(this.newData);
let newItems = [...this.list];
newItems.splice(oldIndex, 1);
newItems.splice(newIndex, 0, this.draggingItem);
this.list = [...newItems];
const result = this.list.map((item, index) => ({
id: item.id,
app_id: item.app_id,
sort: index + 1,
}));
const {
data: { code },
} = await appPersonal({ personal_app: JSON.stringify(result) });
if (code === 1) {
this.getApplicationList();
}
}
}
this.ismove = false;
},
dragover(e) {
e.preventDefault();
},
},
};
</script>
<style lang="scss" scoped>
.systemListPage {
position: relative;
display: flex;
flex-wrap: wrap;
justify-content: center;
flex-direction: column;
max-width: 1200px;
.search {
margin: 50px 0;
.input {
font-size: 16px;
background-color: transparent;
width: 610px;
height: 50px;
border-radius: 15px;
border: #ccc;
&:focus {
outline: none;
}
img {
width: 20px;
height: 20px;
line-height: 20px;
}
}
::v-deep .el-input__prefix {
display: flex;
align-items: center;
justify-content: center;
padding-left: 10px;
padding-top: 5px;
}
}
.container {
display: flex;
flex-wrap: wrap;
padding-left: 0;
.systemList {
position: relative;
padding: 30px;
margin-bottom: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&:hover {
background-color: #e3e3e3;
border-radius: 20px;
.fixedThumbnails {
position: absolute;
top: 10px;
right: 10px;
width: 20px;
height: 20px;
background-size: 20px 20px;
cursor: pointer;
}
.fixedThumbnails_fixed {
position: absolute;
top: 10px;
right: 10px;
width: 20px;
height: 20px;
background-size: 20px 20px;
cursor: pointer;
}
}
.item {
position: relative;
// padding: 0 20px;
width: 78px;
height: 78px;
text-align: center;
line-height: 78px;
background-color: #fcf1ef;
border-radius: 20px;
font-family: "Arial Normal", "Arial", sans-serif;
font-weight: 400;
font-style: normal;
font-size: 18px;
z-index: 100;
&:nth-child(2) {
width: 80px;
height: 80px;
text-align: center;
line-height: 80px;
background-color: #fcf1ef !important;
border-radius: 20px;
font-weight: 400;
font-style: normal;
font-size: 24px;
}
.topItem {
position: absolute;
top: -103px;
left: 88px;
padding: 10px;
height: 70px;
border-radius: 15px;
z-index: 6;
background-color: #fff;
-webkit-box-shadow: 8px 9px 21px 0px rgba(62, 66, 66, 0.1);
-moz-box-shadow: 8px 9px 21px 0px rgba(62, 66, 66, 0.1);
box-shadow: 8px 9px 21px 0px rgba(62, 66, 66, 0.1);
.attr-list {
display: flex;
justify-content: space-around;
line-height: 30px;
.attr-item {
height: 70px;
width: 45px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 0 5px;
.number {
color: #fff;
font-weight: 700;
width: 30px;
height: 30px;
border-radius: 50%;
text-align: center;
line-height: 30px;
background-color: #7f7f7f;
cursor: pointer;
box-sizing: border-box;
font-size: 14px;
}
.active {
border: 2px solid yellowgreen;
}
.title {
font-size: 14px;
}
}
}
}
.bottomItem {
position: absolute;
top: 1px;
left: 88px;
border-radius: 15px;
z-index: 6;
background-color: #fff;
-webkit-box-shadow: 8px 9px 21px 0px rgba(62, 66, 66, 0.1);
-moz-box-shadow: 8px 9px 21px 0px rgba(62, 66, 66, 0.1);
box-shadow: 8px 9px 21px 0px rgba(62, 66, 66, 0.1);
// transition: 0.2s ease-out;
.big_box {
display: flex;
flex-direction: column;
overflow: scroll;
padding: 12px;
max-height: 400px;
.func-list {
line-height: 20px;
cursor: pointer;
border-bottom: 1px solid #e8eaec;
.func-item {
width: 250px;
height: 41px;
display: flex;
align-items: center;
padding: 0 10px;
.pic {
margin-right: 10px;
img {
height: 20px;
}
}
.title {
font-size: 14px;
}
}
&:hover {
// border-radius: 15px;
background-color: #e8eaec;
}
&:last-child {
// border-bottom: none;
}
&:first-child:hover {
border-radius: 15px 15px 0 0;
}
&:last-child:hover {
// border-radius: 0 0 15px 15px;
}
}
.tj {
position: sticky;
top: 0;
height: 30px;
line-height: 30px;
font-size: 14px;
text-align: left;
border-radius: 15px 15px 0 0;
background-color: #fff;
border-bottom: 1px solid #e8eaec;
}
}
}
.title {
font-size: 23px;
}
}
.otheritem {
position: relative;
// padding: 0 20px;
height: 76px;
width: 76px;
text-align: center;
line-height: 76px;
background-color: #fcf1ef;
border-radius: 20px;
font-family: "Arial Normal", "Arial", sans-serif;
font-weight: 400;
font-style: normal;
font-size: 17px;
border: 1px solid #d7d7d7;
box-sizing: border-box;
.title {
font-size: 23px;
}
}
.name {
margin-top: 17px;
font-size: 15px;
}
}
}
.flip-list-move {
transition: transform 0.3s;
}
}
::v-deep .search input.el-input__inner {
border-radius: 15px !important;
height: 50px;
}
</style>
dragstart(item) {
this.draggingItem = item;
},
touchstart(e, item) {
console.log("touchstart-->", e, item);
},
touchmove(e, item) {
e.preventDefault();
console.log("touchmove-->", item);
},
touchend(e, item) {
e.preventDefault();
console.log("touchend-->", item);
},
dragover(item) {
if (item !== this.draggingItem && this.lastItem !== item) {
const fromIndex = this.list.indexOf(this.draggingItem);
const toIndex = this.list.indexOf(item);
const temp = this.list[fromIndex];
[this.list[fromIndex], this.list[toIndex]] = [this.list[toIndex], temp];
this.list = [...this.list];
}
this.lastItem = item;
},
async dragend() {
const result = this.list.map((item, index) => ({
id: item.id,
app_id: item.app_id,
sort: index + 1,
}));
const {
data: { code },
} = await appPersonal({ personal_app: JSON.stringify(result) });
if (code === 1) {
this.getApplicationList();
}
},