424 lines
12 KiB
Vue
424 lines
12 KiB
Vue
<template>
|
||
<view>
|
||
<view class="search-wrap uni-flex uni-row">
|
||
<view class="flex-item input-wrap">
|
||
<input class="uni-input" maxlength="50" :placeholder="$lang('files.list.searchPlaceholder')" v-model="keyword" @confirm="search"
|
||
@input="__set_model($event, 'keyword')" />
|
||
<text class="iconfont icon-sousuo3" @tap="search"></text>
|
||
</view>
|
||
</view>
|
||
<mescroll-uni ref="mescroll" top="100" @getData="getData" :style="tabBarPagePaddingStyle">
|
||
<view slot="list">
|
||
<block v-if="list.length > 0">
|
||
<view class="article-wrap">
|
||
<ns-adv keyword="NS_ARTICLE" class-name="adv-wrap"></ns-adv>
|
||
<block v-for="(item, index) in list" :key="index">
|
||
<view class="item" @tap="toDetail(item)">
|
||
<view class="pdf-icon">
|
||
<text class="pdf-icon-p">P</text>
|
||
<view class="pdf-icon-fold"></view>
|
||
<view class="pdf-icon-lines">
|
||
<view class="pdf-icon-line"></view>
|
||
<view class="pdf-icon-line"></view>
|
||
<view class="pdf-icon-line"></view>
|
||
</view>
|
||
</view>
|
||
<view class="info-wrap">
|
||
<view class="title">{{ item.files_title }}</view>
|
||
<view class="read-wrap">
|
||
<text>{{ $lang('files.list.viewPdf') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</block>
|
||
</view>
|
||
</block>
|
||
<block v-else>
|
||
<view class="empty-wrap">
|
||
<ns-empty :text="$lang('files.list.emptyText')" :isIndex="false"></ns-empty>
|
||
</view>
|
||
</block>
|
||
</view>
|
||
</mescroll-uni>
|
||
<loading-cover ref="loadingCover"></loading-cover>
|
||
<privacy-popup ref="privacyPopup"></privacy-popup>
|
||
|
||
<!-- 底部tabBar -->
|
||
<view id="tab-bar">
|
||
<diy-bottom-nav></diy-bottom-nav>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
category_id: '',
|
||
list: [],
|
||
title: '',
|
||
keyword: ''
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
if (options.category_id > 0) {
|
||
this.category_id = options.category_id
|
||
}
|
||
},
|
||
onShow() {
|
||
},
|
||
methods: {
|
||
__set_model(event, field) {
|
||
this[field] = event.detail.value
|
||
},
|
||
search() {
|
||
this.list = []
|
||
this.$refs.mescroll.refresh()
|
||
},
|
||
getData(page) {
|
||
this.$api.sendRequest({
|
||
url: '/api/files/getpage',
|
||
data: {
|
||
page_size: page.size,
|
||
page: page.num,
|
||
category_id: this.category_id,
|
||
keyword: this.keyword
|
||
},
|
||
success: res => {
|
||
let list = []
|
||
let message = res.message
|
||
if (res.code === 0 && res.data) {
|
||
list = res.data.list
|
||
if (!this.title && res.data.list.length > 0) {
|
||
const first = res.data.list[0]
|
||
const firstOrig = (first && first.$orig) ? first.$orig : first
|
||
uni.setNavigationBarTitle({
|
||
title: firstOrig.category_name || ''
|
||
})
|
||
}
|
||
} else {
|
||
this.$util.showToast({
|
||
title: message
|
||
})
|
||
}
|
||
page.endSuccess(list.length)
|
||
if (page.num === 1) {
|
||
this.list = []
|
||
}
|
||
this.list = this.list.concat(list.map(item => {
|
||
// 兼容两种后端结构:自带 $orig(如 cases 接口)或扁平结构
|
||
const src = (item && item.$orig) ? item.$orig : item
|
||
return {
|
||
files_id: src.files_id,
|
||
files_title: src.files_title,
|
||
files_url: src.files_url,
|
||
files_desc: src.files_desc,
|
||
category_id: src.category_id,
|
||
category_name: src.category_name,
|
||
// 保留完整原对象引用,避免后续扩展字段丢失
|
||
$orig: src
|
||
}
|
||
}))
|
||
if (this.$refs.loadingCover) {
|
||
this.$refs.loadingCover.hide()
|
||
}
|
||
},
|
||
fail: () => {
|
||
page.endErr()
|
||
if (this.$refs.loadingCover) {
|
||
this.$refs.loadingCover.hide()
|
||
}
|
||
}
|
||
})
|
||
},
|
||
toDetail(item) {
|
||
const title = (item.files_title || '文件').toString().replace(/[\\/:*?"<>|\r\n\t]/g, '_');
|
||
// 根据 URL 推断后缀(若无扩展名则默认 pdf)
|
||
let ext = 'pdf';
|
||
if (item.files_url) {
|
||
const clean = item.files_url.split('?')[0];
|
||
const matched = clean.match(/\.([a-zA-Z0-9]+)$/);
|
||
if (matched) ext = matched[1].toLowerCase();
|
||
}
|
||
const fileName = `${title}.${ext}`;
|
||
const fileType =
|
||
['pdf'].includes(ext) ? 'pdf'
|
||
: ['doc', 'docx'].includes(ext) ? 'word'
|
||
: ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv'].includes(ext) ? 'video'
|
||
: 'pdf';
|
||
const previewPage = `/pages_tool/file-preview/file-preview?fileName=${encodeURIComponent(fileName)}&fileUrl=${encodeURIComponent(item.files_url)}&fileType=${encodeURIComponent(fileType)}`;
|
||
|
||
// ========== H5 端:跳转预览页(web-view 走 iframe);失败则新标签页打开原链接 ==========
|
||
// #ifdef H5
|
||
uni.navigateTo({
|
||
url: previewPage,
|
||
fail: () => {
|
||
try { window.open(item.files_url, '_blank'); } catch (e) {
|
||
uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' });
|
||
}
|
||
}
|
||
});
|
||
return;
|
||
// #endif
|
||
|
||
// ========== 非 H5 端:下载文件后按平台分支打开 ==========
|
||
uni.showLoading({ title: this.$lang('files.list.loading'), mask: true });
|
||
uni.downloadFile({
|
||
url: item.files_url,
|
||
success: res => {
|
||
if (res.statusCode !== 200) {
|
||
uni.hideLoading();
|
||
uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' });
|
||
return;
|
||
}
|
||
|
||
// ----- 微信小程序:saveFile 重命名 + openDocument(短文件名标题)-----
|
||
// #ifdef MP-WEIXIN
|
||
const fs = uni.getFileSystemManager();
|
||
// 重命名临时文件到用户目录,用短文件名 —— openDocument 的标题会取 filePath 的文件名部分,从而显示短名"乐瑞固企业介绍"而非 tmp_xxx
|
||
const targetPath = `${wx.env.USER_DATA_PATH}/fs_${Date.now()}_${title}.${ext}`;
|
||
try {
|
||
// saveFile:复制临时文件到持久目录并改名(临时文件在某些基础库上禁止直接 rename)
|
||
fs.saveFile({
|
||
tempFilePath: res.tempFilePath,
|
||
filePath: targetPath,
|
||
success: r => {
|
||
uni.hideLoading();
|
||
uni.openDocument({
|
||
filePath: r.savedFilePath,
|
||
fileType: ext,
|
||
showMenu: true,
|
||
fail: () => {
|
||
uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' });
|
||
},
|
||
complete: () => {
|
||
// 预览结束后清理,避免占用持久空间(失败忽略)
|
||
try { fs.removeSavedFile({ filePath: r.savedFilePath }); } catch (e) {}
|
||
}
|
||
});
|
||
},
|
||
fail: () => {
|
||
// saveFile 失败(配额等),直接用临时文件 openDocument 兜底
|
||
uni.hideLoading();
|
||
uni.openDocument({
|
||
filePath: res.tempFilePath,
|
||
fileType: ext,
|
||
showMenu: true,
|
||
fail: () => uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' })
|
||
});
|
||
}
|
||
});
|
||
} catch (e) {
|
||
// 极端异常兜底
|
||
uni.hideLoading();
|
||
uni.openDocument({
|
||
filePath: res.tempFilePath,
|
||
fileType: ext,
|
||
showMenu: true,
|
||
fail: () => uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' })
|
||
});
|
||
}
|
||
// #endif
|
||
|
||
// ----- App / 其他小程序:直接 openDocument 打开临时文件;失败兜底跳转预览页 -----
|
||
// #ifndef MP-WEIXIN
|
||
uni.hideLoading();
|
||
uni.openDocument({
|
||
filePath: res.tempFilePath,
|
||
fileType: ext,
|
||
showMenu: true,
|
||
fail: () => {
|
||
uni.navigateTo({
|
||
url: previewPage,
|
||
fail: () => uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' })
|
||
});
|
||
}
|
||
});
|
||
// #endif
|
||
},
|
||
fail: () => {
|
||
uni.hideLoading();
|
||
uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' });
|
||
},
|
||
complete: res => {
|
||
if (res && res.statusCode === 404) {
|
||
uni.hideLoading();
|
||
uni.showToast({ title: this.$lang('files.list.fileNotExist'), icon: 'none' });
|
||
}
|
||
}
|
||
});
|
||
},
|
||
imgError(index) {
|
||
if (this.list[index]) {
|
||
this.list[index].cover_img = this.$util.getDefaultImage().article
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.search-wrap {
|
||
flex: 0.5;
|
||
padding: 30rpx 30rpx 0;
|
||
font-size: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.search-wrap .iconfont {
|
||
margin-left: 16rpx;
|
||
font-size: 36rpx;
|
||
}
|
||
|
||
.search-wrap .input-wrap {
|
||
flex: 1;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
background: #fff;
|
||
height: 64rpx;
|
||
padding-left: 10rpx;
|
||
border-radius: 70rpx;
|
||
}
|
||
|
||
.search-wrap .input-wrap input {
|
||
width: 90%;
|
||
background: #fff;
|
||
font-size: 24rpx;
|
||
height: 100%;
|
||
padding: 0 25rpx 0 40rpx;
|
||
line-height: 50rpx;
|
||
border-radius: 40rpx;
|
||
}
|
||
|
||
.search-wrap .input-wrap text {
|
||
font-size: 32rpx;
|
||
color: #909399;
|
||
width: 80rpx;
|
||
text-align: center;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.empty-wrap {
|
||
padding-top: 200rpx;
|
||
}
|
||
|
||
.article-wrap {
|
||
background: #f8f8f8;
|
||
}
|
||
|
||
.article-wrap .adv-wrap {
|
||
margin: 24rpx 24rpx 0 24rpx;
|
||
width: auto;
|
||
}
|
||
|
||
.article-wrap .item {
|
||
display: flex;
|
||
padding: 20rpx;
|
||
background-color: #fff;
|
||
margin: 24rpx;
|
||
border-radius: 16rpx;
|
||
}
|
||
|
||
.article-wrap .item .pdf-icon {
|
||
margin-right: 20rpx;
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
flex-shrink: 0;
|
||
background-color: #e64340;
|
||
border-radius: 10rpx;
|
||
position: relative;
|
||
overflow: hidden;
|
||
box-shadow: 0 2rpx 8rpx rgba(230, 67, 64, 0.2);
|
||
}
|
||
|
||
.article-wrap .item .pdf-icon .pdf-icon-p {
|
||
position: absolute;
|
||
top: 2rpx;
|
||
left: 8rpx;
|
||
color: #ffffff;
|
||
font-size: 40rpx;
|
||
font-weight: 900;
|
||
font-family: Arial, Helvetica, sans-serif;
|
||
line-height: 1;
|
||
letter-spacing: 0;
|
||
}
|
||
|
||
.article-wrap .item .pdf-icon .pdf-icon-fold {
|
||
position: absolute;
|
||
top: 0;
|
||
right: 0;
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
background: linear-gradient(135deg, transparent 50%, #ffeceb 50%);
|
||
border-bottom-left-radius: 4rpx;
|
||
}
|
||
|
||
.article-wrap .item .pdf-icon .pdf-icon-lines {
|
||
position: absolute;
|
||
right: 6rpx;
|
||
bottom: 6rpx;
|
||
width: 36rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
}
|
||
|
||
.article-wrap .item .pdf-icon .pdf-icon-line {
|
||
width: 100%;
|
||
height: 3rpx;
|
||
background-color: #ffffff;
|
||
opacity: 0.85;
|
||
margin-bottom: 4rpx;
|
||
border-radius: 2rpx;
|
||
}
|
||
|
||
.article-wrap .item .pdf-icon .pdf-icon-line:nth-child(1) {
|
||
width: 100%;
|
||
}
|
||
|
||
.article-wrap .item .pdf-icon .pdf-icon-line:nth-child(2) {
|
||
width: 80%;
|
||
}
|
||
|
||
.article-wrap .item .pdf-icon .pdf-icon-line:nth-child(3) {
|
||
width: 60%;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.article-wrap .item .info-wrap {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
min-width: 0;
|
||
}
|
||
|
||
.article-wrap .item .info-wrap .title {
|
||
font-weight: 700;
|
||
color: #303133;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 1;
|
||
-webkit-box-orient: vertical;
|
||
font-size: 28rpx;
|
||
line-height: 1.4;
|
||
white-space: normal;
|
||
word-break: break-all;
|
||
}
|
||
|
||
.article-wrap .item .info-wrap .read-wrap {
|
||
display: flex;
|
||
color: #999ca7;
|
||
justify-content: flex-start;
|
||
align-items: center;
|
||
margin-top: 10rpx;
|
||
line-height: 1;
|
||
}
|
||
|
||
.article-wrap .item .info-wrap .read-wrap text {
|
||
font-size: 24rpx;
|
||
}
|
||
</style> |