<template>
<view>
<view style="padding: 15px;">
<uni-easyinput class="uni-mt-5" suffixIcon="search" v-model="searchTxt" placeholder="搜索网盘文件"
@iconClick="getFolders"></uni-easyinput>
</view>
<view style="padding: 0 15px;margin-bottom: 10px;" v-if="hisFolders.length > 1">
<uni-breadcrumb separator="/">
<uni-breadcrumb-item v-for="(folder,index) in hisFolders" :key="index">
{{folder.itemName}}
</uni-breadcrumb-item>
</uni-breadcrumb>
</view>
<view>
<uni-list>
<template v-for="item in folders">
<template>
<uni-list-item :title="item.originalName || item.itemName" :note="item.createTime"
:thumb="'../../static/images/pan/' + getfileType(item) + '.png'" thumb-size="base"
:key="item.id" :ellipsis="1" clickable @click.native="showFile(item)"
@longpress.native="(e)=>getFileMenu(item,e)" />
</template>
</template>
</uni-list>
</view>
<uni-popup ref="popup_newfolder" background-color="#fff" style="height:300px" :is-mask-click="false">
<view style="height:300px">
<view>
<uni-nav-bar shadow left-icon="left" leftText="返回" rightText="完成" title="新建目录"
@clickLeft="clickLeft" @clickRight="clickRight" />
</view>
<view style="text-align: center;padding-top: 20px;">
<image style="width: 100px; height: 100px; background-color: #fff;" mode="scaleToFill"
src="../../static/images/pan/folder.png"></image>
</view>
<view style="padding: 20px;">
<uni-easyinput v-model="itemName" focus placeholder="新建目录"
style="text-align: center;"></uni-easyinput>
</view>
</view>
</uni-popup>
<uni-popup ref="popup_newfile" background-color="#fff" style="height:300px" :is-mask-click="false">
<view style="height:300px">
<view>
<uni-nav-bar shadow left-icon="left" leftText="返回" title="上传文件" @clickLeft="clickLeft"
@clickRight="clickRight" />
</view>
<view class="example-body">
<view style="padding: 20px;margin: 0 auto;">
<button @click="testf">选择文件</button>
</view>
</view>
</view>
</uni-popup>
<view>
<uni-fab ref="fab" :horizontal="horizontal" :vertical="vertical" :direction="direction" :content="content"
@fabClick="fabClick" @trigger="trigger" />
</view>
<view>
</view>
<!-- 长按菜单弹窗 -->
<uni-popup ref="popup_menu" type="bottom" background-color="transparent" :is-mask-click="false">
<view class="menu-container">
<!-- 简单的文件信息显示 -->
<view class="menu-item info-item" style="background-color: #f5f5f5;">
<text class="menu-text">{{ currentFileName }}</text>
</view>
<view class="menu-item" @click="downloadFile()">
<uni-icons type="download" size="20" color="#333"></uni-icons>
<text class="menu-text">下载</text>
</view>
<view class="menu-item" @click="renameFile()">
<uni-icons type="compose" size="20" color="#333"></uni-icons>
<text class="menu-text">重命名</text>
</view>
<view class="menu-item" @click="deleteFile()">
<uni-icons type="trash" size="20" color="#ff4d4f"></uni-icons>
<text class="menu-text delete-text">删除</text>
</view>
<view class="menu-item menu-cancel" @click="closeMenu">
<uni-icons type="close" size="20" color="#333"></uni-icons>
<text class="menu-text">取消</text>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
const lemonjkFileSelect = uni.requireNativePlugin('lemonjk-FileSelect');
import {
addFolder,
listAllFolder
} from '@/api/pan/folder.js';
import upload from '@/utils/upload';
import config from '@/config';
const baseUrl = config.baseUrl;
const resUrl = config.resUrl;
export default {
data() {
return {
horizontal: 'right',
vertical: 'bottom',
direction: 'horizontal',
content: [{
iconPath: '../../static/images/pan/fab/folder.png',
selectedIconPath: '../../static/images/pan/fab/folder.png',
text: '目录',
active: false
},
{
iconPath: '../../static/images/pan/fab/file.png',
selectedIconPath: '../../static/images/pan/fab/file.png',
text: '文件',
active: false
}
],
searchTxt: '',
itemName: '',
itemType: '',
currentid: 0,
hisFolders: [{
id: 0,
itemName: '首页'
}],
folders: [],
video: {},
isPopupNewFolderOpen: false,
isPopupNewFileOpen: false,
userid: this.$store.state.user.id,
currentFile: null,
currentFileName: '',
isMenuOpen: false,
};
},
mounted() {
this.getFolders();
},
methods: {
getFolders() {
uni.showLoading({
title: '正在加载...'
})
listAllFolder({
pid: this.currentid,
userid: this.userid
}).then(res => {
uni.hideLoading()
let folders = res.data;
let images = [];
for (let f of folders) {
if (f.itemType == '文件' && this.getfileType(f) == 'image') {
images.push({
...f,
url: `${resUrl}/${f.itemName}`,
content: f.originalName
});
}
f.url = `${resUrl}/${f.itemName}`
}
this.folders = folders;
this.images = images;
});
},
change(e) {
this.currentimage = e.detail.current
},
clickItem(e) {
this.swiperDotIndex = e
},
fabClick() {},
trigger(e) {
let text = e.item.text;
this.$refs.fab.close();
this.itemType = text;
switch (text) {
case '目录':
this.itemName = ''
this.$refs.popup_newfolder.open('bottom');
this.isPopupNewFolderOpen = true;
break;
case '文件':
this.$refs.popup_newfile.open('bottom');
this.isPopupNewFileOpen = true;
break;
}
},
clickLeft() {
this.$refs.popup_newfolder.close();
this.$refs.popup_newfile.close();
this.isPopupNewFolderOpen = false
this.isPopupNewFileOpen = false
},
clickRight() {
let itemName = this.itemName;
if (null == itemName || itemName.length == 0) {
this.$modal.msgError('请输入目录名称');
return;
}
addFolder({
pid: this.currentid,
itemName: this.itemName,
itemType: this.itemType
}).then(res => {
this.$modal.msgSuccess('操作成功');
this.$refs.popup_newfolder.close();
this.getFolders();
});
},
getfileType(file) {
let itemType = file.itemType
if (itemType == '目录') {
return 'folder'
}
let filename = file.itemName
const lastDotIndex = filename.lastIndexOf('.');
if (lastDotIndex === -1) {
return 'file';
}
const extension = filename.substring(lastDotIndex + 1);
let type = '';
switch (extension) {
case 'txt':
type = 'txt';
break;
case 'doc':
case 'docx':
type = 'word';
break;
case 'ppt':
case 'pptx':
type = 'ppt';
break;
case 'xlsx':
case 'xls':
type = 'excel';
break;
case 'jpg':
case 'jpeg':
case 'png':
type = 'image';
break;
case 'avi':
case 'mov':
case 'mkv':
case 'mpg':
case 'mpeg':
case 'flv':
case 'mp4':
type = 'video';
break;
default:
type = 'file';
}
return type;
},
showFile(item) {
if (this.getfileType(item) == 'image') {
let images = this.images
const index = images.findIndex(image => image.itemName === item.itemName);
let data = {
images: images,
index: index
}
uni.navigateTo({
url: './imageViewer?data=' + JSON.stringify(data),
})
} else if (this.getfileType(item) == 'video') {
uni.navigateTo({
url: './videoPlayer?video=' + JSON.stringify(item),
})
} else if (this.getfileType(item) == 'folder') {
this.showFolder(item)
}
},
getFileMenu(item, e) {
console.log(item);
this.currentFileName = item.originalName || item.itemName || '';
this.currentFile = item;
this.isMenuOpen = true;
this.$refs.popup_menu.open('bottom');
},
closeMenu() {
this.$refs.popup_menu.close();
this.isMenuOpen = false;
this.currentFile = null;
this.currentFileName = '';
},
downloadFile(file) {
console.log('下载文件:', file);
// 这里实现下载逻辑
uni.showToast({
title: '下载功能开发中',
icon: 'none'
});
this.closeMenu();
},
renameFile(file) {
console.log('重命名文件:', file);
// 这里实现重命名逻辑
uni.showToast({
title: '重命名功能开发中',
icon: 'none'
});
this.closeMenu();
},
deleteFile(file) {
console.log('删除文件:', file);
uni.showModal({
title: '确认删除',
content: `确定要删除文件"${file.originalName || file.itemName}"吗?`,
confirmText: '删除',
confirmColor: '#ff4d4f',
success: (res) => {
if (res.confirm) {
// 这里实现删除逻辑
uni.showToast({
title: '删除功能开发中',
icon: 'none'
});
}
this.closeMenu();
}
});
},
showFolder(item) {
this.currentid = item.id
this.hisFolders.push(item)
this.getFolders()
},
testf() {
const _this = this;
lemonjkFileSelect.isHaveSecurityScopeGrant({
type: 'FILE_PERMISSION'
}, result => {
if (result.result == 'yes') {
lemonjkFileSelect.showPicker({
mimeType: '*/*',
utisType: ['public.data'],
pathScope: '/Download',
navTitle: '文件选择',
navTextColor: '#55ff00',
navBarBgColor: '#00aaff',
theme: 'auto',
showHideFile: 'yes',
filterConfig: {
fileSize: String(1 * 1024 * 1024 * 1024),
fileExtension: [
'bmp', 'gif', 'jpg', 'jpeg', 'png',
'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'html', 'htm', 'txt',
'rar', 'zip', 'gz', 'bz2',
'mp4', 'avi', 'rmvb',
'pdf'
]
}
}, result => {
let code = result.code;
if (code == 0) {
let filePath = result.files[0].filePath;
let fileName = result.files[0].fileName;
let url = '/common/panUpload';
uni.showLoading({
title: '正在上传....'
});
upload({
url: url,
name: 'file',
formData: {
'currentid': _this.currentid
},
filePath: filePath
}).then(res => {
uni.hideLoading();
uni.showToast({
title: res.msg
});
_this.$refs.popup_newfile.close();
_this.getFolders();
}).catch(err => {
uni.hideLoading();
console.log(err);
});
}
});
} else {
uni.showModal({
content: '需要申请文件访问权限,是否同意',
success(e) {
if (e.confirm) {
lemonjkFileSelect.reqCustomPickerPermission({}, result => {
if (result.code == 3002) {
// 用户同意了授权
} else {
// 用户拒绝了授权
}
});
}
}
});
}
});
}
},
onBackPress() {
if (this.$refs.fab.isShow) {
this.$refs.fab.close();
return true;
}
if (this.isMenuOpen) {
this.closeMenu();
return true;
}
if (this.isPopupNewFolderOpen) {
this.$refs.popup_newfolder.close();
this.isPopupNewFolderOpen = false
return true;
}
if (this.isPopupNewFileOpen) {
this.$refs.popup_newfile.close();
this.isPopupNewFileOpen = false
return true;
}
if (this.currentid != 0) {
let hisFolders = this.hisFolders
hisFolders.pop()
let currentid = hisFolders[hisFolders.length - 1].id
this.currentid = currentid
this.getFolders()
return true;
}
return false;
}
};
</script>
<style lang="scss" scoped>
/* #ifndef APP-NVUE */
page {
display: flex;
flex-direction: column;
box-sizing: border-box;
background-color: #fff;
min-height: 100%;
height: auto;
}
view {
font-size: 14px;
line-height: inherit;
}
/* #endif */
.example-body {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
padding: 20rpx;
}
.example-body-item {
flex-direction: row;
justify-content: center;
align-items: center;
margin: 15rpx;
padding: 15rpx;
height: 60rpx;
/* #ifndef APP-NVUE */
display: flex;
padding: 0 15rpx;
/* #endif */
flex: 1;
border-color: #e5e5e5;
border-style: solid;
border-width: 1px;
border-radius: 5px;
}
.example-body-item-text {
font-size: 28rpx;
color: #333;
}
.example-body-dots {
width: 16rpx;
height: 16rpx;
border-radius: 50px;
background-color: #333333;
margin-left: 10rpx;
}
.active {
border-style: solid;
border-color: #007aff;
border-width: 1px;
}
/* 长按菜单样式 */
.menu-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 10px 0;
width: 100%;
border-radius: 8px;
background-color: #fff;
border: 1px solid #000;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
.menu-item {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
width: 100%;
padding: 10px 20px;
margin: 0;
border-radius: 0;
background-color: transparent;
transition: all 0.3s ease;
}
.menu-item:hover {
background-color: #f5f5f5;
}
.menu-item.menu-cancel {
margin-top: 0;
border-top: 1px solid #e0e0e0;
padding-top: 10px;
}
.menu-text {
margin-left: 10px;
color: #000;
font-size: 14px;
}
.menu-text.delete-text {
color: #ff4d4f;
}
</style> - 发布:2026-01-14 18:10
- 更新:2026-01-14 18:10
- 阅读:682
产品分类: uniapp/App
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: 10 22H2
HBuilderX类型: 正式
HBuilderX版本号: 4.87
手机系统: Android
手机系统版本号: Android 13
手机厂商: OPPO
手机机型: A55
页面类型: vue
vue版本: vue2
打包方式: 云端
项目创建方式: HBuilderX
示例代码:
操作步骤:
长按uni-list-item弹出popup,点击取消关闭popup,再长按uni-list-item
长按uni-list-item弹出popup,点击取消关闭popup,再长按uni-list-item
预期结果:
再次弹出popup并传递item和event
再次弹出popup并传递item和event
实际结果:
没有进入getFileMenu函数
没有进入getFileMenu函数
bug描述:
我在uni-list-item组件中加入@longpress.native,用来长按触发getFileMenu函数弹出popup组件。关闭popup组件后再次长按uni-list-item无法触发长按事件函数getFileMenu。