This commit is contained in:
Mrx
2026-06-04 18:13:01 +08:00
parent fdb6f278d6
commit 2bf0b13891
5 changed files with 126 additions and 7 deletions

View File

@@ -14,3 +14,7 @@ VITE_DEVTOOLS=true
# 是否注入全局loading
VITE_INJECT_APP_LOADING=true
# 前台 H5 站点(报告预览链接)
# VITE_H5_ORIGIN=http://127.0.0.1:5678
VITE_H5_ORIGIN=https://www.quannengcha.com

View File

@@ -17,3 +17,6 @@ VITE_INJECT_APP_LOADING=true
# 打包后是否生成dist.zip
VITE_ARCHIVER=true
# 前台 H5 站点(报告预览链接)
VITE_H5_ORIGIN=https://www.quannengcha.com

View File

@@ -113,6 +113,14 @@ export namespace OrderQueryApi {
export interface UpdateQueryCleanupConfigResponse {
success: boolean;
}
export interface GenerateShareLinkRequest {
order_id: string;
}
export interface GenerateShareLinkResponse {
share_link: string;
}
}
/**
@@ -175,7 +183,18 @@ async function updateQueryCleanupConfig(
);
}
/**
* 生成报告 H5 分享链接(后台预览用)
*/
async function generateOrderQueryShareLink(orderId: string) {
return requestClient.post<OrderQueryApi.GenerateShareLinkResponse>(
'/query/generate_share_link',
{ order_id: orderId },
);
}
export {
generateOrderQueryShareLink,
getOrderQueryDetail,
getQueryCleanupConfigList,
getQueryCleanupDetailList,

View File

@@ -0,0 +1,19 @@
/**
* qnc-webview-v3 H5 站点根地址(不含 /api/v1
* 后台生成报告预览链接时使用。
*/
export function getH5Origin() {
const fromEnv = import.meta.env.VITE_H5_ORIGIN?.trim();
if (fromEnv) {
return fromEnv.replace(/\/$/, '');
}
return import.meta.env.DEV
? 'http://127.0.0.1:5678'
: 'https://www.quannengcha.com';
}
/** 与前台 ShareReportButton 一致:/report/share/:shareLinkId */
export function buildReportShareUrl(shareLinkId: string) {
const base = getH5Origin();
return `${base}/report/share/${encodeURIComponent(shareLinkId)}`;
}

View File

@@ -3,7 +3,7 @@ import type { JsonViewerAction } from '@vben/common-ui';
import type { OrderQueryApi } from '#/api/order/query';
import { onMounted, ref } from 'vue';
import { onMounted, ref, computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { JsonViewer, Page } from '@vben/common-ui';
@@ -18,7 +18,8 @@ import {
Tag,
} from 'ant-design-vue';
import { getOrderQueryDetail } from '#/api/order/query';
import { getOrderQueryDetail, generateOrderQueryShareLink } from '#/api/order/query';
import { buildReportShareUrl } from '#/config/h5';
const route = useRoute();
const router = useRouter();
@@ -42,6 +43,7 @@ function isValidOrderIdForQuery(id: string) {
return true;
}
const loading = ref(false);
const shareLinkLoading = ref(false);
const queryDetail = ref<OrderQueryApi.QueryDetail>();
// 查询状态配置
@@ -122,6 +124,57 @@ function handleCopied(_event: JsonViewerAction) {
message.success('已复制JSON');
}
const canPreviewReport = computed(() => queryDetail.value?.query_state === 'success');
async function fetchReportShareUrl() {
if (!queryDetail.value?.order_id) {
message.warning('缺少订单信息');
return '';
}
shareLinkLoading.value = true;
try {
const res = await generateOrderQueryShareLink(queryDetail.value.order_id);
const linkId = res?.share_link?.trim();
if (!linkId) {
message.error('生成报告链接失败');
return '';
}
return buildReportShareUrl(linkId);
}
catch {
message.error('生成报告链接失败');
return '';
}
finally {
shareLinkLoading.value = false;
}
}
async function handlePreviewReport() {
if (!canPreviewReport.value) {
message.warning('仅查询成功的订单可预览报告');
return;
}
const url = await fetchReportShareUrl();
if (!url) {
return;
}
window.open(url, '_blank', 'noopener,noreferrer');
}
async function handleCopyReportLink() {
if (!canPreviewReport.value) {
message.warning('仅查询成功的订单可复制报告链接');
return;
}
const url = await fetchReportShareUrl();
if (!url) {
return;
}
await navigator.clipboard.writeText(url);
message.success('报告链接已复制');
}
onMounted(() => {
fetchQueryDetail();
});
@@ -143,11 +196,32 @@ onMounted(() => {
<template #title>
<div class="flex items-center justify-between">
<span class="text-lg font-medium">订单查询详情</span>
<div class="flex items-center gap-2">
<span class="text-gray-500">查询状态:</span>
<Tag v-if="queryDetail" :color="getQueryStateConfig(queryDetail.query_state).color">
{{ getQueryStateConfig(queryDetail.query_state).label }}
</Tag>
<div class="flex items-center gap-3">
<div class="flex items-center gap-2">
<span class="text-gray-500">查询状态:</span>
<Tag v-if="queryDetail" :color="getQueryStateConfig(queryDetail.query_state).color">
{{ getQueryStateConfig(queryDetail.query_state).label }}
</Tag>
</div>
<div v-if="queryDetail" class="flex items-center gap-2">
<Button
type="primary"
size="small"
:loading="shareLinkLoading"
:disabled="!canPreviewReport"
@click="handlePreviewReport"
>
预览报告
</Button>
<Button
size="small"
:loading="shareLinkLoading"
:disabled="!canPreviewReport"
@click="handleCopyReportLink"
>
复制链接
</Button>
</div>
</div>
</div>
</template>