Files
qhmes/jeecgboot-vue3/src/views/monitor/mynews/DetailModal.vue
2026-04-03 09:56:14 +08:00

394 lines
11 KiB
Vue
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>
<BasicModal
v-bind="$attrs"
@register="registerModal"
title="查看详情"
:width="800"
:minHeight="600"
:showCancelBtn="false"
:showOkBtn="false"
:height="88"
:destroyOnClose="true"
@visible-change="handleVisibleChange"
>
<template #title>
<span class="basic-title">查看详情</span>
<div class="print-btn" @click="onPrinter">
<Icon icon="ant-design:printer-filled" />
<span class="print-text">打印</span>
</div>
</template>
<a-card class="daily-article">
<a-card-meta :title="content.titile">
<template #description>
<div class="article-desc">
<span>发布人{{ content.sender }}</span>
<span>发布时间{{ content.sendTime }}</span>
<span v-if="content.visitsNum">
<a-tooltip placement="top" title="访问次数" :autoAdjustOverflow="true">
<eye-outlined class="item-icon" /> {{ content.visitsNum }}
</a-tooltip>
</span>
</div>
</template>
</a-card-meta>
<a-divider />
<div v-html="content.msgContent" class="article-content"></div>
<div>
<a-button v-if="hasHref" @click="jumpToHandlePage">前往办理<ArrowRightOutlined /></a-button>
</div>
</a-card>
<template v-if="noticeFiles && noticeFiles.length > 0">
<div class="files-title">相关附件</div>
<template v-for="(file, index) in noticeFiles" :key="index">
<div class="files-area">
<div class="files-area-text">
<span>
<paper-clip-outlined />
<a
target="_blank"
rel="noopener noreferrer"
:title="file.fileName"
:href="getFileAccessHttpUrl(file.filePath)"
class="ant-upload-list-item-name"
>{{ file.fileName }}</a
>
</span>
</div>
<div class="files-area-operate">
<download-outlined class="item-icon" @click="handleDownloadFile(file.filePath)" />
<eye-outlined class="item-icon" @click="handleViewFile(file.filePath)" />
</div>
</div>
</template>
<a v-if="noticeFiles.length > 1" :href="downLoadFiles + '?id=' + content.id + '&token=' + getToken()" target="_blank" style="margin: 15px 6px; color: #5ac0fa">
<download-outlined class="item-icon" style="margin-right: 5px" /><span>批量下载所有附件</span>
</a>
</template>
</BasicModal>
</template>
<script lang="ts" setup>
import { BasicModal, useModalInner } from '/@/components/Modal';
import { ArrowRightOutlined, PaperClipOutlined, DownloadOutlined, EyeOutlined } from '@ant-design/icons-vue';
import { addVisitsNum } from '@/views/system/notice/notice.api';
import { useRouter } from 'vue-router';
import xss from 'xss';
import { options } from './XssWhiteList';
import { ref, unref } from 'vue';
import { getElectronFileUrl, getFileAccessHttpUrl } from '@/utils/common/compUtils';
import { useGlobSetting } from '@/hooks/setting';
import { encryptByBase64 } from '@/utils/cipher';
import { getToken } from '@/utils/auth';
import {defHttp} from "@/utils/http/axios";
import {$electron} from "@/electron";
const router = useRouter();
const glob = useGlobSetting();
const isUpdate = ref(true);
const content = ref<any>({});
const noticeFiles = ref([]);
/**
* 下载文件路径
*/
const downLoadFiles = `${glob.domainUrl}/sys/annountCement/downLoadFiles`;
const emit = defineEmits(['close', 'register']);
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
isUpdate.value = !!data?.isUpdate;
noticeFiles.value = [];
if (unref(isUpdate)) {
//data.record.msgContent = '<p>2323</p><input onmouseover=alert(1)>xss test';
// 代码逻辑说明: VUEN-1702 【禁止问题】sql注入漏洞
if (data.record.msgContent) {
// 代码逻辑说明: 【QQYUN-7049】3.6.0版本 通知公告中发布的富文本消息,在我的消息中查看没有样式---
data.record.msgContent = xss(data.record.msgContent, options);
}
// 代码逻辑说明: [QQYUN-12521]通知公告消息增加访问量
if (!data.record?.busId) {
await addVisitsNum({ id: data.record.id });
}
content.value = data.record;
if(content.value.sender){
const userInfo = await defHttp.get({ url: '/sys/user/queryUserComponentData?isMultiTranslate=true', params: { username: content.value.sender } });
content.value.sender = userInfo && userInfo?.records && userInfo?.records.length>0
?userInfo.records.find((item) => item.username === content.value.sender)?.realname : content.value.sender;
}
console.log('data---------->>>', data);
if (data.record?.files && data.record?.files.length > 0) {
noticeFiles.value = data.record.files.split(',').map((item) => {
return {
fileName: item.split('/').pop(),
filePath: item,
};
});
}
showHrefButton();
}
});
const hasHref = ref(false);
//查看消息详情可以跳转
function showHrefButton() {
if (content.value.busId) {
hasHref.value = true;
}
}
//跳转至办理页面
function jumpToHandlePage() {
let temp: any = content.value;
if (temp.busId) {
//这个busId是 任务ID
let jsonStr = temp.msgAbstract;
let query = {};
try {
if (jsonStr) {
let temp = JSON.parse(jsonStr);
if (temp) {
Object.keys(temp).map((k) => {
query[k] = temp[k];
});
}
}
} catch (e) {
console.log('参数解析异常', e);
}
console.log('query', query, jsonStr);
console.log('busId', temp.busId);
if (Object.keys(query).length > 0) {
// taskId taskDefKey procInsId
router.push({ path: '/task/handle/' + temp.busId, query: query });
} else {
router.push({ path: '/task/handle/' + temp.busId });
}
}
closeModal();
}
//打印
function onPrinter() {
// 获取要打印的内容
const printContent = document.querySelector('.daily-article');
if (!printContent) return;
// 创建一个iframe来处理打印
const printFrame = document.createElement('iframe');
printFrame.style.position = 'absolute';
printFrame.style.width = '0';
printFrame.style.height = '0';
printFrame.style.border = 'none';
printFrame.style.left = '-9999px';
printFrame.onload = function () {
const frameDoc = printFrame.contentDocument || printFrame.contentWindow?.document;
if (!frameDoc) return;
// 复制内容到iframe
const clone = printContent.cloneNode(true);
frameDoc.body.appendChild(clone);
// 添加打印样式
const style = frameDoc.createElement('style');
style.innerHTML = `
body {
margin: 0;
padding: 15px;
font-family: Arial, sans-serif;
}
img {
max-width: 100%;
height: auto;
}
@page {
size: auto;
margin: 15mm;
}
@media print {
body {
padding: 0;
}
}
.ant-card-meta-detail {
display: flex !important ;
justify-content: center !important;
align-items: center !important;
flex-direction: column !important;
}
.ant-card-meta-title {
font-size: 22px !important;
color: rgba(51, 51, 51, 0.88);
font-weight: 600;
font-size: 16px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.ant-card .ant-card-meta-description {
color: rgba(51, 51, 51, 0.45);
}
`;
frameDoc.head.appendChild(style);
// 确保图片加载完成
const images = frameDoc.getElementsByTagName('img');
let imagesToLoad = images.length;
const printWhenReady = () => {
if (imagesToLoad === 0) {
setTimeout(() => {
printFrame.contentWindow?.focus();
printFrame.contentWindow?.print();
document.body.removeChild(printFrame);
}, 300);
}
};
if (imagesToLoad === 0) {
printWhenReady();
} else {
Array.from(images).forEach((img) => {
img.onload = () => {
imagesToLoad--;
printWhenReady();
};
// 处理可能已经缓存的图片
if (img.complete && img.naturalWidth !== 0) {
imagesToLoad--;
printWhenReady();
}
});
}
};
document.body.appendChild(printFrame);
}
/**
* 下载文件
* @param filePath
*/
function handleDownloadFile(filePath) {
window.open(getFileAccessHttpUrl(filePath), '_blank');
}
/**
* 预览文件
* @param filePath
*/
function handleViewFile(filePath) {
if (filePath) {
console.log('glob.onlineUrl', glob.viewUrl);
let url = encodeURIComponent(encryptByBase64(filePath));
let previewUrl = `${glob.viewUrl}?url=` + url;
//update-begin-author:liusq---date:2025-12-16--for: JHHB-1139桌面端 文件预览统一修改
if($electron.isElectron()){
previewUrl = getElectronFileUrl(filePath);
}
//update-end-author:liusq---date:2025-12-16--for: JHHB-1139桌面端 文件预览统一修改
window.open(previewUrl, '_blank');
}
}
function handleVisibleChange(visible: boolean) {
if (!visible) {
emit('close');
}
}
</script>
<style scoped lang="less">
.daily-article {
:deep(.ant-card-meta-detail) {
display: flex !important;
justify-content: center !important;
align-items: center !important;
flex-direction: column !important;
}
:deep(.ant-card-meta-detail .ant-card-meta-title) {
font-size: 22px !important;
}
}
.print-btn {
position: absolute;
right: 100px;
top: 20px;
cursor: pointer;
color: #a3a3a5;
z-index: 999;
.print-text {
margin-left: 5px;
font-size: 14px;
}
&:hover {
color: #40a9ff;
}
}
.detail-iframe {
border: 0;
width: 100%;
height: 100%;
min-height: 600px;
}
.files-title {
font-size: 16px;
margin: 10px;
font-weight: 600;
color: #333;
}
.files-area {
display: flex;
align-items: center;
justify-content: flex-start;
margin: 6px;
&:hover {
background-color: #f5f5f5;
}
.files-area-text {
display: flex;
.ant-upload-list-item-name {
margin: 0 6px;
color: #56befa;
}
}
.files-area-operate {
display: flex;
margin-left: 10px;
.item-icon {
cursor: pointer;
margin: 0 6px;
&:hover {
color: #56befa;
}
}
}
}
.article-desc {
display: flex;
align-items: center;
span:not(:first-child) {
margin-left: 5px;
}
}
/* 确保打印内容中的图片有最大宽度限制 */
.article-content img {
max-width: 100%;
height: auto;
}
.basic-title{
position: relative;
display: flex;
padding-left: 7px;
font-size: 16px;
font-weight: 500;
line-height: 24px;
color: rgba(0,0,0,0.88);
cursor: move;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
</style>