恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。 == 此快照内容 == - 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091) - 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static) - 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB) - 交接文档 go.md + go-code-reference/endpoints/entities/database.md - 多代理建设脚本 .claude/wf-*.js == 状态 == - 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板) - 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用 - W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成) - 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456 == 排除(gitignore, 可再生) == node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui) 完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules) 时间戳: 20260615-191517 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
import { createApp } from 'vue'
|
|
import ElementPlus, { ElMessage } from 'element-plus'
|
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
|
// pdf.js worker: resolve the bundled worker via Vite's `?url` so it gets a
|
|
// hashed asset URL in the build (and a dev URL in serve). Set once globally so
|
|
// every FilePreview render reuses it. Without this pdf.js throws
|
|
// "No GlobalWorkerOptions.workerSrc specified".
|
|
import * as pdfjsLib from 'pdfjs-dist'
|
|
import pdfWorkerUrl from 'pdfjs-dist/build/pdf.worker.min.mjs?url'
|
|
import App from './App.vue'
|
|
import router from './router'
|
|
|
|
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorkerUrl
|
|
import './styles/erp-ui.css'
|
|
import './styles/modern.css'
|
|
// 移动端响应式总表:必须最后导入,靠 !important 压过各页 scoped 与内联定宽(仅 <=768px 生效)。
|
|
import './styles/responsive.css'
|
|
|
|
declare global {
|
|
interface Window {
|
|
__modernRuntimeConsoleErrors?: string[]
|
|
}
|
|
}
|
|
|
|
window.__modernRuntimeConsoleErrors = window.__modernRuntimeConsoleErrors || []
|
|
|
|
function runtimeMessage(value: unknown) {
|
|
if (value instanceof Error) return value.stack || value.message
|
|
if (typeof value === 'string') return value
|
|
try {
|
|
return JSON.stringify(value)
|
|
} catch {
|
|
return String(value)
|
|
}
|
|
}
|
|
|
|
const originalConsoleError = window.console.error.bind(window.console)
|
|
window.console.error = (...args: unknown[]) => {
|
|
window.__modernRuntimeConsoleErrors?.push(args.map(runtimeMessage).join(' '))
|
|
originalConsoleError(...args)
|
|
}
|
|
|
|
window.addEventListener('error', (event) => {
|
|
window.__modernRuntimeConsoleErrors?.push(event.error ? runtimeMessage(event.error) : event.message)
|
|
})
|
|
|
|
window.addEventListener('unhandledrejection', (event) => {
|
|
window.__modernRuntimeConsoleErrors?.push(runtimeMessage(event.reason))
|
|
})
|
|
|
|
const app = createApp(App)
|
|
|
|
// 全局错误兜底:任何组件渲染/生命周期/侦听器里抛出的未捕获异常,统一记录控制台
|
|
// 并轻提示用户,避免「白屏无提示」。App.vue 的 onErrorCaptured 负责渲染友好降级页,
|
|
// 这里只做日志 + 轻提示,二者互补。lastErrorToastAt 节流,防止抖动式连环弹窗。
|
|
let lastErrorToastAt = 0
|
|
app.config.errorHandler = (err, _instance, info) => {
|
|
const message = err instanceof Error ? err.stack || err.message : String(err)
|
|
window.__modernRuntimeConsoleErrors?.push(`[vue:${info}] ${message}`)
|
|
originalConsoleError(`[Vue errorHandler] ${info}`, err)
|
|
const now = Date.now()
|
|
if (now - lastErrorToastAt > 3000) {
|
|
lastErrorToastAt = now
|
|
ElMessage.error('页面出现异常,部分内容可能无法正常显示,请刷新或稍后重试')
|
|
}
|
|
}
|
|
|
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|
app.component(key, component)
|
|
}
|
|
|
|
app.use(ElementPlus)
|
|
app.use(router)
|
|
app.mount('#app')
|