fix(admin): 发版 chunk 自动刷新、nginx 缓存策略与审计页 i18n
lazy route 加载失败时刷新入口;index.html 不缓存;补全 audit.col.operator/ip 等拆包遗漏 key。
This commit is contained in:
@@ -357,10 +357,14 @@ const adminPages: Record<string, string> = {
|
||||
'bet.col.result': 'Result',
|
||||
|
||||
'audit.module_ph': 'e.g. USERS, AGENTS',
|
||||
'audit.col.time': 'Time',
|
||||
'audit.col.operator': 'Operator',
|
||||
'audit.col.action': 'Action',
|
||||
'audit.col.module': 'Module',
|
||||
'audit.col.target_id': 'Target ID',
|
||||
'audit.col.time': 'Time',
|
||||
'audit.col.ip': 'IP',
|
||||
'audit.operator_system': 'System',
|
||||
'audit.operator_player': 'Player',
|
||||
'audit.action.CREATE_PLAYER': 'Create player',
|
||||
'audit.action.UPDATE_PLAYER': 'Update player',
|
||||
'audit.action.RESET_DATABASE': 'Reset database',
|
||||
|
||||
@@ -358,10 +358,14 @@ const adminPages: Record<string, string> = {
|
||||
'bet.col.result': '赛果',
|
||||
|
||||
'audit.module_ph': '如 USERS、AGENTS',
|
||||
'audit.col.time': '时间',
|
||||
'audit.col.operator': '操作人',
|
||||
'audit.col.action': '操作',
|
||||
'audit.col.module': '模块',
|
||||
'audit.col.target_id': '目标 ID',
|
||||
'audit.col.time': '时间',
|
||||
'audit.col.ip': 'IP',
|
||||
'audit.operator_system': '系统',
|
||||
'audit.operator_player': '玩家',
|
||||
'audit.action.CREATE_PLAYER': '新建玩家',
|
||||
'audit.action.UPDATE_PLAYER': '更新玩家',
|
||||
'audit.action.RESET_DATABASE': '重置数据库',
|
||||
|
||||
@@ -250,4 +250,28 @@ router.beforeEach(async (to) => {
|
||||
return true;
|
||||
});
|
||||
|
||||
/** 发版后旧 index.html 可能引用已不存在的 hash chunk,自动刷新一次拉最新入口。 */
|
||||
function isLazyChunkLoadError(err: unknown): boolean {
|
||||
const msg = err instanceof Error ? err.message : String(err ?? '');
|
||||
return (
|
||||
msg.includes('Failed to fetch dynamically imported module') ||
|
||||
msg.includes('Importing a module script failed') ||
|
||||
msg.includes('error loading dynamically imported module')
|
||||
);
|
||||
}
|
||||
|
||||
const CHUNK_RELOAD_FLAG = 'admin:chunk-reload';
|
||||
|
||||
router.onError((error, to) => {
|
||||
if (!isLazyChunkLoadError(error)) throw error;
|
||||
const target = to.fullPath || '/';
|
||||
if (!sessionStorage.getItem(CHUNK_RELOAD_FLAG)) {
|
||||
sessionStorage.setItem(CHUNK_RELOAD_FLAG, target);
|
||||
window.location.assign(target);
|
||||
return;
|
||||
}
|
||||
sessionStorage.removeItem(CHUNK_RELOAD_FLAG);
|
||||
throw error;
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -9,6 +9,17 @@ server {
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
|
||||
|
||||
# 带 hash 的静态资源可长期缓存;index.html 禁止缓存,避免发版后引用旧 chunk
|
||||
location /assets/ {
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location = /index.html {
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Pragma "no-cache";
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://api:3000;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
@@ -10,6 +10,16 @@ server {
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
|
||||
|
||||
location /assets/ {
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location = /index.html {
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Pragma "no-cache";
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
set $api_upstream api:3000;
|
||||
proxy_pass http://$api_upstream;
|
||||
|
||||
Reference in New Issue
Block a user