Files
work-leave-front/preview-ut/main-print.ts
T
wanghu 2e36d7a9c8
build / build (push) Successful in 9m55s
commit
2026-10-10 15:58:02 +08:00

99 lines
4.6 KiB
TypeScript

// 独立预览入口:打印请假单页(LeavePrint.vue)的视觉/交互验收。
//
// 与 main-list.ts 同一套思路:业务 dev 端口受 CAS 保护,自动化浏览器截不到真实页面,
// 这里用 mock-api 的页内 fetch 拦截独立渲染(无需登录、无需 mock-server)。
//
// 用法:
// npx vite --config preview.vite.config.ts --port 8099
// 打开 http://localhost:8099/preview-print.html → 屏幕预览(A4 纸张样式)
// 加 ?probe=1 跑断言并把结果写入 document.title
//
// 说明:window.print() 会弹浏览器打印对话框,自动化环境不可控,探针只断言
// 「打印 CSS 已注入 + html.leave-print-mode 已挂载」,纸张效果以屏幕截图核对。
import { createApp, h } from "vue";
import { createRouter, createMemoryHistory, RouterView } from "vue-router";
import { createPinia } from "pinia";
import ViewUIPlus from "view-ui-plus";
import "view-ui-plus/dist/styles/viewuiplus.css";
import "@/assets/styles/main.scss";
import "@/assets/styles/layout.css";
import "@/assets/styles/icons.css";
import "virtual:uno.css";
import "virtual:svg-icons-register";
import utils from "@/utils";
import config from "@/assets/config/host.config";
import { installApiStub } from "./mock-api";
import LeavePrint from "@/views/leave/LeavePrint.vue";
installApiStub();
const RUNTIME_ERRORS: string[] = [];
window.addEventListener("error", (e) => RUNTIME_ERRORS.push(String(e.message || e)));
window.addEventListener("unhandledrejection", (e) => RUNTIME_ERRORS.push(`reject:${e.reason}`));
const router = createRouter({
history: createMemoryHistory(),
routes: [{ path: "/print", component: LeavePrint }],
});
const app = createApp({ render: () => h(RouterView) });
app.use(createPinia());
app.use(router);
app.use(ViewUIPlus);
app.config.globalProperties.$conf = config;
app.config.globalProperties.$utils = utils;
// 先 install 再跳转:install 前的 push 在部分 vue-router 4 小版本上会丢初始导航
router.push("/print?leaveId=4");
router.isReady().then(() => app.mount("#app"));
if (new URLSearchParams(location.search).has("probe")) {
setTimeout(() => {
const out: string[] = [];
let bad = 0;
const say = (ok: boolean, msg: string) => {
if (!ok) bad++;
out.push(`${msg}${ok ? "=ok" : "=FAIL"}`);
};
// 挂载期间应给 html 打上打印模式类(print CSS 作用域开关)
say(document.documentElement.classList.contains("leave-print-mode"), "modeClass");
// 全局打印规则已注入(非 scoped 块存在 @media print + .header-container 隐藏)
let printRule = false;
for (const sheet of Array.from(document.styleSheets)) {
try {
for (const rule of Array.from(sheet.cssRules || [])) {
const r = rule as CSSMediaRule;
if (r.type === CSSRule.MEDIA_RULE && /print/.test(r.conditionText || "")) {
if (/header-container/.test(r.cssText)) printRule = true;
}
}
} catch {
/* 跨域样式表忽略 */
}
}
say(printRule, "printRule");
// 单据渲染:标题 / 信息表 / 审批记录 / 签字栏
say(!!document.querySelector(".print-sheet"), "sheet");
const title = document.querySelector<HTMLElement>(".sheet-title");
say(!!title && title.textContent!.includes("教职工请假单"), `title(${title?.textContent})`);
say(document.querySelectorAll(".sheet-table").length >= 3, `tables(${document.querySelectorAll(".sheet-table").length})`);
say(document.querySelectorAll(".flow-table tbody tr").length === 3, `steps(${document.querySelectorAll(".flow-table tbody tr").length})`);
say(!!document.querySelector(".status-stamp"), "stamp");
// 数据正确性:产假 80 小时 + 状态「已通过」
const bodyText = document.querySelector(".print-sheet")?.textContent || "";
say(bodyText.includes("产假"), "typeName");
say(bodyText.includes("80 小时"), "hours");
say(bodyText.includes("已通过"), "statusName");
say(bodyText.includes("2026-10-09 19:28"), "applyTime");
// 工具栏存在(打印/返回按钮)
say(document.querySelectorAll(".print-toolbar .ivu-btn").length === 2, "toolbar");
say(RUNTIME_ERRORS.length === 0, `errs(${RUNTIME_ERRORS.length})`);
document.title = `PRINT|bad=${bad}|` + out.join("|") + (RUNTIME_ERRORS.length ? "|" + RUNTIME_ERRORS.slice(0, 2).join("~") : "");
}, 2200);
}