|
|
@@ -5,37 +5,44 @@
|
|
|
<block v-for="(item, index) in list.data" :key="item.id">
|
|
|
<view
|
|
|
class="list"
|
|
|
- :class="{ 'dragging': draggedIndex === index }"
|
|
|
+ :class="{
|
|
|
+ 'dragging': draggedIndex === index,
|
|
|
+ 'target-position': targetIndex === index && isDragging && targetIndex !== draggedIndex
|
|
|
+ }"
|
|
|
:style="{
|
|
|
transform: transformStyle(index),
|
|
|
transition: isDragging ? 'none' : 'transform 0.3s ease',
|
|
|
- zIndex: draggedIndex === index ? 999 : 1
|
|
|
+ zIndex: draggedIndex === index ? 999 : (targetIndex === index && isDragging ? 888 : 1)
|
|
|
}">
|
|
|
<view class="list-img">
|
|
|
<image :src="item.cover" mode="aspectFit" ></image>
|
|
|
</view>
|
|
|
- <view class="list-det">
|
|
|
- <view class="app-size-28 app-color-0" style="font-size:30upx;font-weight:bold;">{{ item.name || item.goodsName}}</view>
|
|
|
+ <view class="list-det" style="position:absolute;top:10upx;left:125upx;">
|
|
|
+ <view class="app-size-28 app-color-0" style="font-size:28upx;font-weight:bold;">{{ item.name || item.goodsName}}</view>
|
|
|
</view>
|
|
|
|
|
|
- <text v-if="index > 0" style="right:335upx;" class="move-btn" @click.stop="topFn(item.id)">↑</text>
|
|
|
- <text v-if="index > 0" style="right:350upx;line-height: 12upx;" class="move-btn-line">-</text>
|
|
|
+ <view class="list-det" style="position:absolute;bottom:10upx;left:122upx;">
|
|
|
+ <view v-if="item.priceType == 1" class="app-size-28 app-color-0" style="font-size:24upx;">¥{{ item.price}}</view>
|
|
|
+ <view v-else class="app-size-28 app-color-0" style="font-size:24upx;border:1px solid #ccc;border-radius:30upx;padding:3upx 15upx;">无价格</view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <text v-if="index > 0" style="right:375upx;" class="move-btn move-btn-top" :class="{ 'disabled': isOperating }" @click.stop="topFn(item.id)" title="置顶">⇈</text>
|
|
|
|
|
|
- <text v-if="index < list.data.length - 1" style="right:255upx;" class="move-btn" @click.stop="bottomFn(item.id)">↓</text>
|
|
|
- <text v-if="index < list.data.length - 1" style="right:272upx;line-height: 72upx;" class="move-btn-line">-</text>
|
|
|
+ <text v-if="index < list.data.length - 1" style="right:290upx;" class="move-btn move-btn-bottom" :class="{ 'disabled': isOperating }" @click.stop="bottomFn(item.id)" title="置底">⇊</text>
|
|
|
+
|
|
|
|
|
|
- <text style="right:170upx;" class="move-btn" @click.stop="upFn(item.id)">↑</text>
|
|
|
- <text style="right:95upx;" class="move-btn" @click.stop="downFn(item.id)">↓</text>
|
|
|
+ <text style="right:205upx;" class="move-btn move-btn-up" :class="{ 'disabled': isOperating }" @click.stop="upFn(item.id)" title="上移一位">↑</text>
|
|
|
+ <text style="right:120upx;" class="move-btn move-btn-down" :class="{ 'disabled': isOperating }" @click.stop="downFn(item.id)" title="下移一位">↓</text>
|
|
|
|
|
|
<view
|
|
|
- style="position:absolute;top:58upx;right:28upx;cursor:move;"
|
|
|
+ style="position:absolute;top:50upx;right:14upx;cursor:move;"
|
|
|
class="drag-handle"
|
|
|
:data-index="index"
|
|
|
:data-id="item.id"
|
|
|
@touchstart="dragStart"
|
|
|
@touchmove="dragMove"
|
|
|
@touchend="dragEnd">
|
|
|
- <text style="color:#333333;font-size:45upx;">≡</text>
|
|
|
+ <text style="color:#666666;font-size:48upx;padding:8upx 6upx;line-height:1;">≡</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</block>
|
|
|
@@ -58,19 +65,32 @@ export default {
|
|
|
mixins: [list],
|
|
|
data() {
|
|
|
return {
|
|
|
- categoryId: '', // 分类ID
|
|
|
draggedIndex: -1,
|
|
|
draggedItem: null,
|
|
|
dragOffsetY: 0,
|
|
|
isDragging: false,
|
|
|
- itemHeight: 160, // 列表项高度,单位upx
|
|
|
+ itemHeight: 160, // 列表项高度,单位upx(与CSS中的height保持一致)
|
|
|
startY: 0,
|
|
|
+ scrollTop: 0, // 页面滚动高度
|
|
|
+ originalOrder: [], // 原始顺序,用于拖拽失败时恢复
|
|
|
+ targetIndex: -1, // 目标交换位置的索引
|
|
|
+ isOperating: false, // 防止快速点击操作按钮
|
|
|
+ totalNum: 0, // 总数量
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onPageScroll(e) {
|
|
|
+ // 拖拽期间禁止更新滚动高度
|
|
|
+ if (!this.isDragging) {
|
|
|
+ this.scrollTop = e.scrollTop
|
|
|
}
|
|
|
},
|
|
|
onPullDownRefresh() {
|
|
|
this.resetList()
|
|
|
this._list().then(res => {
|
|
|
uni.stopPullDownRefresh()
|
|
|
+ }).catch(err => {
|
|
|
+ console.error('下拉刷新失败:', err)
|
|
|
+ uni.stopPullDownRefresh()
|
|
|
})
|
|
|
},
|
|
|
onReachBottom() {
|
|
|
@@ -82,13 +102,6 @@ export default {
|
|
|
uni.stopPullDownRefresh()
|
|
|
}
|
|
|
},
|
|
|
- onLoad(options) {
|
|
|
- // 接收传递过来的分类ID参数
|
|
|
- if (options && options.id) {
|
|
|
- this.categoryId = options.id
|
|
|
- }
|
|
|
- //this.init()
|
|
|
- },
|
|
|
methods: {
|
|
|
async init() {
|
|
|
// 确保list.data是数组
|
|
|
@@ -100,37 +113,15 @@ export default {
|
|
|
_list() {
|
|
|
// 传递分类ID参数和分页参数到API
|
|
|
const params = {
|
|
|
- categoryId: this.categoryId,
|
|
|
+ cId: this.option.id,
|
|
|
page: this.list.page,
|
|
|
pageSize: this.list.pageSize
|
|
|
}
|
|
|
- console.log('请求参数:', params)
|
|
|
- console.log('当前list.data:', this.list.data)
|
|
|
- console.log('list.data类型:', Array.isArray(this.list.data) ? 'Array' : typeof this.list.data)
|
|
|
|
|
|
return getListB(params).then(res => {
|
|
|
- console.log('API返回数据:', res)
|
|
|
-
|
|
|
- // 确保返回的数据结构符合预期
|
|
|
- const responseData = {
|
|
|
- code: res.code,
|
|
|
- msg: res.msg,
|
|
|
- data: {
|
|
|
- list: res.data && res.data.list ? res.data.list : [],
|
|
|
- finished: res.moreData,
|
|
|
- totalPage: res.totalPage || 1
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- console.log('处理后的数据:', responseData)
|
|
|
- console.log('处理后的数据 -- :', res)
|
|
|
-
|
|
|
// 使用mixin提供的completes方法处理分页数据
|
|
|
this.completes(res)
|
|
|
-
|
|
|
- console.log('最终列表数据:', this.list.data)
|
|
|
- console.log('列表长度:', this.list.data.length)
|
|
|
- console.log('是否还有更多数据:', this.list.finished)
|
|
|
+ this.totalNum = Number(res.data.total)
|
|
|
}).catch(err => {
|
|
|
console.error('API请求失败:', err)
|
|
|
this.list.loading = false
|
|
|
@@ -146,54 +137,97 @@ export default {
|
|
|
},
|
|
|
|
|
|
dragStart(e) {
|
|
|
+ // 防止重复触发
|
|
|
+ if (this.isDragging) return
|
|
|
+
|
|
|
+ this.isDragging = true
|
|
|
+
|
|
|
const index = parseInt(e.currentTarget.dataset.index)
|
|
|
+ if (isNaN(index) || index < 0 || index >= this.list.data.length) {
|
|
|
+ this.isDragging = false
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
this.draggedIndex = index
|
|
|
this.draggedItem = this.list.data[index]
|
|
|
this.startY = e.touches[0].clientY
|
|
|
- this.isDragging = true
|
|
|
+ this.targetIndex = index // 初始化目标位置为当前位置
|
|
|
+
|
|
|
+ // 保存原始顺序,用于拖拽失败时恢复
|
|
|
+ this.originalOrder = [...this.list.data]
|
|
|
+
|
|
|
+ // 添加拖拽模式样式,防止页面滚动
|
|
|
+ this.toggleDragMode(true)
|
|
|
+
|
|
|
+ // 阻止默认行为,防止页面滚动(兼容微信端与H5)
|
|
|
+ if (e.preventDefault) {
|
|
|
+ e.preventDefault()
|
|
|
+ }
|
|
|
+ if (e.stopPropagation) {
|
|
|
+ e.stopPropagation()
|
|
|
+ }
|
|
|
+ return false
|
|
|
},
|
|
|
|
|
|
dragMove(e) {
|
|
|
if (!this.isDragging || this.draggedIndex === -1) return
|
|
|
|
|
|
+ // 验证触摸点是否存在
|
|
|
+ if (!e.touches || !e.touches[0]) return
|
|
|
+
|
|
|
+ // 阻止默认行为,防止页面滚动(兼容微信端与H5)
|
|
|
+ if (e.preventDefault) {
|
|
|
+ e.preventDefault()
|
|
|
+ }
|
|
|
+ if (e.stopPropagation) {
|
|
|
+ e.stopPropagation()
|
|
|
+ }
|
|
|
+
|
|
|
const currentY = e.touches[0].clientY
|
|
|
const deltaY = currentY - this.startY
|
|
|
|
|
|
// 根据设备像素比例转换为upx单位,确保在不同设备上表现一致
|
|
|
- const pixelRatio = uni.getSystemInfoSync().pixelRatio || 2
|
|
|
- const deltaYupx = deltaY * (750 / uni.getSystemInfoSync().windowWidth)
|
|
|
+ const systemInfo = uni.getSystemInfoSync()
|
|
|
+ const pixelRatio = 750 / systemInfo.windowWidth
|
|
|
+ const deltaYupx = deltaY * pixelRatio
|
|
|
|
|
|
- this.dragOffsetY = deltaYupx
|
|
|
+ // 限制拖拽范围,防止超出列表边界
|
|
|
+ const maxOffset = (this.list.data.length - 1 - this.draggedIndex) * this.itemHeight
|
|
|
+ const minOffset = -this.draggedIndex * this.itemHeight
|
|
|
+ const limitedOffset = Math.max(minOffset, Math.min(maxOffset, deltaYupx))
|
|
|
|
|
|
- // 更精确地计算目标位置
|
|
|
- const itemHeightUpx = this.itemHeight * (750 / uni.getSystemInfoSync().windowWidth)
|
|
|
+ this.dragOffsetY = limitedOffset
|
|
|
|
|
|
- // 使用更精确的计算方法确定移动的项目数
|
|
|
- const moveDistance = Math.abs(deltaYupx)
|
|
|
- const moveDirection = deltaYupx > 0 ? 1 : -1
|
|
|
- const moveItems = Math.floor(moveDistance / (itemHeightUpx * 0.5)) * moveDirection
|
|
|
+ // 实时计算目标位置,让用户看到将要交换的元素
|
|
|
+ const moveItems = Math.round(limitedOffset / this.itemHeight)
|
|
|
+ this.targetIndex = Math.max(0, Math.min(this.list.data.length - 1, this.draggedIndex + moveItems))
|
|
|
+ },
|
|
|
+
|
|
|
+ dragEnd() {
|
|
|
+ if (!this.isDragging) return
|
|
|
|
|
|
- // 确保目标索引在有效范围内
|
|
|
+ // 计算最终位置
|
|
|
+ const moveItems = Math.round(this.dragOffsetY / this.itemHeight)
|
|
|
const targetIndex = Math.max(0, Math.min(this.list.data.length - 1, this.draggedIndex + moveItems))
|
|
|
|
|
|
+ // 如果位置有变化,则更新数组
|
|
|
if (targetIndex !== this.draggedIndex) {
|
|
|
- // 交换元素位置
|
|
|
const newData = [...this.list.data]
|
|
|
const draggedItem = newData[this.draggedIndex]
|
|
|
+
|
|
|
+ // 移除拖拽项
|
|
|
newData.splice(this.draggedIndex, 1)
|
|
|
+ // 插入到新位置
|
|
|
newData.splice(targetIndex, 0, draggedItem)
|
|
|
|
|
|
- // 更新数据和拖拽状态
|
|
|
this.list.data = newData
|
|
|
- this.draggedIndex = targetIndex
|
|
|
- this.startY = currentY
|
|
|
- this.dragOffsetY = 0
|
|
|
+
|
|
|
+ // 更新排序值并发送到后端
|
|
|
+ this.updateSortOrder()
|
|
|
}
|
|
|
- },
|
|
|
-
|
|
|
- dragEnd(e) {
|
|
|
- console.log('dragEnd')
|
|
|
- if (!this.isDragging) return
|
|
|
+
|
|
|
+ // 移除拖拽模式样式
|
|
|
+ this.toggleDragMode(false)
|
|
|
|
|
|
// 重置拖拽状态
|
|
|
this.draggedIndex = -1
|
|
|
@@ -201,19 +235,17 @@ export default {
|
|
|
this.dragOffsetY = 0
|
|
|
this.isDragging = false
|
|
|
this.startY = 0
|
|
|
-
|
|
|
- // 更新排序值并发送到后端
|
|
|
- this.updateSortOrder()
|
|
|
+ this.originalOrder = []
|
|
|
+ this.targetIndex = -1 // 重置目标位置
|
|
|
},
|
|
|
|
|
|
updateSortOrder() {
|
|
|
// 更新每个项目的inTurn值,从大到小排序(值越大越靠前)
|
|
|
const sortData = this.list.data.map((item, index) => ({
|
|
|
id: item.id,
|
|
|
- inTurn: this.list.data.length - index // 反向索引,使第一个项目有最大值
|
|
|
+ inTurn: this.totalNum - index // 反向索引,使第一个项目有最大值
|
|
|
}))
|
|
|
-
|
|
|
- console.log(sortData)
|
|
|
+ // console.log('排序数据:', sortData)
|
|
|
|
|
|
// 调用API更新排序
|
|
|
sort({ items: sortData }).then(res => {
|
|
|
@@ -221,17 +253,64 @@ export default {
|
|
|
this.$msg('排序更新成功')
|
|
|
} else {
|
|
|
this.$msg('排序更新失败')
|
|
|
+ // 恢复原始顺序
|
|
|
+ this.list.data = this.originalOrder
|
|
|
}
|
|
|
}).catch(err => {
|
|
|
console.error('更新排序失败:', err)
|
|
|
this.$msg('排序更新失败')
|
|
|
+ // 恢复原始顺序
|
|
|
+ this.list.data = this.originalOrder
|
|
|
})
|
|
|
},
|
|
|
|
|
|
+ // 切换拖拽模式,防止页面滚动
|
|
|
+ toggleDragMode(isDragging) {
|
|
|
+ // #ifdef H5
|
|
|
+ // H5平台:直接操作body样式
|
|
|
+ if (isDragging) {
|
|
|
+ document.body.classList.add('dragging-mode')
|
|
|
+ } else {
|
|
|
+ document.body.classList.remove('dragging-mode')
|
|
|
+ }
|
|
|
+ // #endif
|
|
|
+
|
|
|
+ // #ifndef H5
|
|
|
+ // 微信小程序、App:使用页面样式和滚动API
|
|
|
+ if (isDragging) {
|
|
|
+ uni.setPageStyle({
|
|
|
+ style: {
|
|
|
+ 'overflow': 'hidden',
|
|
|
+ 'position': 'fixed',
|
|
|
+ 'width': '100%',
|
|
|
+ 'top': `-${this.scrollTop}px`,
|
|
|
+ 'left': '0',
|
|
|
+ 'right': '0'
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ uni.setPageStyle({
|
|
|
+ style: {
|
|
|
+ 'overflow': '',
|
|
|
+ 'position': '',
|
|
|
+ 'width': '',
|
|
|
+ 'top': '',
|
|
|
+ 'left': '',
|
|
|
+ 'right': ''
|
|
|
+ }
|
|
|
+ })
|
|
|
+ uni.pageScrollTo({
|
|
|
+ scrollTop: this.scrollTop,
|
|
|
+ duration: 0
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // #endif
|
|
|
+ },
|
|
|
+
|
|
|
// 原有的上移下移方法
|
|
|
upFn(id) {
|
|
|
- console.log('upFn: ' + id)
|
|
|
-
|
|
|
+ if (this.isOperating) return
|
|
|
+ this.isOperating = true
|
|
|
const index = this.list.data.findIndex(item => item.id === id)
|
|
|
if (index > 0) {
|
|
|
const newData = [...this.list.data]
|
|
|
@@ -241,11 +320,16 @@ export default {
|
|
|
this.list.data = newData
|
|
|
this.updateSortOrder()
|
|
|
}
|
|
|
+
|
|
|
+ // 防抖延迟
|
|
|
+ setTimeout(() => {
|
|
|
+ this.isOperating = false
|
|
|
+ }, 300)
|
|
|
},
|
|
|
|
|
|
downFn(id) {
|
|
|
- console.log('downFn: ' + id)
|
|
|
-
|
|
|
+ if (this.isOperating) return
|
|
|
+ this.isOperating = true
|
|
|
const index = this.list.data.findIndex(item => item.id === id)
|
|
|
if (index < this.list.data.length - 1) {
|
|
|
const newData = [...this.list.data]
|
|
|
@@ -255,12 +339,17 @@ export default {
|
|
|
this.list.data = newData
|
|
|
this.updateSortOrder()
|
|
|
}
|
|
|
+
|
|
|
+ // 防抖延迟
|
|
|
+ setTimeout(() => {
|
|
|
+ this.isOperating = false
|
|
|
+ }, 300)
|
|
|
},
|
|
|
|
|
|
// 置顶
|
|
|
topFn(id) {
|
|
|
- console.log('topFn: ' + id)
|
|
|
-
|
|
|
+ if (this.isOperating) return
|
|
|
+ this.isOperating = true
|
|
|
const index = this.list.data.findIndex(item => item.id === id)
|
|
|
if (index > 0) {
|
|
|
const newData = [...this.list.data]
|
|
|
@@ -273,11 +362,17 @@ export default {
|
|
|
this.list.data = newData
|
|
|
this.updateSortOrder()
|
|
|
}
|
|
|
+
|
|
|
+ // 防抖延迟
|
|
|
+ setTimeout(() => {
|
|
|
+ this.isOperating = false
|
|
|
+ }, 300)
|
|
|
},
|
|
|
+
|
|
|
// 置底
|
|
|
bottomFn(id) {
|
|
|
- console.log('bottomFn: ' + id)
|
|
|
-
|
|
|
+ if (this.isOperating) return
|
|
|
+ this.isOperating = true
|
|
|
const index = this.list.data.findIndex(item => item.id === id)
|
|
|
if (index < this.list.data.length - 1) {
|
|
|
const newData = [...this.list.data]
|
|
|
@@ -290,6 +385,11 @@ export default {
|
|
|
this.list.data = newData
|
|
|
this.updateSortOrder()
|
|
|
}
|
|
|
+
|
|
|
+ // 防抖延迟
|
|
|
+ setTimeout(() => {
|
|
|
+ this.isOperating = false
|
|
|
+ }, 300)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -310,9 +410,6 @@ export default {
|
|
|
color: $fontColor3;
|
|
|
border-bottom: 1px solid $borderColor;
|
|
|
position:relative;
|
|
|
- .list-index {
|
|
|
- width: 50upx;
|
|
|
- }
|
|
|
.list-img {
|
|
|
width: 130upx;
|
|
|
height: 130upx;
|
|
|
@@ -330,61 +427,175 @@ export default {
|
|
|
margin-top: 0;
|
|
|
}
|
|
|
}
|
|
|
- .list-operate {
|
|
|
- width:480upx;
|
|
|
- margin-top:10upx;
|
|
|
- @include disFlex(center, space-between);
|
|
|
- .operate-det {
|
|
|
- width:490upx;
|
|
|
- padding-left:120upx;
|
|
|
- & > span {
|
|
|
- border:1px solid #ccc;
|
|
|
- border-radius:25upx;
|
|
|
- padding:5upx 20upx 5upx 20upx;
|
|
|
- font-size:25upx;
|
|
|
- margin-left:35upx;
|
|
|
- &:first-child {
|
|
|
- margin-left: 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.move-btn {
|
|
|
position: absolute;
|
|
|
- top:65upx;
|
|
|
- color:blue;
|
|
|
- border:1px solid #CCCCCC;
|
|
|
- padding: 6upx 12upx;
|
|
|
- border-radius:50%;
|
|
|
- z-index: 9999;
|
|
|
+ top: 60upx;
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 60upx;
|
|
|
+ height: 60upx;
|
|
|
+ color: #fff;
|
|
|
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
+ border: 2px solid rgba(255, 255, 255, 0.3);
|
|
|
+ border-radius: 50%;
|
|
|
+ font-size: 28upx; /* 增大20% */
|
|
|
+ font-weight: bold;
|
|
|
+ box-shadow: 0 4upx 12upx rgba(102, 126, 234, 0.3);
|
|
|
+ transition: all 0.2s ease;
|
|
|
+ z-index: 9999;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ /* 触摸反馈 */
|
|
|
+ &:active {
|
|
|
+ transform: scale(0.95);
|
|
|
+ box-shadow: 0 2upx 8upx rgba(102, 126, 234, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 悬停效果 */
|
|
|
+ &:hover {
|
|
|
+ transform: translateY(-2upx);
|
|
|
+ box-shadow: 0 6upx 20upx rgba(102, 126, 234, 0.4);
|
|
|
+ }
|
|
|
}
|
|
|
-.move-btn-line {
|
|
|
- position: absolute;
|
|
|
- top:65upx;
|
|
|
- color:blue;
|
|
|
- font-size: 26upx;
|
|
|
- z-index: 1;
|
|
|
+
|
|
|
+/* 置顶按钮 - 红色渐变 */
|
|
|
+.move-btn-top {
|
|
|
+ // background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
|
|
|
+ // box-shadow: 0 4upx 12upx rgba(255, 107, 107, 0.3);
|
|
|
+ background: linear-gradient(135deg, #feca57 0%, #ff9ff3 100%);
|
|
|
+ box-shadow: 0 4upx 12upx rgba(254, 202, 87, 0.3);
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 6upx 20upx rgba(255, 107, 107, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ box-shadow: 0 2upx 8upx rgba(255, 107, 107, 0.5);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 置底按钮 - 橙色渐变 */
|
|
|
+.move-btn-bottom {
|
|
|
+ background: linear-gradient(135deg, #feca57 0%, #ff9ff3 100%);
|
|
|
+ box-shadow: 0 4upx 12upx rgba(254, 202, 87, 0.3);
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 6upx 20upx rgba(254, 202, 87, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ box-shadow: 0 2upx 8upx rgba(254, 202, 87, 0.5);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 上移按钮 - 绿色渐变 */
|
|
|
+.move-btn-up {
|
|
|
+ background: linear-gradient(135deg, #48dbfb 0%, #0abde3 100%);
|
|
|
+ box-shadow: 0 4upx 12upx rgba(72, 219, 251, 0.3);
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 6upx 20upx rgba(72, 219, 251, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ box-shadow: 0 2upx 8upx rgba(72, 219, 251, 0.5);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 下移按钮 - 紫色渐变 */
|
|
|
+.move-btn-down {
|
|
|
+ // background: linear-gradient(135deg, #a55eea 0%, #8854d0 100%);
|
|
|
+ // box-shadow: 0 4upx 12upx rgba(165, 94, 234, 0.3);
|
|
|
+ background: linear-gradient(135deg, #48dbfb 0%, #0abde3 100%);
|
|
|
+ box-shadow: 0 4upx 12upx rgba(72, 219, 251, 0.3);
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 6upx 20upx rgba(165, 94, 234, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ box-shadow: 0 2upx 8upx rgba(165, 94, 234, 0.5);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+/* 按钮禁用状态 */
|
|
|
+.move-btn.disabled {
|
|
|
+ opacity: 0.5;
|
|
|
+ transform: none !important;
|
|
|
+ box-shadow: 0 2upx 6upx rgba(0, 0, 0, 0.1) !important;
|
|
|
+ pointer-events: none;
|
|
|
+ cursor: not-allowed;
|
|
|
+ &:hover, &:active {
|
|
|
+ transform: none !important;
|
|
|
+ box-shadow: 0 2upx 6upx rgba(0, 0, 0, 0.1) !important;
|
|
|
+ }
|
|
|
+}
|
|
|
// 拖拽相关样式
|
|
|
.list.dragging {
|
|
|
border: 2px dashed #007AFF !important;
|
|
|
- box-shadow: 0 4px 20px rgba(0, 122, 255, 0.3) !important;
|
|
|
- background-color: rgba(0, 122, 255, 0.05) !important;
|
|
|
- opacity: 0.85;
|
|
|
- border-radius: 12upx;
|
|
|
- transform: scale(1.05);
|
|
|
+ box-shadow: 0 8upx 40upx rgba(0, 122, 255, 0.25) !important;
|
|
|
+ background-color: rgba(0, 122, 255, 0.08) !important;
|
|
|
+ opacity: 0.9;
|
|
|
+ border-radius: 16upx;
|
|
|
+ transform: scale(1.02);
|
|
|
+ transition: none !important; /* 拖拽时禁用过渡动画 */
|
|
|
+}
|
|
|
+
|
|
|
+.list.target-position {
|
|
|
+ border: 3px solid #52C41A !important; /* 使用绿色边框区别于拖拽元素 */
|
|
|
+ box-shadow: 0 6upx 30upx rgba(82, 196, 26, 0.3) !important;
|
|
|
+ background-color: rgba(82, 196, 26, 0.1) !important;
|
|
|
+ opacity: 0.95;
|
|
|
+ border-radius: 16upx;
|
|
|
+ transform: scale(1.01);
|
|
|
+ transition: all 0.2s ease !important; /* 目标位置保持平滑过渡 */
|
|
|
+
|
|
|
+ /* 添加一个内部指示器 */
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ width: 100upx;
|
|
|
+ height: 6upx;
|
|
|
+ background: linear-gradient(90deg, #52C41A, #73D13D);
|
|
|
+ border-radius: 3upx;
|
|
|
+ opacity: 0.8;
|
|
|
+ z-index: 99990;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.drag-handle {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 80upx;
|
|
|
+ height: 75upx;
|
|
|
+ border-radius: 12upx;
|
|
|
+ background-color: rgba(0, 0, 0, 0.03);
|
|
|
transition: all 0.2s ease;
|
|
|
+ -webkit-touch-callout: none; /* 禁用长按菜单 */
|
|
|
+ -webkit-user-select: none; /* 禁用文本选择 */
|
|
|
+ user-select: none;
|
|
|
+ touch-action: none; /* 禁用浏览器默认触摸行为 */
|
|
|
+
|
|
|
+ /* 增加触摸反馈 */
|
|
|
+ &:active {
|
|
|
+ transform: scale(1.1);
|
|
|
+ background-color: rgba(0, 122, 255, 0.1);
|
|
|
+ box-shadow: 0 4upx 16upx rgba(0, 122, 255, 0.2);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.drag-handle:active {
|
|
|
- transform: scale(1.1);
|
|
|
- opacity: 0.8;
|
|
|
+/* 防止拖拽时页面滚动 */
|
|
|
+.dragging-mode {
|
|
|
+ overflow: hidden !important;
|
|
|
+ touch-action: none !important;
|
|
|
+ -webkit-overflow-scrolling: auto !important;
|
|
|
}
|
|
|
</style>
|