<template>
<view class="container">
<!-- 顶部标题 -->
<view class="header">
<text class="title">藏品布局工具</text>
</view>
<view class="main-content">
<!-- 中间:布局区域 -->
<view class="center-panel">
<text class="panel-title">布局区域</text>
<movable-area class="layout-area" ref="layoutArea">
<!-- 选中的背景图 -->
<image v-if="data.default" :src="data.default.bgImg" class="background-image"></image>
<!-- 可拖拽的藏品 -->
<movable-view direction="all" scale @change="(e:any) => handleDragChange(index,item, e)"
v-for="(item,index) in addedCollections" :key="item.id" class="draggable-item" :x="item.x"
:y="item.y" :width="item.width" :height="item.height" @scale="(e:any)=>onScale(item,e)"
:scale-value="item.scale" scale-min='0.8' scale-max='2' :animation="false"
:style="{ zIndex: item.zIndex, position: 'absolute' }" :data-id="item.id">
{{item.scale}}
<image :src="(item.thumbnail)" mode="widthFix" class="collection-img"
:style="{width:'100px',height:'100px'}"></image>
</movable-view>
</movable-area>
</view>
<!-- 右侧:藏品列表 -->
<view class="right-panel">
<text class="panel-title">我的藏品</text>
<view class="my-collections">
<view class="collection-item" v-for="item in data.cpList" :key="item.id"
@tap="addItemDirectly(item)">
<image :src="(item.thumbnail)" mode="aspectFill" class="collection-img"
:style="{width:'100px',height:'100px'}"></image>
</view>
</view>
</view>
</view>
<!-- 底部操作按钮 -->
<view class="bottom-actions">
<button class="action-btn" @click="resetLayout">重置布局</button>
<button class="action-btn primary" @click="saveLayout">保存布局</button>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted, nextTick, watch, reactive } from 'vue';
import { onLoad } from "@dcloudio/uni-app";
const data = reactive<any>({
default:{bgImg: 'https://oss.elianip.com/images/2025/August/64201b5f309c69a43dc8c0355da67aa5a01a21.jpg'},
cpList: [
{ "id": 350315, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749023825, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1256, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": "0", "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },
{ "id": 350314, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749023454, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1255, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 0, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },
{ "id": 350313, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749022226, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1254, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 1, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },
{ "id": 350312, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749022166, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1253, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 1, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },
{ "id": 350311, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749022089, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1252, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 1, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },
{ "id": 350310, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749019534, "nftIntro": "农历九月初九,二九相重,称为重九。九是阳数,所以“重九”又叫“重阳”。九九重阳,寓意长长久久。在1989年,我国把每年农历的九月初九定为“老人节”,所谓百善孝为先,重阳节敬老,最能体现古人德孝这一独特而朴素的自然道德观。", "nftName": "重阳节", "nftId": 366, "imagePath": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "txId": "", "amount": 1, "nftSn": 1251, "totalQuantity": 2023, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 2592000, "transferCount": 1, "isNew": 1, "thumbnail": "https://oss.elianip.com/images/2023/October/43087f618f516c70b4a418b02a8de803924915.jpg", "tag": "", "tagImage": "", "lockTime": 0 },
{ "id": 350287, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749017366, "nftIntro": "民以食为天,我们感恩土地的馈赠喜看稻菽千重浪,同时铭记“珍惜盘中餐的古训,珍惜每一粒粮食。在世界粮食日川渝数藏推出主题藏品《五谷丰登》以此向那些默默耕耘的农耕人致敬。", "nftName": "五谷丰登", "nftId": 534, "imagePath": "https://oss.elianip.com/images/2024/October/96ea720504a0d927850a764e1b21f7b341bfc1.jpg", "txId": "", "amount": 1, "nftSn": 1819, "totalQuantity": 2024, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 0, "transferCount": 1, "isNew": 1, "thumbnail": "/images/2024/October/eb2ee5e11906f4bd10a48c34b8b28a6f988120.jpg", "tag": "", "tagImage": "", "lockTime": 0 },
{ "id": 350285, "userId": "952aedf8-4141-4fac-b6d4-3effdcf9fecc", "createTime": 1749017366, "nftIntro": "民以食为天,我们感恩土地的馈赠喜看稻菽千重浪,同时铭记“珍惜盘中餐的古训,珍惜每一粒粮食。在世界粮食日川渝数藏推出主题藏品《五谷丰登》以此向那些默默耕耘的农耕人致敬。", "nftName": "五谷丰登", "nftId": 534, "imagePath": "https://oss.elianip.com/images/2024/October/96ea720504a0d927850a764e1b21f7b341bfc1.jpg", "txId": "", "amount": 1, "nftSn": 1818, "totalQuantity": 2024, "artistName": "川渝数藏", "artistLogo": "https://oss.elianip.com/images/2023/July/5.png", "frozenTime": 0, "transferCount": 1, "isNew": 1, "thumbnail": "/images/2024/October/eb2ee5e11906f4bd10a48c34b8b28a6f988120.jpg", "tag": "", "tagImage": "", "lockTime": 0 }],
scale: 1,
addedCollections:[]
})
onLoad((option) => {
//data.default = JSON.parse(option?.item || '{}')
//getNftListfn()
})
const getNftListfn = async () => {
//let { list } = await getNftList(1, 100);
//data.cpList = list
}
// 响应式状态
const addedCollections = ref<any>([]);
const layoutArea = ref(null);
const layoutAreaRect = ref({ width: 0, height: 0 });
const maxZIndex = ref(0);
// 初始化
onMounted(() => {
// 修复1:Vue3 setup中没有this,移除第二个参数
// 修复2:确保DOM渲染完成后获取尺寸
nextTick(() => {
getLayoutAreaRect().then(() => {
console.log('布局区域尺寸初始化完成', layoutAreaRect.value);
});
});
});
// 获取布局区域尺寸(改为Promise确保异步执行完成)
const getLayoutAreaRect = () : Promise<void> => {
return new Promise((resolve) => {
uni.createSelectorQuery()
.select(".layout-area")
.boundingClientRect((rect : any) => {
if (rect) {
layoutAreaRect.value = {
width: rect.width,
height: rect.height
};
}
resolve();
})
.exec();
});
};
// 直接添加藏品
const addItemDirectly = async (item : any) => {
// 确保尺寸已获取
if (!layoutAreaRect.value.width) {
await getLayoutAreaRect();
}
addItemToLayout(item);
};
// 更新zIndex
const updateMaxZIndex = () => {
maxZIndex.value = Math.max(...addedCollections.value.map((item : any) => item.zIndex || 0));
};
// 添加藏品到布局区域
const addItemToLayout = (item : any) => {
/* if(addedCollections.value.length>0){
addedCollections.value.map((item:any)=>{
item.x=item.oldx
item.y=item.oldy
item.scale=item.scaleold
console.log(item,'map')
return item
})
} */
for (const key in addedCollections.value) {
if (data.addedCollections && data.addedCollections.hasOwnProperty(key)) {
addedCollections.value[key] = data.addedCollections[key];
}
}
const randomX =20 //Math.ceil(Math.random() * (layoutAreaRect.value.width - 100)) + 20;
const randomY =20// Math.ceil(Math.random() * (layoutAreaRect.value.height - 100)) + 20;
const newItem = {
...item,
x: randomX,
y: randomY,
//oldx:randomX,
//oldy:randomY,
scale: 1,
//scaleold: 1,
width: '100px',
height: '100px',
zIndex: maxZIndex.value + 1,
};
console.log(addedCollections.value)
addedCollections.value.push(newItem)
data.addedCollections=JSON.parse(JSON.stringify(addedCollections.value))
console.log(addedCollections.value)
updateMaxZIndex();
};
// 处理拖拽位置变化
const handleDragChange = (index : number, item : any, e : any) => {
console.log(e)
updateMaxZIndex();
/* item.zIndex = maxZIndex.value + 1;
item.oldx = e.detail.x;
item.oldy = e.detail.y; */
console.log(item)
const targetItem = data.addedCollections.find((el : any) => el.id === item.id);
targetItem.x=e.detail.x;
targetItem.y=e.detail.y;
targetItem.zIndex=maxZIndex.value + 1
/*
const targetItem = addedCollections.value.find((el : any) => el.id === item.id);
if (targetItem) {
}
if (addedCollections.value[index]) {
addedCollections.value[index].x = e.detail.x;
addedCollections.value[index].y = e.detail.y;
} */
}
const onScale = (item : any,e : any) => {
console.log(e)
/* item.scaleold = e.detail.scale
item.oldx = e.detail.x;
item.oldy = e.detail.y; */
const targetItem = data.addedCollections.find((el : any) => el.id === item.id);
targetItem.y=e.detail.y;
targetItem.x=e.detail.x;
targetItem.scale=e.detail.scale;
console.log('item,',item)
}
// 重置布局
const resetLayout = () => {
uni.showModal({
title: '提示',
content: '确定要清空当前布局吗?',
success: res => {
if (res.confirm) {
addedCollections.value = [];
}
}
});
};
// 保存布局
const saveLayout = async () => {
if (addedCollections.value.length === 0) {
uni.showToast({ title: '请添加藏品到布局', icon: 'none' });
return;
}
};
</script>
<style scoped>
/* 保持原有样式不变 */
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
background-color: #f5f5f5;
}
.header {
padding: 16px;
background-color: #333;
color: white;
text-align: center;
}
.title {
font-size: 18px;
font-weight: bold;
}
.main-content {
display: flex;
flex: 1;
padding: 16px;
gap: 16px;
box-sizing: border-box;
}
.right-panel {
width: 200px;
background-color: white;
border-radius: 8px;
padding: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.center-panel {
flex: 1;
background-color: white;
border-radius: 8px;
padding: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
}
.panel-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
color: #333;
padding-bottom: 8px;
border-bottom: 1px solid #eee;
}
.my-collections {
display: flex;
flex-direction: column;
gap: 10px;
overflow-y: auto;
flex: 1;
}
.collection-item {
width: 100%;
height: 80px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
position: relative;
}
.collection-item:active {
opacity: 0.8;
transform: scale(0.98);
}
.bg-img,
.collection-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.layout-area {
flex: 1;
background-color: #f9f9f9;
border-radius: 8px;
overflow: hidden;
position: relative;
min-height: 500px;
width: 100%;
}
.background-image {
width: 100%;
height: 100%;
object-fit: contain;
z-index: 0;
}
.draggable-item {
width: 100px;
height: 100px;
}
.bottom-actions {
padding: 16px;
display: flex;
gap: 12px;
justify-content: center;
background-color: white;
border-top: 1px solid #eee;
}
.action-btn {
padding: 10px 20px;
border-radius: 6px;
font-size: 14px;
border: 1px solid #ddd;
background-color: white;
color: #333;
}
.action-btn.primary {
background-color: #007aff;
color: white;
border-color: #007aff;
}
@media (max-width: 768px) {
.main-content {
flex-direction: column;
}
.right-panel {
width: 100%;
height: 200px;
}
.my-collections {
flex-direction: row;
}
.collection-item {
flex: 1;
height: 150px;
}
}
</style>

