From 5190a0cc9ccab3f0346dc781d0c3f87ae85f3bcd Mon Sep 17 00:00:00 2001
From: wangys <3401275564@qq.com>
Date: Thu, 8 Jan 2026 13:20:40 +0800
Subject: [PATCH] =?UTF-8?q?web=E6=89=93=E5=8C=85=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker/urbanLifeline/nginx/.env.example | 14 +
.../nginx/docker-compose.yml | 8 +-
.../nginx/nginx/cert/server.crt | 0
.../nginx/nginx/cert/server.key | 0
.../nginx/nginx}/conf.d/default.conf | 3 +-
.../nginx/nginx/nginx.conf | 0
.../nginx/volumes/cert/server.crt | 0
.../nginx/volumes/cert/server.key | 0
.../nginx/volumes}/conf.d/default.conf | 0
.../nginx/volumes/nginx.conf | 0
docker/urbanLifeline/serv/docker-compose.yml | 36 +-
docker/urbanLifeline/web/docker-compose.yml | 13 +-
.../layouts/SidebarLayout/SidebarLayout.vue | 2 +-
urbanLifelineWeb/packages/bidding/src/main.ts | 3 +
.../bidding/src/router/dynamicRoute.ts | 7 +-
.../AdminSidebarLayout/AdminSidebarLayout.vue | 2 +-
.../layouts/SidebarLayout/SidebarLayout.vue | 2 +-
.../packages/platform/src/main.ts | 3 +
.../platform/src/router/dynamicRoute.ts | 7 +-
.../src/views/admin/overview/OverviewView.vue | 2 +-
.../userManagement/UserManagementView.vue | 2 +-
.../views/public/Agents/AgentPlatformView.vue | 2 +-
.../Agents/components/AgentCard/AgentCard.vue | 2 +-
.../Agents/components/AgentEdit/AgentEdit.vue | 2 +-
.../src/views/public/Chat/AIChatView.vue | 2 +-
.../components/ChatDefault/ChatDefault.vue | 2 +-
.../documentDetail/DocumentDetail.vue | 7 +-
.../documentSegment/DocumentSegment.scss | 42 +-
.../documentSegment/DocumentSegment.vue | 4 +-
.../dynamicFormItem/DynamicFormItem.vue | 4 +-
.../file/fileHistory/FileHistory.vue | 4 +-
.../components/file/fileupload/FileUpload.vue | 4 +-
.../src/components/iframe/IframeView.scss | 75 +++
.../src/components/iframe/IframeView.vue | 82 +--
.../AdminSidebarLayout/AdminSidebarLayout.vue | 4 +-
.../src/layouts/BlankLayout/BlankLayout.vue | 8 +-
.../SubSidebarLayout/SubSidebarLayout.scss | 624 ++++++------------
.../SubSidebarLayout/SubSidebarLayout.vue | 4 +-
.../shared/src/styles/components.scss | 8 +
.../packages/shared/src/styles/index.scss | 6 +
.../packages/shared/src/styles/index.ts | 9 +
.../packages/shared/src/styles/layouts.scss | 1 +
.../packages/shared/vite.config.ts | 17 +-
.../layouts/SidebarLayout/SidebarLayout.vue | 2 +-
.../packages/workcase/src/main.ts | 3 +
.../workcase/src/router/dynamicRoute.ts | 7 +-
.../src/views/admin/agent/AgentView.vue | 2 +-
.../admin/customerChat/CustomerChatView.vue | 2 +-
.../views/admin/knowledge/KnowLedgeView.vue | 2 +-
.../log/knowledgeLog/KnowledgeLogView.vue | 2 +-
.../admin/log/systemLog/SystemLogView.vue | 2 +-
.../admin/log/workcaseLog/WorkcaseLogView.vue | 2 +-
.../src/views/admin/overview/OverviewView.vue | 2 +-
.../src/views/public/AIChat/AIChatView.vue | 2 +-
.../public/AIChat/components/ChatHistory.vue | 2 +-
.../ChatRoom/ChatMessage/ChatMessage.vue | 2 +-
.../views/public/ChatRoom/ChatRoomView.vue | 2 +-
.../ChatRoom/MeetingCard/MeetingCard.vue | 2 +-
.../public/ChatRoom/chatRoom/ChatRoom.vue | 2 +-
.../CommentMessageCard/CommentMessageCard.vue | 2 +-
.../public/JitsiMeeting/JitsiMeetingView.vue | 2 +-
.../WorkcaseDetail/WorkcaseDetail.vue | 2 +-
.../pages/meeting/Meeting.uvue | 2 +-
63 files changed, 463 insertions(+), 600 deletions(-)
create mode 100644 docker/urbanLifeline/nginx/.env.example
rename docker/{ => urbanLifeline}/nginx/docker-compose.yml (74%)
rename docker/{ => urbanLifeline}/nginx/nginx/cert/server.crt (100%)
rename docker/{ => urbanLifeline}/nginx/nginx/cert/server.key (100%)
rename docker/{nginx/volumes => urbanLifeline/nginx/nginx}/conf.d/default.conf (99%)
rename docker/{ => urbanLifeline}/nginx/nginx/nginx.conf (100%)
rename docker/{ => urbanLifeline}/nginx/volumes/cert/server.crt (100%)
rename docker/{ => urbanLifeline}/nginx/volumes/cert/server.key (100%)
rename docker/{nginx/nginx => urbanLifeline/nginx/volumes}/conf.d/default.conf (100%)
rename docker/{ => urbanLifeline}/nginx/volumes/nginx.conf (100%)
create mode 100644 urbanLifelineWeb/packages/shared/src/components/iframe/IframeView.scss
create mode 100644 urbanLifelineWeb/packages/shared/src/styles/components.scss
create mode 100644 urbanLifelineWeb/packages/shared/src/styles/index.scss
create mode 100644 urbanLifelineWeb/packages/shared/src/styles/index.ts
create mode 100644 urbanLifelineWeb/packages/shared/src/styles/layouts.scss
diff --git a/docker/urbanLifeline/nginx/.env.example b/docker/urbanLifeline/nginx/.env.example
new file mode 100644
index 00000000..25d71062
--- /dev/null
+++ b/docker/urbanLifeline/nginx/.env.example
@@ -0,0 +1,14 @@
+# ------------------------------
+# 挂载目录配置
+# ------------------------------
+# 数据目录
+DATA_ROOT=./volumes
+
+# 配置文件目录
+CONFIG_ROOT=./volumes
+
+# 配置文件位置
+CONFIG_FILE_ROOT=./volumes
+
+# SSL证书目录
+SSL_ROOT=
\ No newline at end of file
diff --git a/docker/nginx/docker-compose.yml b/docker/urbanLifeline/nginx/docker-compose.yml
similarity index 74%
rename from docker/nginx/docker-compose.yml
rename to docker/urbanLifeline/nginx/docker-compose.yml
index 95634099..b808748f 100644
--- a/docker/nginx/docker-compose.yml
+++ b/docker/urbanLifeline/nginx/docker-compose.yml
@@ -17,11 +17,11 @@ services:
environment:
TZ: Asia/Shanghai
volumes:
- - ./volumes/nginx/logs:/var/log/nginx
- - ./volumes/nginx.conf:/etc/nginx/nginx.conf:ro
- - ./volumes/conf.d:/etc/nginx/conf.d:ro
+ - ${LOG_ROOT:-./volumes/nginx/logs}:/var/log/nginx
+ - ${CONFIG_FILE_ROOT:-./volumes/nginx.conf}:/etc/nginx/nginx.conf:ro
+ - ${CONFIG_ROOT:-./volumes/conf.d}:/etc/nginx/conf.d:ro
# SSL 证书(可选)
- - ./volumes/cert:/etc/nginx/ssl:ro
+ - ${SSL_ROOT:-./volumes/cert}:/etc/nginx/ssl:ro
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
diff --git a/docker/nginx/nginx/cert/server.crt b/docker/urbanLifeline/nginx/nginx/cert/server.crt
similarity index 100%
rename from docker/nginx/nginx/cert/server.crt
rename to docker/urbanLifeline/nginx/nginx/cert/server.crt
diff --git a/docker/nginx/nginx/cert/server.key b/docker/urbanLifeline/nginx/nginx/cert/server.key
similarity index 100%
rename from docker/nginx/nginx/cert/server.key
rename to docker/urbanLifeline/nginx/nginx/cert/server.key
diff --git a/docker/nginx/volumes/conf.d/default.conf b/docker/urbanLifeline/nginx/nginx/conf.d/default.conf
similarity index 99%
rename from docker/nginx/volumes/conf.d/default.conf
rename to docker/urbanLifeline/nginx/nginx/conf.d/default.conf
index 1e54c772..6ea53116 100644
--- a/docker/nginx/volumes/conf.d/default.conf
+++ b/docker/urbanLifeline/nginx/nginx/conf.d/default.conf
@@ -125,7 +125,7 @@ server {
# 后端 API 代理
location /urban-lifeline/ {
- proxy_pass http://gateway/;
+ proxy_pass http://gateway;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
@@ -148,3 +148,4 @@ server {
root /usr/share/nginx/html;
}
}
+
diff --git a/docker/nginx/nginx/nginx.conf b/docker/urbanLifeline/nginx/nginx/nginx.conf
similarity index 100%
rename from docker/nginx/nginx/nginx.conf
rename to docker/urbanLifeline/nginx/nginx/nginx.conf
diff --git a/docker/nginx/volumes/cert/server.crt b/docker/urbanLifeline/nginx/volumes/cert/server.crt
similarity index 100%
rename from docker/nginx/volumes/cert/server.crt
rename to docker/urbanLifeline/nginx/volumes/cert/server.crt
diff --git a/docker/nginx/volumes/cert/server.key b/docker/urbanLifeline/nginx/volumes/cert/server.key
similarity index 100%
rename from docker/nginx/volumes/cert/server.key
rename to docker/urbanLifeline/nginx/volumes/cert/server.key
diff --git a/docker/nginx/nginx/conf.d/default.conf b/docker/urbanLifeline/nginx/volumes/conf.d/default.conf
similarity index 100%
rename from docker/nginx/nginx/conf.d/default.conf
rename to docker/urbanLifeline/nginx/volumes/conf.d/default.conf
diff --git a/docker/nginx/volumes/nginx.conf b/docker/urbanLifeline/nginx/volumes/nginx.conf
similarity index 100%
rename from docker/nginx/volumes/nginx.conf
rename to docker/urbanLifeline/nginx/volumes/nginx.conf
diff --git a/docker/urbanLifeline/serv/docker-compose.yml b/docker/urbanLifeline/serv/docker-compose.yml
index 25b5872f..9405a8a2 100644
--- a/docker/urbanLifeline/serv/docker-compose.yml
+++ b/docker/urbanLifeline/serv/docker-compose.yml
@@ -4,6 +4,31 @@
# ================================================
services:
+ # ====================== Redis 缓存 ======================
+ redis:
+ image: redis:7-alpine
+ container_name: urban-lifeline-redis
+ restart: unless-stopped
+ networks:
+ - urban-lifeline
+ expose:
+ - "6379"
+ environment:
+ TZ: Asia/Shanghai
+ command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-redis123}
+ volumes:
+ - ${REDIS_DATA:-./volumes/redis}:/data
+ deploy:
+ resources:
+ limits:
+ memory: ${REDIS_MEMORY_LIMIT:-512M}
+ healthcheck:
+ test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-redis123}", "ping"]
+ interval: 10s
+ timeout: 5s
+ retries: 3
+
+ # ====================== 后端服务 ======================
urban-lifeline-serv:
image: urban-lifeline-serv:${IMAGE_VERSION:-latest}
container_name: urban-lifeline-serv
@@ -12,13 +37,20 @@ services:
- .env
networks:
- urban-lifeline
- ports:
- - "${GATEWAY_PORT:-8080}:8080"
+ # 不对外暴露端口,仅通过 nginx 反向代理访问
+ expose:
+ - "8080"
environment:
TZ: Asia/Shanghai
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
NACOS_SERVER_ADDR: ${NACOS_SERVER_ADDR:-nacos:8848}
NACOS_NAMESPACE: ${NACOS_NAMESPACE:-}
+ REDIS_HOST: urban-lifeline-redis
+ REDIS_PORT: 6379
+ REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123}
+ depends_on:
+ redis:
+ condition: service_healthy
volumes:
# 配置文件目录
- ${CONFIG_ROOT:-./volumes/config}:/app/config:ro
diff --git a/docker/urbanLifeline/web/docker-compose.yml b/docker/urbanLifeline/web/docker-compose.yml
index cad5b07c..e74efb04 100644
--- a/docker/urbanLifeline/web/docker-compose.yml
+++ b/docker/urbanLifeline/web/docker-compose.yml
@@ -12,12 +12,13 @@ services:
- .env
networks:
- urban-lifeline
- ports:
- - "${SHARED_PORT:-8000}:8000"
- - "${PLATFORM_PORT:-8001}:8001"
- - "${WORKCASE_PORT:-8002}:8002"
- - "${BIDDING_PORT:-8003}:8003"
- - "${WORKCASE_WECHAT_PORT:-8004}:8004"
+ # 不对外暴露端口,仅通过 nginx 反向代理访问
+ expose:
+ - "8000"
+ - "8001"
+ - "8002"
+ - "8003"
+ - "8004"
environment:
TZ: Asia/Shanghai
SHARED_PORT: ${SHARED_PORT:-8000}
diff --git a/urbanLifelineWeb/packages/bidding/src/layouts/SidebarLayout/SidebarLayout.vue b/urbanLifelineWeb/packages/bidding/src/layouts/SidebarLayout/SidebarLayout.vue
index fd579891..95570543 100644
--- a/urbanLifelineWeb/packages/bidding/src/layouts/SidebarLayout/SidebarLayout.vue
+++ b/urbanLifelineWeb/packages/bidding/src/layouts/SidebarLayout/SidebarLayout.vue
@@ -245,5 +245,5 @@ watch(
diff --git a/urbanLifelineWeb/packages/bidding/src/main.ts b/urbanLifelineWeb/packages/bidding/src/main.ts
index 26ef90d0..72441ffb 100644
--- a/urbanLifelineWeb/packages/bidding/src/main.ts
+++ b/urbanLifelineWeb/packages/bidding/src/main.ts
@@ -3,6 +3,9 @@ import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
+// 导入 shared 的全局样式(Module Federation 远程模块样式)
+import 'shared/styles'
+
import App from './App.vue'
import router from './router/'
diff --git a/urbanLifelineWeb/packages/bidding/src/router/dynamicRoute.ts b/urbanLifelineWeb/packages/bidding/src/router/dynamicRoute.ts
index d846f7d6..ed0af139 100644
--- a/urbanLifelineWeb/packages/bidding/src/router/dynamicRoute.ts
+++ b/urbanLifelineWeb/packages/bidding/src/router/dynamicRoute.ts
@@ -11,7 +11,7 @@
import type { RouteRecordRaw } from 'vue-router'
import router from './index'
-import { SidebarLayout, BlankLayout, SubSidebarLayout } from '@/layouts'
+import { SidebarLayout } from '@/layouts'
// 动态导入 shared 模块(避免顶层 import 阻塞)
async function loadSharedModules() {
@@ -25,10 +25,11 @@ async function loadSharedModules() {
// Bidding 布局组件映射
const biddingLayoutMap: Record Promise> = {
'SidebarLayout': () => Promise.resolve({ default: SidebarLayout }),
- 'BlankLayout': () => Promise.resolve({ default: BlankLayout }),
'NavigationLayout': () => Promise.resolve({ default: SidebarLayout }),
'BasicLayout': () => Promise.resolve({ default: SidebarLayout }),
- 'SubSidebarLayout': () => Promise.resolve({ default: SubSidebarLayout })
+ // 动态导入 shared 的布局组件,避免静态导入阻塞
+ 'BlankLayout': () => import('shared/layouts').then(m => ({ default: m.BlankLayout })),
+ 'SubSidebarLayout': () => import('shared/layouts').then(m => ({ default: m.SubSidebarLayout }))
}
// 视图组件加载器
diff --git a/urbanLifelineWeb/packages/platform/src/layouts/AdminSidebarLayout/AdminSidebarLayout.vue b/urbanLifelineWeb/packages/platform/src/layouts/AdminSidebarLayout/AdminSidebarLayout.vue
index da220064..982c62c4 100644
--- a/urbanLifelineWeb/packages/platform/src/layouts/AdminSidebarLayout/AdminSidebarLayout.vue
+++ b/urbanLifelineWeb/packages/platform/src/layouts/AdminSidebarLayout/AdminSidebarLayout.vue
@@ -251,5 +251,5 @@ watch(
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/platform/src/layouts/SidebarLayout/SidebarLayout.vue b/urbanLifelineWeb/packages/platform/src/layouts/SidebarLayout/SidebarLayout.vue
index 0ef4cbf7..30108963 100644
--- a/urbanLifelineWeb/packages/platform/src/layouts/SidebarLayout/SidebarLayout.vue
+++ b/urbanLifelineWeb/packages/platform/src/layouts/SidebarLayout/SidebarLayout.vue
@@ -269,5 +269,5 @@ watch(
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/platform/src/main.ts b/urbanLifelineWeb/packages/platform/src/main.ts
index e2b26825..f467f988 100644
--- a/urbanLifelineWeb/packages/platform/src/main.ts
+++ b/urbanLifelineWeb/packages/platform/src/main.ts
@@ -5,6 +5,9 @@ import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
+// 导入 shared 的全局样式(Module Federation 远程模块样式)
+import 'shared/styles'
+
import App from './App.vue'
import router from './router/'
import { AES_SECRET_KEY } from './config'
diff --git a/urbanLifelineWeb/packages/platform/src/router/dynamicRoute.ts b/urbanLifelineWeb/packages/platform/src/router/dynamicRoute.ts
index e5396274..75762d32 100644
--- a/urbanLifelineWeb/packages/platform/src/router/dynamicRoute.ts
+++ b/urbanLifelineWeb/packages/platform/src/router/dynamicRoute.ts
@@ -11,7 +11,7 @@
import type { RouteRecordRaw } from 'vue-router'
import router from './index'
-import { SidebarLayout, BlankLayout, AdminSidebarLayout, SubSidebarLayout } from '@/layouts'
+import { SidebarLayout, AdminSidebarLayout } from '@/layouts'
// 动态导入 shared 模块(避免顶层 import 阻塞)
async function loadSharedModules() {
@@ -25,11 +25,12 @@ async function loadSharedModules() {
// Platform 布局组件映射
const platformLayoutMap: Record Promise> = {
'SidebarLayout': () => Promise.resolve({ default: SidebarLayout }),
- 'BlankLayout': () => Promise.resolve({ default: BlankLayout }),
'NavigationLayout': () => Promise.resolve({ default: SidebarLayout }),
'BasicLayout': () => Promise.resolve({ default: SidebarLayout }),
'AdminSidebarLayout': () => Promise.resolve({ default: AdminSidebarLayout }),
- 'SubSidebarLayout': () => Promise.resolve({ default: SubSidebarLayout })
+ // 动态导入 shared 的布局组件,避免静态导入阻塞
+ 'BlankLayout': () => import('shared/layouts').then(m => ({ default: m.BlankLayout })),
+ 'SubSidebarLayout': () => import('shared/layouts').then(m => ({ default: m.SubSidebarLayout }))
}
// 视图组件加载器
diff --git a/urbanLifelineWeb/packages/platform/src/views/admin/overview/OverviewView.vue b/urbanLifelineWeb/packages/platform/src/views/admin/overview/OverviewView.vue
index 4e7e9919..e0a2c51d 100644
--- a/urbanLifelineWeb/packages/platform/src/views/admin/overview/OverviewView.vue
+++ b/urbanLifelineWeb/packages/platform/src/views/admin/overview/OverviewView.vue
@@ -7,5 +7,5 @@
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/platform/src/views/admin/userManagement/UserManagementView.vue b/urbanLifelineWeb/packages/platform/src/views/admin/userManagement/UserManagementView.vue
index 1e4d725d..d249c512 100644
--- a/urbanLifelineWeb/packages/platform/src/views/admin/userManagement/UserManagementView.vue
+++ b/urbanLifelineWeb/packages/platform/src/views/admin/userManagement/UserManagementView.vue
@@ -7,5 +7,5 @@
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/platform/src/views/public/Agents/AgentPlatformView.vue b/urbanLifelineWeb/packages/platform/src/views/public/Agents/AgentPlatformView.vue
index 8ef8a202..30025adc 100644
--- a/urbanLifelineWeb/packages/platform/src/views/public/Agents/AgentPlatformView.vue
+++ b/urbanLifelineWeb/packages/platform/src/views/public/Agents/AgentPlatformView.vue
@@ -252,5 +252,5 @@ const handleSaveAgent = async (agentData: Partial) => {
diff --git a/urbanLifelineWeb/packages/platform/src/views/public/Agents/components/AgentCard/AgentCard.vue b/urbanLifelineWeb/packages/platform/src/views/public/Agents/components/AgentCard/AgentCard.vue
index 08bcbe38..d561c5c6 100644
--- a/urbanLifelineWeb/packages/platform/src/views/public/Agents/components/AgentCard/AgentCard.vue
+++ b/urbanLifelineWeb/packages/platform/src/views/public/Agents/components/AgentCard/AgentCard.vue
@@ -39,5 +39,5 @@ defineEmits<{
diff --git a/urbanLifelineWeb/packages/platform/src/views/public/Agents/components/AgentEdit/AgentEdit.vue b/urbanLifelineWeb/packages/platform/src/views/public/Agents/components/AgentEdit/AgentEdit.vue
index dcd8c80c..9c2c1285 100644
--- a/urbanLifelineWeb/packages/platform/src/views/public/Agents/components/AgentEdit/AgentEdit.vue
+++ b/urbanLifelineWeb/packages/platform/src/views/public/Agents/components/AgentEdit/AgentEdit.vue
@@ -248,5 +248,5 @@ const handleSave = () => {
diff --git a/urbanLifelineWeb/packages/platform/src/views/public/Chat/AIChatView.vue b/urbanLifelineWeb/packages/platform/src/views/public/Chat/AIChatView.vue
index 6a703740..2c4958e8 100644
--- a/urbanLifelineWeb/packages/platform/src/views/public/Chat/AIChatView.vue
+++ b/urbanLifelineWeb/packages/platform/src/views/public/Chat/AIChatView.vue
@@ -423,5 +423,5 @@ onMounted(() => {
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/platform/src/views/public/Chat/components/ChatDefault/ChatDefault.vue b/urbanLifelineWeb/packages/platform/src/views/public/Chat/components/ChatDefault/ChatDefault.vue
index f6c0f3c8..44d9d593 100644
--- a/urbanLifelineWeb/packages/platform/src/views/public/Chat/components/ChatDefault/ChatDefault.vue
+++ b/urbanLifelineWeb/packages/platform/src/views/public/Chat/components/ChatDefault/ChatDefault.vue
@@ -105,5 +105,5 @@ const handleSuggestionClick = (suggestion: string) => {
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentDetail/DocumentDetail.vue b/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentDetail/DocumentDetail.vue
index 857ee867..a9125f35 100644
--- a/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentDetail/DocumentDetail.vue
+++ b/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentDetail/DocumentDetail.vue
@@ -4,6 +4,9 @@
-
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentSegment/DocumentSegment.scss b/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentSegment/DocumentSegment.scss
index 9e456abe..fd499675 100644
--- a/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentSegment/DocumentSegment.scss
+++ b/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentSegment/DocumentSegment.scss
@@ -1,3 +1,4 @@
+// 文档分段组件样式 - 去掉 scoped 以支持 Module Federation
.segment-dialog {
:deep(.el-dialog) {
border-radius: 14px;
@@ -10,7 +11,6 @@
font-size: 18px;
font-weight: 500;
color: #101828;
- letter-spacing: -0.02em;
}
}
@@ -47,21 +47,12 @@
overflow-y: auto;
padding-right: 4px;
- &::-webkit-scrollbar {
- width: 6px;
- }
-
- &::-webkit-scrollbar-track {
- background: transparent;
- }
-
+ &::-webkit-scrollbar { width: 6px; }
+ &::-webkit-scrollbar-track { background: transparent; }
&::-webkit-scrollbar-thumb {
background: #D1D5DB;
border-radius: 3px;
-
- &:hover {
- background: #9CA3AF;
- }
+ &:hover { background: #9CA3AF; }
}
.segment-item {
@@ -77,9 +68,7 @@
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.12);
}
- &:last-child {
- margin-bottom: 0;
- }
+ &:last-child { margin-bottom: 0; }
}
.segment-header {
@@ -93,7 +82,6 @@
font-weight: 500;
color: #101828;
font-size: 14px;
- letter-spacing: -0.01em;
white-space: nowrap;
}
@@ -101,7 +89,6 @@
flex: 1;
font-size: 12px;
color: #6A7282;
- letter-spacing: -0.01em;
white-space: nowrap;
}
@@ -115,14 +102,6 @@
.segment-content {
margin-bottom: 12px;
-
- .el-textarea {
- textarea {
- font-family: inherit;
- font-size: 14px;
- line-height: 1.6;
- }
- }
.segment-text {
padding: 12px;
@@ -134,7 +113,6 @@
font-size: 14px;
white-space: pre-wrap;
word-break: break-word;
- letter-spacing: -0.01em;
}
}
@@ -170,7 +148,6 @@
gap: 6px;
font-size: 13px;
color: #667085;
- letter-spacing: -0.01em;
.el-icon {
font-size: 14px;
@@ -190,13 +167,6 @@
font-size: 14px;
color: #6A7282;
margin: 0;
- letter-spacing: -0.01em;
}
}
-}
-
-.pagination-container {
- margin-top: 16px;
- display: flex;
- justify-content: center;
-}
+}
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentSegment/DocumentSegment.vue b/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentSegment/DocumentSegment.vue
index fa804b3d..5ff8ccf8 100644
--- a/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentSegment/DocumentSegment.vue
+++ b/urbanLifelineWeb/packages/shared/src/components/ai/knowledge/documentSegment/DocumentSegment.vue
@@ -496,6 +496,6 @@ function formatTimestamp(timestamp: number): string {
}
-
diff --git a/urbanLifelineWeb/packages/shared/src/components/dynamicFormItem/DynamicFormItem.vue b/urbanLifelineWeb/packages/shared/src/components/dynamicFormItem/DynamicFormItem.vue
index 231289a0..ea74a24c 100644
--- a/urbanLifelineWeb/packages/shared/src/components/dynamicFormItem/DynamicFormItem.vue
+++ b/urbanLifelineWeb/packages/shared/src/components/dynamicFormItem/DynamicFormItem.vue
@@ -576,6 +576,6 @@ defineExpose({
})
-
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/components/file/fileHistory/FileHistory.vue b/urbanLifelineWeb/packages/shared/src/components/file/fileHistory/FileHistory.vue
index c22c2eab..83407345 100644
--- a/urbanLifelineWeb/packages/shared/src/components/file/fileHistory/FileHistory.vue
+++ b/urbanLifelineWeb/packages/shared/src/components/file/fileHistory/FileHistory.vue
@@ -150,6 +150,6 @@ const handleCustomAction = (key: string, row: KnowledgeFileVO) => {
}
-
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/components/file/fileupload/FileUpload.vue b/urbanLifelineWeb/packages/shared/src/components/file/fileupload/FileUpload.vue
index 98cecf24..c6eb689e 100644
--- a/urbanLifelineWeb/packages/shared/src/components/file/fileupload/FileUpload.vue
+++ b/urbanLifelineWeb/packages/shared/src/components/file/fileupload/FileUpload.vue
@@ -574,6 +574,6 @@ defineExpose({
})
-
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/components/iframe/IframeView.scss b/urbanLifelineWeb/packages/shared/src/components/iframe/IframeView.scss
new file mode 100644
index 00000000..d5cfc06d
--- /dev/null
+++ b/urbanLifelineWeb/packages/shared/src/components/iframe/IframeView.scss
@@ -0,0 +1,75 @@
+// IframeView 组件样式
+.iframe-view {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+
+ .iframe-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 16px;
+ background: var(--el-bg-color);
+ border-bottom: 1px solid var(--el-border-color-light);
+ flex-shrink: 0;
+
+ .iframe-title {
+ font-size: 16px;
+ font-weight: 500;
+ color: var(--el-text-color-primary);
+ }
+ }
+
+ .iframe-content {
+ width: 100%;
+ height: 100%;
+ border: none;
+ flex: 1;
+
+ &.with-header {
+ height: calc(100% - 49px);
+ }
+ }
+
+ .iframe-error {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ color: var(--el-text-color-secondary);
+
+ .error-icon {
+ font-size: 48px;
+ margin-bottom: 16px;
+ color: var(--el-color-warning);
+ }
+ }
+
+ .iframe-loading {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background: var(--el-bg-color);
+ gap: 12px;
+
+ .is-loading {
+ animation: iframe-rotating 1.5s linear infinite;
+ color: var(--el-color-primary);
+ }
+ }
+}
+
+@keyframes iframe-rotating {
+ from { transform: rotate(0deg); }
+ to { transform: rotate(360deg); }
+}
diff --git a/urbanLifelineWeb/packages/shared/src/components/iframe/IframeView.vue b/urbanLifelineWeb/packages/shared/src/components/iframe/IframeView.vue
index 792d440f..0234e8c1 100644
--- a/urbanLifelineWeb/packages/shared/src/components/iframe/IframeView.vue
+++ b/urbanLifelineWeb/packages/shared/src/components/iframe/IframeView.vue
@@ -140,83 +140,7 @@ onUnmounted(() => {
})
-
diff --git a/urbanLifelineWeb/packages/shared/src/layouts/AdminSidebarLayout/AdminSidebarLayout.vue b/urbanLifelineWeb/packages/shared/src/layouts/AdminSidebarLayout/AdminSidebarLayout.vue
index f7247986..2c0a0acd 100644
--- a/urbanLifelineWeb/packages/shared/src/layouts/AdminSidebarLayout/AdminSidebarLayout.vue
+++ b/urbanLifelineWeb/packages/shared/src/layouts/AdminSidebarLayout/AdminSidebarLayout.vue
@@ -353,6 +353,6 @@ watch(
)
-
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/layouts/BlankLayout/BlankLayout.vue b/urbanLifelineWeb/packages/shared/src/layouts/BlankLayout/BlankLayout.vue
index e57dd5cc..18589fbc 100644
--- a/urbanLifelineWeb/packages/shared/src/layouts/BlankLayout/BlankLayout.vue
+++ b/urbanLifelineWeb/packages/shared/src/layouts/BlankLayout/BlankLayout.vue
@@ -9,10 +9,6 @@
// 适用于全屏页面,如聊天页面、独立功能页等
-
diff --git a/urbanLifelineWeb/packages/shared/src/layouts/SubSidebarLayout/SubSidebarLayout.scss b/urbanLifelineWeb/packages/shared/src/layouts/SubSidebarLayout/SubSidebarLayout.scss
index b08b2d0b..a90e12b9 100644
--- a/urbanLifelineWeb/packages/shared/src/layouts/SubSidebarLayout/SubSidebarLayout.scss
+++ b/urbanLifelineWeb/packages/shared/src/layouts/SubSidebarLayout/SubSidebarLayout.scss
@@ -1,8 +1,11 @@
-// ==================== 品牌色变量 ====================
+// ==================== Shared Layouts 样式 ====================
+// 所有样式都用根类名包裹,避免全局污染
+
$brand-color: #0055AA;
$brand-color-light: #EBF5FF;
$brand-color-hover: #004488;
+// ==================== SubSidebarLayout ====================
.sidebar-layout {
display: flex;
width: 100%;
@@ -10,451 +13,246 @@ $brand-color-hover: #004488;
overflow: hidden;
background: #f8fafc;
font-family: 'Inter', 'Noto Sans SC', sans-serif;
-}
-// ==================== 2级侧边栏(子导航样式)====================
-.sidebar {
- width: 224px;
- height: 100%;
- background: #fff;
- display: flex;
- flex-direction: column;
- color: #333;
- flex-shrink: 0;
- transition: all 0.3s ease;
- border-right: 1px solid #f1f5f9;
- position: relative;
-
- &.collapsed {
- width: 64px;
- overflow: visible;
+ .sidebar {
+ width: 224px;
+ height: 100%;
+ background: #fff;
+ display: flex;
+ flex-direction: column;
+ color: #333;
+ flex-shrink: 0;
+ transition: all 0.3s ease;
+ border-right: 1px solid #f1f5f9;
+ position: relative;
- .sidebar-header {
- padding: 16px 0;
- justify-content: center;
+ &.collapsed {
+ width: 64px;
+ overflow: visible;
- .logo {
- display: none;
+ .sidebar-header {
+ padding: 16px 0;
+ justify-content: center;
+ .logo { display: none; }
+ .collapse-btn { display: flex; }
}
- .collapse-btn {
- display: flex;
- }
- }
-
- .nav-item {
- justify-content: center;
- padding: 10px;
- margin: 2px 8px;
-
- span {
- display: none;
+ .nav-item {
+ justify-content: center;
+ padding: 10px;
+ margin: 2px 8px;
+ span { display: none; }
+ .expand-icon { display: none; }
+ &:hover .nav-tooltip { opacity: 1; visibility: visible; }
}
- .expand-icon {
- display: none;
- }
-
- // 折叠状态下显示 tooltip
- &:hover .nav-tooltip {
- opacity: 1;
- visibility: visible;
- }
- }
-
- .nav-child-item {
- display: none;
- }
-
- .user-section {
- justify-content: center;
- padding: 16px 8px;
+ .nav-child-item { display: none; }
+ .user-section { justify-content: center; padding: 16px 8px; }
}
}
-}
-// 侧边栏头部
-.sidebar-header {
- height: 64px;
- padding: 0 16px;
- border-bottom: 1px solid #f1f5f9;
- display: flex;
- align-items: center;
- justify-content: space-between;
-}
+ .sidebar-header {
+ height: 64px;
+ padding: 0 16px;
+ border-bottom: 1px solid #f1f5f9;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
-.collapse-btn {
- width: 32px;
- height: 32px;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 8px;
- cursor: pointer;
- color: #94a3b8;
- background: transparent;
- border: none;
- transition: all 0.2s;
- flex-shrink: 0;
-
- &:hover {
- background: #f1f5f9;
- color: #64748b;
- }
-
- svg {
- width: 20px;
- height: 20px;
- }
-}
-
-// 展开按钮(折叠状态显示在右侧)
-.expand-toggle {
- position: absolute;
- right: -12px;
- top: 80px;
- width: 24px;
- height: 24px;
- background: #fff;
- border: 1px solid #e2e8f0;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
- transition: all 0.2s;
- z-index: 10;
-
- &:hover {
- background: #f8fafc;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- }
-
- .el-icon {
- font-size: 14px;
- color: #64748b;
- }
-}
-
-.logo {
- display: flex;
- align-items: center;
- gap: 8px;
-
- .logo-icon {
+ .collapse-btn {
width: 32px;
height: 32px;
- background: #3b82f6;
- border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
- flex-shrink: 0;
-
- .el-icon {
- font-size: 18px;
- color: #fff;
- }
- }
-
- .logo-img {
- width: 100%;
- height: 32px;
border-radius: 8px;
- object-fit: contain;
- }
-
- .logo-text {
- font-size: 15px;
- font-weight: 600;
- color: #1e293b;
- white-space: nowrap;
- }
-}
-
-// 导航菜单
-.nav-menu {
- flex: 1;
- // overflow-y: auto;
- padding: 8px 0;
-
- &::-webkit-scrollbar {
- width: 4px;
- }
-
- &::-webkit-scrollbar-thumb {
- background: rgba(0, 0, 0, 0.1);
- border-radius: 4px;
- }
-
- &::-webkit-scrollbar-track {
- background: transparent;
- }
-}
-
-.nav-section {
- padding: 0;
-}
-
-// 导航分组容器
-.nav-group {
- margin-bottom: 4px;
-}
-
-// 子菜单容器(二级)
-.nav-children {
- padding-left: 12px;
-}
-
-// 子菜单项包装器
-.nav-child-wrapper {
- margin-bottom: 2px;
-}
-
-// 三级菜单容器
-.nav-sub-children {
- padding-left: 12px;
-}
-
-// 1级导航项(分组标题)
-.nav-item {
- position: relative;
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 8px;
- padding: 10px 16px;
- margin: 2px 8px;
- border-radius: 8px;
- cursor: pointer;
- transition: all 0.2s ease;
- color: #64748b;
- font-size: 14px;
- font-weight: 500;
-
- &:hover {
- background: #f8fafc;
- color: #475569;
- }
-
- &.active {
- background: $brand-color-light;
- color: $brand-color;
- }
-
- &.has-children {
cursor: pointer;
- }
-
- .el-icon {
- font-size: 18px;
- flex-shrink: 0;
- }
-
- span {
- flex: 1;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- .expand-icon {
- font-size: 14px;
color: #94a3b8;
- transition: transform 0.2s;
- }
-
- // 折叠时的 Tooltip
- .nav-tooltip {
- position: absolute;
- left: calc(100% + 16px);
- top: 50%;
- transform: translateY(-50%);
- background: #1e293b;
- color: #fff;
- padding: 6px 12px;
- border-radius: 6px;
- font-size: 12px;
- white-space: nowrap;
- z-index: 100;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
- opacity: 0;
- visibility: hidden;
+ background: transparent;
+ border: none;
transition: all 0.2s;
- pointer-events: none;
+ flex-shrink: 0;
- .tooltip-arrow {
- position: absolute;
- right: 100%;
- top: 50%;
- transform: translateY(-50%);
- border: 5px solid transparent;
- border-right-color: #1e293b;
- }
+ &:hover { background: #f1f5f9; color: #64748b; }
+ svg { width: 20px; height: 20px; }
}
-}
-// 2级导航项(子菜单)
-.nav-child-item {
- padding: 8px 16px 8px 40px;
- margin: 1px 8px;
- border-radius: 6px;
- font-size: 13px;
- font-weight: 400;
-
- &:hover {
- background: #f8fafc;
- color: #475569;
- }
-
- &.active {
- background: $brand-color;
- color: #fff;
- font-weight: 500;
-
- .el-icon {
- color: #fff;
- }
- }
-
- .el-icon {
- font-size: 16px;
- }
-}
-
-// 3级导航项
-.nav-sub-child-item {
- padding: 6px 16px 6px 56px;
- margin: 1px 8px;
- border-radius: 6px;
- font-size: 13px;
- font-weight: 400;
- color: #64748b;
-
- &:hover {
- background: #f8fafc;
- color: #475569;
- }
-
- &.active {
- background: $brand-color;
- color: #fff;
- }
-}
-
-// 用户信息
-.user-section {
- padding: 16px;
- border-top: 1px solid #f1f5f9;
- cursor: pointer;
- transition: background 0.2s;
-
- &:hover {
- background: #f8fafc;
- }
-
- .user-info-wrapper {
+ .expand-toggle {
+ position: absolute;
+ right: -12px;
+ top: 80px;
+ width: 24px;
+ height: 24px;
+ background: #fff;
+ border: 1px solid #e2e8f0;
+ border-radius: 50%;
display: flex;
align-items: center;
- gap: 12px;
+ justify-content: center;
+ cursor: pointer;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+ transition: all 0.2s;
+ z-index: 10;
+
+ &:hover { background: #f8fafc; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); }
}
-
- .user-avatar {
- flex-shrink: 0;
+
+ .logo {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+
+ .logo-img {
+ width: 100%;
+ height: 32px;
+ border-radius: 8px;
+ object-fit: contain;
+ }
+
+ .logo-text {
+ font-size: 15px;
+ font-weight: 600;
+ color: #1e293b;
+ white-space: nowrap;
+ }
}
-
- .user-name {
+
+ .nav-menu {
+ flex: 1;
+ padding: 8px 0;
+
+ &::-webkit-scrollbar { width: 4px; }
+ &::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.1); border-radius: 4px; }
+ &::-webkit-scrollbar-track { background: transparent; }
+ }
+
+ .nav-section { padding: 0; }
+ .nav-group { margin-bottom: 4px; }
+ .nav-children { padding-left: 12px; }
+ .nav-child-wrapper { margin-bottom: 2px; }
+ .nav-sub-children { padding-left: 12px; }
+
+ .nav-item {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ padding: 10px 16px;
+ margin: 2px 8px;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ color: #64748b;
font-size: 14px;
font-weight: 500;
- color: #374151;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-}
-
-// ==================== 主内容区 ====================
-.main-content {
- flex: 1;
- height: 100%;
- overflow: hidden;
- background: #f8fafc;
- position: relative;
-}
-
-// iframe 容器
-.iframe-container {
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: column;
- position: relative;
-}
-
-.iframe-header {
- height: 56px;
- padding: 0 24px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- border-bottom: 1px solid #e2e8f0;
- background: #fff;
- flex-shrink: 0;
-}
-
-.iframe-title {
- font-size: 16px;
- font-weight: 600;
- color: #1e293b;
-}
-
-.content-iframe {
- flex: 1;
- width: 100%;
- height: 100%;
- border: none;
- background: #fff;
-}
-
-.iframe-loading {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 12px;
- color: $brand-color;
- font-size: 14px;
- z-index: 10;
-
- .el-icon {
- font-size: 32px;
- }
-}
-
-// ==================== 响应式 ====================
-@media (max-width: 768px) {
- .sidebar {
- width: 64px;
- &:not(.collapsed) {
- width: 224px;
- position: fixed;
- left: 0;
- top: 0;
- z-index: 1000;
- box-shadow: 4px 0 16px rgba(0, 0, 0, 0.1);
+ &:hover { background: #f8fafc; color: #475569; }
+ &.active { background: $brand-color-light; color: $brand-color; }
+ &.has-children { cursor: pointer; }
+
+ span {
+ flex: 1;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
- }
-
- .iframe-header {
- padding: 0 16px;
- .iframe-title {
+ .expand-icon {
font-size: 14px;
+ color: #94a3b8;
+ transition: transform 0.2s;
+ }
+
+ .nav-tooltip {
+ position: absolute;
+ left: calc(100% + 16px);
+ top: 50%;
+ transform: translateY(-50%);
+ background: #1e293b;
+ color: #fff;
+ padding: 6px 12px;
+ border-radius: 6px;
+ font-size: 12px;
+ white-space: nowrap;
+ z-index: 100;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ opacity: 0;
+ visibility: hidden;
+ transition: all 0.2s;
+ pointer-events: none;
+
+ .tooltip-arrow {
+ position: absolute;
+ right: 100%;
+ top: 50%;
+ transform: translateY(-50%);
+ border: 5px solid transparent;
+ border-right-color: #1e293b;
+ }
+ }
+ }
+
+ .nav-child-item {
+ padding: 8px 16px 8px 40px;
+ margin: 1px 8px;
+ border-radius: 6px;
+ font-size: 13px;
+ font-weight: 400;
+
+ &:hover { background: #f8fafc; color: #475569; }
+ &.active {
+ background: $brand-color;
+ color: #fff;
+ font-weight: 500;
+ }
+ }
+
+ .nav-sub-child-item {
+ padding: 6px 16px 6px 56px;
+ margin: 1px 8px;
+ border-radius: 6px;
+ font-size: 13px;
+ font-weight: 400;
+ color: #64748b;
+
+ &:hover { background: #f8fafc; color: #475569; }
+ &.active { background: $brand-color; color: #fff; }
+ }
+
+ .main-content {
+ flex: 1;
+ height: 100%;
+ overflow: hidden;
+ background: #f8fafc;
+ position: relative;
+ }
+
+ &.no-sidebar .main-content {
+ width: 100%;
+ }
+
+ // 响应式
+ @media (max-width: 768px) {
+ .sidebar {
+ width: 64px;
+
+ &:not(.collapsed) {
+ width: 224px;
+ position: fixed;
+ left: 0;
+ top: 0;
+ z-index: 1000;
+ box-shadow: 4px 0 16px rgba(0, 0, 0, 0.1);
+ }
}
}
}
+
+// ==================== BlankLayout ====================
+.blank-layout {
+ width: 100%;
+ height: 100vh;
+ overflow: hidden;
+}
diff --git a/urbanLifelineWeb/packages/shared/src/layouts/SubSidebarLayout/SubSidebarLayout.vue b/urbanLifelineWeb/packages/shared/src/layouts/SubSidebarLayout/SubSidebarLayout.vue
index 00b4195d..b829066f 100644
--- a/urbanLifelineWeb/packages/shared/src/layouts/SubSidebarLayout/SubSidebarLayout.vue
+++ b/urbanLifelineWeb/packages/shared/src/layouts/SubSidebarLayout/SubSidebarLayout.vue
@@ -497,6 +497,6 @@ watch(
)
-
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/src/styles/components.scss b/urbanLifelineWeb/packages/shared/src/styles/components.scss
new file mode 100644
index 00000000..a1cda4b4
--- /dev/null
+++ b/urbanLifelineWeb/packages/shared/src/styles/components.scss
@@ -0,0 +1,8 @@
+// ==================== Shared Components 样式 ====================
+// 导入各组件的 scss 文件
+
+@use '../components/iframe/IframeView.scss';
+@use '../components/file/fileupload/FileUpload.scss';
+@use '../components/file/fileHistory/FileHistory.scss';
+@use '../components/dynamicFormItem/DynamicFormItem.scss';
+@use '../components/ai/knowledge/documentSegment/DocumentSegment.scss';
diff --git a/urbanLifelineWeb/packages/shared/src/styles/index.scss b/urbanLifelineWeb/packages/shared/src/styles/index.scss
new file mode 100644
index 00000000..8c78ea3f
--- /dev/null
+++ b/urbanLifelineWeb/packages/shared/src/styles/index.scss
@@ -0,0 +1,6 @@
+// ==================== Shared 全局样式 ====================
+// 这个文件需要在宿主应用的 main.ts 中导入
+// import 'shared/styles'
+
+@use './layouts.scss';
+@use './components.scss';
diff --git a/urbanLifelineWeb/packages/shared/src/styles/index.ts b/urbanLifelineWeb/packages/shared/src/styles/index.ts
new file mode 100644
index 00000000..293f6ccd
--- /dev/null
+++ b/urbanLifelineWeb/packages/shared/src/styles/index.ts
@@ -0,0 +1,9 @@
+// ==================== Shared 全局样式入口 ====================
+// 这个文件作为样式的 JS 入口,确保 CSS 被正确加载
+// 在宿主应用中使用: import 'shared/styles'
+
+// 导入所有样式(Vite 会自动处理 CSS 注入)
+import './index.scss'
+
+// 导出空对象,让 Module Federation 能正确处理
+export {}
diff --git a/urbanLifelineWeb/packages/shared/src/styles/layouts.scss b/urbanLifelineWeb/packages/shared/src/styles/layouts.scss
new file mode 100644
index 00000000..b0ee9bb1
--- /dev/null
+++ b/urbanLifelineWeb/packages/shared/src/styles/layouts.scss
@@ -0,0 +1 @@
+@use '../layouts/SubSidebarLayout/SubSidebarLayout.scss'
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/shared/vite.config.ts b/urbanLifelineWeb/packages/shared/vite.config.ts
index de6d287f..9450426e 100644
--- a/urbanLifelineWeb/packages/shared/vite.config.ts
+++ b/urbanLifelineWeb/packages/shared/vite.config.ts
@@ -70,7 +70,11 @@ export default defineConfig({
'./config': './src/config/index.ts',
// ========== Layouts 布局模块 ==========
- './layouts': './src/layouts/index.ts'
+ './layouts': './src/layouts/index.ts',
+
+ // ========== Styles 样式模块 ==========
+ // 直接暴露 SCSS 文件,确保 CSS 在远程加载时被正确注入
+ './styles': './src/styles/index.scss'
},
// 共享依赖(重要:避免重复加载)
shared: {
@@ -101,9 +105,18 @@ export default defineConfig({
minify: false,
cssCodeSplit: false,
sourcemap: true,
+ // 确保 CSS 被提取到单独的文件中
+ cssMinify: true,
rollupOptions: {
output: {
- format: 'es'
+ format: 'es',
+ // 确保 CSS 文件名可预测
+ assetFileNames: (assetInfo) => {
+ if (assetInfo.name === 'style.css') {
+ return 'assets/style.css'
+ }
+ return 'assets/[name]-[hash][extname]'
+ }
}
}
},
diff --git a/urbanLifelineWeb/packages/workcase/src/layouts/SidebarLayout/SidebarLayout.vue b/urbanLifelineWeb/packages/workcase/src/layouts/SidebarLayout/SidebarLayout.vue
index b22467f6..3ee5ec25 100644
--- a/urbanLifelineWeb/packages/workcase/src/layouts/SidebarLayout/SidebarLayout.vue
+++ b/urbanLifelineWeb/packages/workcase/src/layouts/SidebarLayout/SidebarLayout.vue
@@ -214,5 +214,5 @@ watch(
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/workcase/src/main.ts b/urbanLifelineWeb/packages/workcase/src/main.ts
index ef72afb8..1641f550 100644
--- a/urbanLifelineWeb/packages/workcase/src/main.ts
+++ b/urbanLifelineWeb/packages/workcase/src/main.ts
@@ -5,6 +5,9 @@ import 'element-plus/dist/index.css'
import './assets/css/common.scss'
+// 导入 shared 的全局样式(Module Federation 远程模块样式)
+import 'shared/styles'
+
import App from './App.vue'
import router from './router/'
import { AES_SECRET_KEY } from './config/index'
diff --git a/urbanLifelineWeb/packages/workcase/src/router/dynamicRoute.ts b/urbanLifelineWeb/packages/workcase/src/router/dynamicRoute.ts
index 345e2de6..d7b7a162 100644
--- a/urbanLifelineWeb/packages/workcase/src/router/dynamicRoute.ts
+++ b/urbanLifelineWeb/packages/workcase/src/router/dynamicRoute.ts
@@ -11,7 +11,7 @@
import type { RouteRecordRaw } from 'vue-router'
import router from './index'
-import { SidebarLayout, BlankLayout, SubSidebarLayout } from '@/layouts'
+import { SidebarLayout } from '@/layouts'
// 动态导入 shared 模块(避免顶层 import 阻塞)
async function loadSharedModules() {
@@ -25,10 +25,11 @@ async function loadSharedModules() {
// Workcase 布局组件映射
const workcaseLayoutMap: Record Promise> = {
'SidebarLayout': () => Promise.resolve({ default: SidebarLayout }),
- 'BlankLayout': () => Promise.resolve({ default: BlankLayout }),
'NavigationLayout': () => Promise.resolve({ default: SidebarLayout }),
'BasicLayout': () => Promise.resolve({ default: SidebarLayout }),
- 'SubSidebarLayout': () => Promise.resolve({ default: SubSidebarLayout })
+ // 动态导入 shared 的布局组件,避免静态导入阻塞
+ 'BlankLayout': () => import('shared/layouts').then(m => ({ default: m.BlankLayout })),
+ 'SubSidebarLayout': () => import('shared/layouts').then(m => ({ default: m.SubSidebarLayout }))
}
// 视图组件加载器
diff --git a/urbanLifelineWeb/packages/workcase/src/views/admin/agent/AgentView.vue b/urbanLifelineWeb/packages/workcase/src/views/admin/agent/AgentView.vue
index 1c82e607..aa6c10b8 100644
--- a/urbanLifelineWeb/packages/workcase/src/views/admin/agent/AgentView.vue
+++ b/urbanLifelineWeb/packages/workcase/src/views/admin/agent/AgentView.vue
@@ -163,7 +163,7 @@ const testAgent = () => {
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/workcase/src/views/admin/log/knowledgeLog/KnowledgeLogView.vue b/urbanLifelineWeb/packages/workcase/src/views/admin/log/knowledgeLog/KnowledgeLogView.vue
index 78fccd1f..80cd521f 100644
--- a/urbanLifelineWeb/packages/workcase/src/views/admin/log/knowledgeLog/KnowledgeLogView.vue
+++ b/urbanLifelineWeb/packages/workcase/src/views/admin/log/knowledgeLog/KnowledgeLogView.vue
@@ -267,7 +267,7 @@ onMounted(() => {
diff --git a/urbanLifelineWeb/packages/workcase/src/views/public/AIChat/components/ChatHistory.vue b/urbanLifelineWeb/packages/workcase/src/views/public/AIChat/components/ChatHistory.vue
index 459883a6..15fe99e9 100644
--- a/urbanLifelineWeb/packages/workcase/src/views/public/AIChat/components/ChatHistory.vue
+++ b/urbanLifelineWeb/packages/workcase/src/views/public/AIChat/components/ChatHistory.vue
@@ -48,5 +48,5 @@ const handleLoadChat = (chatId: number) => {
diff --git a/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/ChatMessage/ChatMessage.vue b/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/ChatMessage/ChatMessage.vue
index 7b2989c9..ab67cecb 100644
--- a/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/ChatMessage/ChatMessage.vue
+++ b/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/ChatMessage/ChatMessage.vue
@@ -351,7 +351,7 @@ watch(activeTab, async (newVal) => {
})
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/MeetingCard/MeetingCard.vue b/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/MeetingCard/MeetingCard.vue
index 139afc60..479e26ab 100644
--- a/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/MeetingCard/MeetingCard.vue
+++ b/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/MeetingCard/MeetingCard.vue
@@ -270,5 +270,5 @@ async function handleJoinMeeting() {
}
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/chatRoom/ChatRoom.vue b/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/chatRoom/ChatRoom.vue
index 137e654c..b387f455 100644
--- a/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/chatRoom/ChatRoom.vue
+++ b/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/chatRoom/ChatRoom.vue
@@ -459,5 +459,5 @@ defineExpose({
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/chatRoom/CommentMessageCard/CommentMessageCard.vue b/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/chatRoom/CommentMessageCard/CommentMessageCard.vue
index f068c022..d15adc32 100644
--- a/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/chatRoom/CommentMessageCard/CommentMessageCard.vue
+++ b/urbanLifelineWeb/packages/workcase/src/views/public/ChatRoom/chatRoom/CommentMessageCard/CommentMessageCard.vue
@@ -130,5 +130,5 @@ const handleSubmit = async () => {
diff --git a/urbanLifelineWeb/packages/workcase/src/views/public/JitsiMeeting/JitsiMeetingView.vue b/urbanLifelineWeb/packages/workcase/src/views/public/JitsiMeeting/JitsiMeetingView.vue
index 435290d6..bf6e05ee 100644
--- a/urbanLifelineWeb/packages/workcase/src/views/public/JitsiMeeting/JitsiMeetingView.vue
+++ b/urbanLifelineWeb/packages/workcase/src/views/public/JitsiMeeting/JitsiMeetingView.vue
@@ -316,5 +316,5 @@ onUnmounted(() => {
diff --git a/urbanLifelineWeb/packages/workcase/src/views/public/workcase/WorkcaseDetail/WorkcaseDetail.vue b/urbanLifelineWeb/packages/workcase/src/views/public/workcase/WorkcaseDetail/WorkcaseDetail.vue
index bc946d49..1e5ae0b7 100644
--- a/urbanLifelineWeb/packages/workcase/src/views/public/workcase/WorkcaseDetail/WorkcaseDetail.vue
+++ b/urbanLifelineWeb/packages/workcase/src/views/public/workcase/WorkcaseDetail/WorkcaseDetail.vue
@@ -747,5 +747,5 @@ const submitProcessRecord = async () => {
\ No newline at end of file
diff --git a/urbanLifelineWeb/packages/workcase_wechat/pages/meeting/Meeting.uvue b/urbanLifelineWeb/packages/workcase_wechat/pages/meeting/Meeting.uvue
index 6c355880..df307aa9 100644
--- a/urbanLifelineWeb/packages/workcase_wechat/pages/meeting/Meeting.uvue
+++ b/urbanLifelineWeb/packages/workcase_wechat/pages/meeting/Meeting.uvue
@@ -339,5 +339,5 @@ function openInBrowser() {