Files
qiming/qiming-mobile/subpackages/pages/file-preview-page/file-preview-page.uvue

320 lines
8.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container page-container">
<!-- 导航栏 -->
<custom-nav-bar :title="fileName" show-back>
<template v-slot:right>
<!-- #ifdef H5 || WEB -->
<text
class="iconfont icon-ShareAltOutlined font-48"
@click="handleShare"
></text>
<!-- #endif -->
</template>
</custom-nav-bar>
<view class="file-preview-content">
<!-- 加载中 -->
<!-- <template v-if="isLoading">
<view class="loading-box">
<image
class="icon-loading-image"
src="@/static/assets/icon_loading.svg"
mode="widthFix"
/>
</view>
</template> -->
<!-- Web-View 预览 -->
<template v-if="previewUrl">
<!-- #ifdef H5 || WEB -->
<iframe
class="w-full h-full"
frameborder="0"
:src="previewUrl"
></iframe>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<web-view
class="w-full h-full"
:src="previewUrl"
id="webview"
></web-view>
<!-- #endif -->
</template>
</view>
</view>
</template>
<script setup lang="uts">
import { onAddToFavorites } from "@dcloudio/uni-app";
import {
parseUrlInfo,
getFileName,
} from "@/subpackages/utils/parseUrlInfo.uts";
import { useI18n } from "@/utils/i18n";
const { t } = useI18n();
// 请求工具
import {
apiUserTicketCreate,
apiAgentConversationShare,
} from "@/servers/agentDev.uts";
import { SUCCESS_CODE } from "@/constants/codes.constants";
// 环境配置
import { API_BASE_URL } from "@/constants/config";
const previewUrl = ref<string>(""); // 预览地址
const fileName = ref<string>(""); // 文件名
const pageTitle = ref<string>(""); // 页面标题
const fileType = ref<string>(""); // 文件类型
const isLoading = ref<boolean>(true); // 是否加载中
const conversationId = ref<string>(null); // 会话ID
const fileProxyUrl = ref<string>(""); // 文件路径
const sk = ref<string>(""); // sk 微信小程序中需要 sk 查询参数
const isDev = process.env.NODE_ENV === "development";
let baseUrl = "";
// #ifdef H5 || WEB
baseUrl = isDev ? API_BASE_URL : window?.location?.origin;
// #endif
// #ifdef MP-WEIXIN
baseUrl = API_BASE_URL;
// #endif
/**
* 获取 shareKey
*/
const getConversationShareKey = async (
conversationId: string,
content: string = "",
): Promise<string> => {
const params = {
conversationId,
type: "CONVERSATION",
content,
};
const { data, code } = await apiAgentConversationShare(params);
if (code !== SUCCESS_CODE || !data?.shareKey) {
throw new Error(t("Mobile.FilePreview.getShareKeyFailed"));
}
return data.shareKey;
};
// 分享文件
const handleShare = async () => {
if (!baseUrl) {
uni.showToast({
title: t("Mobile.FilePreview.shareDomainMissing"),
icon: "none",
duration: 2000,
});
return;
}
try {
const shareKey = await getConversationShareKey(
conversationId.value,
fileProxyUrl.value || "",
);
const previewUrlValue = `${baseUrl}/static/file-preview.html?sk=${shareKey}`;
// 复制到剪切板
uni.setClipboardData({
data: previewUrlValue,
success: () => {
uni.showToast({
title: t("Mobile.FilePreview.shareSuccess"),
icon: "none",
duration: 2000,
});
},
fail: () => {
uni.showToast({
title: t("Mobile.FilePreview.shareFailed"),
icon: "none",
duration: 2000,
});
},
});
} catch (error) {
console.error("分享失败:", error);
uni.showToast({
title: t("Mobile.FilePreview.shareFailed"),
icon: "none",
duration: 2000,
});
}
};
// 获取 ticket
const getTicket = async () => {
try {
const { code, data } = await apiUserTicketCreate();
return code === SUCCESS_CODE && data ? data : "";
} catch (e) {
console.log(e);
return "";
}
};
// 设置 html 文件标题
const setHtmlTitle = (url: string) => {
uni.request({
url,
method: "GET",
success: (res) => {
const data = res.data;
// 使用正则表达式提取 <title>...</title> 中的内容
const match = data.match(/<title[^>]*>([^<]+)<\/title>/i);
if (match && match[1]) {
const title = match[1].trim();
// 赋值给 pageTitle
pageTitle.value = title;
// 更新导航栏标题
uni.setNavigationBarTitle({
title: title,
});
}
},
fail: (err) => {
console.error("获取 html 失败", err);
},
});
};
onLoad(async (options: { cId: number; fileProxyUrl: string }) => {
let { cId, fileProxyUrl: fileProxyUrlValue } = options;
if (!cId || !fileProxyUrlValue) {
uni.showToast({
title: t("Mobile.FilePreview.invalidParams"),
icon: "none",
});
isLoading.value = false;
return;
}
const { path, query } = parseUrlInfo(decodeURIComponent(fileProxyUrlValue));
fileProxyUrl.value = path;
// 得到文件名
const fileNameValue = getFileName(path);
conversationId.value = cId;
fileName.value = fileNameValue;
uni.setNavigationBarTitle({ title: fileNameValue });
// 得到文件类型
const fileTypeValue = fileNameValue.split(".").pop();
fileType.value = fileTypeValue;
try {
if (query?.sk) {
// 有 sk 参数,直接使用
sk.value = query.sk;
previewUrl.value = `${baseUrl}/static/file-preview.html?sk=${query.sk}`;
// 设置 html 文件标题
setHtmlTitle(baseUrl + fileProxyUrl.value + "?sk=" + query.sk);
} else {
// 没有 sk 参数,需要获取 shareKey 和 _ticket
// 1. 获取 shareKey 用于后续分享功能
let shareKey = await getConversationShareKey(cId, path);
sk.value = shareKey;
const fileUrl = encodeURIComponent(`${fileProxyUrl.value}`);
// #ifdef H5 || WEB
if (isDev) {
// _sk 用于下载功能_ticket 用于当前页面访问_ticket 只能消费一次,适合当前用户自己访问)
const _ticket = await getTicket();
previewUrl.value = `${baseUrl}/static/file-preview.html?fileUrl=${baseUrl + fileUrl}&_ticket=${_ticket}&_sk=${shareKey}`;
} else {
previewUrl.value = `${baseUrl}/static/file-preview.html?fileUrl=${baseUrl + fileUrl}&sk=${shareKey}`;
}
// #endif
// #ifdef MP-WEIXIN
// _sk 用于下载功能_ticket 用于当前页面访问_ticket 只能消费一次,适合当前用户自己访问)
const _ticket = await getTicket();
previewUrl.value = `${baseUrl}/static/file-preview.html?fileUrl=${baseUrl + fileUrl}&_ticket=${_ticket}&_sk=${shareKey}`;
// 设置 html 文件标题
setHtmlTitle(baseUrl + fileProxyUrl.value + "?sk=" + shareKey);
// #endif
}
} catch (error) {
console.error("构建预览URL失败:", error);
} finally {
isLoading.value = false;
}
});
// #ifdef MP-WEIXIN
// 转发给朋友
// 分享到首页,由首页自动跳转到文件预览页面,解决分享后无返回按钮问题
onShareAppMessage(() => {
return {
title: pageTitle.value || fileName.value || "",
path:
"/pages/index/index?cId=" +
conversationId.value +
"&fileProxyUrl=" +
encodeURIComponent(`${fileProxyUrl.value}?sk=${sk.value}`),
};
});
// 收藏
onAddToFavorites(() => {
return {
title: pageTitle.value || fileName.value || "",
path:
"/pages/index/index?cId=" +
conversationId.value +
"&fileProxyUrl=" +
encodeURIComponent(`${fileProxyUrl.value}?sk=${sk.value}`),
};
});
// #endif
</script>
<style scoped lang="scss">
.container {
height: 100%;
display: flex;
flex-direction: column;
.file-preview-content {
flex: 1;
overflow: hidden;
}
.loading-box {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
.icon-loading-image {
width: 48rpx;
height: 48rpx;
margin-right: 10rpx;
-webkit-touch-callout: none !important;
-webkit-user-select: none !important;
user-select: none !important;
}
}
.text-gray-500 {
color: #999;
}
}
</style>