- 发布:2025-08-15 09:21
- 更新:2025-08-15 09:53
- 阅读:33
产品分类: uniapp/小程序/微信
PC开发环境操作系统: Mac
PC开发环境操作系统版本号: 10.15.1
HBuilderX类型: 正式
HBuilderX版本号: 4.75
第三方开发者工具版本号: 4.75
基础库版本号: 3.8.10
项目创建方式: HBuilderX
示例代码:
操作步骤:
缩放到最大时候拖动x为0坐标,然后点击下面新增图片再重新动态上一个元素x=0,会远距离不等于0,只要不是最大就正常
缩放到最大时候拖动x为0坐标,然后点击下面新增图片再重新动态上一个元素x=0,会远距离不等于0,只要不是最大就正常
预期结果:
没有bug
没有bug
实际结果:
缩放到最大时候拖动x为0坐标,然后点击下面新增图片再重新动态上一个元素x=0,会远距离不等于0
缩放到最大时候拖动x为0坐标,然后点击下面新增图片再重新动态上一个元素x=0,会远距离不等于0
bug描述:
movable-view 进行可拖拽和可缩放大小功能,缩放到最大时候拖动x为0坐标,然后再重新动态x=0,会远距离不等于0

测试一下原生微信小程序是否也有同样的问题
-
1***@qq.com (作者)
现已修复这个bug,但是又出现了另外一个bug,sace放大到最大的状态,然后弄到x=0,然后新增图片,看元素上一个最大的坐标没变化,但是离开x不等于0
2025-08-15 11:38
-
-