From 8673eb5ecac47bcc9e0ca2908eb4eb64bbd23ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=AE=8F=E5=87=AF?= Date: Sat, 23 May 2026 23:05:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend-web/docs/multi-agent-step1-api.md | 492 ++++ frontend-web/docs/multi-agent-step3-api.md | 264 ++ .../src/open-canvas/api/writing-export.ts | 69 + .../components/artifact/WritingToolbar.tsx | 9 +- .../roundtable-planning/api/multi-agent.ts | 411 +++- .../pages/RoundtablePlanningPage.tsx | 412 +++- .../app/gateway/routers/multi_agent.py | 521 +++- .../middlewares/skill_stop_middleware.py | 36 +- .../deerflow/tools/builtins/__init__.py | 2 + .../builtins/agent_orchestration_tool.py | 46 + .../packages/harness/deerflow/tools/tools.py | 3 +- situation-overview-web/public/Config.js | 10 - .../public/moment/locale/ar.js | 134 - .../public/moment/locale/sq.js | 67 - .../public/moment/locale/tr.js | 93 - .../public/moment/moment-with-locales.min.js | 1 - .../public/moment/moment.min.js | 1 - .../vis/timeline/moment-with-locales.min.js | 1 - .../vis/timeline/vis-timeline-graph2d.min.css | 2 - .../vis/timeline/vis-timeline-graph2d.min.js | 34 - situation-overview-web/public/vis/vis.css | 1355 ----------- situation-overview-web/public/vis/vis.js | 47 - situation-overview-web/public/vite.svg | 1 - situation-overview-web/src/App.vue | 24 - situation-overview-web/src/api/user.js | 21 - .../src/common/actionStatus.js | 7 - situation-overview-web/src/common/chatData.js | 12 - .../src/common/sourceType.js | 4 - .../src/common/taskLevel.js | 5 - .../src/common/taskStatus.js | 16 - .../src/components/AIChatExtract/index.vue | 36 - .../src/components/ActionOverview.vue | 702 ------ .../src/components/ActionPlanning.vue | 448 ---- .../ActionPlanning/PerformanceEvaluation.vue | 242 -- .../src/components/HelloWorld.vue | 43 - .../src/components/InfoChatView/index.vue | 549 ----- .../src/components/Overview/index.vue | 206 -- .../src/components/SentimentAnalysis.vue | 132 - .../SentimentAnalysis/AssessmentContent.vue | 359 --- .../BattlefieldEnvironment.vue | 358 --- .../DeterminationContent.vue | 544 ----- .../SentimentAnalysis/EnemySituation.vue | 424 ---- .../SentimentAnalysis/HandleContent.vue | 488 ---- .../SentimentAnalysis/JudgmentConclusion.vue | 223 -- .../SentimentAnalysis/StrategyOverview.vue | 270 --- .../SentimentAnalysis/SuggestionContent.vue | 67 - .../src/components/SituationAssessment.vue | 548 ----- .../src/components/TaskAnalysis.vue | 35 - .../components/TaskAnalysis/AnalysisData.vue | 719 ------ .../components/TaskAnalysis/TaskDataList.vue | 142 -- .../TaskAnalysis/TaskDataSearch.vue | 367 --- .../src/components/TaskDetails.vue | 335 --- .../TaskDetails/BattlefieldEnvironment.vue | 356 --- .../components/TaskDetails/EnemySituation.vue | 773 ------ .../components/TaskDetails/OurSituation.vue | 548 ----- .../src/components/TaskDetails/Power.vue | 94 - .../TaskDetails/component/Resources.vue | 514 ---- .../src/components/Template.vue | 20 - .../src/components/TreeDataMap.vue | 337 --- .../components/details-dialog/DocDetails.vue | 78 - .../src/components/dialog/AddTaskDialog.vue | 310 --- .../components/dialog/CommonInfoDialog.vue | 137 -- .../src/components/graph/G6NetworkGraph.vue | 1330 ---------- .../graph/modal/components/Audience.vue | 176 -- .../graph/modal/components/Strategy.vue | 195 -- .../graph/modal/components/Yqxg.vue | 365 --- .../src/components/graph/modal/index.vue | 65 - .../AnalysisTool.vue | 114 - .../intelligent-helper-drawer/ChatContent.vue | 67 - .../intelligent-helper-drawer/ChatList.vue | 373 --- .../IntelligentHelperDrawer.vue | 30 - .../InteractiveAnalysis.vue | 37 - .../src/components/markdown/CodeData.vue | 194 -- .../src/components/scrollingloading/index.vue | 71 - .../src/components/searchTaskList/index.vue | 391 --- .../src/components/shared/Empty.vue | 22 - .../src/components/views/PieChart.vue | 279 --- .../src/components/views/TabsContent.vue | 32 - situation-overview-web/src/main.js | 17 - situation-overview-web/src/router/index.js | 91 - .../src/service/request-axios-service.js | 47 - .../src/service/request-crud.service.js | 141 -- situation-overview-web/src/store/index.js | 43 - situation-overview-web/src/style.css | 0 .../src/style/tdesign-style.less | 134 - situation-overview-web/src/style/theme.less | 676 ------ situation-overview-web/src/utils/request.js | 34 - situation-overview-web/src/views/Chart.vue | 128 - .../src/views/Dashboard.vue | 130 - situation-overview-web/src/views/Graph.vue | 91 - .../src/views/GroupContent.vue | 32 - situation-overview-web/src/views/Home.vue | 97 - situation-overview-web/src/views/Map.vue | 71 - .../views/action/components/actionDetail.vue | 206 -- .../views/action/components/bociDetail.vue | 260 -- .../src/views/action/index.vue | 280 --- .../src/views/control/components/g6Tp.vue | 228 -- .../src/views/control/components/timeline.vue | 144 -- .../src/views/control/components/zxtp.vue | 761 ------ .../src/views/control/index.vue | 2145 ----------------- .../src/views/homeOverview/index.vue | 1337 ---------- .../views/reply/components/G6NetworkGraph.vue | 1061 -------- .../src/views/reply/components/all-asp.vue | 65 - .../views/reply/components/asp-echarts.vue | 221 -- .../src/views/reply/components/edit-group.vue | 104 - .../reply/components/information-list.vue | 668 ----- .../reply/components/information-putin.vue | 610 ----- .../reply/components/input-recomendations.vue | 210 -- .../src/views/reply/components/office.vue | 161 -- .../reply/components/part/Media-list.vue | 259 -- .../reply/components/part/action-unit.vue | 167 -- .../src/views/reply/components/part/big-v.vue | 287 --- .../views/reply/components/part/hot-trend.vue | 514 ---- .../reply/components/part/media-port.vue | 395 --- .../reply/components/part/narr-theme.vue | 298 --- .../components/part/relevantActors-item.vue | 274 --- .../reply/components/part/stand-area.vue | 202 -- .../reply/components/part/table-line.vue | 69 - .../reply/components/part/trans-plat.vue | 302 --- .../reply/components/part/word-cloud.vue | 240 -- .../views/reply/components/pie-echarts.vue | 127 - .../src/views/reply/components/pivotket.vue | 348 --- .../src/views/reply/components/point-list.vue | 227 -- .../components/pointDialog-morelevel.vue | 469 ---- .../prehensiveEvaluation-fangan.vue | 128 - .../reply/components/prehensiveEvaluation.vue | 458 ---- .../views/reply/components/radar-echart.vue | 142 -- .../views/reply/components/reachAudience.vue | 344 --- .../reply/components/replyComparison-one.vue | 636 ----- .../reply/components/replyComparison-two.vue | 864 ------- .../reply/components/replyComparison.vue | 54 - .../src/views/reply/components/rzyx.vue | 289 --- .../src/views/reply/components/svg-link.vue | 43 - .../src/views/reply/components/table-two.vue | 47 - .../views/reply/components/task-detail.vue | 286 --- .../src/views/reply/components/task-list.vue | 281 --- .../src/views/reply/components/title-logo.vue | 37 - .../views/reply/components/translateEnTo.js | 37 - .../reply/components/truncatedTooltipItem.vue | 155 -- .../src/views/reply/components/type.js | 467 ---- .../views/reply/components/vulnerability.vue | 408 ---- .../src/views/reply/components/xd-trend.vue | 219 -- .../src/views/reply/components/xdcloud.vue | 148 -- .../src/views/reply/index.vue | 489 ---- .../src/views/sentiment/index.vue | 628 ----- .../src/views/situation-overview/index.vue | 815 ------- .../views/task/components/taskStatistics.vue | 140 -- .../src/views/task/index.vue | 282 --- 148 files changed, 2050 insertions(+), 37963 deletions(-) create mode 100644 frontend-web/docs/multi-agent-step1-api.md create mode 100644 frontend-web/docs/multi-agent-step3-api.md create mode 100644 frontend-web/src/open-canvas/api/writing-export.ts create mode 100644 offline-backend-20260512/backend/packages/harness/deerflow/tools/builtins/agent_orchestration_tool.py delete mode 100644 situation-overview-web/public/Config.js delete mode 100644 situation-overview-web/public/moment/locale/ar.js delete mode 100644 situation-overview-web/public/moment/locale/sq.js delete mode 100644 situation-overview-web/public/moment/locale/tr.js delete mode 100644 situation-overview-web/public/moment/moment-with-locales.min.js delete mode 100644 situation-overview-web/public/moment/moment.min.js delete mode 100644 situation-overview-web/public/vis/timeline/moment-with-locales.min.js delete mode 100644 situation-overview-web/public/vis/timeline/vis-timeline-graph2d.min.css delete mode 100644 situation-overview-web/public/vis/timeline/vis-timeline-graph2d.min.js delete mode 100644 situation-overview-web/public/vis/vis.css delete mode 100644 situation-overview-web/public/vis/vis.js delete mode 100644 situation-overview-web/public/vite.svg delete mode 100644 situation-overview-web/src/App.vue delete mode 100644 situation-overview-web/src/api/user.js delete mode 100644 situation-overview-web/src/common/actionStatus.js delete mode 100644 situation-overview-web/src/common/chatData.js delete mode 100644 situation-overview-web/src/common/sourceType.js delete mode 100644 situation-overview-web/src/common/taskLevel.js delete mode 100644 situation-overview-web/src/common/taskStatus.js delete mode 100644 situation-overview-web/src/components/AIChatExtract/index.vue delete mode 100644 situation-overview-web/src/components/ActionOverview.vue delete mode 100644 situation-overview-web/src/components/ActionPlanning.vue delete mode 100644 situation-overview-web/src/components/ActionPlanning/PerformanceEvaluation.vue delete mode 100644 situation-overview-web/src/components/HelloWorld.vue delete mode 100644 situation-overview-web/src/components/InfoChatView/index.vue delete mode 100644 situation-overview-web/src/components/Overview/index.vue delete mode 100644 situation-overview-web/src/components/SentimentAnalysis.vue delete mode 100644 situation-overview-web/src/components/SentimentAnalysis/AssessmentContent.vue delete mode 100644 situation-overview-web/src/components/SentimentAnalysis/BattlefieldEnvironment.vue delete mode 100644 situation-overview-web/src/components/SentimentAnalysis/DeterminationContent.vue delete mode 100644 situation-overview-web/src/components/SentimentAnalysis/EnemySituation.vue delete mode 100644 situation-overview-web/src/components/SentimentAnalysis/HandleContent.vue delete mode 100644 situation-overview-web/src/components/SentimentAnalysis/JudgmentConclusion.vue delete mode 100644 situation-overview-web/src/components/SentimentAnalysis/StrategyOverview.vue delete mode 100644 situation-overview-web/src/components/SentimentAnalysis/SuggestionContent.vue delete mode 100644 situation-overview-web/src/components/SituationAssessment.vue delete mode 100644 situation-overview-web/src/components/TaskAnalysis.vue delete mode 100644 situation-overview-web/src/components/TaskAnalysis/AnalysisData.vue delete mode 100644 situation-overview-web/src/components/TaskAnalysis/TaskDataList.vue delete mode 100644 situation-overview-web/src/components/TaskAnalysis/TaskDataSearch.vue delete mode 100644 situation-overview-web/src/components/TaskDetails.vue delete mode 100644 situation-overview-web/src/components/TaskDetails/BattlefieldEnvironment.vue delete mode 100644 situation-overview-web/src/components/TaskDetails/EnemySituation.vue delete mode 100644 situation-overview-web/src/components/TaskDetails/OurSituation.vue delete mode 100644 situation-overview-web/src/components/TaskDetails/Power.vue delete mode 100644 situation-overview-web/src/components/TaskDetails/component/Resources.vue delete mode 100644 situation-overview-web/src/components/Template.vue delete mode 100644 situation-overview-web/src/components/TreeDataMap.vue delete mode 100644 situation-overview-web/src/components/details-dialog/DocDetails.vue delete mode 100644 situation-overview-web/src/components/dialog/AddTaskDialog.vue delete mode 100644 situation-overview-web/src/components/dialog/CommonInfoDialog.vue delete mode 100644 situation-overview-web/src/components/graph/G6NetworkGraph.vue delete mode 100644 situation-overview-web/src/components/graph/modal/components/Audience.vue delete mode 100644 situation-overview-web/src/components/graph/modal/components/Strategy.vue delete mode 100644 situation-overview-web/src/components/graph/modal/components/Yqxg.vue delete mode 100644 situation-overview-web/src/components/graph/modal/index.vue delete mode 100644 situation-overview-web/src/components/intelligent-helper-drawer/AnalysisTool.vue delete mode 100644 situation-overview-web/src/components/intelligent-helper-drawer/ChatContent.vue delete mode 100644 situation-overview-web/src/components/intelligent-helper-drawer/ChatList.vue delete mode 100644 situation-overview-web/src/components/intelligent-helper-drawer/IntelligentHelperDrawer.vue delete mode 100644 situation-overview-web/src/components/intelligent-helper-drawer/InteractiveAnalysis.vue delete mode 100644 situation-overview-web/src/components/markdown/CodeData.vue delete mode 100644 situation-overview-web/src/components/scrollingloading/index.vue delete mode 100644 situation-overview-web/src/components/searchTaskList/index.vue delete mode 100644 situation-overview-web/src/components/shared/Empty.vue delete mode 100644 situation-overview-web/src/components/views/PieChart.vue delete mode 100644 situation-overview-web/src/components/views/TabsContent.vue delete mode 100644 situation-overview-web/src/main.js delete mode 100644 situation-overview-web/src/router/index.js delete mode 100644 situation-overview-web/src/service/request-axios-service.js delete mode 100644 situation-overview-web/src/service/request-crud.service.js delete mode 100644 situation-overview-web/src/store/index.js delete mode 100644 situation-overview-web/src/style.css delete mode 100644 situation-overview-web/src/style/tdesign-style.less delete mode 100644 situation-overview-web/src/style/theme.less delete mode 100644 situation-overview-web/src/utils/request.js delete mode 100644 situation-overview-web/src/views/Chart.vue delete mode 100644 situation-overview-web/src/views/Dashboard.vue delete mode 100644 situation-overview-web/src/views/Graph.vue delete mode 100644 situation-overview-web/src/views/GroupContent.vue delete mode 100644 situation-overview-web/src/views/Home.vue delete mode 100644 situation-overview-web/src/views/Map.vue delete mode 100644 situation-overview-web/src/views/action/components/actionDetail.vue delete mode 100644 situation-overview-web/src/views/action/components/bociDetail.vue delete mode 100644 situation-overview-web/src/views/action/index.vue delete mode 100644 situation-overview-web/src/views/control/components/g6Tp.vue delete mode 100644 situation-overview-web/src/views/control/components/timeline.vue delete mode 100644 situation-overview-web/src/views/control/components/zxtp.vue delete mode 100644 situation-overview-web/src/views/control/index.vue delete mode 100644 situation-overview-web/src/views/homeOverview/index.vue delete mode 100644 situation-overview-web/src/views/reply/components/G6NetworkGraph.vue delete mode 100644 situation-overview-web/src/views/reply/components/all-asp.vue delete mode 100644 situation-overview-web/src/views/reply/components/asp-echarts.vue delete mode 100644 situation-overview-web/src/views/reply/components/edit-group.vue delete mode 100644 situation-overview-web/src/views/reply/components/information-list.vue delete mode 100644 situation-overview-web/src/views/reply/components/information-putin.vue delete mode 100644 situation-overview-web/src/views/reply/components/input-recomendations.vue delete mode 100644 situation-overview-web/src/views/reply/components/office.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/Media-list.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/action-unit.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/big-v.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/hot-trend.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/media-port.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/narr-theme.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/relevantActors-item.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/stand-area.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/table-line.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/trans-plat.vue delete mode 100644 situation-overview-web/src/views/reply/components/part/word-cloud.vue delete mode 100644 situation-overview-web/src/views/reply/components/pie-echarts.vue delete mode 100644 situation-overview-web/src/views/reply/components/pivotket.vue delete mode 100644 situation-overview-web/src/views/reply/components/point-list.vue delete mode 100644 situation-overview-web/src/views/reply/components/pointDialog-morelevel.vue delete mode 100644 situation-overview-web/src/views/reply/components/prehensiveEvaluation-fangan.vue delete mode 100644 situation-overview-web/src/views/reply/components/prehensiveEvaluation.vue delete mode 100644 situation-overview-web/src/views/reply/components/radar-echart.vue delete mode 100644 situation-overview-web/src/views/reply/components/reachAudience.vue delete mode 100644 situation-overview-web/src/views/reply/components/replyComparison-one.vue delete mode 100644 situation-overview-web/src/views/reply/components/replyComparison-two.vue delete mode 100644 situation-overview-web/src/views/reply/components/replyComparison.vue delete mode 100644 situation-overview-web/src/views/reply/components/rzyx.vue delete mode 100644 situation-overview-web/src/views/reply/components/svg-link.vue delete mode 100644 situation-overview-web/src/views/reply/components/table-two.vue delete mode 100644 situation-overview-web/src/views/reply/components/task-detail.vue delete mode 100644 situation-overview-web/src/views/reply/components/task-list.vue delete mode 100644 situation-overview-web/src/views/reply/components/title-logo.vue delete mode 100644 situation-overview-web/src/views/reply/components/translateEnTo.js delete mode 100644 situation-overview-web/src/views/reply/components/truncatedTooltipItem.vue delete mode 100644 situation-overview-web/src/views/reply/components/type.js delete mode 100644 situation-overview-web/src/views/reply/components/vulnerability.vue delete mode 100644 situation-overview-web/src/views/reply/components/xd-trend.vue delete mode 100644 situation-overview-web/src/views/reply/components/xdcloud.vue delete mode 100644 situation-overview-web/src/views/reply/index.vue delete mode 100644 situation-overview-web/src/views/sentiment/index.vue delete mode 100644 situation-overview-web/src/views/situation-overview/index.vue delete mode 100644 situation-overview-web/src/views/task/components/taskStatistics.vue delete mode 100644 situation-overview-web/src/views/task/index.vue diff --git a/frontend-web/docs/multi-agent-step1-api.md b/frontend-web/docs/multi-agent-step1-api.md new file mode 100644 index 00000000..62f36b0c --- /dev/null +++ b/frontend-web/docs/multi-agent-step1-api.md @@ -0,0 +1,492 @@ +# 多智能体圆桌 · Step 1 · 任务理解智能体接口与实现 + +> Step 1(`/page/roundtable/planning` 的"任务意图与澄清"页)对应 `RoundtablePlanningPage.tsx` 里 `currentStep === 1` 的渲染分支。当前它是纯前端 mock —— 用户发消息后 `setTimeout(1500)` 拼一段固定话术回。本文档定义一个**内置任务理解智能体 + 2 个轻量接口**,让 step 1 跑起来真正的对话,为 step 2 输入更高质量的"任务目标 + 约束"。 +> +> 整体风格直接参照 `multi-agent-api.md` / `multi-agent-backend-dev.md`。 + +--- + +## 1. 目标与边界 + +### ✅ 要做的事 +- 内置一个智能体:**任务理解智能体**(`roundtable-intent`),跟 6 个 roundtable 席位同等地位 +- 提供 2 个接口:`/api/intent/init` 和 `/api/intent/stream` +- 复用 step 2 的 SSE 协议风格(前端只需 1 个新 helper) +- 让用户跟智能体多轮澄清后,把最终"目标 + 约束"传给 step 2 的 `runOrchestration` + +### ❌ 不做的事 +- 不重新设计澄清协议(直接用 `ask_clarification` 工具 + ClarificationMiddleware 现成机制,跟 step 2 leader 一样) +- 不做"自动跳过"按钮的真实业务逻辑(保留前端按钮形态即可) +- 不做时间线(timelineEntries)的后端持久化(前端临时状态够用) +- 不做"评分/置信度"等假指标 +- 不做单独的"任务理解专员模型选择"——直接用全局 `DEFAULT_MODEL` + +--- + +## 2. 数据流概览 + +``` +[Step 1 入口] + ↓ +前端:POST /api/intent/init + ← {agent_id: "roundtable-intent", thread_id: "..."} + +用户输入第一句话:"帮我规划一个生产系统安全改造方案" + ↓ +前端:POST /api/intent/stream (SSE) + ← (流式 AI 文本) "好的,预算大致是多少?" + ← {status: "asking", content: "..."} ← 智能体反问中,需要用户继续 + +用户回:"500 万左右" + ↓ +前端再次 POST /api/intent/stream + ← (流式) "明白,还有什么时间约束吗?" + ← {status: "asking", ...} + +...对话进行几轮 ... + +用户:可以了 + ↓ +前端再 POST /api/intent/stream + ← (流式) "好,我理解的任务是: <汇总>" + ← {status: "done", content: "<最终汇总文本>", summary: {...}} ← 信息充分,可进入 step 2 + +[Step 1 完成 → Step 2 init] + 前端把 summary.objective + summary.constraints 拼成 step 2 的 buildInitialIntent() +``` + +--- + +## 3. 接口设计 + +跟 step 2 完全同构。`/api/intent/init` 简化版(只建 1 个 thread + 1 个 agent,没有"协调"概念);`/api/intent/stream` 跟 `/api/multi-agent/run/stream` 的 special 分支几乎一样。 + +### 3.1 `POST /api/intent/init` + +**请求体** +```json +{ + "model": "deepseek-chat" // 可选,默认全局 DEFAULT_MODEL +} +``` + +**响应 200** +```json +{ + "status": "success", + "agent_id": "roundtable-intent", + "thread_id": "" +} +``` + +**行为**: +1. 鉴权(透传 `Authorization`) +2. 调上游 `POST /api/threads` 建 1 个 thread +3. 直接返回 `agent_id = "roundtable-intent"`(**这是内置 agent,不需要每次新建**) + +**与 step 2 `/init` 的区别**: +- 没有"协调智能体"概念,只有 1 个 agent +- 没有 6 个 sub 席位,只有 1 个 thread +- 不需要传 `agent_names` 数组 +- `agent_id` 是固定字符串 `"roundtable-intent"`,不带 timestamp 后缀(智能体本身是内置、长期、复用的) + +### 3.2 `POST /api/intent/stream` + +**请求体** +```json +{ + "thread_id": "", + "message": "用户这一轮要说的话", + "model": "deepseek-chat" // 可选 +} +``` + +**响应**:`text/event-stream`,SSE 流式。 + +**SSE 帧组成**: +1. 透传上游 LangGraph 的所有帧(`event: metadata` / `event: messages` / `event: values`)—— 前端用现有的 `extractAiTextDelta` 解析 AI 文本增量 +2. 流末追加一个**状态帧**(跟 step 2 同样模式): + + ```json + { + "status": "asking" | "done" | "error", + "content": "<本轮 AI 文本>", + "summary": { + "objective": "...", // 仅 status=done 时有: 任务目标 + "constraints": ["...", ...], // 仅 status=done 时有: 约束清单 + "assumptions": ["...", ...] // 仅 status=done 时有: 关键假设 + } + } + ``` + +**`status` 取值**: +- `"asking"` —— 智能体还在追问,前端应该把焦点放回输入框 +- `"done"` —— 智能体宣布"信息已充分",前端就可以亮起"进入下一步"按钮,并拿 `summary` 拼 step 2 的初始 intent +- `"error"` —— 上游异常,`content` 里是错误信息 + +**判定 done/asking 的简单策略**(后端实现): +- 智能体在 SOUL 里被告知:信息已充分时**必须**调 `present_intent_summary` 工具(或直接在 AIMessage 里用一个固定标记 `[INTENT_READY]`),后端识别后发 `done` 帧 +- 否则一律是 `asking` + +> 上面"summary 工具"是新增的内置工具吗?不一定。最省事的做法是**让模型用 JSON 块输出**,后端用正则提取: +> +> ``` +> [INTENT_READY] +> ```json +> {"objective": "...", "constraints": ["..."], "assumptions": ["..."]} +> ``` +> ``` +> +> 后端流末扫一下最末 AIMessage 里有没有这个标记,有就 parse JSON 出来填到 summary,发 `done`;没有就发 `asking`。 + +--- + +## 4. 内置智能体配置 + +**位置**:`offline-backend-20260512/backend/.deer-flow/agents/roundtable-intent/` + +### 4.1 `config.yaml` +```yaml +id: roundtable-intent +name: 任务理解智能体 +description: 帮助用户明确任务目标、约束、关键假设,为后续多智能体圆桌研讨准备结构化输入。 +``` + +### 4.2 `SOUL.md` + +```markdown +# 任务理解智能体 + +## 角色定位 +你是多智能体圆桌研讨的"任务理解专员"。你的工作是在用户和 6 个圆桌席位之间架一座桥: +通过 2-5 轮简短追问,把用户模糊的需求转化成结构化的「任务目标 + 约束 + 关键假设」。 + +## 核心职责 +- 用清晰、简短的问题引导用户补全关键信息(优先级: 目标 > 硬约束 > 软偏好) +- 不要追问已经清楚的事 +- 不要做方案,不要给具体技术建议——那是后面 6 个席位的工作 +- 信息足够后,立即停止追问,产出结构化汇总 + +## 信息充分性判定 +当满足以下条件时,认为信息已充分: +1. 明确的任务目标(至少能写出一句 "用户希望实现 X") +2. 至少 1 条硬约束(预算/时间/合规/范围之一) +3. 没有明显的歧义点 + +## 信息汇总产出 +信息充分时,你必须在回复末尾输出**精确的标记 + JSON 块**(给后端识别用): + +``` +[INTENT_READY] +```json +{ + "objective": "用一句话写出用户最终要做的事", + "constraints": ["预算 ≤ XXX 万", "时间 ≤ XXX 天", ...], + "assumptions": ["假设 1", "假设 2", ...] +} +``` +``` + +输出前可以先用自然语言总结一遍给用户看(让用户能 review 内容),再附上述标记 + JSON。 + +## 输出风格 +- 一次回复不超过 3 句话 +- 提问要具体,不要"还有什么补充吗"这种空问 +- 用 emoji 简短点缀(❓ 表示问题, ✅ 表示明确, 📋 表示汇总) + +## 边界 +- 不调用 agent_orchestration(这是 step 2 的协调智能体的事) +- 不写文件、不做计算、不联网 +- 用户消息歧义大时,优先调 ask_clarification 工具引导 +``` + +### 4.3 注册方式 + +跟现有 6 个 `roundtable-*` 一样,通过 `_sync_legacy_agents()`(`app/gateway/routers/agents.py`)在下次任意 `/api/agents` 请求时自动 upsert 进 `agents` 表,`user_id IS NULL` 标记为内置。**零代码改动**。 + +--- + +## 5. 后端实现要点 + +### 5.1 新建 router 文件 +**位置**:`offline-backend-20260512/backend/app/gateway/routers/intent.py` + +```python +"""任务理解智能体接口 - Step 1 的极简包装。 + +跟 multi_agent.py 同构但简化: +- 没有 broadcast(单 thread,无需广播) +- 没有派活逻辑 +- 没有 leader/special 分支,只有一种调用方式 +- 流末状态帧解析 [INTENT_READY] 标记决定 status=done/asking +""" + +from fastapi import APIRouter, Body, HTTPException, Request +from fastapi.responses import StreamingResponse +import httpx, json, re, asyncio, logging + +logger = logging.getLogger(__name__) +router = APIRouter(prefix="/api/intent", tags=["intent"]) + +# 复用 multi_agent.py 里已有的工具函数 +from app.gateway.routers.multi_agent import ( + _loopback_base, _auth_headers, + _create_thread, _stream_upstream, _parse_last_messages, + _flatten_content, _run_payload, +) + +INTENT_AGENT_ID = "roundtable-intent" + +_INTENT_READY_PATTERN = re.compile( + r"\[INTENT_READY\]\s*```json\s*(\{.*?\})\s*```", + re.DOTALL, +) + + +@router.post("/init") +async def init_intent(request: Request, payload: dict = Body(...)) -> dict: + base = _loopback_base(request) + headers = _auth_headers(request) + async with httpx.AsyncClient(timeout=None) as client: + thread_id = await _create_thread(client, base, headers) + return { + "status": "success", + "agent_id": INTENT_AGENT_ID, + "thread_id": thread_id, + } + + +@router.post("/stream") +async def stream_intent(request: Request, payload: dict = Body(...)) -> StreamingResponse: + thread_id = str(payload.get("thread_id") or "").strip() + message = str(payload.get("message") or "").strip() + model_name = str(payload.get("model") or "deepseek-chat") + if not thread_id or not message: + raise HTTPException(status_code=400, detail="thread_id and message required") + + base = _loopback_base(request) + headers = _auth_headers(request) + + async def gen(): + async with httpx.AsyncClient(timeout=None) as client: + try: + body = _run_payload( + agent_name=INTENT_AGENT_ID, + model_name=model_name, + thread_id=thread_id, + new_message=message, + excluded_tools=["web_search", "present_files", + "view_image", "agent_orchestration"], + skill_stop_names=[], + ) + captured = [] + async for line, done in _stream_upstream(client, base, headers, thread_id, body): + if line is not None: + yield (line if line.endswith("\n") else line + "\n") + elif done is not None: + captured = done + + messages = _parse_last_messages(captured) + last_ai = {} + for m in reversed(messages): + if isinstance(m, dict) and (m.get("type") or "").lower() in ("ai", "aimessage", "aimessagechunk"): + last_ai = m + break + content = _flatten_content(last_ai.get("content", "")) + + # 检测 [INTENT_READY] 标记 + match = _INTENT_READY_PATTERN.search(content) + if match: + try: + summary = json.loads(match.group(1)) + except json.JSONDecodeError: + summary = None + frame = {"status": "done", "content": content, "summary": summary} + else: + frame = {"status": "asking", "content": content} + yield f"data: {json.dumps(frame, ensure_ascii=False)}\n\n" + except HTTPException as exc: + yield f"data: {json.dumps({'status':'error','content':f'[{exc.status_code}] {exc.detail}'}, ensure_ascii=False)}\n\n" + except Exception as exc: + logger.exception("intent stream failure") + yield f"data: {json.dumps({'status':'error','content':f'unexpected: {exc!r}'}, ensure_ascii=False)}\n\n" + + return StreamingResponse( + gen(), + media_type="text/event-stream", + headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no", "Connection": "keep-alive"}, + ) +``` + +### 5.2 在 `app/gateway/app.py` 注册 +```python +from app.gateway.routers import intent +app.include_router(intent.router) +``` + +--- + +## 6. 前端实现要点 + +### 6.1 新增 API helper +**位置**:`frontend-web/src/roundtable-planning/api/intent.ts` + +```ts +import { apiFetch } from "@/core/api/fetch-client"; +import { getBackendBaseURL } from "@/core/config"; + +export interface IntentInitResponse { + status: "success"; + agent_id: string; + thread_id: string; +} + +export async function initIntent(model?: string): Promise { + const res = await apiFetch(`${getBackendBaseURL()}/api/intent/init`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ model }), + }); + if (!res.ok) throw new Error(`init intent failed (${res.status}): ${await res.text()}`); + return res.json(); +} + +export interface IntentSummary { + objective: string; + constraints: string[]; + assumptions?: string[]; +} + +export interface StreamIntentRequest { + threadId: string; + message: string; + model?: string; + signal?: AbortSignal; + onTextDelta?: (text: string, id: string) => void; +} + +export interface StreamIntentResult { + status: "asking" | "done" | "error"; + content: string; + summary: IntentSummary | null; +} + +export async function streamIntent(req: StreamIntentRequest): Promise { + // 实现:reader 循环跟 streamMultiAgent 几乎一样,只是状态帧解析改成 + // {status, content, summary?} 格式。 + // ...(参考 multi-agent.ts 的 streamMultiAgent 改写,简化 80%) +} +``` + +### 6.2 改造 `RoundtablePlanningPage.tsx` 的 step1 渲染 + +替换 `handleSendMessage`: + +```ts +const [intentThreadId, setIntentThreadId] = useState(null); +const [intentReady, setIntentReady] = useState(null); + +useEffect(() => { + if (currentStep === 1 && !intentThreadId) { + initIntent(DEFAULT_MODEL).then(r => setIntentThreadId(r.thread_id)); + } +}, [currentStep]); + +const handleSendMessage = async () => { + if (!inputText.trim() || !intentThreadId) return; + const userText = inputText.trim(); + // (push user msg to interactiveMessages 略) + setInputText(""); + + // 占位 agent 气泡 + const agentMsgId = pushAgentPlaceholder("任务理解智能体"); + + const res = await streamIntent({ + threadId: intentThreadId, + message: userText, + model: DEFAULT_MODEL, + onTextDelta: (delta) => appendToAgentMsg(agentMsgId, delta), + }); + + finalizeAgentMsg(agentMsgId, res.content); + if (res.status === "done" && res.summary) { + setIntentReady(res.summary); + triggerToast("✅ 任务理解完成,可以进入圆桌研讨"); + } +}; +``` + +### 6.3 "进入 step 2"按钮的联动 + +- 当前页面已有"完成澄清/进入下一步"按钮(应该是路由到 `currentStep === 2`) +- 改造:只有 `intentReady !== null` 时该按钮才 enabled +- 点击后:把 `intentReady.objective + intentReady.constraints` 写入 `buildInitialIntent()` 的源(替换现在按 `interactiveMessages` 找最后一条 user msg + budgetLimit 拼接的逻辑) + +```ts +const buildInitialIntent = useCallback(() => { + if (intentReady) { + return `${intentReady.objective}\n\n约束条件:\n${intentReady.constraints.map(c => `- ${c}`).join("\n")}\n\n请基于上述目标与约束,在圆桌内调度合适的子智能体完成研讨。`; + } + // fallback: 旧逻辑保留兜底 + const lastUserMessage = [...interactiveMessages].reverse().find(m => m.sender === "user"); + const userIntent = lastUserMessage?.content ?? "请围绕给定任务展开圆桌研讨"; + const constraints = `预算硬约束:${budgetLimit} 万元`; + return `${userIntent}\n\n约束条件:${constraints}\n\n请基于上述目标与约束,在圆桌内调度合适的子智能体完成研讨。`; +}, [interactiveMessages, budgetLimit, intentReady]); +``` + +--- + +## 7. 实施清单 + +| 优先级 | 项 | 文件 | +|---|---|---| +| P0 | 内置 agent 目录 | `backend/.deer-flow/agents/roundtable-intent/{config.yaml,SOUL.md}` | +| P0 | 新 router | `backend/app/gateway/routers/intent.py` | +| P0 | 注册 router | `backend/app/gateway/app.py`(一行 `include_router`) | +| P0 | 前端 helper | `frontend-web/src/roundtable-planning/api/intent.ts` | +| P0 | 前端页面改造 | `frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx`(handleSendMessage + buildInitialIntent + 入口 useEffect) | +| P1 | step 1 进入下一步按钮 disabled 状态联动 `intentReady` | 同上 | +| P2 | 单测 | `backend/tests/test_intent.py`(init 返回 agent_id 固定值, stream 识别 INTENT_READY 标记) | +| P3 | 失败兜底(INTENT_READY 标记被模型遗漏时的"用户手动确认进入下一步"按钮) | 前端 | + +--- + +## 8. 与 step 2 的衔接 + +``` +step 1 输出: intentReady.objective + intentReady.constraints + ↓ +step 2 入口: buildInitialIntent() 拼成 leader 的 new_message + ↓ +step 2 leader 不再需要主动反问澄清(因为 step1 已经清完了), + 除非模型遇到完全意料之外的歧义 + ↓ +研讨更聚焦,减少 step2 阶段的 clarification 轮次 +``` + +副产物:协调智能体的 SOUL 可以稍微调整(参考 `multi_agent.py:soul = "#核心定位..."` 那段),加一句"用户已经经过任务理解智能体澄清,task 描述里包含目标+约束,请直接开始派活而不是再反问",进一步减少 step2 的反问。 + +--- + +## 9. 路径速查 + +| 资源 | 位置 | +|---|---| +| Step 1 渲染 | `RoundtablePlanningPage.tsx` 内 `currentStep === 1` 分支(约 line 1418+) | +| 新增前端 helper | `frontend-web/src/roundtable-planning/api/intent.ts` | +| 新增后端 router | `offline-backend-20260512/backend/app/gateway/routers/intent.py` | +| 内置 agent | `offline-backend-20260512/backend/.deer-flow/agents/roundtable-intent/` | +| 路由注册 | `offline-backend-20260512/backend/app/gateway/app.py` | +| 参照实现 | `multi_agent.py`(接口模式、SSE 包装、状态帧) | + +--- + +## 10. 验收清单 + +- [ ] 进入 step 1 自动调 `/api/intent/init`,拿到 thread_id +- [ ] 用户每次发消息后,任务理解智能体真实流式输出(不是 setTimeout) +- [ ] 智能体能在 2-5 轮对话后自动停止追问,发 `status: done` 帧并附 summary +- [ ] step 2 的初始 intent 用 step1 的 summary 拼接,不再依赖 `budgetLimit` 这种页面状态 +- [ ] 离开/重新进入 step 1 时,thread_id 状态干净(不会带着上次的对话) +- [ ] 任何接口失败都不让 step 1 卡死(容错的"用旧 mock 兜底"或者明确错误提示) diff --git a/frontend-web/docs/multi-agent-step3-api.md b/frontend-web/docs/multi-agent-step3-api.md new file mode 100644 index 00000000..b0b76023 --- /dev/null +++ b/frontend-web/docs/multi-agent-step3-api.md @@ -0,0 +1,264 @@ +# 多智能体圆桌 · Step 3 · 接口与对接说明 + +> Step 3(`/page/roundtable/planning` 的"最终方案展示"页)对应 `frontend-web/src/roundtable-planning/components/HighFidelityReport.tsx`。当前页面是产品早期的"展厅效果",绝大多数内容是硬编码 mock。本文档梳理**真正需要的数据**、**用哪些接口**、**前后端怎么对接**。 + +--- + +## 1. 改造方向(在做什么,不做什么) + +### ✅ 保留并对接真实数据 + +| 区块 | 现状 | 改造后 | +|---|---|---| +| 标题栏 + 生成时间 | 硬编码"2026-05-21 11:01:12" | 用本地 `Date.now()` 或 init/最后一次 leader 完成时刻 | +| "已达成共识"徽章 | 静态显示 | step2 自然收敛(`leaderRes.dispatched.length === 0`)后才显示 | +| **总控最终结论** | 完全是 mock 文本 | 取最后一次 `leaderRes.content`(已经在 step2 拿到了) | +| **各席位最终交付(折叠卡片)** | 当前 step3 没渲染 | 取每个 sub 线程的最后一条 AIMessage 文本 | +| **生成的报告文件清单** | 5 张假"档案" | 真实列出 `outputs/` 目录里的所有产出(markdown / pdf / csv 等) | +| **文件下载** | 假 toast | 用现有 `GET /api/threads/{tid}/artifacts/{path}` | +| "重新起草新规划" | 调用 `setCurrentStep(1)` 重置 | **保留**,含义就是回到 step1 重新开始 | + +### ❌ 不做(直接删 / 不接口) + +| 区块 | 原因 | +|---|---| +| 4 张 metric 卡片(设计全要素通过率 99.4% / Tier III+ / 终审共识度 42 轮研商 / 90.3分)| 全是按 `budgetLimit` 编出来的"展厅指标",没有真实数据源 | +| 三阶段推进路线图(0-24h / 24-60h / 60-72h 三张卡)| 假设业务必然是 72 小时交付,写死场景,不通用 | +| "采纳理由与最终裁定判词"段 | 整段都是模板话术,没接口能算出"90.3 分总评" | +| "12 轮极限对抗研商" 数据 | 当前没记录"轮次"语义,临时就用 leader 实际轮数代替即可,不值得为它出接口 | +| "签发起草成果并投产运行" 按钮 | 无对应业务动作(不是要部署、不是要审批),删掉 | +| "执行摘要" 段写死的 3 个 bullet | 模板话术,跟实际任务无关 | + +最终 step3 页面只保留四块:**头部状态 + 总控结论 + 席位交付列表 + 文件下载清单**,再加底部"重新起草"。 + +--- + +## 2. 数据来源全景 + +``` +┌───────────────────────────────────────────────────────────┐ +│ step2 全程结束时,前端手里已经有的本地状态 │ +├───────────────────────────────────────────────────────────┤ +│ coordinatorName: "roundtable-coordinator-xxx" │ +│ threadIds: { [agent_name]: thread_id, ... } │ ← /init 返回 +│ step2RoundtableDialogues: [...所有气泡, 含每个 sub 最终 │ +│ 交付的 content...] │ +│ leaderRes.content (最后一次 leader 的 final text) │ +└───────────────────────────────────────────────────────────┘ + +后端权威数据(需要时从后端拉): +- 每个 sub 线程的完整 state → GET /api/threads/{tid}/state +- 单个 outputs 文件内容/下载 → GET /api/threads/{tid}/artifacts/{path} +- outputs 目录文件清单 ❗暂无 → 新增接口(见 §3) +``` + +**关键判断**:席位最终交付文本 + 总控结论文本 **已经在 step2 内存里**,无需重新调接口。文件清单是**目前唯一缺失**的数据源。 + +--- + +## 3. 接口需求 + +### 3.1 新增(**必需**):列出某 thread 的产出文件 + +``` +GET /api/multi-agent/sessions/artifacts?thread_id= +``` + +或者更通用、放进 artifacts 路由下: + +``` +GET /api/threads/{thread_id}/artifacts +``` + +**为什么需要**:现有 artifacts endpoint 只能"按已知路径下载文件",没有"列出目录"功能。Step 3 需要知道 sub-agent 写到 `/mnt/user-data/outputs/` 下哪些文件,才能在前端列出可下载清单。 + +**响应**: +```json +{ + "thread_id": "", + "files": [ + { + "path": "mnt/user-data/outputs/方案设计报告_生产系统安全改造技术方案.md", + "name": "方案设计报告_生产系统安全改造技术方案.md", + "size_bytes": 12480, + "mime_type": "text/markdown", + "modified_at": "2026-05-23T14:32:30.123Z" + }, + ... + ] +} +``` + +**实现建议**: +- 列 `backend/.deer-flow/users/{user_id}/threads/{thread_id}/user-data/outputs/` 下的文件 +- 鉴权复用 `@require_permission("threads", "read", owner_check=True)` +- 路径要做 traversal 保护(虚拟路径仅限 `mnt/user-data/outputs/`) + +### 3.2 新增(**可选,体感优化**):一次性聚合 step3 数据 + +``` +POST /api/multi-agent/sessions/summary +Body: { + "main_agent_name": "roundtable-coordinator-xxx", + "thread_ids": { "": "", ... } +} +``` + +**为什么可选**:不加这个接口的话,前端需要为每个席位发一次 `GET /state` + 一次 `GET /artifacts`(共 7-13 次 round-trip)。加了这个接口,**一次返回所有数据**。 + +**响应**: +```json +{ + "main_agent_name": "roundtable-coordinator-xxx", + "coordinator": { + "thread_id": "...", + "final_text": "...", // 最后一条 AIMessage content + "dispatch_rounds": 3 // leader 派活的轮数(可选展示) + }, + "seats": [ + { + "agent_name": "roundtable-intelligence", + "thread_id": "...", + "display_name": "情报收集", + "final_text": "...", // 最后一条 AIMessage content + "files": [ // 该席位写到 outputs/ 的文件 + { "path": "...", "name": "...", "size_bytes": ..., "mime_type": "..." } + ] + }, + ... + ] +} +``` + +**取舍**: +- 优点:1 次请求 vs 13 次;体验更顺 +- 缺点:等于把 3.1 + N 次 state 读放到一个 endpoint,实现稍复杂 +- 推荐:**先做 3.1,3.2 暂缓**;前端用现有 endpoint 串起来够用 + +### 3.3 复用(**无需改动**) + +| Endpoint | 用途 | +|---|---| +| `GET /api/threads/{tid}/state` | 取席位 / 总控线程的完整状态,提取最后一条 AIMessage content | +| `GET /api/threads/{tid}/artifacts/{path}` | 点击文件名预览或下载(已有 `?download=true` 支持) | + +> Note: 这两个 endpoint 已经在 `app.gateway.routers.threads` / `app.gateway.routers.artifacts` 里实现,前端 `fetch-client` 也有现成调用方式。 + +--- + +## 4. 前后端对接流程 + +### 4.1 进入 step3 时 + +```ts +// 触发条件:runOrchestration 自然结束(leaderRes.dispatched.length === 0 +// 且无 clarification),用户点"达成共识生成全案成果"按钮 / 自动跳转。 + +// 前端手里已有:threadIds, coordinatorName, 最后的 leaderRes +// 1. 总控结论文本 — 已在内存,直接用 +const consensusText = lastLeaderRes.content; + +// 2. 各席位交付 — 已在 step2RoundtableDialogues 里,过滤"子智能体交付"的卡片 +const seatDeliveries = step2RoundtableDialogues + .filter(d => d.confidence === "子智能体交付") + .map(d => ({ sender: d.sender, content: d.content })); + +// 3. 文件清单 — 调新接口 +const filesPerSeat = await Promise.all( + Object.entries(threadIds) + .filter(([name]) => name !== coordinatorName) + .map(async ([name, tid]) => ({ + agentName: name, + files: (await fetch(`/api/threads/${tid}/artifacts`).then(r => r.json())).files, + })), +); +``` + +### 4.2 用户点击文件时 + +```ts +// 在线预览(mime 是 markdown/text/pdf 自动 inline) +window.open(`/api/threads/${threadId}/artifacts/${encodeURIComponent(filePath)}`); + +// 强制下载 +window.open(`/api/threads/${threadId}/artifacts/${encodeURIComponent(filePath)}?download=true`); +``` + +### 4.3 "重新起草新规划" 按钮 + +```ts +// 跟现在一样,纯前端:清掉 dialogues + 跳 step1 +setCurrentStep(1); +setInteractiveMessages(...); // 已有逻辑 +setStep2RoundtableDialogues([]); +// 不需要调任何接口 +``` + +--- + +## 5. 改造前端的具体文件清单 + +| 文件 | 改动 | +|---|---| +| `frontend-web/src/roundtable-planning/components/HighFidelityReport.tsx` | **大改**。删除四张 metric 卡 / 三阶段路线图 / 论证要件 / 裁定判词;新增结论卡 + 席位折叠列表 + 文件清单 | +| `frontend-web/src/roundtable-planning/api/multi-agent.ts` | 新增 `listSessionArtifacts(threadId)` helper(封装 §3.1 接口) | +| `frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx` | 把 `threadIds` / `coordinatorName` / `lastLeaderContent` 传进 `HighFidelityReport` 的 props(目前没传) | + +--- + +## 6. 改造后端的具体文件清单 + +| 文件 | 改动 | +|---|---| +| `offline-backend-20260512/backend/app/gateway/routers/artifacts.py` | 新增 `GET /api/threads/{tid}/artifacts`(不带 path,列目录) | +| `offline-backend-20260512/backend/CLAUDE.md` | 在 artifacts 路由表里增加新条目说明 | +| `offline-backend-20260512/backend/tests/test_artifacts_list.py` | 列目录新接口的单测(覆盖:空目录返回 [];traversal 路径返回 403;不存在 thread 返回 404)| + +--- + +## 7. 实施优先级 + +| 优先级 | 项 | 备注 | +|---|---|---| +| P0 | 新增 `GET /api/threads/{tid}/artifacts` 列文件接口 | 必需,没它前端无法列文件 | +| P0 | step3 大改:删 mock 区块、加结论/席位/文件三块 | 主要价值改造 | +| P1 | 前端 helper `listSessionArtifacts` | 封装 fetch + 类型 | +| P2 | 单测 `test_artifacts_list.py` | 上线后跟进 | +| P3 | `POST /api/multi-agent/sessions/summary` 聚合接口 | 13 次→1 次,体感优化,**非必需** | + +--- + +## 8. 显式不做的事 ❌ + +1. **不做"PDF 导出"**:后端没有现成 PDF 渲染管线,要做就是单独的项目。当前页面那个 `导出方案 PDF` 按钮直接删掉,或者保留按钮但点击只触发 `window.print()`(让浏览器自己生成 PDF)。 +2. **不做"安全分享"**:项目里已有 `/api/thread-shares`(per-thread 分享)和 `/api/public/shares`(公开页面),但那是针对单个 thread 的,不是多 thread 会话的。要做"多 thread 整合分享"是新功能,远超 step3 的范围。 +3. **不做"指标雷达图"**(什么 90.3 分总评):没有真实数据源,强行加只会变成下一个 mock。 +4. **不做"签发投产"**:纯展示按钮,不接业务系统,删。 +5. **不做"轮次/对抗次数"显示**:除非前端记一下 `dispatch_count`,否则后端没现成统计。如果真要展示,用现成的"派活了几次"代替"对抗 N 轮"。 + +--- + +## 9. 验收清单 + +step3 改造完成后应该能: + +- [ ] 看到当前 session 的总控最终结论,markdown 渲染 +- [ ] 看到 6 个席位各自的最终交付内容(默认折叠,点击展开) +- [ ] 看到所有 sub-agent 写到 outputs 的文件列表,含文件名、大小、类型 icon +- [ ] 点击文件名能在线预览(markdown / pdf / 图片) +- [ ] 点击下载按钮能下载(带正确文件名) +- [ ] 点"重新起草新规划"能回到 step1 且 step2 内存清空 +- [ ] 页面不再包含任何来自 `budgetLimit` 的"假指标" + +--- + +## 10. 路径速查 + +| 资源 | 位置 | +|---|---| +| Step 3 组件 | `frontend-web/src/roundtable-planning/components/HighFidelityReport.tsx` | +| 父页面 (state 持有者) | `frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx` | +| 前端 API helper | `frontend-web/src/roundtable-planning/api/multi-agent.ts` | +| 后端 artifacts 路由 | `offline-backend-20260512/backend/app/gateway/routers/artifacts.py` | +| 后端 multi-agent 路由 | `offline-backend-20260512/backend/app/gateway/routers/multi_agent.py` | +| 物理 outputs 目录 | `backend/.deer-flow/users/{user_id}/threads/{thread_id}/user-data/outputs/` | diff --git a/frontend-web/src/open-canvas/api/writing-export.ts b/frontend-web/src/open-canvas/api/writing-export.ts new file mode 100644 index 00000000..57367122 --- /dev/null +++ b/frontend-web/src/open-canvas/api/writing-export.ts @@ -0,0 +1,69 @@ +import { apiFetch } from "@/core/api/fetch-client"; +import { getBackendBaseURL } from "@/core/config"; + +function filenameFromContentDisposition(header: string | null): string | null { + if (!header) return null; + const star = /filename\*=(?:UTF-8'')?([^;]+)/i.exec(header); + if (star) { + const raw = star[1].replace(/["']/g, "").trim(); + try { + return decodeURIComponent(raw); + } catch { + return raw; + } + } + const plain = /filename="?([^";\n]+)"?/i.exec(header); + return plain ? plain[1].trim() : null; +} + +function sanitizeFallbackFilename(title: string | undefined): string { + const base = (title?.trim() || "document").replace(/[<>:"/\\|?*\x00-\x1f]+/g, "_"); + return base.toLowerCase().endsWith(".docx") ? base : `${base}.docx`; +} + +async function downloadBlobResponse(response: Response, fallbackFilename: string) { + if (!response.ok) { + const error = await response + .json() + .catch(() => ({ detail: "导出 Word 失败" })); + const detail = error.detail; + if (typeof detail === "string") throw new Error(detail); + throw new Error("导出 Word 失败"); + } + + const blob = await response.blob(); + const filename = + filenameFromContentDisposition(response.headers.get("Content-Disposition")) ?? + fallbackFilename; + const url = URL.createObjectURL(blob); + const anchor = document.createElement("a"); + anchor.href = url; + anchor.download = filename; + anchor.rel = "noopener"; + document.body.appendChild(anchor); + anchor.click(); + anchor.remove(); + window.setTimeout(() => URL.revokeObjectURL(url), 30_000); +} + +/** 调用后端导出 AI 写作草稿为 Word,仅传正文 markdown,不传目录/大纲。 */ +export async function downloadAIWritingDocx(options: { + title?: string; + draftMarkdown: string; +}): Promise { + const draftMarkdown = options.draftMarkdown.trim(); + if (!draftMarkdown) { + throw new Error("文档内容为空"); + } + + const response = await apiFetch(`${getBackendBaseURL()}/api/ai-writing/export/docx`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + title: options.title?.trim() || undefined, + draft_markdown: draftMarkdown, + }), + }); + + await downloadBlobResponse(response, sanitizeFallbackFilename(options.title)); +} diff --git a/frontend-web/src/open-canvas/components/artifact/WritingToolbar.tsx b/frontend-web/src/open-canvas/components/artifact/WritingToolbar.tsx index 1c9202d9..6d77ff86 100644 --- a/frontend-web/src/open-canvas/components/artifact/WritingToolbar.tsx +++ b/frontend-web/src/open-canvas/components/artifact/WritingToolbar.tsx @@ -25,7 +25,7 @@ import { TooltipTrigger, } from "@/components/ui/tooltip"; import { CanvasModelSelector } from "../selectors/CanvasModelSelector"; -import { exportMarkdownToDocx } from "../../utils/export-docx"; +import { downloadAIWritingDocx } from "../../api/writing-export"; interface ToolbarButtonProps { onClick: () => void; @@ -82,9 +82,12 @@ export function WritingToolbar({ editor, markdown, title }: WritingToolbarProps) if (!canExport) return; setExporting(true); try { - await exportMarkdownToDocx(markdown ?? "", title); + await downloadAIWritingDocx({ + title, + draftMarkdown: markdown ?? "", + }); } catch (err) { - console.error("[export-docx] failed", err); + console.error("[writing-export] failed", err); toast.error("导出 Word 失败,请稍后重试"); } finally { setExporting(false); diff --git a/frontend-web/src/roundtable-planning/api/multi-agent.ts b/frontend-web/src/roundtable-planning/api/multi-agent.ts index e9f59417..ebe98422 100644 --- a/frontend-web/src/roundtable-planning/api/multi-agent.ts +++ b/frontend-web/src/roundtable-planning/api/multi-agent.ts @@ -3,10 +3,27 @@ import { getBackendBaseURL } from "@/core/config"; export type ThreadIdMap = Record; +export interface SeatReadyEvent { + agentName: string; + threadId: string; + displayName: string; + description: string; +} + +export interface CoordinatorReadyEvent { + mainAgentName: string; + threadId: string; +} + export interface InitMultiAgentRequest { agentNames: string[]; mainAgentName: string; model?: string; + /** Fires the moment each sub-agent's thread is ready (real completion order). */ + onSeatReady?: (event: SeatReadyEvent) => void; + /** Fires when the coordinator's thread + agent have been created. */ + onCoordinatorReady?: (event: CoordinatorReadyEvent) => void; + signal?: AbortSignal; } export interface InitMultiAgentResponse { @@ -15,6 +32,12 @@ export interface InitMultiAgentResponse { thread_ids: ThreadIdMap; } +/** + * Open the /api/multi-agent/init SSE stream. Fires per-seat / coordinator + * callbacks as events arrive so the UI can light up roles individually, and + * resolves with the final {main_agent_name, thread_ids} once init_done lands. + * If the server emits an "error" frame mid-stream, the promise rejects. + */ export async function initMultiAgent( payload: InitMultiAgentRequest, ): Promise { @@ -26,18 +49,114 @@ export async function initMultiAgent( main_agent_name: payload.mainAgentName, model: payload.model, }), + signal: payload.signal, }); - if (!res.ok) { + if (!res.ok || !res.body) { const text = await res.text().catch(() => ""); throw new Error(`init multi-agent failed (${res.status}): ${text}`); } - return (await res.json()) as InitMultiAgentResponse; + + const reader = res.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ""; + let mainAgentName = ""; + let threadIds: ThreadIdMap | null = null; + let aborted = false; + let errorDetail: string | null = null; + + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split("\n"); + buffer = lines.pop() ?? ""; + + for (const rawLine of lines) { + const line = rawLine.trimEnd(); + if (!line.startsWith("data:")) continue; + const data = line.slice(5).trim(); + if (!data) continue; + let parsed: unknown; + try { + parsed = JSON.parse(data); + } catch { + continue; + } + if (!parsed || typeof parsed !== "object") continue; + const obj = parsed as Record; + const event = typeof obj.event === "string" ? obj.event : ""; + switch (event) { + case "seat_ready": { + payload.onSeatReady?.({ + agentName: String(obj.agent_name ?? ""), + threadId: String(obj.thread_id ?? ""), + displayName: String(obj.display_name ?? ""), + description: String(obj.description ?? ""), + }); + break; + } + case "coordinator_ready": { + payload.onCoordinatorReady?.({ + mainAgentName: String(obj.main_agent_name ?? ""), + threadId: String(obj.thread_id ?? ""), + }); + break; + } + case "init_done": { + mainAgentName = String(obj.main_agent_name ?? ""); + threadIds = (obj.thread_ids ?? {}) as ThreadIdMap; + break; + } + case "error": { + errorDetail = String(obj.detail ?? "unknown init error"); + break; + } + default: + // Unknown event — ignore for forward-compat. + break; + } + } + } + } catch (err) { + aborted = (err as Error)?.name === "AbortError" || payload.signal?.aborted === true; + if (!aborted) throw err; + } + + if (errorDetail) { + throw new Error(`init multi-agent failed: ${errorDetail}`); + } + if (aborted) { + throw new DOMException("init aborted", "AbortError"); + } + if (!threadIds || !mainAgentName) { + throw new Error("init multi-agent stream ended without init_done"); + } + return { + status: "success", + main_agent_name: mainAgentName, + thread_ids: threadIds, + }; } export type StreamAgentType = "leader" | "special"; export type LeaderDispatch = [string, string]; +/** + * High-level phases the SSE stream goes through. Used by the UI to show + * "what the backend is doing" while the user waits — most of the time before + * a first token is upstream/LLM latency, which feels like a stall otherwise. + * + * - `connecting` — fetch sent, no frames yet + * - `connected` — got the `event: metadata` frame (run_id assigned) + * - `streaming` — first AI text chunk arrived; tokens flowing + * - `tool_calling` — model emitted a tool_call chunk (e.g. agent_orchestration, + * present_files); usually means the run is about to interrupt + * - `tool_result` — a tool result message came back; brief, may go back to streaming + */ +export type StreamPhase = "connecting" | "connected" | "streaming" | "tool_calling" | "tool_result"; + export interface StreamMultiAgentRequest { agentType: StreamAgentType; dAgentThreadId: ThreadIdMap; @@ -54,6 +173,25 @@ export interface StreamMultiAgentRequest { * `messageId` is stable per AI message so callers can group deltas. */ onTextDelta?: (text: string, messageId: string) => void; + /** + * Fires whenever the inferred SSE phase changes. The UI can use this to + * show progressive status messages during the inevitable first-token wait. + * `name` is the tool name when phase is `tool_calling` (or empty otherwise). + */ + onPhaseChange?: (phase: StreamPhase, name?: string) => void; +} + +export interface ClarificationPayload { + /** Raw question text from the model's ask_clarification args. */ + question: string; + /** Optional category hint from the model (e.g. "missing_info"). */ + clarificationType: string; + /** Free-text reason the model needs clarification. */ + context: string; + /** Suggested answer chips (may be empty). */ + options: unknown[]; + /** Whether the user is allowed to type a custom answer. */ + allowCustom: boolean; } export interface StreamMultiAgentResult { @@ -65,6 +203,14 @@ export interface StreamMultiAgentResult { content: string; /** Echoed agent_name of the agent that produced this run. */ agentName: string | null; + /** + * Populated when the leader called ask_clarification — the run ended without + * dispatching, and the model is asking the user a question instead. When + * present, callers should render `content` (or `clarification.question` as + * a fallback) as a question and collect a user reply rather than treating + * an empty `dispatched` as consensus. + */ + clarification: ClarificationPayload | null; } /** @@ -76,6 +222,11 @@ function isFinalStatusFrame(value: unknown): value is { status: LeaderDispatch[] | string; content?: string; agent_name?: string; + question?: string; + clarification_type?: string; + clarification_context?: string; + options?: unknown[]; + allow_custom?: boolean; } { if (!value || typeof value !== "object") return false; if (!("status" in value) || !("content" in value)) return false; @@ -125,6 +276,44 @@ function extractAiTextDelta(parsed: unknown): { text: string; id: string } | nul return { text, id }; } +/** + * Trigger a browser download for a text blob. No-op outside the browser. + * Used by streamMultiAgent's dump-to-file debug mode. + */ +function downloadTextBlob(filename: string, text: string): void { + if (typeof window === "undefined" || typeof document === "undefined") return; + try { + const blob = new Blob([text], { type: "text/plain;charset=utf-8" }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = filename; + a.style.display = "none"; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + // Defer revoke so the browser has a chance to start the download. + setTimeout(() => URL.revokeObjectURL(url), 60_000); + } catch (err) { + // Downloads must never break the actual stream — just log and continue. + console.warn("[stream] downloadTextBlob failed:", err); + } +} + +/** + * Whether streamMultiAgent should auto-download the raw SSE transcript to a + * .txt when each call ends. Default ON for now because we're debugging the + * "sub-agent stream looks empty" issue and the browser console truncates + * large message logs. Toggle from devtools: + * window.__MULTI_AGENT_DUMP__ = false + */ +function isDumpEnabled(): boolean { + if (typeof window === "undefined") return false; + const flag = (window as unknown as { __MULTI_AGENT_DUMP__?: boolean }).__MULTI_AGENT_DUMP__; + // Default: enabled. Only disabled if explicitly set to false. + return flag !== false; +} + /** * Open an SSE connection to /api/multi-agent/run/stream and resolve once the * stream completes. The final frame (`{status: ...}`) is interpreted; every @@ -168,66 +357,184 @@ export async function streamMultiAgent( typeof window !== "undefined" && (window as unknown as { __MULTI_AGENT_DEBUG__?: boolean }).__MULTI_AGENT_DEBUG__ !== false; - const result: StreamMultiAgentResult = { dispatched: [], message: null, content: "", agentName: null }; + // Raw SSE transcript buffer. Every raw line read from the stream (event:, + // data:, blank framing lines, anything) is appended verbatim so the dumped + // .txt is byte-for-byte what the frontend received off the socket. This is + // independent of parsing: even malformed/non-JSON frames end up in the file. + const dumpEnabled = isDumpEnabled(); + const transcript: string[] = dumpEnabled + ? [ + `# multi-agent stream transcript`, + `# agent_type: ${req.agentType}`, + `# agent_name: ${req.agentName}`, + `# started_at: ${new Date().toISOString()}`, + `# new_message: ${req.newMessage.replace(/\n/g, " ⏎ ")}`, + `# model: ${req.model ?? "(default)"}`, + `# ---- raw SSE follows ----`, + "", + ] + : []; - while (true) { - const { done, value } = await reader.read(); - if (done) break; - buffer += decoder.decode(value, { stream: true }); + const result: StreamMultiAgentResult = { + dispatched: [], + message: null, + content: "", + agentName: null, + clarification: null, + }; - const lines = buffer.split("\n"); - buffer = lines.pop() ?? ""; + // Inferred SSE phase + a tiny helper so we only fire onPhaseChange when the + // value actually changes (the reader loop sees many frames per phase). + let currentPhase: StreamPhase = "connecting"; + req.onPhaseChange?.("connecting"); + const setPhase = (next: StreamPhase, name?: string) => { + if (next === currentPhase && !name) return; + currentPhase = next; + req.onPhaseChange?.(next, name); + }; - for (const rawLine of lines) { - const line = rawLine.trimEnd(); - if (!line) continue; - if (line.startsWith("event:")) { - lastEvent = line.slice(6).trim(); - continue; - } - if (!line.startsWith("data:")) continue; - const payload = line.slice(5).trim(); - if (!payload) continue; + // Wrap the read loop so we always flush the transcript to disk, even on + // abort / network failure. Otherwise an interrupted run would lose the very + // evidence we want to inspect. + const finishDump = (reason: string) => { + if (!dumpEnabled) return; + transcript.push(""); + transcript.push(`# ---- stream ended (${reason}) ----`); + transcript.push(`# ended_at: ${new Date().toISOString()}`); + transcript.push(`# frames_parsed: ${frameSeq}`); + transcript.push(`# final_content_length: ${result.content.length}`); + transcript.push(`# dispatched_count: ${result.dispatched.length}`); + const tsSafe = new Date().toISOString().replace(/[:.]/g, "-"); + const nameSafe = req.agentName.replace(/[^a-zA-Z0-9_-]/g, "_"); + const filename = `multi-agent_${req.agentType}_${nameSafe}_${tsSafe}.txt`; + downloadTextBlob(filename, transcript.join("\n")); + }; - let parsed: unknown; - try { - parsed = JSON.parse(payload); - } catch { - if (debugEnabled) console.debug(debugLabel, `bad JSON in event=${lastEvent}:`, payload.slice(0, 200)); - continue; - } + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + const chunk = decoder.decode(value, { stream: true }); + buffer += chunk; - frameSeq += 1; - if (debugEnabled) console.debug(debugLabel, `frame#${frameSeq} event=${lastEvent}`, parsed); + const lines = buffer.split("\n"); + buffer = lines.pop() ?? ""; - if (isFinalStatusFrame(parsed)) { - if (Array.isArray(parsed.status)) { - result.dispatched = parsed.status; - } else { - result.message = parsed.status; + for (const rawLine of lines) { + // Record EVERY raw line — including blank framing lines and event: + // headers — so the dumped transcript matches what the socket sent. + if (dumpEnabled) transcript.push(rawLine); + + const line = rawLine.trimEnd(); + if (!line) continue; + if (line.startsWith("event:")) { + lastEvent = line.slice(6).trim(); + // First metadata frame = run accepted by upstream. Move phase out + // of "connecting" so the UI can switch from "调度中" to "已连接". + if (lastEvent === "metadata" && currentPhase === "connecting") { + setPhase("connected"); + } + continue; } - if (typeof parsed.content === "string") { - result.content = parsed.content; - } - if (typeof parsed.agent_name === "string") { - result.agentName = parsed.agent_name; - } - continue; - } + if (!line.startsWith("data:")) continue; + const payload = line.slice(5).trim(); + if (!payload) continue; - const delta = extractAiTextDelta(parsed); - if (delta) { - if (debugEnabled) console.debug(debugLabel, `→ delta (${delta.text.length} chars)`); - req.onTextDelta?.(delta.text, delta.id); - } + let parsed: unknown; + try { + parsed = JSON.parse(payload); + } catch { + if (debugEnabled) console.debug(debugLabel, `bad JSON in event=${lastEvent}:`, payload.slice(0, 200)); + continue; + } - req.onUpstreamFrame?.(parsed); + frameSeq += 1; + if (debugEnabled) console.debug(debugLabel, `frame#${frameSeq} event=${lastEvent}`, parsed); + + // Phase inference from LangGraph messages-tuple frames. We only flip + // to tool_calling/tool_result on chunks that clearly indicate them; + // everything else with non-empty AI text means we're streaming. + if (lastEvent === "messages" && Array.isArray(parsed) && parsed.length > 0) { + const chunk = parsed[0]; + if (chunk && typeof chunk === "object") { + const chunkObj = chunk as Record; + const chunkType = String(chunkObj.type ?? "").toLowerCase(); + const toolCalls = chunkObj.tool_calls; + const toolCallChunks = chunkObj.tool_call_chunks; + const content = chunkObj.content; + const hasToolCall = + (Array.isArray(toolCalls) && toolCalls.length > 0) || + (Array.isArray(toolCallChunks) && toolCallChunks.length > 0); + if (chunkType === "tool") { + setPhase("tool_result"); + } else if (hasToolCall) { + // Pick the most informative name we can find in either field. + const firstCall = Array.isArray(toolCalls) && toolCalls.length > 0 + ? (toolCalls[0] as Record) + : Array.isArray(toolCallChunks) && toolCallChunks.length > 0 + ? (toolCallChunks[0] as Record) + : null; + const toolName = firstCall && typeof firstCall.name === "string" ? firstCall.name : ""; + setPhase("tool_calling", toolName); + } else if ( + (chunkType === "ai" || chunkType === "aimessagechunk" || chunkType === "aimessage") && + ((typeof content === "string" && content.length > 0) || (Array.isArray(content) && content.length > 0)) + ) { + setPhase("streaming"); + } + } + } + + if (isFinalStatusFrame(parsed)) { + if (Array.isArray(parsed.status)) { + result.dispatched = parsed.status; + } else { + result.message = parsed.status; + // "clarification" status carries the leader's ask_clarification + // payload. Extract the structured fields so the page can render + // a question (or chip choices) instead of mistaking the run for + // a consensus. + if (parsed.status === "clarification") { + result.clarification = { + question: typeof parsed.question === "string" ? parsed.question : "", + clarificationType: + typeof parsed.clarification_type === "string" ? parsed.clarification_type : "", + context: + typeof parsed.clarification_context === "string" ? parsed.clarification_context : "", + options: Array.isArray(parsed.options) ? parsed.options : [], + allowCustom: parsed.allow_custom !== false, + }; + } + } + if (typeof parsed.content === "string") { + result.content = parsed.content; + } + if (typeof parsed.agent_name === "string") { + result.agentName = parsed.agent_name; + } + continue; + } + + const delta = extractAiTextDelta(parsed); + if (delta) { + if (debugEnabled) console.debug(debugLabel, `→ delta (${delta.text.length} chars)`); + req.onTextDelta?.(delta.text, delta.id); + } + + req.onUpstreamFrame?.(parsed); + } } - } - if (debugEnabled) { - console.debug(debugLabel, `stream ended after ${frameSeq} frames; final content length=${result.content.length}`); + if (debugEnabled) { + console.debug(debugLabel, `stream ended after ${frameSeq} frames; final content length=${result.content.length}`); + } + finishDump("normal"); + return result; + } catch (err) { + // Flush whatever we got so the user can still inspect the transcript on + // abort / network drop. Then rethrow so callers' own handling runs. + const aborted = (err as Error)?.name === "AbortError" || req.signal?.aborted === true; + finishDump(aborted ? "aborted" : `error: ${(err as Error)?.message ?? String(err)}`); + throw err; } - - return result; } diff --git a/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx b/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx index ada16bca..7ef56684 100644 --- a/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx +++ b/frontend-web/src/roundtable-planning/pages/RoundtablePlanningPage.tsx @@ -1,4 +1,6 @@ import React, { useState, useEffect, useRef, useCallback } from "react"; +import ReactMarkdown from "react-markdown"; +import remarkGfm from "remark-gfm"; import { HighFidelityReport } from "@/roundtable-planning/components/HighFidelityReport"; import { useTheme } from "@/contexts/ThemeContext"; import { cn } from "@/lib/utils"; @@ -6,7 +8,9 @@ import { useModels } from "@/core/models/hooks"; import { initMultiAgent, streamMultiAgent, + type ClarificationPayload, type LeaderDispatch, + type StreamPhase, type ThreadIdMap, } from "@/roundtable-planning/api/multi-agent"; import { @@ -39,7 +43,8 @@ import { Cpu, CornerDownRight, Star, - ShieldCheck + ShieldCheck, + Loader2, } from "lucide-react"; // --- Custom Crisp SVGs to Match High Fidelity Avatars --- @@ -306,6 +311,11 @@ export default function RoundtablePlanningPage() { const [isInitializing, setIsInitializing] = useState(false); const [initError, setInitError] = useState(null); const [isOrchestrating, setIsOrchestrating] = useState(false); + // When the coordinator calls ask_clarification, the leader run ends with + // this payload populated; the page renders a question card and only + // resumes orchestration once the user replies. + const [pendingClarification, setPendingClarification] = useState(null); + const [clarificationDraft, setClarificationDraft] = useState(""); const orchestrationCancelRef = useRef(false); const step2InitRef = useRef(false); // Tracks every AbortController active in this Step 2 visit so the "停止" / @@ -368,6 +378,38 @@ export default function RoundtablePlanningPage() { ]); }, []); + // Translate an inferred SSE phase into a human-readable confidence label + // for the dialogue bubble. We keep the bubble's existing in-progress + // confidence ("调度中" / "正在输出…") when phase doesn't add information, + // and switch to a specific label when something specific is happening. + const phaseLabel = useCallback((phase: StreamPhase, agentType: "leader" | "special", toolName?: string): string => { + switch (phase) { + case "connecting": + return "调度中"; + case "connected": + return "已连接,等待响应"; + case "tool_calling": + if (toolName === "agent_orchestration") return "正在派活"; + if (toolName === "ask_clarification") return "正在提问"; + if (toolName === "present_files") return "正在交付文件"; + return toolName ? `调用工具:${toolName}` : "调用工具"; + case "tool_result": + return "处理工具结果"; + case "streaming": + return agentType === "leader" ? "正在派活说明" : "正在输出"; + default: + return agentType === "leader" ? "调度中" : "正在输出…"; + } + }, []); + + // Update only the confidence field of a streaming card by id. Used by the + // phase callback so we can change the label without touching content. + const setDialogueConfidence = useCallback((id: number, confidence: string) => { + setStep2RoundtableDialogues(prev => + prev.map(d => (d.id === id ? { ...d, confidence } : d)), + ); + }, []); + // Streaming variant: append a placeholder card and return its id so subsequent // text deltas can be appended in-place via appendToDialogue. const appendStreamingDialogue = useCallback((card: { @@ -501,8 +543,10 @@ export default function RoundtablePlanningPage() { safetyCounter += 1; highlightSpeaker(2); - // Leader bubble — created BEFORE the call so users see "正在输出…" the - // moment the request is in flight, then text fills in as deltas arrive. + // Leader bubble — created BEFORE the call so users see "调度中" the + // moment the request is in flight, then phase changes flip the + // confidence label so the user sees what the backend is actually + // doing during the ~1-2s first-token wait. const leaderBubbleId = appendStreamingDialogue({ sender: "总控协调", avatarType: "blue", @@ -523,6 +567,9 @@ export default function RoundtablePlanningPage() { model: DEFAULT_MODEL, signal: leaderAborter.signal, onTextDelta: (text) => appendToDialogue(leaderBubbleId, text), + onPhaseChange: (phase, toolName) => { + setDialogueConfidence(leaderBubbleId, phaseLabel(phase, "leader", toolName)); + }, }); } catch (err) { activeAbortersRef.current.delete(leaderAborter); @@ -536,6 +583,18 @@ export default function RoundtablePlanningPage() { if (orchestrationCancelRef.current) break; + // Clarification branch — leader asked the user a question. Stop the + // auto loop, surface the question card, and wait for the user to + // reply before another leader cycle. + if (leaderRes.clarification) { + finalizeDialogue(leaderBubbleId, leaderRes.content, "等待用户澄清"); + highlightSpeaker(null); + setPendingClarification(leaderRes.clarification); + setClarificationDraft(""); + triggerToast("❓ 总控需要补充信息,请回答下方问题后继续"); + break; + } + finalizeDialogue( leaderBubbleId, leaderRes.content, @@ -549,52 +608,59 @@ export default function RoundtablePlanningPage() { break; } - // Dispatch all sub-agents in parallel; per-seat model preference - // overrides the default if the user picked one in the drawer. Each - // sub-agent gets its own streaming bubble that fills independently. - await Promise.allSettled( - leaderRes.dispatched.map(async ([subName, task]) => { - if (orchestrationCancelRef.current) return; - const meta = AGENT_NAME_TO_ROLE[subName.toLowerCase()]; - // Add this speaker to the concurrent active set so its avatar - // lights up alongside any other sub-agents streaming in parallel. - if (meta) markSpeakerStreaming(meta.speakerId); - const perSeatModel = meta ? agentConfigs[meta.speakerId]?.model : undefined; + // Dispatch sub-agents sequentially (one at a time). Running them in + // parallel meant N concurrent SSE streams each triggering a full-list + // setState on every token delta, which made the browser stutter badly + // when the leader 派活给多个席位。改为顺序后,同一时刻只有一个 SSE 在跑。 + for (const [subName, task] of leaderRes.dispatched) { + if (orchestrationCancelRef.current) break; + const meta = AGENT_NAME_TO_ROLE[subName.toLowerCase()]; + if (meta) markSpeakerStreaming(meta.speakerId); + const perSeatModel = meta ? agentConfigs[meta.speakerId]?.model : undefined; - const subBubbleId = appendStreamingDialogue({ - sender: meta?.displayName ?? subName, - avatarType: meta?.avatarType ?? "blue", - initialContent: "", - confidence: "正在输出…", + const subBubbleId = appendStreamingDialogue({ + sender: meta?.displayName ?? subName, + avatarType: meta?.avatarType ?? "blue", + initialContent: "", + confidence: "调度中", + }); + + const subAborter = new AbortController(); + activeAbortersRef.current.add(subAborter); + let aborted = false; + try { + const specRes = await streamMultiAgent({ + agentType: "special", + dAgentThreadId: ids, + agentName: subName, + newMessage: task, + model: perSeatModel || DEFAULT_MODEL, + signal: subAborter.signal, + onTextDelta: (text) => appendToDialogue(subBubbleId, text), + onPhaseChange: (phase, toolName) => { + setDialogueConfidence(subBubbleId, phaseLabel(phase, "special", toolName)); + }, }); - - const subAborter = new AbortController(); - activeAbortersRef.current.add(subAborter); - try { - const specRes = await streamMultiAgent({ - agentType: "special", - dAgentThreadId: ids, - agentName: subName, - newMessage: task, - model: perSeatModel || DEFAULT_MODEL, - signal: subAborter.signal, - onTextDelta: (text) => appendToDialogue(subBubbleId, text), - }); - if (orchestrationCancelRef.current) return; + if (orchestrationCancelRef.current) { + finalizeDialogue(subBubbleId, specRes.content || "(已停止)", "已停止"); + aborted = true; + } else { finalizeDialogue(subBubbleId, specRes.content, "子智能体交付"); - } catch (err) { - if (subAborter.signal.aborted || (err as Error).name === "AbortError") { - finalizeDialogue(subBubbleId, "(已停止)", "已停止"); - } else { - console.error(`[special:${subName}] error:`, err); - finalizeDialogue(subBubbleId, `(错误) ${(err as Error).message}`, "调用失败"); - } - } finally { - activeAbortersRef.current.delete(subAborter); - if (meta) markSpeakerIdle(meta.speakerId); } - }), - ); + } catch (err) { + if (subAborter.signal.aborted || (err as Error).name === "AbortError") { + finalizeDialogue(subBubbleId, "(已停止)", "已停止"); + aborted = true; + } else { + console.error(`[special:${subName}] error:`, err); + finalizeDialogue(subBubbleId, `(错误) ${(err as Error).message}`, "调用失败"); + } + } finally { + activeAbortersRef.current.delete(subAborter); + if (meta) markSpeakerIdle(meta.speakerId); + } + if (aborted) break; + } if (orchestrationCancelRef.current) break; @@ -635,6 +701,12 @@ export default function RoundtablePlanningPage() { abortAllInFlight(); step2InitRef.current = false; setIsOrchestrating(false); + setPendingClarification(null); + setClarificationDraft(""); + // Re-entering step 2 should start with the discussion nominally + // "running" so the suspend button comes back; the prior visit might + // have ended in a paused state. + setIsRoundTableRunning(true); return; } @@ -654,6 +726,23 @@ export default function RoundtablePlanningPage() { agentNames: ROUNDTABLE_AGENT_IDS, mainAgentName: coord, model: DEFAULT_MODEL, + // As each sub-agent's thread comes online, flip every role that + // shares the agentId to "在线". Some seats reuse the same agent + // (e.g. seat 8 reuses roundtable-summary) so we match on agentId + // rather than a single id. + onSeatReady: ({ agentName }) => { + if (cancelled) return; + const id = agentName.toLowerCase(); + setRoles(prev => + prev.map(r => (r.agentId === id ? { ...r, status: "在线" } : r)), + ); + }, + // Coordinator readiness is a no-op for the role list (the + // coordinator isn't rendered as a seat), but we keep the hook in + // case we want to drop a "系统" toast later. + onCoordinatorReady: () => { + if (cancelled) return; + }, }); if (cancelled) return; setThreadIds(initRes.thread_ids); @@ -851,11 +940,15 @@ export default function RoundtablePlanningPage() { }; // Step 2 role statuses transition when entering roundtable! + // On Step 2 entry we set every agent seat to "正在上线" (spinner state); + // the /init SSE stream then flips each one to "在线" as its thread/agent + // actually finishes on the backend. Seat 1 (human commander) stays online + // throughout — it's not part of the bring-up. useEffect(() => { if (currentStep === 1) { setRoles(makeRoles("等待激活", { 2: "在线" })); } else if (currentStep === 2) { - setRoles(makeRoles("在线", { 8: "等待陈述" })); + setRoles(makeRoles("正在上线", { 1: "在线" })); } else { setRoles(makeRoles("已完成")); } @@ -887,6 +980,36 @@ export default function RoundtablePlanningPage() { void runOrchestration(`用户人工干预新指令:${userText}\n\n请结合当前讨论状态,决定是否继续派活或直接给出更新后的结论。`, threadIds, coordinatorName); }; + // Submit the user's answer to the coordinator's clarification question and + // resume orchestration. The reply is fed back as the next leader prompt on + // the same coordinator thread (no re-init needed). + const submitClarification = (rawAnswer: string) => { + const answer = rawAnswer.trim(); + if (!answer) return; + if (!threadIds || !coordinatorName) { + triggerToast("⚠️ 圆桌尚未就绪,无法回复澄清"); + return; + } + if (isOrchestrating) { + triggerToast("⏳ 当前轮次仍在进行中,请稍候"); + return; + } + const question = pendingClarification?.question || "(澄清问题)"; + appendDialogue({ + sender: "用户 (澄清回复)", + avatarType: "human", + content: `🗣 回复总控提问:${answer}`, + confidence: "澄清回复", + }); + setPendingClarification(null); + setClarificationDraft(""); + void runOrchestration( + `用户已回复你刚才的澄清问题。\n问题:${question}\n用户回答:${answer}\n请基于该回答继续派活或给出结论。`, + threadIds, + coordinatorName, + ); + }; + return (
{ const isActive = role.status === "在线" || role.status === "研讨中" || role.status === "已完成"; const isOngoing = role.status === "研讨中"; - + const isBootingUp = role.status === "正在上线"; + return ( -
@@ -1229,18 +1357,22 @@ export default function RoundtablePlanningPage() { ) : role.status === "已完成" ? ( + ) : isBootingUp ? ( + ) : ( )} {role.status} @@ -1608,23 +1740,33 @@ export default function RoundtablePlanningPage() { >极速
- {isRoundTableRunning ? ( - - ) : ( - - )} + ) : null}
@@ -1995,17 +2137,165 @@ export default function RoundtablePlanningPage() { {msg.time} -

- {msg.content} +

+ {/* Pre-streaming hint — when the bubble is created but + no AI token has arrived yet, show a small spinner + + the current phase label so the user can see the + backend is doing something (调度中 → 已连接 → + 正在派活/调用工具 → 流式输出). */} + {msg.streaming && !msg.content && ( +
+ + {msg.confidence} +
+ )} +

{children}

, + ul: ({ children }) =>
    {children}
, + ol: ({ children }) =>
    {children}
, + li: ({ children }) =>
  • {children}
  • , + h1: ({ children }) =>

    {children}

    , + h2: ({ children }) =>

    {children}

    , + h3: ({ children }) =>

    {children}

    , + h4: ({ children }) =>

    {children}

    , + strong: ({ children }) => {children}, + em: ({ children }) => {children}, + code: ({ children, className }) => { + const isBlock = /language-/.test(className ?? ""); + if (isBlock) { + return ( +
    +                                    {children}
    +                                  
    + ); + } + return ( + + {children} + + ); + }, + blockquote: ({ children }) => ( +
    + {children} +
    + ), + a: ({ children, href }) => ( + + {children} + + ), + table: ({ children }) => ( + {children}
    + ), + th: ({ children }) => ( + + {children} + + ), + td: ({ children }) => ( + {children} + ), + hr: () =>
    , + }} + > + {msg.content ?? ""} +
    {msg.streaming && ( )} -

    +
    ))} + {/* Clarification card — shown only when the coordinator asked + the user a question via ask_clarification. The auto-loop is + paused; replying resumes orchestration on the same threads. */} + {pendingClarification && ( +
    +
    + +
    +
    + + 总控协调需要澄清 + + {pendingClarification.clarificationType && ( + + {pendingClarification.clarificationType} + + )} +
    + {pendingClarification.context && ( +

    + {pendingClarification.context} +

    + )} +

    + {pendingClarification.question} +

    + {Array.isArray(pendingClarification.options) && + pendingClarification.options.length > 0 && ( +
    + {pendingClarification.options.map((opt, idx) => { + const label = + typeof opt === "string" + ? opt + : opt && typeof opt === "object" && "label" in (opt as object) + ? String((opt as { label: unknown }).label ?? "") + : String(opt ?? ""); + if (!label) return null; + return ( + + ); + })} +
    + )} + {pendingClarification.allowCustom !== false && ( +
    + setClarificationDraft(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter") submitClarification(clarificationDraft); + }} + placeholder="输入你的回答…" + className="flex-1 bg-white border border-amber-300 rounded-xl px-3 py-2 text-xs focus:outline-none focus:border-amber-500 focus:ring-1 focus:ring-amber-200 font-medium" + /> + +
    + )} +
    +
    +
    + )} + {/* Console control / Custom injection bar */}
    tuple[str, str]: - match = _TOOL_CALL_PATTERN.search(text) + +def _validate_agent_id(value: str, field: str) -> str: + if not _AGENT_ID_PATTERN.match(value): + raise HTTPException( + status_code=400, + detail=( + f"{field} '{value}' is not a valid agent id. " + f"Must match ^[A-Za-z0-9_-]+$ (use the hyphen-case id, not the display name)." + ), + ) + return value + + +def _extract_dispatch(tool_call: dict[str, Any]) -> tuple[str, str]: + """Return ``(agent_name, task)`` parsed from a leader tool call. + + Two formats are accepted: + + 1. **Structured** — ``{"name": "agent_orchestration", "args": {"agent_name": ..., "task": ...}}``. + This is what most LLMs emit when told to "use the agent_orchestration skill", + and the form the roundtable coordinator's SOUL prompt elicits. + + 2. **Legacy bash argv** — ``{"name": "bash", "args": {"command": '... .py "X" "Y" ...'}}``. + Kept as a fallback so older skills that dispatch through bash still work. + """ + name = (tool_call.get("name") or "").lower() + args = tool_call.get("args") + + # Format 1: structured agent_orchestration call. + if name == "agent_orchestration" and isinstance(args, dict): + agent_name = str(args.get("agent_name") or "").strip() + task = str(args.get("task") or "").strip() + if agent_name and task: + return _strip_display_suffix(agent_name), task + + # Format 2: legacy bash + .py "X" "Y". + match = _TOOL_CALL_PATTERN.search(str(args)) if match: - return match.group(1), match.group(2) + return _strip_display_suffix(match.group(1)), match.group(2) + return "", "" +def _strip_display_suffix(agent_name: str) -> str: + """Tolerate models that paste the human-readable suffix into agent_name. + + The coordinator SOUL lists each seat as ``agent_name: roundtable-x(中文):...`` + so weaker models sometimes echo the entire ``roundtable-x(中文)`` label + back as the dispatch target. Strip everything from the first non-id + character onward so we recover the bare hyphen-case id; if what's left + still violates the id pattern we hand it back untouched and let the + upstream validator reject it. + """ + head = re.split(r"[^A-Za-z0-9_-]", agent_name, maxsplit=1)[0] + return head or agent_name + + def _flatten_content(content: Any) -> str: if isinstance(content, str): return content @@ -195,7 +250,22 @@ def _run_payload( @router.post("/init") -async def init_multi_agent(request: Request, payload: dict = Body(...)) -> dict[str, Any]: +async def init_multi_agent(request: Request, payload: dict = Body(...)) -> StreamingResponse: + """Streaming /init. + + Emits text/event-stream frames as each seat/coordinator becomes ready, so + the frontend can visualize the parallel bring-up rather than blocking on + one bulk JSON. Frames: + + data: {"event":"seat_ready","agent_name":"...","thread_id":"...","display_name":"...","description":"..."} + data: {"event":"coordinator_ready","main_agent_name":"...","thread_id":"..."} + data: {"event":"init_done","main_agent_name":"...","thread_ids":{...}} + data: {"event":"error","detail":"..."} # on failure + + Validation errors (missing agent_names, bad id pattern) still raise + HTTPException synchronously so the connection fails fast with a real 4xx + instead of a 200 SSE that just carries an error frame. + """ agent_names_in = payload.get("agent_names") or [] agent_names: list[str] = [str(name).lower() for name in agent_names_in] main_agent_name: str = str(payload.get("main_agent_name") or "main-agent").lower() @@ -204,61 +274,112 @@ async def init_multi_agent(request: Request, payload: dict = Body(...)) -> dict[ if not agent_names: raise HTTPException(status_code=400, detail="agent_names is required") + for name in agent_names: + _validate_agent_id(name, "agent_names entry") + _validate_agent_id(main_agent_name, "main_agent_name") + base = _loopback_base(request) headers = _auth_headers(request) - async with httpx.AsyncClient(timeout=None) as client: - # Optimization A: fetch every sub-agent's metadata and create its - # thread concurrently. With 6 seats this turns ~12 sequential - # loopback round-trips into one wave of 12 parallel ones. - async def _prepare_sub_agent(sub_id: str) -> tuple[str, str, str]: - info = await _get_agent(client, base, headers, sub_id) - sub_name = str(info["name"]).lower() - thread_id = await _create_thread(client, base, headers) - return sub_name, thread_id, info.get("description", "") or "" + def _frame(payload: dict[str, Any]) -> str: + return f"data: {json.dumps(payload, ensure_ascii=False)}\n\n" - prepared = await asyncio.gather(*(_prepare_sub_agent(sid) for sid in agent_names)) + async def stream_generator() -> AsyncIterator[str]: + async with httpx.AsyncClient(timeout=None) as client: + try: + # Per-seat prepare task — same body as before, but we no longer + # await them with asyncio.gather. Instead, asyncio.as_completed + # surfaces them in REAL completion order so we can emit a + # seat_ready frame the moment each finishes. + async def _prepare_sub_agent(sub_id: str) -> tuple[str, str, str, str]: + info = await _get_agent(client, base, headers, sub_id) + display_name = str(info.get("name") or sub_id) + description = info.get("description", "") or "" + thread_id = await _create_thread(client, base, headers) + return sub_id.lower(), thread_id, display_name, description - agent_threads: dict[str, str] = {sub_name: thread_id for sub_name, thread_id, _ in prepared} - descriptions: list[str] = [ - f"agent_name:{sub_name},{description}" for sub_name, _, description in prepared - ] + tasks = [asyncio.create_task(_prepare_sub_agent(sid)) for sid in agent_names] + prepared: list[tuple[str, str, str, str]] = [] + try: + for fut in asyncio.as_completed(tasks): + sid, thread_id, display_name, description = await fut + prepared.append((sid, thread_id, display_name, description)) + yield _frame({ + "event": "seat_ready", + "agent_name": sid, + "thread_id": thread_id, + "display_name": display_name, + "description": description, + }) + except Exception: + # Cancel any still-pending sibling so we don't leak tasks + # past the AsyncClient close. + for t in tasks: + if not t.done(): + t.cancel() + raise - soul = ( - "#核心定位:\n" - "用途:根据用户的任务目标,调用其他智能体干活,只负责协调汇总," - "当你觉得已有信息支持回答用户问题时候,停止调度,并输出最后的结果\n" - "#调度方法:\n" - "通过使用agent_orchestration技能调用其他智能体干活,使用技能时传入agent_name和需要做的活\n" - "#可调度智能体:\n" - f"{descriptions}" - ) + agent_threads: dict[str, str] = {sid: thread_id for sid, thread_id, _, _ in prepared} + descriptions: list[str] = [ + f"- agent_name: {sid}({display_name}):{description}" + for sid, _, display_name, description in prepared + ] - agent_threads[main_agent_name] = await _create_thread(client, base, headers) - ok, result = await _create_agent( - client, - base, - headers, - name=main_agent_name, - description="你是总控控制协调智能体,负责协调其他智能体干活", - model=model, - skills=["agent_orchestration"], - soul=soul, - agent_id=main_agent_name, - ) - if not ok and isinstance(result, str) and "exists" not in result: - raise HTTPException(status_code=500, detail=f"create coordinator agent failed: {result}") + soul = ( + "#核心定位:\n" + "用途:根据用户的任务目标,调用其他智能体干活,只负责协调汇总," + "当你觉得已有信息支持回答用户问题时候,停止调度,并输出最后的结果\n" + "#调度方法:\n" + "通过使用agent_orchestration技能调用其他智能体干活,使用技能时传入agent_name和需要做的活。" + "注意:agent_name 必须严格使用下方列出的英文 id(例如 roundtable-intelligence)," + "不要把括号里的中文显示名拼进 agent_name 里。\n" + "#可调度智能体:\n" + + "\n".join(descriptions) + ) - # Optimization C: the sub-agent SOULs already declare "你只在被点到时 - # 发言,由总控协调智能体派活", so the old intro broadcast (one human - # message per thread, 6 × GET-state + 6 × POST-state) is redundant. - # Skipping it removes the slowest stage of init entirely. + coord_thread = await _create_thread(client, base, headers) + agent_threads[main_agent_name] = coord_thread + ok, result = await _create_agent( + client, + base, + headers, + name=main_agent_name, + description="你是总控控制协调智能体,负责协调其他智能体干活", + model=model, + skills=["agent_orchestration"], + soul=soul, + agent_id=main_agent_name, + ) + if not ok and isinstance(result, str) and "exists" not in result: + yield _frame({"event": "error", "detail": f"create coordinator agent failed: {result}"}) + return - return { - "status": "success", - "main_agent_name": main_agent_name, - "thread_ids": agent_threads, - } + yield _frame({ + "event": "coordinator_ready", + "main_agent_name": main_agent_name, + "thread_id": coord_thread, + }) + yield _frame({ + "event": "init_done", + "main_agent_name": main_agent_name, + "thread_ids": agent_threads, + }) + except HTTPException as exc: + logger.warning("multi-agent init HTTPException: %s %s", exc.status_code, exc.detail) + yield _frame({"event": "error", "detail": f"[{exc.status_code}] {exc.detail}"}) + except Exception as exc: + logger.exception("multi-agent init unexpected failure") + yield _frame({"event": "error", "detail": f"unexpected: {exc!r}"}) + + return StreamingResponse( + stream_generator(), + media_type="text/event-stream", + headers={ + "Cache-Control": "no-cache", + "X-Accel-Buffering": "no", + "Connection": "keep-alive", + }, + ) # --------------------------------------------------------------------------- @@ -277,37 +398,112 @@ async def _stream_upstream( url = f"{base}/api/threads/{thread_id}/runs/stream" captured: list[str] = [] + t_send = time.perf_counter() async with client.stream("POST", url, json=body, headers=headers) as resp: + t_headers = time.perf_counter() if resp.status_code != 200: body_text = (await resp.aread()).decode("utf-8", "replace")[:1000] raise HTTPException( status_code=502, detail=f"upstream {url} returned HTTP {resp.status_code}: {body_text}", ) + agent_for_log = (body.get("context") or {}).get("agent_name") or thread_id + logger.info( + "[upstream-timing] %s headers_in=%.3fs", + agent_for_log, + t_headers - t_send, + ) + first_line = True async for line in resp.aiter_lines(): if not line: continue + if first_line: + first_line = False + logger.info( + "[upstream-timing] %s first_line=%.3fs (LangGraph runtime startup + LLM first byte)", + agent_for_log, + time.perf_counter() - t_headers, + ) yield line, None if line.startswith("data:"): captured.append(line) yield None, captured -def _parse_last_message(captured: list[str]) -> dict[str, Any]: - if len(captured) < 2: - raise HTTPException( - status_code=502, - detail=f"upstream produced no usable data lines (got {len(captured)})", - ) - raw = captured[-2][5:].strip() - try: - parsed = json.loads(raw) - except json.JSONDecodeError as exc: - raise HTTPException(status_code=502, detail=f"failed to parse upstream frame: {exc}") from exc - messages = parsed.get("messages") or [] - if not messages: - return {} - return messages[-1] or {} +def _parse_last_messages(captured: list[str]) -> list[dict[str, Any]]: + """Return the full ``messages`` list from the most recent ``values`` snapshot. + + The upstream sends the final ``values`` frame second-to-last (the very last + line is the ``end`` event with ``null``). We tolerate trailing non-JSON + frames (e.g. ``data: null``) by scanning backwards for the first frame that + successfully parses as a state object with a ``messages`` key. + """ + if not captured: + raise HTTPException(status_code=502, detail="upstream produced no data lines") + + for raw_line in reversed(captured): + raw = raw_line[5:].strip() if raw_line.startswith("data:") else raw_line.strip() + if not raw or raw == "null": + continue + try: + parsed = json.loads(raw) + except json.JSONDecodeError: + continue + if isinstance(parsed, dict) and "messages" in parsed: + messages = parsed.get("messages") or [] + if isinstance(messages, list): + return messages + + raise HTTPException(status_code=502, detail="no parseable values frame in upstream stream") + + +def _find_trailing_ai_text(messages: list[dict[str, Any]], *, exclude_text: str = "") -> str: + """Return the text content of the latest AIMessage with no tool_calls. + + Used by the clarification branch: ClarificationMiddleware ends the run + after emitting the structured ToolMessage, but the model often produces a + richer human-readable follow-up AIMessage right before the interrupt. + Prefer that text over the brief preamble that accompanied the + ask_clarification tool_call. When the only trailing AIMessage matches the + preamble (``exclude_text``), return empty so the caller can fall back to + the question itself. + """ + for msg in reversed(messages): + if not isinstance(msg, dict): + continue + if (msg.get("type") or "").lower() not in ("ai", "aimessage", "aimessagechunk"): + continue + if msg.get("tool_calls"): + continue + text = _flatten_content(msg.get("content", "")).strip() + if not text: + continue + if exclude_text and text == exclude_text.strip(): + continue + return text + return "" + + +def _find_dispatch_message(messages: list[dict[str, Any]]) -> dict[str, Any]: + """Locate the latest AIMessage that carries dispatch tool calls. + + The very last message can be a skill-stop ToolMessage injected by + ``SkillStopMiddleware`` when it intercepts the dispatch, or a clarification + ToolMessage. Either way, the actionable tool_calls live on the AIMessage + *before* it, so we walk backwards until we hit one with ``tool_calls``. + Returns the latest AIMessage when none of them carry tool_calls so the + caller can still extract its text content. + """ + last_ai: dict[str, Any] = {} + for msg in reversed(messages): + if not isinstance(msg, dict): + continue + if (msg.get("type") or "").lower() in ("ai", "aimessage", "aimessagechunk"): + if not last_ai: + last_ai = msg + if msg.get("tool_calls"): + return msg + return last_ai async def _leader_run( @@ -320,48 +516,144 @@ async def _leader_run( skill_stop_names: list[str], model_name: str, ) -> AsyncIterator[str | dict[str, Any]]: - await _broadcast(client, base, headers, "总控智能体收到用户消息:" + new_message, agent_threads, [agent_name]) + # Fine-grained timing for the leader path. The user reported the + # coordinator "stalls before output" — we log each major await so we can + # see whether the wait is in pre-broadcast scheduling, upstream stream + # setup, first-token latency, or post-stream parsing. + t0 = time.perf_counter() + + pre_broadcast_task = asyncio.create_task( + _broadcast(client, base, headers, "总控智能体收到用户消息:" + new_message, agent_threads, [agent_name]) + ) thread_id = agent_threads[agent_name] + effective_stop_names = list({"agent_orchestration", *skill_stop_names}) body = _run_payload( agent_name=agent_name, model_name=model_name, thread_id=thread_id, new_message=new_message, excluded_tools=["web_search"], - skill_stop_names=skill_stop_names, + skill_stop_names=effective_stop_names, + ) + t_payload_built = time.perf_counter() + logger.info( + "[leader-timing] %s payload_built=%.3fs (broadcast running in background)", + agent_name, + t_payload_built - t0, ) captured: list[str] = [] + first_line_ts: float | None = None + line_count = 0 async for line, done in _stream_upstream(client, base, headers, thread_id, body): if line is not None: + if first_line_ts is None: + first_line_ts = time.perf_counter() + logger.info( + "[leader-timing] %s first_upstream_line=%.3fs since_entry=%.3fs", + agent_name, + first_line_ts - t_payload_built, + first_line_ts - t0, + ) + line_count += 1 yield line elif done is not None: captured = done + t_stream_done = time.perf_counter() + logger.info( + "[leader-timing] %s upstream_stream_complete=%.3fs lines=%d since_entry=%.3fs", + agent_name, + t_stream_done - (first_line_ts or t_payload_built), + line_count, + t_stream_done - t0, + ) + + messages = _parse_last_messages(captured) + # Pre-broadcast must finish before we yield the final status frame on any + # branch — the seats that get dispatched next rely on having seen the + # original user message. The upstream LLM stream usually takes several + # seconds, so the broadcast has typically already completed and this + # await is effectively free. + t_before_broadcast_await = time.perf_counter() + try: + await pre_broadcast_task + except Exception as exc: + logger.warning("pre-broadcast failed: %s", exc) + t_after_broadcast_await = time.perf_counter() + logger.info( + "[leader-timing] %s pre_broadcast_await=%.3fs (>0 means broadcast was still in flight after LLM finished)", + agent_name, + t_after_broadcast_await - t_before_broadcast_await, + ) + + dispatch_msg = _find_dispatch_message(messages) + leader_text = _flatten_content(dispatch_msg.get("content", "")) + tool_calls = dispatch_msg.get("tool_calls") or [] + + # Clarification branch: the coordinator called ask_clarification. The + # ClarificationMiddleware intercepts with Command(goto=END) and stashes + # the structured question in the tool_call args; sometimes a richer + # follow-up AIMessage is also produced after the ToolMessage. Emit a + # dedicated frame so the frontend can render it as a question instead of + # treating an empty dispatch as "consensus reached". + clarification_call = next( + (tc for tc in tool_calls if (tc.get("name") or "").lower() == "ask_clarification"), + None, + ) + if clarification_call is not None: + cargs = clarification_call.get("args") or {} + question = str(cargs.get("question") or "").strip() + follow_up = _find_trailing_ai_text(messages, exclude_text=leader_text) + yield { + "status": "clarification", + "content": follow_up or question or leader_text, + "question": question, + "clarification_type": str(cargs.get("clarification_type") or ""), + "clarification_context": str(cargs.get("context") or ""), + "options": cargs.get("options") or [], + "allow_custom": bool(cargs.get("allow_custom", True)), + "agent_name": agent_name, + } + return - last_msg = _parse_last_message(captured) - leader_text = _flatten_content(last_msg.get("content", "")) - tool_calls = last_msg.get("tool_calls") or [] if not tool_calls: yield {"status": [], "content": leader_text, "agent_name": agent_name} return + # Run all dispatch broadcasts concurrently — they target disjoint thread + # sets and we don't care about ordering, so serializing them just + # multiplied latency before the frontend could start a sub-agent run. dispatched: list[list[str]] = [] + dispatch_broadcasts: list[asyncio.Task[None]] = [] for tool_call in tool_calls: try: - sub_name, task_text = _extract_name_task(str(tool_call.get("args", ""))) + sub_name, task_text = _extract_dispatch(tool_call) if not sub_name: continue - await _broadcast( - client, - base, - headers, - f"总控智能体给{sub_name}派活,内容为:" + task_text, - agent_threads, - [agent_name, sub_name], + dispatch_broadcasts.append( + asyncio.create_task( + _broadcast( + client, + base, + headers, + f"总控智能体给{sub_name}派活,内容为:" + task_text, + agent_threads, + [agent_name, sub_name], + ) + ) ) dispatched.append([sub_name, task_text]) except Exception as exc: logger.warning("dispatch failed: %s", exc) + if dispatch_broadcasts: + t_before_dispatch = time.perf_counter() + await asyncio.gather(*dispatch_broadcasts, return_exceptions=True) + logger.info( + "[leader-timing] %s dispatch_broadcasts_await=%.3fs count=%d (gates how soon the next sub agent can start)", + agent_name, + time.perf_counter() - t_before_dispatch, + len(dispatch_broadcasts), + ) yield {"status": dispatched, "content": leader_text, "agent_name": agent_name} @@ -375,38 +667,90 @@ async def _special_run( skill_stop_names: list[str], model_name: str, ) -> AsyncIterator[str | dict[str, Any]]: + # Same instrumentation as _leader_run so all 6 seats are diagnosable. + t0 = time.perf_counter() thread_id = agent_threads[agent_name] body = _run_payload( agent_name=agent_name, model_name=model_name, thread_id=thread_id, new_message=new_message, - excluded_tools=["web_search", "ask_clarification", "present_files", "view_image"], + excluded_tools=["web_search", "ask_clarification", "present_files", "view_image", "agent_orchestration"], skill_stop_names=skill_stop_names, ) + t_payload_built = time.perf_counter() + logger.info( + "[special-timing] %s payload_built=%.3fs", + agent_name, + t_payload_built - t0, + ) captured: list[str] = [] + first_line_ts: float | None = None + line_count = 0 async for line, done in _stream_upstream(client, base, headers, thread_id, body): if line is not None: + if first_line_ts is None: + first_line_ts = time.perf_counter() + logger.info( + "[special-timing] %s first_upstream_line=%.3fs since_entry=%.3fs", + agent_name, + first_line_ts - t_payload_built, + first_line_ts - t0, + ) + line_count += 1 yield line elif done is not None: captured = done + t_stream_done = time.perf_counter() + logger.info( + "[special-timing] %s upstream_stream_complete=%.3fs lines=%d since_entry=%.3fs", + agent_name, + t_stream_done - (first_line_ts or t_payload_built), + line_count, + t_stream_done - t0, + ) - last_msg = _parse_last_message(captured) + messages = _parse_last_messages(captured) + # Sub-agent's final deliverable is the latest AIMessage's text content. + last_msg: dict[str, Any] = {} + for msg in reversed(messages): + if isinstance(msg, dict) and (msg.get("type") or "").lower() in ("ai", "aimessage", "aimessagechunk"): + last_msg = msg + break content = _flatten_content(last_msg.get("content", "")) - await _broadcast( - client, - base, - headers, - f"子智能体{agent_name}完成{new_message}工作,交付内容为:" + content, - agent_threads, - [agent_name], + # Kick the "子智能体完成" broadcast off in the background and yield the + # status frame first — the next leader cycle that depends on this + # broadcast having landed only starts after a fresh /run/stream request + # from the frontend, which is many seconds away (full leader LLM call). + # Awaiting after the yield ensures the task finishes before the AsyncClient + # closes; the SSE connection stays open a bit longer but the frontend has + # already consumed the result. + t_before_post = time.perf_counter() + post_broadcast_task = asyncio.create_task( + _broadcast( + client, + base, + headers, + f"子智能体{agent_name}完成{new_message}工作,交付内容为:" + content, + agent_threads, + [agent_name], + ) ) yield { "status": f"子智能体{agent_name}完成{new_message}工作", "content": content, "agent_name": agent_name, } + try: + await post_broadcast_task + except Exception as exc: + logger.warning("post-broadcast failed: %s", exc) + logger.info( + "[special-timing] %s post_broadcast_total=%.3fs (broadcast time after yield — keeps SSE open this long)", + agent_name, + time.perf_counter() - t_before_post, + ) @router.post("/run/stream") @@ -423,6 +767,9 @@ async def run_multi_agent_stream(request: Request, payload: dict = Body(...)) -> status_code=400, detail=f"agent_name '{agent_name}' is missing from d_agent_thread_id", ) + _validate_agent_id(agent_name, "agent_name") + for key in agent_threads: + _validate_agent_id(key, "d_agent_thread_id key") base = _loopback_base(request) headers = _auth_headers(request) diff --git a/offline-backend-20260512/backend/packages/harness/deerflow/agents/middlewares/skill_stop_middleware.py b/offline-backend-20260512/backend/packages/harness/deerflow/agents/middlewares/skill_stop_middleware.py index f0950fd0..3e39423a 100644 --- a/offline-backend-20260512/backend/packages/harness/deerflow/agents/middlewares/skill_stop_middleware.py +++ b/offline-backend-20260512/backend/packages/harness/deerflow/agents/middlewares/skill_stop_middleware.py @@ -78,21 +78,35 @@ class SkillStopMiddleware(AgentMiddleware[SkillStopMiddlewareState]): """Return the matched skill name if this tool call invokes one of the configured target skills, otherwise ``None``. - Matching today is bash-based: the lead agent reaches into a skill by - running ``python3 scripts/agent_orchestration.py "" ""``, - so we only look at ``bash`` calls and extract the skill name from the - argv-style quoted form. + Two invocation patterns are recognized: + + 1. **Structured tool call** — the model emits a tool call whose ``name`` + literally matches one of the configured skill names (e.g. the + multi-agent leader calling + ``agent_orchestration({"agent_name": "...", "task": "..."})``). + This is the natural form most LLMs produce when told to "use a + skill", and it's the form that drives the roundtable dispatch. + + 2. **Bash + argv** — the legacy form where the lead agent reaches into + a skill by running ``python3 scripts/.py "" ""``. + Kept for backward compatibility with skills that use bash for + dispatch. """ name = tool_call.get("name") or "" - skill_name = "" + lowered_targets = {s.lower() for s in self._skill_names} + + # Pattern 1: structured tool call whose tool name IS the skill name. + if name and (name in self._skill_names or name.lower() in lowered_targets): + logger.info("SkillStopMiddleware: matched structured skill call name=%s", name) + return name + + # Pattern 2: bash invocation with argv-style skill name. if name == "bash" and "args" in tool_call: skill_name, _ = extract_name_task(str(tool_call["args"])) - if not skill_name: - return None - lowered_targets = {s.lower() for s in self._skill_names} - if skill_name in self._skill_names or skill_name.lower() in lowered_targets: - logger.info("SkillStopMiddleware: matched skill_name=%s", skill_name) - return skill_name + if skill_name and (skill_name in self._skill_names or skill_name.lower() in lowered_targets): + logger.info("SkillStopMiddleware: matched bash skill call name=%s", skill_name) + return skill_name + return None def _handle_skill_stop(self, request: ToolCallRequest, skill_name: str) -> Command: diff --git a/offline-backend-20260512/backend/packages/harness/deerflow/tools/builtins/__init__.py b/offline-backend-20260512/backend/packages/harness/deerflow/tools/builtins/__init__.py index b371da44..0c4e45af 100644 --- a/offline-backend-20260512/backend/packages/harness/deerflow/tools/builtins/__init__.py +++ b/offline-backend-20260512/backend/packages/harness/deerflow/tools/builtins/__init__.py @@ -1,3 +1,4 @@ +from .agent_orchestration_tool import agent_orchestration_tool from .clarification_tool import ask_clarification_tool from .memory_tool import memory_tool from .present_file_tool import present_file_tool @@ -10,6 +11,7 @@ __all__ = [ "setup_agent", "present_file_tool", "ask_clarification_tool", + "agent_orchestration_tool", "memory_tool", "scheduled_task_tool", "view_image_tool", diff --git a/offline-backend-20260512/backend/packages/harness/deerflow/tools/builtins/agent_orchestration_tool.py b/offline-backend-20260512/backend/packages/harness/deerflow/tools/builtins/agent_orchestration_tool.py new file mode 100644 index 00000000..a9aa5796 --- /dev/null +++ b/offline-backend-20260512/backend/packages/harness/deerflow/tools/builtins/agent_orchestration_tool.py @@ -0,0 +1,46 @@ +"""Placeholder tool that lets the roundtable leader agent dispatch sub-agents. + +Background +---------- +The multi-agent ``/api/multi-agent/run/stream`` endpoint (``app.gateway.routers.multi_agent``) +drives a *leader* agent whose only job is to delegate work to seat-specific sub-agents. +Its SOUL.md tells the model to "use the agent_orchestration skill, passing agent_name +and task". With no real tool registered under that name, the model used to emit +``{"name": "agent_orchestration", "args": {"agent_name": ..., "task": ...}}`` calls +that the runtime rejected with "agent_orchestration is not a valid tool", driving it +into an unproductive retry loop (a single leader call could exceed 10 000 SSE frames). + +This module exposes a no-op tool with the exact signature the leader naturally +emits. The actual dispatch is handled by ``SkillStopMiddleware`` which intercepts +the call, halts the run, and lets ``multi_agent.py`` parse the AIMessage's +``tool_calls`` to extract ``(agent_name, task)`` pairs for the frontend. +""" + +from langchain.tools import tool + + +@tool("agent_orchestration", parse_docstring=True) +def agent_orchestration_tool(agent_name: str, task: str) -> str: + """Delegate a task to a named sub-agent in the multi-agent roundtable. + + Use this tool ONLY when you are the roundtable coordinator and need to + dispatch work to one of the configured seat agents. Each call delegates + ONE task to ONE agent. Emit multiple calls in the same turn to dispatch + several seats in a single round of the discussion. + + The call is intercepted by the runtime — you do not get a real result + back synchronously. The orchestrator will collect every dispatched + ``(agent_name, task)`` pair, run the corresponding sub-agents, then + re-prompt you with a synthesis instruction once they finish. + + Args: + agent_name: Name of the sub-agent to dispatch. MUST exactly match one of + the names listed in your SOUL prompt's ``可调度智能体`` section. + task: The instruction to hand to that sub-agent. Be specific — the + sub-agent only sees this string (plus its own SOUL prompt), not the + broader conversation context. + """ + # Real handling is in SkillStopMiddleware + the multi_agent router. This + # body only runs as a fallback if the middleware is not configured; it + # returns a placeholder so the model does not see a "not a valid tool" error. + return f"dispatched:{agent_name}" diff --git a/offline-backend-20260512/backend/packages/harness/deerflow/tools/tools.py b/offline-backend-20260512/backend/packages/harness/deerflow/tools/tools.py index 9ad2c249..b8e6d516 100644 --- a/offline-backend-20260512/backend/packages/harness/deerflow/tools/tools.py +++ b/offline-backend-20260512/backend/packages/harness/deerflow/tools/tools.py @@ -6,7 +6,7 @@ from deerflow.config import get_app_config from deerflow.config.app_config import AppConfig from deerflow.reflection import resolve_variable from deerflow.sandbox.security import is_host_bash_allowed -from deerflow.tools.builtins import ask_clarification_tool, memory_tool, present_file_tool, scheduled_task_tool, task_tool, view_image_tool +from deerflow.tools.builtins import agent_orchestration_tool, ask_clarification_tool, memory_tool, present_file_tool, scheduled_task_tool, task_tool, view_image_tool from deerflow.tools.builtins.tool_search import reset_deferred_registry logger = logging.getLogger(__name__) @@ -14,6 +14,7 @@ logger = logging.getLogger(__name__) BUILTIN_TOOLS = [ present_file_tool, ask_clarification_tool, + agent_orchestration_tool, ] SUBAGENT_TOOLS = [ diff --git a/situation-overview-web/public/Config.js b/situation-overview-web/public/Config.js deleted file mode 100644 index 365fb888..00000000 --- a/situation-overview-web/public/Config.js +++ /dev/null @@ -1,10 +0,0 @@ -window.environment = { - b1ConsumerUrl: "http://127.0.0.1:8001/consumer", // http://10.106.71.194:8013/ - // b1ConsumerUrl: "http://localhost:8004/consumer", // http://10.106.71.194:8013/ - - aImagePath: "https://present.a.sit.4.cn/gene", // https://present.a.uat.4.cn present.a.sit.4.cn - g6ImgUrl: "/src/assets", - mapUrl: "https://present.a.sit.4.cn/tiles/{z}/{x}/{y}.jpg", - b1NodeServerUrl: "https://ch1.b.uat.4.cn", - b5ReplyUrl:"https://pg.b.uat.4.cn" -}; diff --git a/situation-overview-web/public/moment/locale/ar.js b/situation-overview-web/public/moment/locale/ar.js deleted file mode 100644 index 1549cc15..00000000 --- a/situation-overview-web/public/moment/locale/ar.js +++ /dev/null @@ -1,134 +0,0 @@ -//! moment.js locale configuration - -;(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' - && typeof require === 'function' ? factory(require('../moment')) : - typeof define === 'function' && define.amd ? define(['../moment'], factory) : - factory(global.moment) -}(this, (function (moment) { 'use strict'; - - - var symbolMap = { - '1': '١', - '2': '٢', - '3': '٣', - '4': '٤', - '5': '٥', - '6': '٦', - '7': '٧', - '8': '٨', - '9': '٩', - '0': '٠' - }, numberMap = { - '١': '1', - '٢': '2', - '٣': '3', - '٤': '4', - '٥': '5', - '٦': '6', - '٧': '7', - '٨': '8', - '٩': '9', - '٠': '0' - }, pluralForm = function (n) { - return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; - }, plurals = { - s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], - m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], - h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], - d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], - M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], - y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] - }, pluralize = function (u) { - return function (number, withoutSuffix, string, isFuture) { - var f = pluralForm(number), - str = plurals[u][pluralForm(number)]; - if (f === 2) { - str = str[withoutSuffix ? 0 : 1]; - } - return str.replace(/%d/i, number); - }; - }, months = [ - 'يناير', - 'فبراير', - 'مارس', - 'أبريل', - 'مايو', - 'يونيو', - 'يوليو', - 'أغسطس', - 'سبتمبر', - 'أكتوبر', - 'نوفمبر', - 'ديسمبر' - ]; - - var ar = moment.defineLocale('ar', { - months : months, - monthsShort : months, - weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), - weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), - weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), - weekdaysParseExact : true, - longDateFormat : { - LT : 'HH:mm', - LTS : 'HH:mm:ss', - L : 'D/\u200FM/\u200FYYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY HH:mm', - LLLL : 'dddd D MMMM YYYY HH:mm' - }, - meridiemParse: /ص|م/, - isPM : function (input) { - return 'م' === input; - }, - meridiem : function (hour, minute, isLower) { - if (hour < 12) { - return 'ص'; - } else { - return 'م'; - } - }, - calendar : { - sameDay: '[اليوم عند الساعة] LT', - nextDay: '[غدًا عند الساعة] LT', - nextWeek: 'dddd [عند الساعة] LT', - lastDay: '[أمس عند الساعة] LT', - lastWeek: 'dddd [عند الساعة] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'بعد %s', - past : 'منذ %s', - s : pluralize('s'), - ss : pluralize('s'), - m : pluralize('m'), - mm : pluralize('m'), - h : pluralize('h'), - hh : pluralize('h'), - d : pluralize('d'), - dd : pluralize('d'), - M : pluralize('M'), - MM : pluralize('M'), - y : pluralize('y'), - yy : pluralize('y') - }, - preparse: function (string) { - return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { - return numberMap[match]; - }).replace(/،/g, ','); - }, - postformat: function (string) { - return string.replace(/\d/g, function (match) { - return symbolMap[match]; - }).replace(/,/g, '،'); - }, - week : { - dow : 6, // Saturday is the first day of the week. - doy : 12 // The week that contains Jan 12th is the first week of the year. - } - }); - - return ar; - -}))); diff --git a/situation-overview-web/public/moment/locale/sq.js b/situation-overview-web/public/moment/locale/sq.js deleted file mode 100644 index eb081df0..00000000 --- a/situation-overview-web/public/moment/locale/sq.js +++ /dev/null @@ -1,67 +0,0 @@ -//! moment.js locale configuration - -;(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' - && typeof require === 'function' ? factory(require('../moment')) : - typeof define === 'function' && define.amd ? define(['../moment'], factory) : - factory(global.moment) -}(this, (function (moment) { 'use strict'; - - - var sq = moment.defineLocale('sq', { - months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'), - monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'), - weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'), - weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'), - weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'), - weekdaysParseExact : true, - meridiemParse: /PD|MD/, - isPM: function (input) { - return input.charAt(0) === 'M'; - }, - meridiem : function (hours, minutes, isLower) { - return hours < 12 ? 'PD' : 'MD'; - }, - longDateFormat : { - LT : 'HH:mm', - LTS : 'HH:mm:ss', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY HH:mm', - LLLL : 'dddd, D MMMM YYYY HH:mm' - }, - calendar : { - sameDay : '[Sot në] LT', - nextDay : '[Nesër në] LT', - nextWeek : 'dddd [në] LT', - lastDay : '[Dje në] LT', - lastWeek : 'dddd [e kaluar në] LT', - sameElse : 'L' - }, - relativeTime : { - future : 'në %s', - past : '%s më parë', - s : 'disa sekonda', - ss : '%d sekonda', - m : 'një minutë', - mm : '%d minuta', - h : 'një orë', - hh : '%d orë', - d : 'një ditë', - dd : '%d ditë', - M : 'një muaj', - MM : '%d muaj', - y : 'një vit', - yy : '%d vite' - }, - dayOfMonthOrdinalParse: /\d{1,2}\./, - ordinal : '%d.', - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); - - return sq; - -}))); diff --git a/situation-overview-web/public/moment/locale/tr.js b/situation-overview-web/public/moment/locale/tr.js deleted file mode 100644 index e3fa275a..00000000 --- a/situation-overview-web/public/moment/locale/tr.js +++ /dev/null @@ -1,93 +0,0 @@ - -;(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' - && typeof require === 'function' ? factory(require('../moment')) : - typeof define === 'function' && define.amd ? define(['../moment'], factory) : - factory(global.moment) -}(this, (function (moment) { 'use strict'; - - var suffixes = { - 1: '\'inci', - 5: '\'inci', - 8: '\'inci', - 70: '\'inci', - 80: '\'inci', - 2: '\'nci', - 7: '\'nci', - 20: '\'nci', - 50: '\'nci', - 3: '\'üncü', - 4: '\'üncü', - 100: '\'üncü', - 6: '\'ncı', - 9: '\'uncu', - 10: '\'uncu', - 30: '\'uncu', - 60: '\'ıncı', - 90: '\'ıncı' - }; - - var tr = moment.defineLocale('tr', { - months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'), - monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'), - weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'), - weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'), - weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'), - longDateFormat : { - LT : 'HH:mm', - LTS : 'HH:mm:ss', - L : 'DD.MM.YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY HH:mm', - LLLL : 'dddd, D MMMM YYYY HH:mm' - }, - calendar : { - sameDay : '[bugün saat] LT', - nextDay : '[yarın saat] LT', - nextWeek : '[gelecek] dddd [saat] LT', - lastDay : '[dün] LT', - lastWeek : '[geçen] dddd [saat] LT', - sameElse : 'L' - }, - relativeTime : { - future : '%s sonra', - past : '%s önce', - s : 'birkaç saniye', - ss : '%d saniye', - m : 'bir dakika', - mm : '%d dakika', - h : 'bir saat', - hh : '%d saat', - d : 'bir gün', - dd : '%d gün', - M : 'bir ay', - MM : '%d ay', - y : 'bir yıl', - yy : '%d yıl' - }, - ordinal: function (number, period) { - switch (period) { - case 'd': - case 'D': - case 'Do': - case 'DD': - return number; - default: - if (number === 0) { // special case for zero - return number + '\'ıncı'; - } - var a = number % 10, - b = number % 100 - a, - c = number >= 100 ? 100 : null; - return number + (suffixes[a] || suffixes[b] || suffixes[c]); - } - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 7 // The week that contains Jan 7th is the first week of the year. - } - }); - - return tr; - -}))); diff --git a/situation-overview-web/public/moment/moment-with-locales.min.js b/situation-overview-web/public/moment/moment-with-locales.min.js deleted file mode 100644 index d81e02ca..00000000 --- a/situation-overview-web/public/moment/moment-with-locales.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,a){"object"==typeof exports&&"undefined"!=typeof module?module.exports=a():"function"==typeof define&&define.amd?define(a):e.moment=a()}(this,function(){"use strict";var e,n;function l(){return e.apply(null,arguments)}function _(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function i(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function o(e){return void 0===e}function m(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function u(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function M(e,a){var t,s=[];for(t=0;t>>0,s=0;sTe(e)?(d=e+1,_-Te(e)):(d=e,_),{year:d,dayOfYear:r}}function Ce(e,a,t){var s,n,d=Ne(e.year(),a,t),r=Math.floor((e.dayOfYear()-d-1)/7)+1;return r<1?s=r+Ie(n=e.year()-1,a,t):r>Ie(e.year(),a,t)?(s=r-Ie(e.year(),a,t),n=e.year()+1):(n=e.year(),s=r),{week:s,year:n}}function Ie(e,a,t){var s=Ne(e,a,t),n=Ne(e+1,a,t);return(Te(e)-s+n)/7}C("w",["ww",2],"wo","week"),C("W",["WW",2],"Wo","isoWeek"),O("week","w"),O("isoWeek","W"),E("week",5),E("isoWeek",5),ie("w",B),ie("ww",B,V),ie("W",B),ie("WW",B,V),Me(["w","ww","W","WW"],function(e,a,t,s){a[s.substr(0,1)]=g(e)});function Ue(e,a){return e.slice(a,7).concat(e.slice(0,a))}C("d",0,"do","day"),C("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),C("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),C("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),C("e",0,0,"weekday"),C("E",0,0,"isoWeekday"),O("day","d"),O("weekday","e"),O("isoWeekday","E"),E("day",11),E("weekday",11),E("isoWeekday",11),ie("d",B),ie("e",B),ie("E",B),ie("dd",function(e,a){return a.weekdaysMinRegex(e)}),ie("ddd",function(e,a){return a.weekdaysShortRegex(e)}),ie("dddd",function(e,a){return a.weekdaysRegex(e)}),Me(["dd","ddd","dddd"],function(e,a,t,s){var n=t._locale.weekdaysParse(e,s,t._strict);null!=n?a.d=n:Y(t).invalidWeekday=e}),Me(["d","e","E"],function(e,a,t,s){a[s]=g(e)});var Ge="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Ve="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var Ke="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var Ze=re;var $e=re;var Be=re;function qe(){function e(e,a){return a.length-e.length}var a,t,s,n,d,r=[],_=[],i=[],o=[];for(a=0;a<7;a++)t=c([2e3,1]).day(a),s=this.weekdaysMin(t,""),n=this.weekdaysShort(t,""),d=this.weekdays(t,""),r.push(s),_.push(n),i.push(d),o.push(s),o.push(n),o.push(d);for(r.sort(e),_.sort(e),i.sort(e),o.sort(e),a=0;a<7;a++)_[a]=me(_[a]),i[a]=me(i[a]),o[a]=me(o[a]);this._weekdaysRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+_.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+r.join("|")+")","i")}function Qe(){return this.hours()%12||12}function Xe(e,a){C(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),a)})}function ea(e,a){return a._meridiemParse}C("H",["HH",2],0,"hour"),C("h",["hh",2],0,Qe),C("k",["kk",2],0,function(){return this.hours()||24}),C("hmm",0,0,function(){return""+Qe.apply(this)+F(this.minutes(),2)}),C("hmmss",0,0,function(){return""+Qe.apply(this)+F(this.minutes(),2)+F(this.seconds(),2)}),C("Hmm",0,0,function(){return""+this.hours()+F(this.minutes(),2)}),C("Hmmss",0,0,function(){return""+this.hours()+F(this.minutes(),2)+F(this.seconds(),2)}),Xe("a",!0),Xe("A",!1),O("hour","h"),E("hour",13),ie("a",ea),ie("A",ea),ie("H",B),ie("h",B),ie("k",B),ie("HH",B,V),ie("hh",B,V),ie("kk",B,V),ie("hmm",q),ie("hmmss",Q),ie("Hmm",q),ie("Hmmss",Q),le(["H","HH"],Ye),le(["k","kk"],function(e,a,t){var s=g(e);a[Ye]=24===s?0:s}),le(["a","A"],function(e,a,t){t._isPm=t._locale.isPM(e),t._meridiem=e}),le(["h","hh"],function(e,a,t){a[Ye]=g(e),Y(t).bigHour=!0}),le("hmm",function(e,a,t){var s=e.length-2;a[Ye]=g(e.substr(0,s)),a[ye]=g(e.substr(s)),Y(t).bigHour=!0}),le("hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[Ye]=g(e.substr(0,s)),a[ye]=g(e.substr(s,2)),a[fe]=g(e.substr(n)),Y(t).bigHour=!0}),le("Hmm",function(e,a,t){var s=e.length-2;a[Ye]=g(e.substr(0,s)),a[ye]=g(e.substr(s))}),le("Hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[Ye]=g(e.substr(0,s)),a[ye]=g(e.substr(s,2)),a[fe]=g(e.substr(n))});var aa,ta=Se("Hours",!0),sa={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Oe,monthsShort:Pe,week:{dow:0,doy:6},weekdays:Ge,weekdaysMin:Ke,weekdaysShort:Ve,meridiemParse:/[ap]\.?m?\.?/i},na={},da={};function ra(e){return e?e.toLowerCase().replace("_","-"):e}function _a(e){var a=null;if(!na[e]&&"undefined"!=typeof module&&module&&module.exports)try{a=aa._abbr,require("./locale/"+e),ia(a)}catch(e){}return na[e]}function ia(e,a){var t;return e&&((t=o(a)?ma(e):oa(e,a))?aa=t:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),aa._abbr}function oa(e,a){if(null===a)return delete na[e],null;var t,s=sa;if(a.abbr=e,null!=na[e])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=na[e]._config;else if(null!=a.parentLocale)if(null!=na[a.parentLocale])s=na[a.parentLocale]._config;else{if(null==(t=_a(a.parentLocale)))return da[a.parentLocale]||(da[a.parentLocale]=[]),da[a.parentLocale].push({name:e,config:a}),null;s=t._config}return na[e]=new j(b(s,a)),da[e]&&da[e].forEach(function(e){oa(e.name,e.config)}),ia(e),na[e]}function ma(e){var a;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return aa;if(!_(e)){if(a=_a(e))return a;e=[e]}return function(e){for(var a,t,s,n,d=0;d=a&&r(n,t,!0)>=a-1)break;a--}d++}return aa}(e)}function ua(e){var a,t=e._a;return t&&-2===Y(e).overflow&&(a=t[Le]<0||11je(t[he],t[Le])?ce:t[Ye]<0||24Ie(t,d,r)?Y(e)._overflowWeeks=!0:null!=i?Y(e)._overflowWeekday=!0:(_=Re(t,s,n,d,r),e._a[he]=_.year,e._dayOfYear=_.dayOfYear)}(e),null!=e._dayOfYear&&(d=la(e._a[he],s[he]),(e._dayOfYear>Te(d)||0===e._dayOfYear)&&(Y(e)._overflowDayOfYear=!0),t=Je(d,0,e._dayOfYear),e._a[Le]=t.getUTCMonth(),e._a[ce]=t.getUTCDate()),a=0;a<3&&null==e._a[a];++a)e._a[a]=r[a]=s[a];for(;a<7;a++)e._a[a]=r[a]=null==e._a[a]?2===a?1:0:e._a[a];24===e._a[Ye]&&0===e._a[ye]&&0===e._a[fe]&&0===e._a[ke]&&(e._nextDay=!0,e._a[Ye]=0),e._d=(e._useUTC?Je:function(e,a,t,s,n,d,r){var _;return e<100&&0<=e?(_=new Date(e+400,a,t,s,n,d,r),isFinite(_.getFullYear())&&_.setFullYear(e)):_=new Date(e,a,t,s,n,d,r),_}).apply(null,r),n=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[Ye]=24),e._w&&void 0!==e._w.d&&e._w.d!==n&&(Y(e).weekdayMismatch=!0)}}var ha=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,La=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ca=/Z|[+-]\d\d(?::?\d\d)?/,Ya=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],ya=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],fa=/^\/?Date\((\-?\d+)/i;function ka(e){var a,t,s,n,d,r,_=e._i,i=ha.exec(_)||La.exec(_);if(i){for(Y(e).iso=!0,a=0,t=Ya.length;at.valueOf():t.valueOf()this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Mt.isLocal=function(){return!!this.isValid()&&!this._isUTC},Mt.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Mt.isUtc=Ra,Mt.isUTC=Ra,Mt.zoneAbbr=function(){return this._isUTC?"UTC":""},Mt.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Mt.dates=t("dates accessor is deprecated. Use date instead.",_t),Mt.months=t("months accessor is deprecated. Use month instead",Ae),Mt.years=t("years accessor is deprecated. Use year instead",ve),Mt.zone=t("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,a){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,a),this):-this.utcOffset()}),Mt.isDSTShifted=t("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var e={};if(k(e,this),(e=va(e))._a){var a=e._isUTC?c(e._a):Ha(e._a);this._isDSTShifted=this.isValid()&&0>>0,s=0;sSe(e)?(r=e+1,o-Se(e)):(r=e,o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(Se(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),C("week","w"),C("isoWeek","W"),F("week",5),F("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=D(e)});function je(e,t){return e.slice(t,7).concat(e.slice(0,t))}I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),C("day","d"),C("weekday","e"),C("isoWeekday","E"),F("day",11),F("weekday",11),F("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=D(e)});var Ze="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var $e="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var qe=ae;var Je=ae;var Be=ae;function Qe(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=he(o[t]),u[t]=he(u[t]),l[t]=he(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Xe(){return this.hours()%12||12}function Ke(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function et(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Xe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)+L(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+L(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+L(this.minutes(),2)+L(this.seconds(),2)}),Ke("a",!0),Ke("A",!1),C("hour","h"),F("hour",13),ue("a",et),ue("A",et),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=D(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=D(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i))});var tt,nt=Te("Hours",!0),st={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ce,monthsShort:He,week:{dow:0,doy:6},weekdays:Ze,weekdaysMin:$e,weekdaysShort:ze,meridiemParse:/[ap]\.?m?\.?/i},it={},rt={};function at(e){return e?e.toLowerCase().replace("_","-"):e}function ot(e){var t=null;if(!it[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=tt._abbr,require("./locale/"+e),ut(t)}catch(e){}return it[e]}function ut(e,t){var n;return e&&((n=l(t)?ht(e):lt(e,t))?tt=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),tt._abbr}function lt(e,t){if(null===t)return delete it[e],null;var n,s=st;if(t.abbr=e,null!=it[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=it[e]._config;else if(null!=t.parentLocale)if(null!=it[t.parentLocale])s=it[t.parentLocale]._config;else{if(null==(n=ot(t.parentLocale)))return rt[t.parentLocale]||(rt[t.parentLocale]=[]),rt[t.parentLocale].push({name:e,config:t}),null;s=n._config}return it[e]=new P(x(s,t)),rt[e]&&rt[e].forEach(function(e){lt(e.name,e.config)}),ut(e),it[e]}function ht(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return tt;if(!o(e)){if(t=ot(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r=t&&a(i,n,!0)>=t-1)break;t--}r++}return tt}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11Pe(n[me],n[_e])?ye:n[ge]<0||24Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ct(e._a[me],s[me]),(e._dayOfYear>Se(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[ve]&&0===e._a[pe]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o;return e<100&&0<=e?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var mt=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_t=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,yt=/Z|[+-]\d\d(?::?\d\d)?/,gt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],vt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function wt(e){var t,n,s,i,r,a,o=e._i,u=mt.exec(o)||_t.exec(o);if(u){for(g(e).iso=!0,t=0,n=gt.length;tn.valueOf():n.valueOf()this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},mn.isLocal=function(){return!!this.isValid()&&!this._isUTC},mn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},mn.isUtc=Et,mn.isUTC=Et,mn.zoneAbbr=function(){return this._isUTC?"UTC":""},mn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},mn.dates=n("dates accessor is deprecated. Use date instead.",un),mn.months=n("months accessor is deprecated. Use month instead",Ue),mn.years=n("years accessor is deprecated. Use year instead",Oe),mn.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),mn.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Ot(e))._a){var t=e._isUTC?y(e._a):bt(e._a);this._isDSTShifted=this.isValid()&&0>>0,s=0;sTe(e)?(d=e+1,_-Te(e)):(d=e,_),{year:d,dayOfYear:r}}function Ce(e,a,t){var s,n,d=Ne(e.year(),a,t),r=Math.floor((e.dayOfYear()-d-1)/7)+1;return r<1?s=r+Ie(n=e.year()-1,a,t):r>Ie(e.year(),a,t)?(s=r-Ie(e.year(),a,t),n=e.year()+1):(n=e.year(),s=r),{week:s,year:n}}function Ie(e,a,t){var s=Ne(e,a,t),n=Ne(e+1,a,t);return(Te(e)-s+n)/7}C("w",["ww",2],"wo","week"),C("W",["WW",2],"Wo","isoWeek"),O("week","w"),O("isoWeek","W"),E("week",5),E("isoWeek",5),ie("w",B),ie("ww",B,V),ie("W",B),ie("WW",B,V),Me(["w","ww","W","WW"],function(e,a,t,s){a[s.substr(0,1)]=g(e)});function Ue(e,a){return e.slice(a,7).concat(e.slice(0,a))}C("d",0,"do","day"),C("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),C("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),C("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),C("e",0,0,"weekday"),C("E",0,0,"isoWeekday"),O("day","d"),O("weekday","e"),O("isoWeekday","E"),E("day",11),E("weekday",11),E("isoWeekday",11),ie("d",B),ie("e",B),ie("E",B),ie("dd",function(e,a){return a.weekdaysMinRegex(e)}),ie("ddd",function(e,a){return a.weekdaysShortRegex(e)}),ie("dddd",function(e,a){return a.weekdaysRegex(e)}),Me(["dd","ddd","dddd"],function(e,a,t,s){var n=t._locale.weekdaysParse(e,s,t._strict);null!=n?a.d=n:Y(t).invalidWeekday=e}),Me(["d","e","E"],function(e,a,t,s){a[s]=g(e)});var Ge="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Ve="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var Ke="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var Ze=re;var $e=re;var Be=re;function qe(){function e(e,a){return a.length-e.length}var a,t,s,n,d,r=[],_=[],i=[],o=[];for(a=0;a<7;a++)t=c([2e3,1]).day(a),s=this.weekdaysMin(t,""),n=this.weekdaysShort(t,""),d=this.weekdays(t,""),r.push(s),_.push(n),i.push(d),o.push(s),o.push(n),o.push(d);for(r.sort(e),_.sort(e),i.sort(e),o.sort(e),a=0;a<7;a++)_[a]=me(_[a]),i[a]=me(i[a]),o[a]=me(o[a]);this._weekdaysRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+_.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+r.join("|")+")","i")}function Qe(){return this.hours()%12||12}function Xe(e,a){C(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),a)})}function ea(e,a){return a._meridiemParse}C("H",["HH",2],0,"hour"),C("h",["hh",2],0,Qe),C("k",["kk",2],0,function(){return this.hours()||24}),C("hmm",0,0,function(){return""+Qe.apply(this)+F(this.minutes(),2)}),C("hmmss",0,0,function(){return""+Qe.apply(this)+F(this.minutes(),2)+F(this.seconds(),2)}),C("Hmm",0,0,function(){return""+this.hours()+F(this.minutes(),2)}),C("Hmmss",0,0,function(){return""+this.hours()+F(this.minutes(),2)+F(this.seconds(),2)}),Xe("a",!0),Xe("A",!1),O("hour","h"),E("hour",13),ie("a",ea),ie("A",ea),ie("H",B),ie("h",B),ie("k",B),ie("HH",B,V),ie("hh",B,V),ie("kk",B,V),ie("hmm",q),ie("hmmss",Q),ie("Hmm",q),ie("Hmmss",Q),le(["H","HH"],Ye),le(["k","kk"],function(e,a,t){var s=g(e);a[Ye]=24===s?0:s}),le(["a","A"],function(e,a,t){t._isPm=t._locale.isPM(e),t._meridiem=e}),le(["h","hh"],function(e,a,t){a[Ye]=g(e),Y(t).bigHour=!0}),le("hmm",function(e,a,t){var s=e.length-2;a[Ye]=g(e.substr(0,s)),a[ye]=g(e.substr(s)),Y(t).bigHour=!0}),le("hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[Ye]=g(e.substr(0,s)),a[ye]=g(e.substr(s,2)),a[fe]=g(e.substr(n)),Y(t).bigHour=!0}),le("Hmm",function(e,a,t){var s=e.length-2;a[Ye]=g(e.substr(0,s)),a[ye]=g(e.substr(s))}),le("Hmmss",function(e,a,t){var s=e.length-4,n=e.length-2;a[Ye]=g(e.substr(0,s)),a[ye]=g(e.substr(s,2)),a[fe]=g(e.substr(n))});var aa,ta=Se("Hours",!0),sa={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Oe,monthsShort:Pe,week:{dow:0,doy:6},weekdays:Ge,weekdaysMin:Ke,weekdaysShort:Ve,meridiemParse:/[ap]\.?m?\.?/i},na={},da={};function ra(e){return e?e.toLowerCase().replace("_","-"):e}function _a(e){var a=null;if(!na[e]&&"undefined"!=typeof module&&module&&module.exports)try{a=aa._abbr,require("./locale/"+e),ia(a)}catch(e){}return na[e]}function ia(e,a){var t;return e&&((t=o(a)?ma(e):oa(e,a))?aa=t:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),aa._abbr}function oa(e,a){if(null===a)return delete na[e],null;var t,s=sa;if(a.abbr=e,null!=na[e])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=na[e]._config;else if(null!=a.parentLocale)if(null!=na[a.parentLocale])s=na[a.parentLocale]._config;else{if(null==(t=_a(a.parentLocale)))return da[a.parentLocale]||(da[a.parentLocale]=[]),da[a.parentLocale].push({name:e,config:a}),null;s=t._config}return na[e]=new j(b(s,a)),da[e]&&da[e].forEach(function(e){oa(e.name,e.config)}),ia(e),na[e]}function ma(e){var a;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return aa;if(!_(e)){if(a=_a(e))return a;e=[e]}return function(e){for(var a,t,s,n,d=0;d=a&&r(n,t,!0)>=a-1)break;a--}d++}return aa}(e)}function ua(e){var a,t=e._a;return t&&-2===Y(e).overflow&&(a=t[Le]<0||11je(t[he],t[Le])?ce:t[Ye]<0||24Ie(t,d,r)?Y(e)._overflowWeeks=!0:null!=i?Y(e)._overflowWeekday=!0:(_=Re(t,s,n,d,r),e._a[he]=_.year,e._dayOfYear=_.dayOfYear)}(e),null!=e._dayOfYear&&(d=la(e._a[he],s[he]),(e._dayOfYear>Te(d)||0===e._dayOfYear)&&(Y(e)._overflowDayOfYear=!0),t=Je(d,0,e._dayOfYear),e._a[Le]=t.getUTCMonth(),e._a[ce]=t.getUTCDate()),a=0;a<3&&null==e._a[a];++a)e._a[a]=r[a]=s[a];for(;a<7;a++)e._a[a]=r[a]=null==e._a[a]?2===a?1:0:e._a[a];24===e._a[Ye]&&0===e._a[ye]&&0===e._a[fe]&&0===e._a[ke]&&(e._nextDay=!0,e._a[Ye]=0),e._d=(e._useUTC?Je:function(e,a,t,s,n,d,r){var _;return e<100&&0<=e?(_=new Date(e+400,a,t,s,n,d,r),isFinite(_.getFullYear())&&_.setFullYear(e)):_=new Date(e,a,t,s,n,d,r),_}).apply(null,r),n=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[Ye]=24),e._w&&void 0!==e._w.d&&e._w.d!==n&&(Y(e).weekdayMismatch=!0)}}var ha=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,La=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ca=/Z|[+-]\d\d(?::?\d\d)?/,Ya=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],ya=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],fa=/^\/?Date\((\-?\d+)/i;function ka(e){var a,t,s,n,d,r,_=e._i,i=ha.exec(_)||La.exec(_);if(i){for(Y(e).iso=!0,a=0,t=Ya.length;at.valueOf():t.valueOf()this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Mt.isLocal=function(){return!!this.isValid()&&!this._isUTC},Mt.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Mt.isUtc=Ra,Mt.isUTC=Ra,Mt.zoneAbbr=function(){return this._isUTC?"UTC":""},Mt.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Mt.dates=t("dates accessor is deprecated. Use date instead.",_t),Mt.months=t("months accessor is deprecated. Use month instead",Ae),Mt.years=t("years accessor is deprecated. Use year instead",ve),Mt.zone=t("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,a){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,a),this):-this.utcOffset()}),Mt.isDSTShifted=t("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var e={};if(k(e,this),(e=va(e))._a){var a=e._isUTC?c(e._a):Ha(e._a);this._isDSTShifted=this.isValid()&&0.vis-custom-time-marker{background-color:inherit;color:#fff;font-size:12px;white-space:nowrap;padding:3px 5px;top:0;cursor:auto;z-index:inherit}.vis-current-time{background-color:#ff7f6e;width:2px;z-index:1;pointer-events:none}.vis-rolling-mode-btn{height:40px;width:40px;position:absolute;top:7px;right:20px;border-radius:50%;font-size:28px;cursor:pointer;opacity:.8;color:#fff;font-weight:700;text-align:center;background:#3876c2}.vis-rolling-mode-btn:before{content:"\26F6"}.vis-rolling-mode-btn:hover{opacity:1}.vis-panel{position:absolute;padding:0;margin:0;box-sizing:border-box}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-top-style:solid;border-bottom-style:solid;overflow:hidden}.vis-left.vis-panel.vis-vertical-scroll,.vis-right.vis-panel.vis-vertical-scroll{height:100%;overflow-x:hidden;overflow-y:scroll}.vis-left.vis-panel.vis-vertical-scroll{direction:rtl}.vis-left.vis-panel.vis-vertical-scroll .vis-content,.vis-right.vis-panel.vis-vertical-scroll{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll .vis-content{direction:rtl}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-background{overflow:hidden}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{position:absolute;width:100%;height:1px;box-shadow:0 0 10px rgba(0,0,0,.8)}.vis-panel .vis-shadow.vis-top{top:-1px;left:0}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}.vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}.vis-timeline{position:relative;border:1px solid #bfbfbf;overflow:hidden;padding:0;margin:0;box-sizing:border-box}.vis-loading-screen{width:100%;height:100%;position:absolute;top:0;left:0}.vis [class*=span]{min-height:0;width:auto}.vis-item{position:absolute;color:#1a1a1a;border-color:#97b0f8;border-width:1px;background-color:#d5ddf6;display:inline-block;z-index:1}.vis-item.vis-selected{border-color:#ffc200;background-color:#fff785;z-index:2}.vis-editable.vis-selected{cursor:move}.vis-item.vis-point.vis-selected{background-color:#fff785}.vis-item.vis-box{text-align:center;border-style:solid;border-radius:2px}.vis-item.vis-point{background:none}.vis-item.vis-dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}.vis-item.vis-range{border-style:solid;border-radius:2px;box-sizing:border-box}.vis-item.vis-background{border:none;background-color:rgba(213,221,246,.4);box-sizing:border-box;padding:0;margin:0}.vis-item .vis-item-overflow{position:relative;width:100%;height:100%;padding:0;margin:0;overflow:hidden}.vis-item-visible-frame{white-space:nowrap}.vis-item.vis-range .vis-item-content{position:relative;display:inline-block}.vis-item.vis-background .vis-item-content{position:absolute;display:inline-block}.vis-item.vis-line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis-item .vis-item-content{white-space:nowrap;box-sizing:border-box;padding:5px}.vis-item .vis-onUpdateTime-tooltip{position:absolute;background:#4f81bd;color:#fff;width:200px;text-align:center;white-space:nowrap;padding:5px;border-radius:1px;transition:.4s;-o-transition:.4s;-moz-transition:.4s;-webkit-transition:.4s}.vis-item .vis-delete,.vis-item .vis-delete-rtl{position:absolute;top:0;width:24px;height:24px;box-sizing:border-box;padding:0 5px;cursor:pointer;-webkit-transition:background .2s linear;-moz-transition:background .2s linear;-ms-transition:background .2s linear;-o-transition:background .2s linear;transition:background .2s linear}.vis-item .vis-delete{right:-24px}.vis-item .vis-delete-rtl{left:-24px}.vis-item .vis-delete-rtl:after,.vis-item .vis-delete:after{content:"\00D7";color:red;font-family:arial,sans-serif;font-size:22px;font-weight:700;-webkit-transition:color .2s linear;-moz-transition:color .2s linear;-ms-transition:color .2s linear;-o-transition:color .2s linear;transition:color .2s linear}.vis-item .vis-delete-rtl:hover,.vis-item .vis-delete:hover{background:red}.vis-item .vis-delete-rtl:hover:after,.vis-item .vis-delete:hover:after{color:#fff}.vis-item .vis-drag-center{position:absolute;width:100%;height:100%;top:0;left:0;cursor:move}.vis-item.vis-range .vis-drag-left{left:-4px;cursor:w-resize}.vis-item.vis-range .vis-drag-left,.vis-item.vis-range .vis-drag-right{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0}.vis-item.vis-range .vis-drag-right{right:-4px;cursor:e-resize}.vis-range.vis-item.vis-readonly .vis-drag-left,.vis-range.vis-item.vis-readonly .vis-drag-right{cursor:auto}.vis-item.vis-cluster{vertical-align:center;text-align:center;border-style:solid;border-radius:2px}.vis-item.vis-cluster-line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis-item.vis-cluster-dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}div.vis-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;font-family:verdana;font-size:14px;color:#000;background-color:#f5f4ed;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid #808074;box-shadow:3px 3px 10px rgba(0,0,0,.2);pointer-events:none;z-index:5}.vis-itemset{position:relative;padding:0;margin:0;box-sizing:border-box}.vis-itemset .vis-background,.vis-itemset .vis-foreground{position:absolute;width:100%;height:100%;overflow:visible}.vis-axis{position:absolute;width:100%;height:0;left:0;z-index:1}.vis-foreground .vis-group{position:relative;box-sizing:border-box;border-bottom:1px solid #bfbfbf}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-nesting-group{cursor:pointer}.vis-label.vis-nested-group.vis-group-level-unknown-but-gte1{background:#f5f5f5}.vis-label.vis-nested-group.vis-group-level-0{background-color:#fff}.vis-ltr .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-left:0}.vis-rtl .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-right:0}.vis-label.vis-nested-group.vis-group-level-1{background-color:rgba(0,0,0,.05)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-left:15px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-right:15px}.vis-label.vis-nested-group.vis-group-level-2{background-color:rgba(0,0,0,.1)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-left:30px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-right:30px}.vis-label.vis-nested-group.vis-group-level-3{background-color:rgba(0,0,0,.15)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-left:45px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-right:45px}.vis-label.vis-nested-group.vis-group-level-4{background-color:rgba(0,0,0,.2)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-left:60px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-right:60px}.vis-label.vis-nested-group.vis-group-level-5{background-color:rgba(0,0,0,.25)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-left:75px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-right:75px}.vis-label.vis-nested-group.vis-group-level-6{background-color:rgba(0,0,0,.3)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-left:90px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-right:90px}.vis-label.vis-nested-group.vis-group-level-7{background-color:rgba(0,0,0,.35)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-left:105px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-right:105px}.vis-label.vis-nested-group.vis-group-level-8{background-color:rgba(0,0,0,.4)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-left:120px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-right:120px}.vis-label.vis-nested-group.vis-group-level-9{background-color:rgba(0,0,0,.45)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-left:135px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-right:135px}.vis-label.vis-nested-group{background-color:rgba(0,0,0,.5)}.vis-ltr .vis-label.vis-nested-group .vis-inner{padding-left:150px}.vis-rtl .vis-label.vis-nested-group .vis-inner{padding-right:150px}.vis-group-level-unknown-but-gte1{border:1px solid red}.vis-label.vis-nesting-group:before{display:inline-block;width:15px}.vis-label.vis-nesting-group.expanded:before{content:"\25BC"}.vis-label.vis-nesting-group.collapsed:before{content:"\25B6"}.vis-rtl .vis-label.vis-nesting-group.collapsed:before{content:"\25C0"}.vis-ltr .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-left:15px}.vis-rtl .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-right:15px}.vis-overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-labelset{overflow:hidden}.vis-labelset,.vis-labelset .vis-label{position:relative;box-sizing:border-box}.vis-labelset .vis-label{left:0;top:0;width:100%;color:#4d4d4d;border-bottom:1px solid #bfbfbf}.vis-labelset .vis-label.draggable{cursor:pointer}.vis-group-is-dragging{background:rgba(0,0,0,.1)}.vis-labelset .vis-label:last-child{border-bottom:none}.vis-labelset .vis-label .vis-inner{display:inline-block;padding:5px}.vis-labelset .vis-label .vis-inner.vis-hidden{padding:0}div.vis-configuration{position:relative;display:block;float:left;font-size:12px}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration-wrapper:after{clear:both;content:"";display:block}div.vis-configuration.vis-config-option-container{display:block;width:495px;background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;margin-top:20px;left:10px;padding-left:5px}div.vis-configuration.vis-config-button{display:block;width:495px;height:25px;vertical-align:middle;line-height:25px;background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;margin-top:20px;left:10px;padding-left:5px;cursor:pointer;margin-bottom:30px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;width:495px;height:25px;vertical-align:middle;line-height:25px}div.vis-configuration.vis-config-item.vis-config-s2{left:10px;background-color:#f7f8fa;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s3{left:20px;background-color:#e4e9f0;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s4{left:30px;background-color:#cfd8e6;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{width:120px;height:25px;line-height:25px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:100px}div.vis-configuration.vis-config-colorBlock{top:1px;width:30px;height:19px;border:1px solid #444;border-radius:2px;padding:0;margin:0;cursor:pointer}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{position:relative;top:-5px;width:60px;padding:1px;margin:0;pointer-events:none}input.vis-configuration.vis-config-range{-webkit-appearance:none;border:0 solid #fff;background-color:transparent;width:300px;height:20px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{width:300px;height:5px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(180deg,#dedede 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#dedede",endColorstr="#c8c8c8",GradientType=0);border:1px solid #999;box-shadow:0 0 3px 0 #aaa;border-radius:3px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;border:1px solid #14334b;height:17px;width:17px;border-radius:50%;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2,#385380);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(180deg,#3876c2 0,#385380);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#3876c2",endColorstr="#385380",GradientType=0);box-shadow:0 0 1px 0 #111927;margin-top:-7px}input.vis-configuration.vis-config-range:focus{outline:none}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(180deg,#9d9d9d 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#9d9d9d",endColorstr="#c8c8c8",GradientType=0)}input.vis-configuration.vis-config-range::-moz-range-track{width:300px;height:10px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(180deg,#dedede 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#dedede",endColorstr="#c8c8c8",GradientType=0);border:1px solid #999;box-shadow:0 0 3px 0 #aaa;border-radius:3px}input.vis-configuration.vis-config-range::-moz-range-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:-moz-focusring{outline:1px solid #fff;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{width:300px;height:5px;background:transparent;border-color:transparent;border-width:6px 0;color:transparent}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{position:absolute;background:rgba(57,76,89,.85);border:2px solid #f2faff;line-height:30px;height:30px;width:150px;text-align:center;color:#fff;font-size:14px;border-radius:4px;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out}.vis-configuration-popup:after,.vis-configuration-popup:before{left:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.vis-configuration-popup:after{border-color:rgba(136,183,213,0) rgba(136,183,213,0) rgba(136,183,213,0) rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0) rgba(194,225,245,0) rgba(194,225,245,0) #f2faff;border-width:12px;margin-top:-12px}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-horizontal{position:absolute;width:100%;height:0;border-bottom:1px solid}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-minor{border-color:#e5e5e5}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-major{border-color:#bfbfbf}.vis-data-axis .vis-y-axis.vis-major{width:100%;position:absolute;color:#4d4d4d;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-major.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-minor{position:absolute;width:100%;color:#bebebe;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-minor.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title{position:absolute;color:#4d4d4d;white-space:nowrap;bottom:20px;text-align:center}.vis-data-axis .vis-y-axis.vis-title.vis-measure{padding:0;margin:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title.vis-left{bottom:0;-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.vis-data-axis .vis-y-axis.vis-title.vis-right{bottom:0;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-ms-transform-origin:right bottom;-o-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.vis-legend{background-color:rgba(247,252,255,.65);padding:5px;border:1px solid #b3b3b3;box-shadow:2px 2px 10px hsla(0,0%,60.4%,.55)}.vis-legend-text{white-space:nowrap;display:inline-block} -/*# sourceMappingURL=vis-timeline-graph2d.min.css.map */ \ No newline at end of file diff --git a/situation-overview-web/public/vis/timeline/vis-timeline-graph2d.min.js b/situation-overview-web/public/vis/timeline/vis-timeline-graph2d.min.js deleted file mode 100644 index fff97195..00000000 --- a/situation-overview-web/public/vis/timeline/vis-timeline-graph2d.min.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * vis-timeline and vis-graph2d - * https://visjs.github.io/vis-timeline/ - * - * Create a fully customizable, interactive timeline with items and ranges. - * - * @version 7.5.1 - * @date 2022-03-01T18:26:09.239Z - * - * @copyright (c) 2011-2017 Almende B.V, http://almende.com - * @copyright (c) 2017-2019 visjs contributors, https://github.com/visjs - * - * @license - * vis.js is dual licensed under both - * - * 1. The Apache 2.0 License - * http://www.apache.org/licenses/LICENSE-2.0 - * - * and - * - * 2. The MIT License - * http://opensource.org/licenses/MIT - * - * vis.js may be distributed under either license. - */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).vis=t.vis||{})}(this,(function(t){var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(t){throw new Error('Could not dynamically require "'+t+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var o={exports:{}};!function(t,e){t.exports=function(){var e,i;function o(){return e.apply(null,arguments)}function r(t){e=t}function s(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function a(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function l(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function h(t){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(t).length;var e;for(e in t)if(l(t,e))return!1;return!0}function u(t){return void 0===t}function d(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function c(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function p(t,e){var i,n=[];for(i=0;i>>0;for(e=0;e0)for(i=0;i<_.length;i++)u(o=e[n=_[i]])||(t[n]=o);return t}function x(t){k(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===w&&(w=!0,o.updateOffset(this),w=!1)}function D(t){return t instanceof x||null!=t&&null!=t._isAMomentObject}function S(t){!1===o.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function C(t,e){var i=!0;return f((function(){if(null!=o.deprecationHandler&&o.deprecationHandler(null,t),i){var n,r,s,a=[];for(r=0;r=0?i?"+":"":"-")+Math.pow(10,Math.max(0,o)).toString().substr(1)+n}var R=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Y=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,j={},H={};function z(t,e,i,n){var o=n;"string"==typeof n&&(o=function(){return this[n]()}),t&&(H[t]=o),e&&(H[e[0]]=function(){return F(o.apply(this,arguments),e[1],e[2])}),i&&(H[i]=function(){return this.localeData().ordinal(o.apply(this,arguments),t)})}function G(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function B(t){var e,i,n=t.match(R);for(e=0,i=n.length;e=0&&Y.test(t);)t=t.replace(Y,n),Y.lastIndex=0,i-=1;return t}var U={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function X(t){var e=this._longDateFormat[t],i=this._longDateFormat[t.toUpperCase()];return e||!i?e:(this._longDateFormat[t]=i.match(R).map((function(t){return"MMMM"===t||"MM"===t||"DD"===t||"dddd"===t?t.slice(1):t})).join(""),this._longDateFormat[t])}var q="Invalid date";function Z(){return this._invalidDate}var $="%d",K=/\d{1,2}/;function J(t){return this._ordinal.replace("%d",t)}var Q={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function tt(t,e,i,n){var o=this._relativeTime[i];return E(o)?o(t,e,i,n):o.replace(/%d/i,t)}function et(t,e){var i=this._relativeTime[t>0?"future":"past"];return E(i)?i(e):i.replace(/%s/i,e)}var it={};function nt(t,e){var i=t.toLowerCase();it[i]=it[i+"s"]=it[e]=t}function ot(t){return"string"==typeof t?it[t]||it[t.toLowerCase()]:void 0}function rt(t){var e,i,n={};for(i in t)l(t,i)&&(e=ot(i))&&(n[e]=t[i]);return n}var st={};function at(t,e){st[t]=e}function lt(t){var e,i=[];for(e in t)l(t,e)&&i.push({unit:e,priority:st[e]});return i.sort((function(t,e){return t.priority-e.priority})),i}function ht(t){return t%4==0&&t%100!=0||t%400==0}function ut(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function dt(t){var e=+t,i=0;return 0!==e&&isFinite(e)&&(i=ut(e)),i}function ct(t,e){return function(i){return null!=i?(ft(this,t,i),o.updateOffset(this,e),this):pt(this,t)}}function pt(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function ft(t,e,i){t.isValid()&&!isNaN(i)&&("FullYear"===e&&ht(t.year())&&1===t.month()&&29===t.date()?(i=dt(i),t._d["set"+(t._isUTC?"UTC":"")+e](i,t.month(),te(i,t.month()))):t._d["set"+(t._isUTC?"UTC":"")+e](i))}function mt(t){return E(this[t=ot(t)])?this[t]():this}function vt(t,e){if("object"==typeof t){var i,n=lt(t=rt(t));for(i=0;i68?1900:2e3)};var ge=ct("FullYear",!0);function ye(){return ht(this.year())}function be(t,e,i,n,o,r,s){var a;return t<100&&t>=0?(a=new Date(t+400,e,i,n,o,r,s),isFinite(a.getFullYear())&&a.setFullYear(t)):a=new Date(t,e,i,n,o,r,s),a}function _e(t){var e,i;return t<100&&t>=0?((i=Array.prototype.slice.call(arguments))[0]=t+400,e=new Date(Date.UTC.apply(null,i)),isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t)):e=new Date(Date.UTC.apply(null,arguments)),e}function we(t,e,i){var n=7+e-i;return-(7+_e(t,0,n).getUTCDay()-e)%7+n-1}function ke(t,e,i,n,o){var r,s,a=1+7*(e-1)+(7+i-n)%7+we(t,n,o);return a<=0?s=ve(r=t-1)+a:a>ve(t)?(r=t+1,s=a-ve(t)):(r=t,s=a),{year:r,dayOfYear:s}}function xe(t,e,i){var n,o,r=we(t.year(),e,i),s=Math.floor((t.dayOfYear()-r-1)/7)+1;return s<1?n=s+De(o=t.year()-1,e,i):s>De(t.year(),e,i)?(n=s-De(t.year(),e,i),o=t.year()+1):(o=t.year(),n=s),{week:n,year:o}}function De(t,e,i){var n=we(t,e,i),o=we(t+1,e,i);return(ve(t)-n+o)/7}function Se(t){return xe(t,this._week.dow,this._week.doy).week}z("w",["ww",2],"wo","week"),z("W",["WW",2],"Wo","isoWeek"),nt("week","w"),nt("isoWeek","W"),at("week",5),at("isoWeek",5),Nt("w",xt),Nt("ww",xt,bt),Nt("W",xt),Nt("WW",xt,bt),zt(["w","ww","W","WW"],(function(t,e,i,n){e[n.substr(0,1)]=dt(t)}));var Ce={dow:0,doy:6};function Te(){return this._week.dow}function Me(){return this._week.doy}function Oe(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")}function Ee(t){var e=xe(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")}function Pe(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}function Ae(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function Ie(t,e){return t.slice(e,7).concat(t.slice(0,e))}z("d",0,"do","day"),z("dd",0,0,(function(t){return this.localeData().weekdaysMin(this,t)})),z("ddd",0,0,(function(t){return this.localeData().weekdaysShort(this,t)})),z("dddd",0,0,(function(t){return this.localeData().weekdays(this,t)})),z("e",0,0,"weekday"),z("E",0,0,"isoWeekday"),nt("day","d"),nt("weekday","e"),nt("isoWeekday","E"),at("day",11),at("weekday",11),at("isoWeekday",11),Nt("d",xt),Nt("e",xt),Nt("E",xt),Nt("dd",(function(t,e){return e.weekdaysMinRegex(t)})),Nt("ddd",(function(t,e){return e.weekdaysShortRegex(t)})),Nt("dddd",(function(t,e){return e.weekdaysRegex(t)})),zt(["dd","ddd","dddd"],(function(t,e,i,n){var o=i._locale.weekdaysParse(t,n,i._strict);null!=o?e.d=o:g(i).invalidWeekday=t})),zt(["d","e","E"],(function(t,e,i,n){e[n]=dt(t)}));var Le="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Ne="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Fe="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Re=Lt,Ye=Lt,je=Lt;function He(t,e){var i=s(this._weekdays)?this._weekdays:this._weekdays[t&&!0!==t&&this._weekdays.isFormat.test(e)?"format":"standalone"];return!0===t?Ie(i,this._week.dow):t?i[t.day()]:i}function ze(t){return!0===t?Ie(this._weekdaysShort,this._week.dow):t?this._weekdaysShort[t.day()]:this._weekdaysShort}function Ge(t){return!0===t?Ie(this._weekdaysMin,this._week.dow):t?this._weekdaysMin[t.day()]:this._weekdaysMin}function Be(t,e,i){var n,o,r,s=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],n=0;n<7;++n)r=m([2e3,1]).day(n),this._minWeekdaysParse[n]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[n]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[n]=this.weekdays(r,"").toLocaleLowerCase();return i?"dddd"===e?-1!==(o=Bt.call(this._weekdaysParse,s))?o:null:"ddd"===e?-1!==(o=Bt.call(this._shortWeekdaysParse,s))?o:null:-1!==(o=Bt.call(this._minWeekdaysParse,s))?o:null:"dddd"===e?-1!==(o=Bt.call(this._weekdaysParse,s))||-1!==(o=Bt.call(this._shortWeekdaysParse,s))||-1!==(o=Bt.call(this._minWeekdaysParse,s))?o:null:"ddd"===e?-1!==(o=Bt.call(this._shortWeekdaysParse,s))||-1!==(o=Bt.call(this._weekdaysParse,s))||-1!==(o=Bt.call(this._minWeekdaysParse,s))?o:null:-1!==(o=Bt.call(this._minWeekdaysParse,s))||-1!==(o=Bt.call(this._weekdaysParse,s))||-1!==(o=Bt.call(this._shortWeekdaysParse,s))?o:null}function We(t,e,i){var n,o,r;if(this._weekdaysParseExact)return Be.call(this,t,e,i);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),n=0;n<7;n++){if(o=m([2e3,1]).day(n),i&&!this._fullWeekdaysParse[n]&&(this._fullWeekdaysParse[n]=new RegExp("^"+this.weekdays(o,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[n]=new RegExp("^"+this.weekdaysShort(o,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[n]=new RegExp("^"+this.weekdaysMin(o,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[n]||(r="^"+this.weekdays(o,"")+"|^"+this.weekdaysShort(o,"")+"|^"+this.weekdaysMin(o,""),this._weekdaysParse[n]=new RegExp(r.replace(".",""),"i")),i&&"dddd"===e&&this._fullWeekdaysParse[n].test(t))return n;if(i&&"ddd"===e&&this._shortWeekdaysParse[n].test(t))return n;if(i&&"dd"===e&&this._minWeekdaysParse[n].test(t))return n;if(!i&&this._weekdaysParse[n].test(t))return n}}function Ve(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=Pe(t,this.localeData()),this.add(t-e,"d")):e}function Ue(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")}function Xe(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=Ae(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7}function qe(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ke.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(l(this,"_weekdaysRegex")||(this._weekdaysRegex=Re),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)}function Ze(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ke.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(l(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Ye),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function $e(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ke.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(l(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=je),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Ke(){function t(t,e){return e.length-t.length}var e,i,n,o,r,s=[],a=[],l=[],h=[];for(e=0;e<7;e++)i=m([2e3,1]).day(e),n=Yt(this.weekdaysMin(i,"")),o=Yt(this.weekdaysShort(i,"")),r=Yt(this.weekdays(i,"")),s.push(n),a.push(o),l.push(r),h.push(n),h.push(o),h.push(r);s.sort(t),a.sort(t),l.sort(t),h.sort(t),this._weekdaysRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Je(){return this.hours()%12||12}function Qe(){return this.hours()||24}function ti(t,e){z(t,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)}))}function ei(t,e){return e._meridiemParse}function ii(t){return"p"===(t+"").toLowerCase().charAt(0)}z("H",["HH",2],0,"hour"),z("h",["hh",2],0,Je),z("k",["kk",2],0,Qe),z("hmm",0,0,(function(){return""+Je.apply(this)+F(this.minutes(),2)})),z("hmmss",0,0,(function(){return""+Je.apply(this)+F(this.minutes(),2)+F(this.seconds(),2)})),z("Hmm",0,0,(function(){return""+this.hours()+F(this.minutes(),2)})),z("Hmmss",0,0,(function(){return""+this.hours()+F(this.minutes(),2)+F(this.seconds(),2)})),ti("a",!0),ti("A",!1),nt("hour","h"),at("hour",13),Nt("a",ei),Nt("A",ei),Nt("H",xt),Nt("h",xt),Nt("k",xt),Nt("HH",xt,bt),Nt("hh",xt,bt),Nt("kk",xt,bt),Nt("hmm",Dt),Nt("hmmss",St),Nt("Hmm",Dt),Nt("Hmmss",St),Ht(["H","HH"],Xt),Ht(["k","kk"],(function(t,e,i){var n=dt(t);e[Xt]=24===n?0:n})),Ht(["a","A"],(function(t,e,i){i._isPm=i._locale.isPM(t),i._meridiem=t})),Ht(["h","hh"],(function(t,e,i){e[Xt]=dt(t),g(i).bigHour=!0})),Ht("hmm",(function(t,e,i){var n=t.length-2;e[Xt]=dt(t.substr(0,n)),e[qt]=dt(t.substr(n)),g(i).bigHour=!0})),Ht("hmmss",(function(t,e,i){var n=t.length-4,o=t.length-2;e[Xt]=dt(t.substr(0,n)),e[qt]=dt(t.substr(n,2)),e[Zt]=dt(t.substr(o)),g(i).bigHour=!0})),Ht("Hmm",(function(t,e,i){var n=t.length-2;e[Xt]=dt(t.substr(0,n)),e[qt]=dt(t.substr(n))})),Ht("Hmmss",(function(t,e,i){var n=t.length-4,o=t.length-2;e[Xt]=dt(t.substr(0,n)),e[qt]=dt(t.substr(n,2)),e[Zt]=dt(t.substr(o))}));var ni=/[ap]\.?m?\.?/i,oi=ct("Hours",!0);function ri(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"}var si,ai={calendar:L,longDateFormat:U,invalidDate:q,ordinal:$,dayOfMonthOrdinalParse:K,relativeTime:Q,months:ee,monthsShort:ie,week:Ce,weekdays:Le,weekdaysMin:Fe,weekdaysShort:Ne,meridiemParse:ni},li={},hi={};function ui(t,e){var i,n=Math.min(t.length,e.length);for(i=0;i0;){if(n=pi(o.slice(0,e).join("-")))return n;if(i&&i.length>=e&&ui(o,i)>=e-1)break;e--}r++}return si}function pi(e){var i=null;if(void 0===li[e]&&t&&t.exports)try{i=si._abbr,n("./locale/"+e),fi(i)}catch(t){li[e]=null}return li[e]}function fi(t,e){var i;return t&&((i=u(e)?gi(t):mi(t,e))?si=i:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),si._abbr}function mi(t,e){if(null!==e){var i,n=ai;if(e.abbr=t,null!=li[t])O("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=li[t]._config;else if(null!=e.parentLocale)if(null!=li[e.parentLocale])n=li[e.parentLocale]._config;else{if(null==(i=pi(e.parentLocale)))return hi[e.parentLocale]||(hi[e.parentLocale]=[]),hi[e.parentLocale].push({name:t,config:e}),null;n=i._config}return li[t]=new I(A(n,e)),hi[t]&&hi[t].forEach((function(t){mi(t.name,t.config)})),fi(t),li[t]}return delete li[t],null}function vi(t,e){if(null!=e){var i,n,o=ai;null!=li[t]&&null!=li[t].parentLocale?li[t].set(A(li[t]._config,e)):(null!=(n=pi(t))&&(o=n._config),e=A(o,e),null==n&&(e.abbr=t),(i=new I(e)).parentLocale=li[t],li[t]=i),fi(t)}else null!=li[t]&&(null!=li[t].parentLocale?(li[t]=li[t].parentLocale,t===fi()&&fi(t)):null!=li[t]&&delete li[t]);return li[t]}function gi(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return si;if(!s(t)){if(e=pi(t))return e;t=[t]}return ci(t)}function yi(){return T(li)}function bi(t){var e,i=t._a;return i&&-2===g(t).overflow&&(e=i[Vt]<0||i[Vt]>11?Vt:i[Ut]<1||i[Ut]>te(i[Wt],i[Vt])?Ut:i[Xt]<0||i[Xt]>24||24===i[Xt]&&(0!==i[qt]||0!==i[Zt]||0!==i[$t])?Xt:i[qt]<0||i[qt]>59?qt:i[Zt]<0||i[Zt]>59?Zt:i[$t]<0||i[$t]>999?$t:-1,g(t)._overflowDayOfYear&&(eUt)&&(e=Ut),g(t)._overflowWeeks&&-1===e&&(e=Kt),g(t)._overflowWeekday&&-1===e&&(e=Jt),g(t).overflow=e),t}var _i=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,wi=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ki=/Z|[+-]\d\d(?::?\d\d)?/,xi=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],Di=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Si=/^\/?Date\((-?\d+)/i,Ci=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,Ti={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Mi(t){var e,i,n,o,r,s,a=t._i,l=_i.exec(a)||wi.exec(a);if(l){for(g(t).iso=!0,e=0,i=xi.length;eve(r)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),i=_e(r,0,t._dayOfYear),t._a[Vt]=i.getUTCMonth(),t._a[Ut]=i.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=s[e]=n[e];for(;e<7;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[Xt]&&0===t._a[qt]&&0===t._a[Zt]&&0===t._a[$t]&&(t._nextDay=!0,t._a[Xt]=0),t._d=(t._useUTC?_e:be).apply(null,s),o=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[Xt]=24),t._w&&void 0!==t._w.d&&t._w.d!==o&&(g(t).weekdayMismatch=!0)}}function ji(t){var e,i,n,o,r,s,a,l,h;null!=(e=t._w).GG||null!=e.W||null!=e.E?(r=1,s=4,i=Fi(e.GG,t._a[Wt],xe(qi(),1,4).year),n=Fi(e.W,1),((o=Fi(e.E,1))<1||o>7)&&(l=!0)):(r=t._locale._week.dow,s=t._locale._week.doy,h=xe(qi(),r,s),i=Fi(e.gg,t._a[Wt],h.year),n=Fi(e.w,h.week),null!=e.d?((o=e.d)<0||o>6)&&(l=!0):null!=e.e?(o=e.e+r,(e.e<0||e.e>6)&&(l=!0)):o=r),n<1||n>De(i,r,s)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(a=ke(i,n,o,r,s),t._a[Wt]=a.year,t._dayOfYear=a.dayOfYear)}function Hi(t){if(t._f!==o.ISO_8601)if(t._f!==o.RFC_2822){t._a=[],g(t).empty=!0;var e,i,n,r,s,a,l=""+t._i,h=l.length,u=0;for(n=V(t._f,t._locale).match(R)||[],e=0;e0&&g(t).unusedInput.push(s),l=l.slice(l.indexOf(i)+i.length),u+=i.length),H[r]?(i?g(t).empty=!1:g(t).unusedTokens.push(r),Gt(r,i,t)):t._strict&&!i&&g(t).unusedTokens.push(r);g(t).charsLeftOver=h-u,l.length>0&&g(t).unusedInput.push(l),t._a[Xt]<=12&&!0===g(t).bigHour&&t._a[Xt]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[Xt]=zi(t._locale,t._a[Xt],t._meridiem),null!==(a=g(t).era)&&(t._a[Wt]=t._locale.erasConvertYear(a,t._a[Wt])),Yi(t),bi(t)}else Li(t);else Mi(t)}function zi(t,e,i){var n;return null==i?e:null!=t.meridiemHour?t.meridiemHour(e,i):null!=t.isPM?((n=t.isPM(i))&&e<12&&(e+=12),n||12!==e||(e=0),e):e}function Gi(t){var e,i,n,o,r,s,a=!1;if(0===t._f.length)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(o=0;othis?this:t:b()}));function Ki(t,e){var i,n;if(1===e.length&&s(e[0])&&(e=e[0]),!e.length)return qi();for(i=e[0],n=1;nthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function kn(){if(!u(this._isDSTShifted))return this._isDSTShifted;var t,e={};return k(e,this),(e=Vi(e))._a?(t=e._isUTC?m(e._a):qi(e._a),this._isDSTShifted=this.isValid()&&hn(e._a,t.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}function xn(){return!!this.isValid()&&!this._isUTC}function Dn(){return!!this.isValid()&&this._isUTC}function Sn(){return!!this.isValid()&&this._isUTC&&0===this._offset}o.updateOffset=function(){};var Cn=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,Tn=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function Mn(t,e){var i,n,o,r=t,s=null;return an(t)?r={ms:t._milliseconds,d:t._days,M:t._months}:d(t)||!isNaN(+t)?(r={},e?r[e]=+t:r.milliseconds=+t):(s=Cn.exec(t))?(i="-"===s[1]?-1:1,r={y:0,d:dt(s[Ut])*i,h:dt(s[Xt])*i,m:dt(s[qt])*i,s:dt(s[Zt])*i,ms:dt(ln(1e3*s[$t]))*i}):(s=Tn.exec(t))?(i="-"===s[1]?-1:1,r={y:On(s[2],i),M:On(s[3],i),w:On(s[4],i),d:On(s[5],i),h:On(s[6],i),m:On(s[7],i),s:On(s[8],i)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(o=Pn(qi(r.from),qi(r.to)),(r={}).ms=o.milliseconds,r.M=o.months),n=new sn(r),an(t)&&l(t,"_locale")&&(n._locale=t._locale),an(t)&&l(t,"_isValid")&&(n._isValid=t._isValid),n}function On(t,e){var i=t&&parseFloat(t.replace(",","."));return(isNaN(i)?0:i)*e}function En(t,e){var i={};return i.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(i.months,"M").isAfter(e)&&--i.months,i.milliseconds=+e-+t.clone().add(i.months,"M"),i}function Pn(t,e){var i;return t.isValid()&&e.isValid()?(e=pn(e,t),t.isBefore(e)?i=En(t,e):((i=En(e,t)).milliseconds=-i.milliseconds,i.months=-i.months),i):{milliseconds:0,months:0}}function An(t,e){return function(i,n){var o;return null===n||isNaN(+n)||(O(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),o=i,i=n,n=o),In(this,Mn(i,n),t),this}}function In(t,e,i,n){var r=e._milliseconds,s=ln(e._days),a=ln(e._months);t.isValid()&&(n=null==n||n,a&&ue(t,pt(t,"Month")+a*i),s&&ft(t,"Date",pt(t,"Date")+s*i),r&&t._d.setTime(t._d.valueOf()+r*i),n&&o.updateOffset(t,s||a))}Mn.fn=sn.prototype,Mn.invalid=rn;var Ln=An(1,"add"),Nn=An(-1,"subtract");function Fn(t){return"string"==typeof t||t instanceof String}function Rn(t){return D(t)||c(t)||Fn(t)||d(t)||jn(t)||Yn(t)||null==t}function Yn(t){var e,i,n=a(t)&&!h(t),o=!1,r=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"];for(e=0;ei.valueOf():i.valueOf()9999?W(i,e?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):E(Date.prototype.toISOString)?e?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",W(i,"Z")):W(i,e?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function to(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t,e,i,n,o="moment",r="";return this.isLocal()||(o=0===this.utcOffset()?"moment.utc":"moment.parseZone",r="Z"),t="["+o+'("]',e=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i="-MM-DD[T]HH:mm:ss.SSS",n=r+'[")]',this.format(t+e+i+n)}function eo(t){t||(t=this.isUtc()?o.defaultFormatUtc:o.defaultFormat);var e=W(this,t);return this.localeData().postformat(e)}function io(t,e){return this.isValid()&&(D(t)&&t.isValid()||qi(t).isValid())?Mn({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function no(t){return this.from(qi(),t)}function oo(t,e){return this.isValid()&&(D(t)&&t.isValid()||qi(t).isValid())?Mn({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function ro(t){return this.to(qi(),t)}function so(t){var e;return void 0===t?this._locale._abbr:(null!=(e=gi(t))&&(this._locale=e),this)}o.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",o.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var ao=C("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",(function(t){return void 0===t?this.localeData():this.locale(t)}));function lo(){return this._locale}var ho=1e3,uo=60*ho,co=60*uo,po=3506328*co;function fo(t,e){return(t%e+e)%e}function mo(t,e,i){return t<100&&t>=0?new Date(t+400,e,i)-po:new Date(t,e,i).valueOf()}function vo(t,e,i){return t<100&&t>=0?Date.UTC(t+400,e,i)-po:Date.UTC(t,e,i)}function go(t){var e,i;if(void 0===(t=ot(t))||"millisecond"===t||!this.isValid())return this;switch(i=this._isUTC?vo:mo,t){case"year":e=i(this.year(),0,1);break;case"quarter":e=i(this.year(),this.month()-this.month()%3,1);break;case"month":e=i(this.year(),this.month(),1);break;case"week":e=i(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":e=i(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":e=i(this.year(),this.month(),this.date());break;case"hour":e=this._d.valueOf(),e-=fo(e+(this._isUTC?0:this.utcOffset()*uo),co);break;case"minute":e=this._d.valueOf(),e-=fo(e,uo);break;case"second":e=this._d.valueOf(),e-=fo(e,ho)}return this._d.setTime(e),o.updateOffset(this,!0),this}function yo(t){var e,i;if(void 0===(t=ot(t))||"millisecond"===t||!this.isValid())return this;switch(i=this._isUTC?vo:mo,t){case"year":e=i(this.year()+1,0,1)-1;break;case"quarter":e=i(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":e=i(this.year(),this.month()+1,1)-1;break;case"week":e=i(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":e=i(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":e=i(this.year(),this.month(),this.date()+1)-1;break;case"hour":e=this._d.valueOf(),e+=co-fo(e+(this._isUTC?0:this.utcOffset()*uo),co)-1;break;case"minute":e=this._d.valueOf(),e+=uo-fo(e,uo)-1;break;case"second":e=this._d.valueOf(),e+=ho-fo(e,ho)-1}return this._d.setTime(e),o.updateOffset(this,!0),this}function bo(){return this._d.valueOf()-6e4*(this._offset||0)}function _o(){return Math.floor(this.valueOf()/1e3)}function wo(){return new Date(this.valueOf())}function ko(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]}function xo(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}}function Do(){return this.isValid()?this.toISOString():null}function So(){return y(this)}function Co(){return f({},g(this))}function To(){return g(this).overflow}function Mo(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Oo(t,e){var i,n,r,s=this._eras||gi("en")._eras;for(i=0,n=s.length;i=0)return l[n]}function Po(t,e){var i=t.since<=t.until?1:-1;return void 0===e?o(t.since).year():o(t.since).year()+(e-t.offset)*i}function Ao(){var t,e,i,n=this.localeData().eras();for(t=0,e=n.length;t(r=De(t,n,o))&&(e=r),Jo.call(this,t,e,i,n,o))}function Jo(t,e,i,n,o){var r=ke(t,e,i,n,o),s=_e(r.year,0,r.dayOfYear);return this.year(s.getUTCFullYear()),this.month(s.getUTCMonth()),this.date(s.getUTCDate()),this}function Qo(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)}z("N",0,0,"eraAbbr"),z("NN",0,0,"eraAbbr"),z("NNN",0,0,"eraAbbr"),z("NNNN",0,0,"eraName"),z("NNNNN",0,0,"eraNarrow"),z("y",["y",1],"yo","eraYear"),z("y",["yy",2],0,"eraYear"),z("y",["yyy",3],0,"eraYear"),z("y",["yyyy",4],0,"eraYear"),Nt("N",jo),Nt("NN",jo),Nt("NNN",jo),Nt("NNNN",Ho),Nt("NNNNN",zo),Ht(["N","NN","NNN","NNNN","NNNNN"],(function(t,e,i,n){var o=i._locale.erasParse(t,n,i._strict);o?g(i).era=o:g(i).invalidEra=t})),Nt("y",Ot),Nt("yy",Ot),Nt("yyy",Ot),Nt("yyyy",Ot),Nt("yo",Go),Ht(["y","yy","yyy","yyyy"],Wt),Ht(["yo"],(function(t,e,i,n){var o;i._locale._eraYearOrdinalRegex&&(o=t.match(i._locale._eraYearOrdinalRegex)),i._locale.eraYearOrdinalParse?e[Wt]=i._locale.eraYearOrdinalParse(t,o):e[Wt]=parseInt(t,10)})),z(0,["gg",2],0,(function(){return this.weekYear()%100})),z(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),Wo("gggg","weekYear"),Wo("ggggg","weekYear"),Wo("GGGG","isoWeekYear"),Wo("GGGGG","isoWeekYear"),nt("weekYear","gg"),nt("isoWeekYear","GG"),at("weekYear",1),at("isoWeekYear",1),Nt("G",Et),Nt("g",Et),Nt("GG",xt,bt),Nt("gg",xt,bt),Nt("GGGG",Tt,wt),Nt("gggg",Tt,wt),Nt("GGGGG",Mt,kt),Nt("ggggg",Mt,kt),zt(["gggg","ggggg","GGGG","GGGGG"],(function(t,e,i,n){e[n.substr(0,2)]=dt(t)})),zt(["gg","GG"],(function(t,e,i,n){e[n]=o.parseTwoDigitYear(t)})),z("Q",0,"Qo","quarter"),nt("quarter","Q"),at("quarter",7),Nt("Q",yt),Ht("Q",(function(t,e){e[Vt]=3*(dt(t)-1)})),z("D",["DD",2],"Do","date"),nt("date","D"),at("date",9),Nt("D",xt),Nt("DD",xt,bt),Nt("Do",(function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient})),Ht(["D","DD"],Ut),Ht("Do",(function(t,e){e[Ut]=dt(t.match(xt)[0])}));var tr=ct("Date",!0);function er(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")}z("DDD",["DDDD",3],"DDDo","dayOfYear"),nt("dayOfYear","DDD"),at("dayOfYear",4),Nt("DDD",Ct),Nt("DDDD",_t),Ht(["DDD","DDDD"],(function(t,e,i){i._dayOfYear=dt(t)})),z("m",["mm",2],0,"minute"),nt("minute","m"),at("minute",14),Nt("m",xt),Nt("mm",xt,bt),Ht(["m","mm"],qt);var ir=ct("Minutes",!1);z("s",["ss",2],0,"second"),nt("second","s"),at("second",15),Nt("s",xt),Nt("ss",xt,bt),Ht(["s","ss"],Zt);var nr,or,rr=ct("Seconds",!1);for(z("S",0,0,(function(){return~~(this.millisecond()/100)})),z(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),z(0,["SSS",3],0,"millisecond"),z(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),z(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),z(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),z(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),z(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),z(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),nt("millisecond","ms"),at("millisecond",16),Nt("S",Ct,yt),Nt("SS",Ct,bt),Nt("SSS",Ct,_t),nr="SSSS";nr.length<=9;nr+="S")Nt(nr,Ot);function sr(t,e){e[$t]=dt(1e3*("0."+t))}for(nr="S";nr.length<=9;nr+="S")Ht(nr,sr);function ar(){return this._isUTC?"UTC":""}function lr(){return this._isUTC?"Coordinated Universal Time":""}or=ct("Milliseconds",!1),z("z",0,0,"zoneAbbr"),z("zz",0,0,"zoneName");var hr=x.prototype;function ur(t){return qi(1e3*t)}function dr(){return qi.apply(null,arguments).parseZone()}function cr(t){return t}hr.add=Ln,hr.calendar=Gn,hr.clone=Bn,hr.diff=$n,hr.endOf=yo,hr.format=eo,hr.from=io,hr.fromNow=no,hr.to=oo,hr.toNow=ro,hr.get=mt,hr.invalidAt=To,hr.isAfter=Wn,hr.isBefore=Vn,hr.isBetween=Un,hr.isSame=Xn,hr.isSameOrAfter=qn,hr.isSameOrBefore=Zn,hr.isValid=So,hr.lang=ao,hr.locale=so,hr.localeData=lo,hr.max=$i,hr.min=Zi,hr.parsingFlags=Co,hr.set=vt,hr.startOf=go,hr.subtract=Nn,hr.toArray=ko,hr.toObject=xo,hr.toDate=wo,hr.toISOString=Qn,hr.inspect=to,"undefined"!=typeof Symbol&&null!=Symbol.for&&(hr[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"}),hr.toJSON=Do,hr.toString=Jn,hr.unix=_o,hr.valueOf=bo,hr.creationData=Mo,hr.eraName=Ao,hr.eraNarrow=Io,hr.eraAbbr=Lo,hr.eraYear=No,hr.year=ge,hr.isLeapYear=ye,hr.weekYear=Vo,hr.isoWeekYear=Uo,hr.quarter=hr.quarters=Qo,hr.month=de,hr.daysInMonth=ce,hr.week=hr.weeks=Oe,hr.isoWeek=hr.isoWeeks=Ee,hr.weeksInYear=Zo,hr.weeksInWeekYear=$o,hr.isoWeeksInYear=Xo,hr.isoWeeksInISOWeekYear=qo,hr.date=tr,hr.day=hr.days=Ve,hr.weekday=Ue,hr.isoWeekday=Xe,hr.dayOfYear=er,hr.hour=hr.hours=oi,hr.minute=hr.minutes=ir,hr.second=hr.seconds=rr,hr.millisecond=hr.milliseconds=or,hr.utcOffset=mn,hr.utc=gn,hr.local=yn,hr.parseZone=bn,hr.hasAlignedHourOffset=_n,hr.isDST=wn,hr.isLocal=xn,hr.isUtcOffset=Dn,hr.isUtc=Sn,hr.isUTC=Sn,hr.zoneAbbr=ar,hr.zoneName=lr,hr.dates=C("dates accessor is deprecated. Use date instead.",tr),hr.months=C("months accessor is deprecated. Use month instead",de),hr.years=C("years accessor is deprecated. Use year instead",ge),hr.zone=C("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",vn),hr.isDSTShifted=C("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",kn);var pr=I.prototype;function fr(t,e,i,n){var o=gi(),r=m().set(n,e);return o[i](r,t)}function mr(t,e,i){if(d(t)&&(e=t,t=void 0),t=t||"",null!=e)return fr(t,e,i,"month");var n,o=[];for(n=0;n<12;n++)o[n]=fr(t,n,i,"month");return o}function vr(t,e,i,n){"boolean"==typeof t?(d(e)&&(i=e,e=void 0),e=e||""):(i=e=t,t=!1,d(e)&&(i=e,e=void 0),e=e||"");var o,r=gi(),s=t?r._week.dow:0,a=[];if(null!=i)return fr(e,(i+s)%7,n,"day");for(o=0;o<7;o++)a[o]=fr(e,(o+s)%7,n,"day");return a}function gr(t,e){return mr(t,e,"months")}function yr(t,e){return mr(t,e,"monthsShort")}function br(t,e,i){return vr(t,e,i,"weekdays")}function _r(t,e,i){return vr(t,e,i,"weekdaysShort")}function wr(t,e,i){return vr(t,e,i,"weekdaysMin")}pr.calendar=N,pr.longDateFormat=X,pr.invalidDate=Z,pr.ordinal=J,pr.preparse=cr,pr.postformat=cr,pr.relativeTime=tt,pr.pastFuture=et,pr.set=P,pr.eras=Oo,pr.erasParse=Eo,pr.erasConvertYear=Po,pr.erasAbbrRegex=Ro,pr.erasNameRegex=Fo,pr.erasNarrowRegex=Yo,pr.months=se,pr.monthsShort=ae,pr.monthsParse=he,pr.monthsRegex=fe,pr.monthsShortRegex=pe,pr.week=Se,pr.firstDayOfYear=Me,pr.firstDayOfWeek=Te,pr.weekdays=He,pr.weekdaysMin=Ge,pr.weekdaysShort=ze,pr.weekdaysParse=We,pr.weekdaysRegex=qe,pr.weekdaysShortRegex=Ze,pr.weekdaysMinRegex=$e,pr.isPM=ii,pr.meridiem=ri,fi("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===dt(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),o.lang=C("moment.lang is deprecated. Use moment.locale instead.",fi),o.langData=C("moment.langData is deprecated. Use moment.localeData instead.",gi);var kr=Math.abs;function xr(){var t=this._data;return this._milliseconds=kr(this._milliseconds),this._days=kr(this._days),this._months=kr(this._months),t.milliseconds=kr(t.milliseconds),t.seconds=kr(t.seconds),t.minutes=kr(t.minutes),t.hours=kr(t.hours),t.months=kr(t.months),t.years=kr(t.years),this}function Dr(t,e,i,n){var o=Mn(e,i);return t._milliseconds+=n*o._milliseconds,t._days+=n*o._days,t._months+=n*o._months,t._bubble()}function Sr(t,e){return Dr(this,t,e,1)}function Cr(t,e){return Dr(this,t,e,-1)}function Tr(t){return t<0?Math.floor(t):Math.ceil(t)}function Mr(){var t,e,i,n,o,r=this._milliseconds,s=this._days,a=this._months,l=this._data;return r>=0&&s>=0&&a>=0||r<=0&&s<=0&&a<=0||(r+=864e5*Tr(Er(a)+s),s=0,a=0),l.milliseconds=r%1e3,t=ut(r/1e3),l.seconds=t%60,e=ut(t/60),l.minutes=e%60,i=ut(e/60),l.hours=i%24,s+=ut(i/24),a+=o=ut(Or(s)),s-=Tr(Er(o)),n=ut(a/12),a%=12,l.days=s,l.months=a,l.years=n,this}function Or(t){return 4800*t/146097}function Er(t){return 146097*t/4800}function Pr(t){if(!this.isValid())return NaN;var e,i,n=this._milliseconds;if("month"===(t=ot(t))||"quarter"===t||"year"===t)switch(e=this._days+n/864e5,i=this._months+Or(e),t){case"month":return i;case"quarter":return i/3;case"year":return i/12}else switch(e=this._days+Math.round(Er(this._months)),t){case"week":return e/7+n/6048e5;case"day":return e+n/864e5;case"hour":return 24*e+n/36e5;case"minute":return 1440*e+n/6e4;case"second":return 86400*e+n/1e3;case"millisecond":return Math.floor(864e5*e)+n;default:throw new Error("Unknown unit "+t)}}function Ar(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*dt(this._months/12):NaN}function Ir(t){return function(){return this.as(t)}}var Lr=Ir("ms"),Nr=Ir("s"),Fr=Ir("m"),Rr=Ir("h"),Yr=Ir("d"),jr=Ir("w"),Hr=Ir("M"),zr=Ir("Q"),Gr=Ir("y");function Br(){return Mn(this)}function Wr(t){return t=ot(t),this.isValid()?this[t+"s"]():NaN}function Vr(t){return function(){return this.isValid()?this._data[t]:NaN}}var Ur=Vr("milliseconds"),Xr=Vr("seconds"),qr=Vr("minutes"),Zr=Vr("hours"),$r=Vr("days"),Kr=Vr("months"),Jr=Vr("years");function Qr(){return ut(this.days()/7)}var ts=Math.round,es={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function is(t,e,i,n,o){return o.relativeTime(e||1,!!i,t,n)}function ns(t,e,i,n){var o=Mn(t).abs(),r=ts(o.as("s")),s=ts(o.as("m")),a=ts(o.as("h")),l=ts(o.as("d")),h=ts(o.as("M")),u=ts(o.as("w")),d=ts(o.as("y")),c=r<=i.ss&&["s",r]||r0,c[4]=n,is.apply(null,c)}function os(t){return void 0===t?ts:"function"==typeof t&&(ts=t,!0)}function rs(t,e){return void 0!==es[t]&&(void 0===e?es[t]:(es[t]=e,"s"===t&&(es.ss=e-1),!0))}function ss(t,e){if(!this.isValid())return this.localeData().invalidDate();var i,n,o=!1,r=es;return"object"==typeof t&&(e=t,t=!1),"boolean"==typeof t&&(o=t),"object"==typeof e&&(r=Object.assign({},es,e),null!=e.s&&null==e.ss&&(r.ss=e.s-1)),n=ns(this,!o,r,i=this.localeData()),o&&(n=i.pastFuture(+this,n)),i.postformat(n)}var as=Math.abs;function ls(t){return(t>0)-(t<0)||+t}function hs(){if(!this.isValid())return this.localeData().invalidDate();var t,e,i,n,o,r,s,a,l=as(this._milliseconds)/1e3,h=as(this._days),u=as(this._months),d=this.asSeconds();return d?(t=ut(l/60),e=ut(t/60),l%=60,t%=60,i=ut(u/12),u%=12,n=l?l.toFixed(3).replace(/\.?0+$/,""):"",o=d<0?"-":"",r=ls(this._months)!==ls(d)?"-":"",s=ls(this._days)!==ls(d)?"-":"",a=ls(this._milliseconds)!==ls(d)?"-":"",o+"P"+(i?r+i+"Y":"")+(u?r+u+"M":"")+(h?s+h+"D":"")+(e||t||l?"T":"")+(e?a+e+"H":"")+(t?a+t+"M":"")+(l?a+n+"S":"")):"P0D"}var us=sn.prototype;return us.isValid=on,us.abs=xr,us.add=Sr,us.subtract=Cr,us.as=Pr,us.asMilliseconds=Lr,us.asSeconds=Nr,us.asMinutes=Fr,us.asHours=Rr,us.asDays=Yr,us.asWeeks=jr,us.asMonths=Hr,us.asQuarters=zr,us.asYears=Gr,us.valueOf=Ar,us._bubble=Mr,us.clone=Br,us.get=Wr,us.milliseconds=Ur,us.seconds=Xr,us.minutes=qr,us.hours=Zr,us.days=$r,us.weeks=Qr,us.months=Kr,us.years=Jr,us.humanize=ss,us.toISOString=hs,us.toString=hs,us.toJSON=hs,us.locale=so,us.localeData=lo,us.toIsoString=C("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",hs),us.lang=ao,z("X",0,0,"unix"),z("x",0,0,"valueOf"),Nt("x",Et),Nt("X",It),Ht("X",(function(t,e,i){i._d=new Date(1e3*parseFloat(t))})),Ht("x",(function(t,e,i){i._d=new Date(dt(t))})),//! moment.js -o.version="2.29.1",r(qi),o.fn=hr,o.min=Ji,o.max=Qi,o.now=tn,o.utc=m,o.unix=ur,o.months=gr,o.isDate=c,o.locale=fi,o.invalid=b,o.duration=Mn,o.isMoment=D,o.weekdays=br,o.parseZone=dr,o.localeData=gi,o.isDuration=an,o.monthsShort=yr,o.weekdaysMin=wr,o.defineLocale=mi,o.updateLocale=vi,o.locales=yi,o.weekdaysShort=_r,o.normalizeUnits=ot,o.relativeTimeRounding=os,o.relativeTimeThreshold=rs,o.calendarFormat=zn,o.prototype=hr,o.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},o}()}(o);var r=o.exports;!function(t){function e(t,e,i,n){var o={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[t+" Tage",t+" Tagen"],w:["eine Woche","einer Woche"],M:["ein Monat","einem Monat"],MM:[t+" Monate",t+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[t+" Jahre",t+" Jahren"]};return e?o[i][0]:o[i][1]}t.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:e,mm:"%d Minuten",h:e,hh:"%d Stunden",d:e,dd:e,w:e,ww:"%d Wochen",M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(o.exports),function(t){var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),i="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),n=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],o=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;t.defineLocale("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,n){return t?/-MMM-/.test(n)?i[t.month()]:e[t.month()]:e},monthsRegex:o,monthsShortRegex:o,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4},invalidDate:"Fecha inválida"})}(o.exports),function(t){var e=/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?|janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,i=[/^janv/i,/^févr/i,/^mars/i,/^avr/i,/^mai/i,/^juin/i,/^juil/i,/^août/i,/^sept/i,/^oct/i,/^nov/i,/^déc/i];t.defineLocale("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsRegex:e,monthsShortRegex:e,monthsStrictRegex:/^(janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,monthsShortStrictRegex:/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?)/i,monthsParse:i,longMonthsParse:i,shortMonthsParse:i,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",w:"une semaine",ww:"%d semaines",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|)/,ordinal:function(t,e){switch(e){case"D":return t+(1===t?"er":"");default:case"M":case"Q":case"DDD":case"d":return t+(1===t?"er":"e");case"w":case"W":return t+(1===t?"re":"e")}},week:{dow:1,doy:4}})}(o.exports),function(t){t.defineLocale("it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:function(){return"[Oggi a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextDay:function(){return"[Domani a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextWeek:function(){return"dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastDay:function(){return"[Ieri a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastWeek:function(){switch(this.day()){case 0:return"[La scorsa] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT";default:return"[Lo scorso] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"}},sameElse:"L"},relativeTime:{future:"tra %s",past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",w:"una settimana",ww:"%d settimane",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})}(o.exports),function(t){t.defineLocale("ja",{eras:[{since:"2019-05-01",offset:1,name:"令和",narrow:"㋿",abbr:"R"},{since:"1989-01-08",until:"2019-04-30",offset:1,name:"平成",narrow:"㍻",abbr:"H"},{since:"1926-12-25",until:"1989-01-07",offset:1,name:"昭和",narrow:"㍼",abbr:"S"},{since:"1912-07-30",until:"1926-12-24",offset:1,name:"大正",narrow:"㍽",abbr:"T"},{since:"1873-01-01",until:"1912-07-29",offset:6,name:"明治",narrow:"㍾",abbr:"M"},{since:"0001-01-01",until:"1873-12-31",offset:1,name:"西暦",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"紀元前",narrow:"BC",abbr:"BC"}],eraYearOrdinalRegex:/(元|\d+)年/,eraYearOrdinalParse:function(t,e){return"元"===e[1]?1:parseInt(e[1]||t,10)},months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日 dddd HH:mm",l:"YYYY/MM/DD",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日(ddd) HH:mm"},meridiemParse:/午前|午後/i,isPM:function(t){return"午後"===t},meridiem:function(t,e,i){return t<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:function(t){return t.week()!==this.week()?"[来週]dddd LT":"dddd LT"},lastDay:"[昨日] LT",lastWeek:function(t){return this.week()!==t.week()?"[先週]dddd LT":"dddd LT"},sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}日/,ordinal:function(t,e){switch(e){case"y":return 1===t?"元年":t+"年";case"d":case"D":case"DDD":return t+"日";default:return t}},relativeTime:{future:"%s後",past:"%s前",s:"数秒",ss:"%d秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}})}(o.exports),function(t){var e="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),i="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),n=[/^jan/i,/^feb/i,/^maart|mrt.?$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],o=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;t.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(t,n){return t?/-MMM-/.test(n)?i[t.month()]:e[t.month()]:e},monthsRegex:o,monthsShortRegex:o,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",w:"één week",ww:"%d weken",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(t){return t+(1===t||8===t||t>=20?"ste":"de")},week:{dow:1,doy:4}})}(o.exports),function(t){var e="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),i="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"),n=[/^sty/i,/^lut/i,/^mar/i,/^kwi/i,/^maj/i,/^cze/i,/^lip/i,/^sie/i,/^wrz/i,/^paź/i,/^lis/i,/^gru/i];function o(t){return t%10<5&&t%10>1&&~~(t/10)%10!=1}function r(t,e,i){var n=t+" ";switch(i){case"ss":return n+(o(t)?"sekundy":"sekund");case"m":return e?"minuta":"minutę";case"mm":return n+(o(t)?"minuty":"minut");case"h":return e?"godzina":"godzinę";case"hh":return n+(o(t)?"godziny":"godzin");case"ww":return n+(o(t)?"tygodnie":"tygodni");case"MM":return n+(o(t)?"miesiące":"miesięcy");case"yy":return n+(o(t)?"lata":"lat")}}t.defineLocale("pl",{months:function(t,n){return t?/D MMMM/.test(n)?i[t.month()]:e[t.month()]:e},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"ndz_pon_wt_śr_czw_pt_sob".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:function(){switch(this.day()){case 0:return"[W niedzielę o] LT";case 2:return"[We wtorek o] LT";case 3:return"[W środę o] LT";case 6:return"[W sobotę o] LT";default:return"[W] dddd [o] LT"}},lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",ss:r,m:r,mm:r,h:r,hh:r,d:"1 dzień",dd:"%d dni",w:"tydzień",ww:r,M:"miesiąc",MM:r,y:"rok",yy:r},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})}(o.exports),function(t){function e(t,e,i){var n,o;return"m"===i?e?"минута":"минуту":t+" "+(n=+t,o={ss:e?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:e?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",ww:"неделя_недели_недель",MM:"месяц_месяца_месяцев",yy:"год_года_лет"}[i].split("_"),n%10==1&&n%100!=11?o[0]:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?o[1]:o[2])}var i=[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i];t.defineLocale("ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:i,longMonthsParse:i,shortMonthsParse:i,monthsRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsShortRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsStrictRegex:/^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,monthsShortStrictRegex:/^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., H:mm",LLLL:"dddd, D MMMM YYYY г., H:mm"},calendar:{sameDay:"[Сегодня, в] LT",nextDay:"[Завтра, в] LT",lastDay:"[Вчера, в] LT",nextWeek:function(t){if(t.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В следующее] dddd, [в] LT";case 1:case 2:case 4:return"[В следующий] dddd, [в] LT";case 3:case 5:case 6:return"[В следующую] dddd, [в] LT"}},lastWeek:function(t){if(t.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd, [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd, [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd, [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",ss:e,m:e,mm:e,h:"час",hh:e,d:"день",dd:e,w:"неделя",ww:e,M:"месяц",MM:e,y:"год",yy:e},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(t){return/^(дня|вечера)$/.test(t)},meridiem:function(t,e,i){return t<4?"ночи":t<12?"утра":t<17?"дня":"вечера"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":return t+"-й";case"D":return t+"-го";case"w":case"W":return t+"-я";default:return t}},week:{dow:1,doy:4}})}(o.exports),function(t){function e(t,e,i){var n,o;return"m"===i?e?"хвилина":"хвилину":"h"===i?e?"година":"годину":t+" "+(n=+t,o={ss:e?"секунда_секунди_секунд":"секунду_секунди_секунд",mm:e?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:e?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"}[i].split("_"),n%10==1&&n%100!=11?o[0]:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?o[1]:o[2])}function i(t){return function(){return t+"о"+(11===this.hours()?"б":"")+"] LT"}}t.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:function(t,e){var i={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")};return!0===t?i.nominative.slice(1,7).concat(i.nominative.slice(0,1)):t?i[/(\[[ВвУу]\]) ?dddd/.test(e)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(e)?"genitive":"nominative"][t.day()]:i.nominative},weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:i("[Сьогодні "),nextDay:i("[Завтра "),lastDay:i("[Вчора "),nextWeek:i("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return i("[Минулої] dddd [").call(this);case 1:case 2:case 4:return i("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",ss:e,m:e,mm:e,h:"годину",hh:e,d:"день",dd:e,M:"місяць",MM:e,y:"рік",yy:e},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(t){return/^(дня|вечора)$/.test(t)},meridiem:function(t,e,i){return t<4?"ночі":t<12?"ранку":t<17?"дня":"вечора"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":case"w":case"W":return t+"-й";case"D":return t+"-го";default:return t}},week:{dow:1,doy:7}})}(o.exports);var s=Function.prototype,a=s.bind,l=s.call,h=a&&a.bind(l),u=a?function(t){return t&&h(l,t)}:function(t){return t&&function(){return l.apply(t,arguments)}},d=Math.ceil,c=Math.floor,p=function(t){var e=+t;return e!=e||0===e?0:(e>0?c:d)(e)},f=function(t){return t&&t.Math==Math&&t},m=f("object"==typeof globalThis&&globalThis)||f("object"==typeof window&&window)||f("object"==typeof self&&self)||f("object"==typeof e&&e)||function(){return this}()||Function("return this")(),v={exports:{}},g=m,y=Object.defineProperty,b=function(t,e){try{y(g,t,{value:e,configurable:!0,writable:!0})}catch(i){g[t]=e}return e},_="__core-js_shared__",w=m[_]||b(_,{}),k=w;(v.exports=function(t,e){return k[t]||(k[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.19.1",mode:"pure",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"});var x,D,S=m.TypeError,C=function(t){if(null==t)throw S("Can't call method on "+t);return t},T=C,M=m.Object,O=function(t){return M(T(t))},E=O,P=u({}.hasOwnProperty),A=Object.hasOwn||function(t,e){return P(E(t),e)},I=u,L=0,N=Math.random(),F=I(1..toString),R=function(t){return"Symbol("+(void 0===t?"":t)+")_"+F(++L+N,36)},Y={},j=function(t){return"function"==typeof t},H=Y,z=m,G=j,B=function(t){return G(t)?t:void 0},W=function(t,e){return arguments.length<2?B(H[t])||B(z[t]):H[t]&&H[t][e]||z[t]&&z[t][e]},V=W("navigator","userAgent")||"",U=m,X=V,q=U.process,Z=U.Deno,$=q&&q.versions||Z&&Z.version,K=$&&$.v8;K&&(D=(x=K.split("."))[0]>0&&x[0]<4?1:+(x[0]+x[1])),!D&&X&&(!(x=X.match(/Edge\/(\d+)/))||x[1]>=74)&&(x=X.match(/Chrome\/(\d+)/))&&(D=+x[1]);var J=D,Q=function(t){try{return!!t()}catch(t){return!0}},tt=J,et=Q,it=!!Object.getOwnPropertySymbols&&!et((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&tt&&tt<41})),nt=it&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,ot=m,rt=v.exports,st=A,at=R,lt=it,ht=nt,ut=rt("wks"),dt=ot.Symbol,ct=dt&&dt.for,pt=ht?dt:dt&&dt.withoutSetter||at,ft=function(t){if(!st(ut,t)||!lt&&"string"!=typeof ut[t]){var e="Symbol."+t;lt&&st(dt,t)?ut[t]=dt[t]:ut[t]=ht&&ct?ct(e):pt(e)}return ut[t]},mt={};mt[ft("toStringTag")]="z";var vt="[object z]"===String(mt),gt=u,yt=gt({}.toString),bt=gt("".slice),_t=function(t){return bt(yt(t),8,-1)},wt=m,kt=vt,xt=j,Dt=_t,St=ft("toStringTag"),Ct=wt.Object,Tt="Arguments"==Dt(function(){return arguments}()),Mt=kt?Dt:function(t){var e,i,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=function(t,e){try{return t[e]}catch(t){}}(e=Ct(t),St))?i:Tt?Dt(e):"Object"==(n=Dt(e))&&xt(e.callee)?"Arguments":n},Ot=Mt,Et=m.String,Pt=function(t){if("Symbol"===Ot(t))throw TypeError("Cannot convert a Symbol value to a string");return Et(t)},At=u,It=p,Lt=Pt,Nt=C,Ft=At("".charAt),Rt=At("".charCodeAt),Yt=At("".slice),jt=function(t){return function(e,i){var n,o,r=Lt(Nt(e)),s=It(i),a=r.length;return s<0||s>=a?t?"":void 0:(n=Rt(r,s))<55296||n>56319||s+1===a||(o=Rt(r,s+1))<56320||o>57343?t?Ft(r,s):n:t?Yt(r,s,s+2):o-56320+(n-55296<<10)+65536}},Ht={codeAt:jt(!1),charAt:jt(!0)},zt=j,Gt=w,Bt=u(Function.toString);zt(Gt.inspectSource)||(Gt.inspectSource=function(t){return Bt(t)});var Wt=Gt.inspectSource,Vt=j,Ut=Wt,Xt=m.WeakMap,qt=Vt(Xt)&&/native code/.test(Ut(Xt)),Zt=j,$t=function(t){return"object"==typeof t?null!==t:Zt(t)},Kt=!Q((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),Jt={},Qt=$t,te=m.document,ee=Qt(te)&&Qt(te.createElement),ie=function(t){return ee?te.createElement(t):{}},ne=ie,oe=!Kt&&!Q((function(){return 7!=Object.defineProperty(ne("div"),"a",{get:function(){return 7}}).a})),re=m,se=$t,ae=re.String,le=re.TypeError,he=function(t){if(se(t))return t;throw le(ae(t)+" is not an object")},ue=Function.prototype.call,de=ue.bind?ue.bind(ue):function(){return ue.apply(ue,arguments)},ce=u({}.isPrototypeOf),pe=W,fe=j,me=ce,ve=nt,ge=m.Object,ye=ve?function(t){return"symbol"==typeof t}:function(t){var e=pe("Symbol");return fe(e)&&me(e.prototype,ge(t))},be=m.String,_e=function(t){try{return be(t)}catch(t){return"Object"}},we=j,ke=_e,xe=m.TypeError,De=function(t){if(we(t))return t;throw xe(ke(t)+" is not a function")},Se=De,Ce=function(t,e){var i=t[e];return null==i?void 0:Se(i)},Te=de,Me=j,Oe=$t,Ee=m.TypeError,Pe=de,Ae=$t,Ie=ye,Le=Ce,Ne=function(t,e){var i,n;if("string"===e&&Me(i=t.toString)&&!Oe(n=Te(i,t)))return n;if(Me(i=t.valueOf)&&!Oe(n=Te(i,t)))return n;if("string"!==e&&Me(i=t.toString)&&!Oe(n=Te(i,t)))return n;throw Ee("Can't convert object to primitive value")},Fe=ft,Re=m.TypeError,Ye=Fe("toPrimitive"),je=function(t,e){if(!Ae(t)||Ie(t))return t;var i,n=Le(t,Ye);if(n){if(void 0===e&&(e="default"),i=Pe(n,t,e),!Ae(i)||Ie(i))return i;throw Re("Can't convert object to primitive value")}return void 0===e&&(e="number"),Ne(t,e)},He=ye,ze=function(t){var e=je(t,"string");return He(e)?e:e+""},Ge=Kt,Be=oe,We=he,Ve=ze,Ue=m.TypeError,Xe=Object.defineProperty;Jt.f=Ge?Xe:function(t,e,i){if(We(t),e=Ve(e),We(i),Be)try{return Xe(t,e,i)}catch(t){}if("get"in i||"set"in i)throw Ue("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var qe,Ze,$e,Ke=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},Je=Jt,Qe=Ke,ti=Kt?function(t,e,i){return Je.f(t,e,Qe(1,i))}:function(t,e,i){return t[e]=i,t},ei=v.exports,ii=R,ni=ei("keys"),oi=function(t){return ni[t]||(ni[t]=ii(t))},ri={},si=qt,ai=m,li=u,hi=$t,ui=ti,di=A,ci=w,pi=oi,fi=ri,mi="Object already initialized",vi=ai.TypeError,gi=ai.WeakMap;if(si||ci.state){var yi=ci.state||(ci.state=new gi),bi=li(yi.get),_i=li(yi.has),wi=li(yi.set);qe=function(t,e){if(_i(yi,t))throw new vi(mi);return e.facade=t,wi(yi,t,e),e},Ze=function(t){return bi(yi,t)||{}},$e=function(t){return _i(yi,t)}}else{var ki=pi("state");fi[ki]=!0,qe=function(t,e){if(di(t,ki))throw new vi(mi);return e.facade=t,ui(t,ki,e),e},Ze=function(t){return di(t,ki)?t[ki]:{}},$e=function(t){return di(t,ki)}}var xi={set:qe,get:Ze,has:$e,enforce:function(t){return $e(t)?Ze(t):qe(t,{})},getterFor:function(t){return function(e){var i;if(!hi(e)||(i=Ze(e)).type!==t)throw vi("Incompatible receiver, "+t+" required");return i}}},Di=Function.prototype,Si=Di.apply,Ci=Di.bind,Ti=Di.call,Mi="object"==typeof Reflect&&Reflect.apply||(Ci?Ti.bind(Si):function(){return Ti.apply(Si,arguments)}),Oi={},Ei={},Pi={}.propertyIsEnumerable,Ai=Object.getOwnPropertyDescriptor,Ii=Ai&&!Pi.call({1:2},1);Ei.f=Ii?function(t){var e=Ai(this,t);return!!e&&e.enumerable}:Pi;var Li=u,Ni=Q,Fi=_t,Ri=m.Object,Yi=Li("".split),ji=Ni((function(){return!Ri("z").propertyIsEnumerable(0)}))?function(t){return"String"==Fi(t)?Yi(t,""):Ri(t)}:Ri,Hi=ji,zi=C,Gi=function(t){return Hi(zi(t))},Bi=Kt,Wi=de,Vi=Ei,Ui=Ke,Xi=Gi,qi=ze,Zi=A,$i=oe,Ki=Object.getOwnPropertyDescriptor;Oi.f=Bi?Ki:function(t,e){if(t=Xi(t),e=qi(e),$i)try{return Ki(t,e)}catch(t){}if(Zi(t,e))return Ui(!Wi(Vi.f,t,e),t[e])};var Ji,Qi=Q,tn=j,en=/#|\.prototype\./,nn=function(t,e){var i=rn[on(t)];return i==an||i!=sn&&(tn(e)?Qi(e):!!e)},on=nn.normalize=function(t){return String(t).replace(en,".").toLowerCase()},rn=nn.data={},sn=nn.NATIVE="N",an=nn.POLYFILL="P",ln=nn,hn=De,un=u(u.bind),dn=function(t,e){return hn(t),void 0===e?t:un?un(t,e):function(){return t.apply(e,arguments)}},cn=m,pn=Mi,fn=u,mn=j,vn=Oi.f,gn=ln,yn=Y,bn=dn,_n=ti,wn=A,kn=function(t){var e=function(i,n,o){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,n)}return new t(i,n,o)}return pn(t,this,arguments)};return e.prototype=t.prototype,e},xn=function(t,e){var i,n,o,r,s,a,l,h,u=t.target,d=t.global,c=t.stat,p=t.proto,f=d?cn:c?cn[u]:(cn[u]||{}).prototype,m=d?yn:yn[u]||_n(yn,u,{})[u],v=m.prototype;for(o in e)i=!gn(d?o:u+(c?".":"#")+o,t.forced)&&f&&wn(f,o),s=m[o],i&&(a=t.noTargetGet?(h=vn(f,o))&&h.value:f[o]),r=i&&a?a:e[o],i&&typeof s==typeof r||(l=t.bind&&i?bn(r,cn):t.wrap&&i?kn(r):p&&mn(r)?fn(r):r,(t.sham||r&&r.sham||s&&s.sham)&&_n(l,"sham",!0),_n(m,o,l),p&&(wn(yn,n=u+"Prototype")||_n(yn,n,{}),_n(yn[n],o,r),t.real&&v&&!v[o]&&_n(v,o,r)))},Dn=Kt,Sn=A,Cn=Function.prototype,Tn=Dn&&Object.getOwnPropertyDescriptor,Mn=Sn(Cn,"name"),On={EXISTS:Mn,PROPER:Mn&&"something"===function(){}.name,CONFIGURABLE:Mn&&(!Dn||Dn&&Tn(Cn,"name").configurable)},En=p,Pn=Math.max,An=Math.min,In=function(t,e){var i=En(t);return i<0?Pn(i+e,0):An(i,e)},Ln=p,Nn=Math.min,Fn=function(t){return t>0?Nn(Ln(t),9007199254740991):0},Rn=function(t){return Fn(t.length)},Yn=Gi,jn=In,Hn=Rn,zn=function(t){return function(e,i,n){var o,r=Yn(e),s=Hn(r),a=jn(n,s);if(t&&i!=i){for(;s>a;)if((o=r[a++])!=o)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},Gn={includes:zn(!0),indexOf:zn(!1)},Bn=A,Wn=Gi,Vn=Gn.indexOf,Un=ri,Xn=u([].push),qn=function(t,e){var i,n=Wn(t),o=0,r=[];for(i in n)!Bn(Un,i)&&Bn(n,i)&&Xn(r,i);for(;e.length>o;)Bn(n,i=e[o++])&&(~Vn(r,i)||Xn(r,i));return r},Zn=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],$n=qn,Kn=Zn,Jn=Object.keys||function(t){return $n(t,Kn)},Qn=Jt,to=he,eo=Gi,io=Jn,no=Kt?Object.defineProperties:function(t,e){to(t);for(var i,n=eo(e),o=io(e),r=o.length,s=0;r>s;)Qn.f(t,i=o[s++],n[i]);return t},oo=W("document","documentElement"),ro=he,so=no,ao=Zn,lo=ri,ho=oo,uo=ie,co=oi("IE_PROTO"),po=function(){},fo=function(t){return" - - diff --git a/situation-overview-web/src/api/user.js b/situation-overview-web/src/api/user.js deleted file mode 100644 index f03218be..00000000 --- a/situation-overview-web/src/api/user.js +++ /dev/null @@ -1,21 +0,0 @@ -import request from './request' - -export const getUserList = () => { - return request.get('/users') -} - -export const getUserById = (id) => { - return request.get(`/users/${id}`) -} - -export const createUser = (data) => { - return request.post('/users', data) -} - -export const updateUser = (id, data) => { - return request.put(`/users/${id}`, data) -} - -export const deleteUser = (id) => { - return request.delete(`/users/${id}`) -} diff --git a/situation-overview-web/src/common/actionStatus.js b/situation-overview-web/src/common/actionStatus.js deleted file mode 100644 index ed080ebf..00000000 --- a/situation-overview-web/src/common/actionStatus.js +++ /dev/null @@ -1,7 +0,0 @@ -export default { - 0: "待签收", - 10: "待分析", - 20: "CEH中", - 25: "CEH完成", - 23: '已终止', -}; diff --git a/situation-overview-web/src/common/chatData.js b/situation-overview-web/src/common/chatData.js deleted file mode 100644 index f7c1e8a1..00000000 --- a/situation-overview-web/src/common/chatData.js +++ /dev/null @@ -1,12 +0,0 @@ -export const deepCopy = (data) => { - return JSON.parse(JSON.stringify(data)); -} - -export const uniqueById = (array) => { - return array.reduce((acc, item) => { - if (!acc.find(x => x.id === item.id)) { - acc.push(item); - } - return acc; - }, []); -}; \ No newline at end of file diff --git a/situation-overview-web/src/common/sourceType.js b/situation-overview-web/src/common/sourceType.js deleted file mode 100644 index 83614d0b..00000000 --- a/situation-overview-web/src/common/sourceType.js +++ /dev/null @@ -1,4 +0,0 @@ -export default { - 0: "本系统创建", - 1: "来自于B3", -}; diff --git a/situation-overview-web/src/common/taskLevel.js b/situation-overview-web/src/common/taskLevel.js deleted file mode 100644 index 87479fde..00000000 --- a/situation-overview-web/src/common/taskLevel.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - 1: "一般", - 2: "紧急", - 3: "加急", -}; diff --git a/situation-overview-web/src/common/taskStatus.js b/situation-overview-web/src/common/taskStatus.js deleted file mode 100644 index e61665c3..00000000 --- a/situation-overview-web/src/common/taskStatus.js +++ /dev/null @@ -1,16 +0,0 @@ -export default { - 0: "待签收", - 10: "待分析", - 20: "分析中", - 25: "分析完成已提交", - 30: "已分析待审核", - 40: "分析审核通过", - 50: "分析审核未通过", - 60: "行动已下发待签收", - 70: "行动已签收待策划", - 80: "行动策划已提交", - 90: "作战方案已提交", - 100: "作战方案待审核", - 110: "作战方案已审核", - 120: "作战方案未通过", -}; diff --git a/situation-overview-web/src/components/AIChatExtract/index.vue b/situation-overview-web/src/components/AIChatExtract/index.vue deleted file mode 100644 index 699de70d..00000000 --- a/situation-overview-web/src/components/AIChatExtract/index.vue +++ /dev/null @@ -1,36 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/ActionOverview.vue b/situation-overview-web/src/components/ActionOverview.vue deleted file mode 100644 index f2d7dcb7..00000000 --- a/situation-overview-web/src/components/ActionOverview.vue +++ /dev/null @@ -1,702 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/ActionPlanning.vue b/situation-overview-web/src/components/ActionPlanning.vue deleted file mode 100644 index 5bbd66f0..00000000 --- a/situation-overview-web/src/components/ActionPlanning.vue +++ /dev/null @@ -1,448 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/ActionPlanning/PerformanceEvaluation.vue b/situation-overview-web/src/components/ActionPlanning/PerformanceEvaluation.vue deleted file mode 100644 index 60406bb8..00000000 --- a/situation-overview-web/src/components/ActionPlanning/PerformanceEvaluation.vue +++ /dev/null @@ -1,242 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/HelloWorld.vue b/situation-overview-web/src/components/HelloWorld.vue deleted file mode 100644 index 546ebbc6..00000000 --- a/situation-overview-web/src/components/HelloWorld.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/InfoChatView/index.vue b/situation-overview-web/src/components/InfoChatView/index.vue deleted file mode 100644 index afc8509a..00000000 --- a/situation-overview-web/src/components/InfoChatView/index.vue +++ /dev/null @@ -1,549 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/Overview/index.vue b/situation-overview-web/src/components/Overview/index.vue deleted file mode 100644 index 548294e3..00000000 --- a/situation-overview-web/src/components/Overview/index.vue +++ /dev/null @@ -1,206 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/SentimentAnalysis.vue b/situation-overview-web/src/components/SentimentAnalysis.vue deleted file mode 100644 index 550a5a46..00000000 --- a/situation-overview-web/src/components/SentimentAnalysis.vue +++ /dev/null @@ -1,132 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/SentimentAnalysis/AssessmentContent.vue b/situation-overview-web/src/components/SentimentAnalysis/AssessmentContent.vue deleted file mode 100644 index a24e0e32..00000000 --- a/situation-overview-web/src/components/SentimentAnalysis/AssessmentContent.vue +++ /dev/null @@ -1,359 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/SentimentAnalysis/BattlefieldEnvironment.vue b/situation-overview-web/src/components/SentimentAnalysis/BattlefieldEnvironment.vue deleted file mode 100644 index 69eaa0a4..00000000 --- a/situation-overview-web/src/components/SentimentAnalysis/BattlefieldEnvironment.vue +++ /dev/null @@ -1,358 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/SentimentAnalysis/DeterminationContent.vue b/situation-overview-web/src/components/SentimentAnalysis/DeterminationContent.vue deleted file mode 100644 index 1f906f76..00000000 --- a/situation-overview-web/src/components/SentimentAnalysis/DeterminationContent.vue +++ /dev/null @@ -1,544 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/SentimentAnalysis/EnemySituation.vue b/situation-overview-web/src/components/SentimentAnalysis/EnemySituation.vue deleted file mode 100644 index 4683719f..00000000 --- a/situation-overview-web/src/components/SentimentAnalysis/EnemySituation.vue +++ /dev/null @@ -1,424 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/SentimentAnalysis/HandleContent.vue b/situation-overview-web/src/components/SentimentAnalysis/HandleContent.vue deleted file mode 100644 index a807f8bd..00000000 --- a/situation-overview-web/src/components/SentimentAnalysis/HandleContent.vue +++ /dev/null @@ -1,488 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/SentimentAnalysis/JudgmentConclusion.vue b/situation-overview-web/src/components/SentimentAnalysis/JudgmentConclusion.vue deleted file mode 100644 index 3e1f9a8a..00000000 --- a/situation-overview-web/src/components/SentimentAnalysis/JudgmentConclusion.vue +++ /dev/null @@ -1,223 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/SentimentAnalysis/StrategyOverview.vue b/situation-overview-web/src/components/SentimentAnalysis/StrategyOverview.vue deleted file mode 100644 index fd0ec950..00000000 --- a/situation-overview-web/src/components/SentimentAnalysis/StrategyOverview.vue +++ /dev/null @@ -1,270 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/SentimentAnalysis/SuggestionContent.vue b/situation-overview-web/src/components/SentimentAnalysis/SuggestionContent.vue deleted file mode 100644 index 046d08ae..00000000 --- a/situation-overview-web/src/components/SentimentAnalysis/SuggestionContent.vue +++ /dev/null @@ -1,67 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/SituationAssessment.vue b/situation-overview-web/src/components/SituationAssessment.vue deleted file mode 100644 index df9bf3f0..00000000 --- a/situation-overview-web/src/components/SituationAssessment.vue +++ /dev/null @@ -1,548 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/TaskAnalysis.vue b/situation-overview-web/src/components/TaskAnalysis.vue deleted file mode 100644 index d201caf0..00000000 --- a/situation-overview-web/src/components/TaskAnalysis.vue +++ /dev/null @@ -1,35 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/TaskAnalysis/AnalysisData.vue b/situation-overview-web/src/components/TaskAnalysis/AnalysisData.vue deleted file mode 100644 index 2d92e778..00000000 --- a/situation-overview-web/src/components/TaskAnalysis/AnalysisData.vue +++ /dev/null @@ -1,719 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/TaskAnalysis/TaskDataList.vue b/situation-overview-web/src/components/TaskAnalysis/TaskDataList.vue deleted file mode 100644 index 1085aa53..00000000 --- a/situation-overview-web/src/components/TaskAnalysis/TaskDataList.vue +++ /dev/null @@ -1,142 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/TaskAnalysis/TaskDataSearch.vue b/situation-overview-web/src/components/TaskAnalysis/TaskDataSearch.vue deleted file mode 100644 index 14d2654a..00000000 --- a/situation-overview-web/src/components/TaskAnalysis/TaskDataSearch.vue +++ /dev/null @@ -1,367 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/TaskDetails.vue b/situation-overview-web/src/components/TaskDetails.vue deleted file mode 100644 index 2807006c..00000000 --- a/situation-overview-web/src/components/TaskDetails.vue +++ /dev/null @@ -1,335 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/TaskDetails/BattlefieldEnvironment.vue b/situation-overview-web/src/components/TaskDetails/BattlefieldEnvironment.vue deleted file mode 100644 index f59c8b06..00000000 --- a/situation-overview-web/src/components/TaskDetails/BattlefieldEnvironment.vue +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - diff --git a/situation-overview-web/src/components/TaskDetails/EnemySituation.vue b/situation-overview-web/src/components/TaskDetails/EnemySituation.vue deleted file mode 100644 index 05812810..00000000 --- a/situation-overview-web/src/components/TaskDetails/EnemySituation.vue +++ /dev/null @@ -1,773 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/TaskDetails/OurSituation.vue b/situation-overview-web/src/components/TaskDetails/OurSituation.vue deleted file mode 100644 index 1d4fe614..00000000 --- a/situation-overview-web/src/components/TaskDetails/OurSituation.vue +++ /dev/null @@ -1,548 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/TaskDetails/Power.vue b/situation-overview-web/src/components/TaskDetails/Power.vue deleted file mode 100644 index b525b3bb..00000000 --- a/situation-overview-web/src/components/TaskDetails/Power.vue +++ /dev/null @@ -1,94 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/TaskDetails/component/Resources.vue b/situation-overview-web/src/components/TaskDetails/component/Resources.vue deleted file mode 100644 index ceaab426..00000000 --- a/situation-overview-web/src/components/TaskDetails/component/Resources.vue +++ /dev/null @@ -1,514 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/Template.vue b/situation-overview-web/src/components/Template.vue deleted file mode 100644 index 4b3150dc..00000000 --- a/situation-overview-web/src/components/Template.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/TreeDataMap.vue b/situation-overview-web/src/components/TreeDataMap.vue deleted file mode 100644 index 120ae624..00000000 --- a/situation-overview-web/src/components/TreeDataMap.vue +++ /dev/null @@ -1,337 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/details-dialog/DocDetails.vue b/situation-overview-web/src/components/details-dialog/DocDetails.vue deleted file mode 100644 index 94ebff4e..00000000 --- a/situation-overview-web/src/components/details-dialog/DocDetails.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/dialog/AddTaskDialog.vue b/situation-overview-web/src/components/dialog/AddTaskDialog.vue deleted file mode 100644 index 90076585..00000000 --- a/situation-overview-web/src/components/dialog/AddTaskDialog.vue +++ /dev/null @@ -1,310 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/dialog/CommonInfoDialog.vue b/situation-overview-web/src/components/dialog/CommonInfoDialog.vue deleted file mode 100644 index 7ed2c016..00000000 --- a/situation-overview-web/src/components/dialog/CommonInfoDialog.vue +++ /dev/null @@ -1,137 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/graph/G6NetworkGraph.vue b/situation-overview-web/src/components/graph/G6NetworkGraph.vue deleted file mode 100644 index 8a95ed00..00000000 --- a/situation-overview-web/src/components/graph/G6NetworkGraph.vue +++ /dev/null @@ -1,1330 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/graph/modal/components/Audience.vue b/situation-overview-web/src/components/graph/modal/components/Audience.vue deleted file mode 100644 index 4165f01e..00000000 --- a/situation-overview-web/src/components/graph/modal/components/Audience.vue +++ /dev/null @@ -1,176 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/graph/modal/components/Strategy.vue b/situation-overview-web/src/components/graph/modal/components/Strategy.vue deleted file mode 100644 index 8d388402..00000000 --- a/situation-overview-web/src/components/graph/modal/components/Strategy.vue +++ /dev/null @@ -1,195 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/graph/modal/components/Yqxg.vue b/situation-overview-web/src/components/graph/modal/components/Yqxg.vue deleted file mode 100644 index b371a5d7..00000000 --- a/situation-overview-web/src/components/graph/modal/components/Yqxg.vue +++ /dev/null @@ -1,365 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/graph/modal/index.vue b/situation-overview-web/src/components/graph/modal/index.vue deleted file mode 100644 index 9008bd84..00000000 --- a/situation-overview-web/src/components/graph/modal/index.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/intelligent-helper-drawer/AnalysisTool.vue b/situation-overview-web/src/components/intelligent-helper-drawer/AnalysisTool.vue deleted file mode 100644 index 0a8000f8..00000000 --- a/situation-overview-web/src/components/intelligent-helper-drawer/AnalysisTool.vue +++ /dev/null @@ -1,114 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/intelligent-helper-drawer/ChatContent.vue b/situation-overview-web/src/components/intelligent-helper-drawer/ChatContent.vue deleted file mode 100644 index 76e7222d..00000000 --- a/situation-overview-web/src/components/intelligent-helper-drawer/ChatContent.vue +++ /dev/null @@ -1,67 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/intelligent-helper-drawer/ChatList.vue b/situation-overview-web/src/components/intelligent-helper-drawer/ChatList.vue deleted file mode 100644 index 2509adb9..00000000 --- a/situation-overview-web/src/components/intelligent-helper-drawer/ChatList.vue +++ /dev/null @@ -1,373 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/intelligent-helper-drawer/IntelligentHelperDrawer.vue b/situation-overview-web/src/components/intelligent-helper-drawer/IntelligentHelperDrawer.vue deleted file mode 100644 index 62ea9116..00000000 --- a/situation-overview-web/src/components/intelligent-helper-drawer/IntelligentHelperDrawer.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/intelligent-helper-drawer/InteractiveAnalysis.vue b/situation-overview-web/src/components/intelligent-helper-drawer/InteractiveAnalysis.vue deleted file mode 100644 index f20cd9cb..00000000 --- a/situation-overview-web/src/components/intelligent-helper-drawer/InteractiveAnalysis.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/markdown/CodeData.vue b/situation-overview-web/src/components/markdown/CodeData.vue deleted file mode 100644 index 3f049caa..00000000 --- a/situation-overview-web/src/components/markdown/CodeData.vue +++ /dev/null @@ -1,194 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/scrollingloading/index.vue b/situation-overview-web/src/components/scrollingloading/index.vue deleted file mode 100644 index cfc1cd82..00000000 --- a/situation-overview-web/src/components/scrollingloading/index.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - - \ No newline at end of file diff --git a/situation-overview-web/src/components/searchTaskList/index.vue b/situation-overview-web/src/components/searchTaskList/index.vue deleted file mode 100644 index d6cf6946..00000000 --- a/situation-overview-web/src/components/searchTaskList/index.vue +++ /dev/null @@ -1,391 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/shared/Empty.vue b/situation-overview-web/src/components/shared/Empty.vue deleted file mode 100644 index c9678229..00000000 --- a/situation-overview-web/src/components/shared/Empty.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/views/PieChart.vue b/situation-overview-web/src/components/views/PieChart.vue deleted file mode 100644 index 10326129..00000000 --- a/situation-overview-web/src/components/views/PieChart.vue +++ /dev/null @@ -1,279 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/components/views/TabsContent.vue b/situation-overview-web/src/components/views/TabsContent.vue deleted file mode 100644 index 768e14b2..00000000 --- a/situation-overview-web/src/components/views/TabsContent.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/main.js b/situation-overview-web/src/main.js deleted file mode 100644 index 412c3ac8..00000000 --- a/situation-overview-web/src/main.js +++ /dev/null @@ -1,17 +0,0 @@ -import { createApp } from "vue"; -import TDesign from "tdesign-vue-next"; -import "tdesign-vue-next/es/style/index.css"; -import "leaflet/dist/leaflet.css"; -import "./style.css"; -import "./style/theme.less"; -import "./style/tdesign-style.less"; -import "./assets/markdown-css/github-markdown.css"; -import App from "./App.vue"; -import store from "./store"; -import router from "./router"; -const app = createApp(App); - -app.use(store); -app.use(router); -app.use(TDesign); -app.mount("#app"); diff --git a/situation-overview-web/src/router/index.js b/situation-overview-web/src/router/index.js deleted file mode 100644 index 60946822..00000000 --- a/situation-overview-web/src/router/index.js +++ /dev/null @@ -1,91 +0,0 @@ -import { path } from "d3"; -import { createRouter, createWebHashHistory } from "vue-router"; - -const routes = [ - { - path: "/", - redirect: "/situation-overview", - }, - // { - // path: "/test", - // component: () => import("@/views/situation-overview.vue"), - // }, - { - path: "/situation-overview", - component: () => import("@/views/situation-overview/index.vue"), - redirect: "/situation-overview/action", - children: [ - { - path: "/situation-overview/monitoring", - name: "监测模式", - }, - { - path: "action", - name: "行动模式", - redirect: "/situation-overview/action/sentiment", - children: [ - { - path: "sentiment", - component: () => import("@/views/sentiment/index.vue"), - }, - { - path: "task", - component: () => import("@/views/task/index.vue"), - }, - { - path: "action", - component: () => import("@/views/action/index.vue"), - }, - { - path: "reply", - component: () => import("@/views/reply/index.vue"), - }, - { - path: "control", - component: () => import("@/views/control/index.vue"), - }, - { - path: "homeoverview", - component: () => import("@/views/homeOverview/index.vue"), - }, - ], - }, - { - path: "query", - name: "查询模式", - }, - ], - }, - { - path: "/dashboard", - name: "Dashboard", - component: () => import("@/views/Dashboard.vue"), - }, - { - path: "/chart", - name: "Chart", - component: () => import("../views/Chart.vue"), - }, - { - path: "/map", - name: "Map", - component: () => import("../views/Map.vue"), - }, - { - path: "/graph", - name: "Graph", - component: () => import("../views/Graph.vue"), - }, - { - path: "/GroupContent", - name: "GroupContent", - component: () => import("../views/GroupContent.vue"), - }, -]; - -const router = createRouter({ - history: createWebHashHistory(), - routes, -}); - -export default router; diff --git a/situation-overview-web/src/service/request-axios-service.js b/situation-overview-web/src/service/request-axios-service.js deleted file mode 100644 index 3292d616..00000000 --- a/situation-overview-web/src/service/request-axios-service.js +++ /dev/null @@ -1,47 +0,0 @@ -import service from "../utils/request"; -export const requestAxiosService = { - get: async (endpoint, params = {}) => { - try { - const response = await service.get(endpoint, { params }); - return response; - } catch (error) { - throw new Error(`GET request failed: ${error.message}`); - } - }, - - post: async (endpoint, data = {}) => { - try { - const response = await service.post(endpoint, data); - return response; - } catch (error) { - throw new Error(`POST request failed: ${error.message}`); - } - }, - - put: async (endpoint, data = {}) => { - try { - const response = await service.put(endpoint, data); - return response; - } catch (error) { - throw new Error(`PUT request failed: ${error.message}`); - } - }, - - update: async (endpoint, data = {}) => { - try { - const response = await service.patch(endpoint, data); - return response; - } catch (error) { - throw new Error(`patch request failed: ${error.message}`); - } - }, - - delete: async (endpoint) => { - try { - const response = await service.delete(endpoint); - return response; - } catch (error) { - throw new Error(`DELETE request failed: ${error.message}`); - } - } -} \ No newline at end of file diff --git a/situation-overview-web/src/service/request-crud.service.js b/situation-overview-web/src/service/request-crud.service.js deleted file mode 100644 index 35331233..00000000 --- a/situation-overview-web/src/service/request-crud.service.js +++ /dev/null @@ -1,141 +0,0 @@ -import { environment } from '@/environments/environment'; -import { requestCrudService } from '@/service/request-axios-service'; - -export interface GetOneParam { - fields?: string[]; // 指定返回的字段 id,name - join?: string[]; // 指定关联表,如 ['user||id,name', 'relation||id'] - cache?: 0 | 1; // 0直接DB,1缓存,默认1缓存 -} -export interface GetAllParam { - fields?: string[] | string; // 指定返回的字段: 多个字段如 'id', 'name' - filter?: string[]; // 指定过滤条件,如 ['name||$eq||batman', 'id||$in||1,2,3', 'field||$isnull', 'relation.id||$eq||1'] - or?: string[]; // 同filter - join?: string[]; // 指定关联表,如 ['user||id,name', 'relation||id'] - cache?: 0 | 1; // 0直接DB,1缓存,默认1缓存 - page?: number; // 页码(会被转换成offset) - offset?: number; // 偏移量 - limit?: number; // 每页数量 - sort?: string[]; // 排序,如 '['name,ASC', 'id,DESC]' - s?: string; - joinTaskAction?: boolean; //是否连行动表查询 - joinTaskActionBoci?: boolean; //策略分析列表使用 -} - -export interface GetAllResponse { - data: any[]; - page: number; - pageCount: number; - count: number; - total: number; - errMsg?: string; -} -let deepCopy = (str: any) => { - return JSON.parse(JSON.stringify(str)); -} -export class RequestCrudService { - - /** - * 获取单个对象 - * @param url 地址 - * @param id ID - * @param params 参数 - * @returns 单个对象 - */ - async getOne(url: string, id: number, params?: GetOneParam): Promise { - const getUrl = `${url}/${id}`; - const res = await requestCrudService.get(getUrl, params); - if (res) return res; - // this.notification.create('error', getUrl, `${res.data}`); - return {}; - } - /** - * 获取多个对象 - * @param url 地址 - * @param params 参数 - * @returns 多个对象数组 - */ - async getAll(url: string, params: GetAllParam | null = null): Promise { - const formattedParams = deepCopy(params || {}); - // 分页默认值 - if (!params || !params.limit) formattedParams.limit = 999; - if (!params || !params.page) formattedParams.page = 1; - // 计算offset - if (params && formattedParams.page) { - formattedParams.offset = (formattedParams.page - 1) * formattedParams.limit!; - delete formattedParams.page; - } - const res = await requestCrudService.get(url, formattedParams); - if (res.status === 200) return res.data; - // this.notification.create('error', url, `${res.data}`); - return { - count: 0, - data: [], - page: 1, - pageCount: 1, - total: 0 - }; - } - /** - * 创建单个对象 - * @param url 地址 - * @param data 单个对象 - * @returns 被创建的单个对象 - */ - async createOne(url: string, data: any) { - const res = await requestCrudService.post(url, data); - if (res.status === 201) return res.data; - // this.notification.create('error', url, `${res.data}`); - return {}; - } - /** - * 创建多个对象 - * @param url 地址 - * @param data 多个对象 - * @returns 被创建的多个对象 - */ - async createMulti(url: string, data: any[]) { - const res = await requestCrudService.post(url, { - bulk: data - }); - if (res.status === 201) return res.data; - // this.notification.create('error', url, `${res.data}`); - return []; - } - /** - * 更新单个对象 - * @param url 地址 - * @param id ID - * @param data 单个对象部分键值对 - * @returns 被修改的单个对象 - */ - async updateOne(url: string, id: number, data: any) { - const res = await requestCrudService.update(`${url}/${id}`, data); - if (res.status === 200) return res.data; - // this.notification.create('error', url, `${res.data}`); - return {}; - } - /** - * 删除单个对象 - * @param url 地址 - * @param id ID - * @returns 操作结果 - */ - async deleteOne(url: string, id: number) { - const res = await requestCrudService.delete(`${url}/${id}`); - if (res.status === 200) return res.data; - // this.notification.create('error', url, `${res.data}`); - return 'error'; - } - // get 请求 - async simpleGet(url: string, params?: any): Promise { - const res = await requestCrudService.get(url, params); - if (res.status === 200) return res.data; - return res.data; - } - // post 请求 - async simplePost(url: string, data: any) { - const res = await requestCrudService.post(url, data); - if (res.status === 200) return res.data; - return res.data; - } -} diff --git a/situation-overview-web/src/store/index.js b/situation-overview-web/src/store/index.js deleted file mode 100644 index ec78060c..00000000 --- a/situation-overview-web/src/store/index.js +++ /dev/null @@ -1,43 +0,0 @@ -import { createStore } from 'vuex' - -export default createStore({ - state: { - count: 0, - user: null, - taskData: null, - targetList: [], - targetData: null, - actionOverview: null, - }, - getters: { - doubleCount: (state) => state.count * 2 - }, - mutations: { - increment(state) { - state.count++ - }, - setUser(state, user) { - state.user = user - }, - setTaskData(state, value) { - state.taskData = value; - }, - setTargetList(state,value) { - state.targetList = value - }, - setTargetData(state,value) { - state.targetData = value - }, - setActionOverview(state,value) { - state.actionOverview = value; - } - }, - actions: { - incrementAsync({ commit }) { - setTimeout(() => { - commit('increment') - }, 1000) - } - }, - modules: {} -}) diff --git a/situation-overview-web/src/style.css b/situation-overview-web/src/style.css deleted file mode 100644 index e69de29b..00000000 diff --git a/situation-overview-web/src/style/tdesign-style.less b/situation-overview-web/src/style/tdesign-style.less deleted file mode 100644 index f575bb11..00000000 --- a/situation-overview-web/src/style/tdesign-style.less +++ /dev/null @@ -1,134 +0,0 @@ -:root { - --td-brand-color-8: '#0062d9'; -} -.t-input { - border-color: var(--td-brand-color); -} - -.t-range-input { - border-color: var(--td-brand-color); -} - -.t-layout, .t-layout__direction-vertical { - background: none; -} - -.t-layout__sider { - background: none; -} - - -// 对话框样式 -.t-dialog { - background: #0f2844 !important; - border: 1px solid; - border-color: #2b8ffe99; - padding: 20px 25px; - border-radius: 4px; -} - -.t-dialog__header { - border-radius: 4px 4px 0 0; - padding: 20px 25px; - padding-top: 0; - box-shadow: none !important; - position: relative; - font-weight: 500; - color: #fff; - font-size: 25px; - background: url('../assets/icon/title-header-logo.svg') no-repeat bottom center !important; -} - -.t-dialog__header .t-dialog__header-content { - justify-content: center; -} - -.t-button--variant-base { - color: #FFFFFF; - background: rgba(3, 38, 80, 0.8); - border-color: rgba(43, 143, 254, 0.6); -} - -.t-button--variant-base.t-button--theme-primary { - background: linear-gradient(102.76deg, #2b8ffe 0%, #0062d9 100%); -} - -.t-drawer__close-btn { - display: none; -} - -// 抽屉样式 -.t-drawer__content-wrapper { - background: #021e3e; -} -.t-drawer__header { - background: linear-gradient(90deg, #0062d9 0%, rgba(0, 98, 217, 0) 100%); - border-bottom: 2px solid; - border-color: rgba(255, 255, 255, 0.2); -} -.t-drawer__body { - background: #021e3e; -} - -// 标签页 - -.t-tabs { - background-color: transparent; -} - -.t-tabs__nav-item.t-is-active { - font-size: var(--fontSize); - font-family: Noto Sans S Chinese; - font-weight: 500; - color: #0062d9; -} - -.t-tabs__nav-item { - font-size: var(--fontSize); -} - -.t-tabs__bar { - background-color: #0062d9; -} - -.t-tabs__nav-container.t-is-top::after { - background: rgba(85, 159, 254, 0.2); -} - -.t-tabs__nav-item:not(.t-is-disabled):not(.t-is-active):hover .t-tabs__nav-item-wrapper{ - background: rgba(255, 255, 255, 0.1); -} - -.t-tabs__btn { - background: rgba(3, 38, 80, 0.8); - border-color: #053e59 !important; -} - -.t-tabs__btn:hover { - background: rgba(3, 38, 80, 0.8); -} - -.t-tabs__nav-item.t-size-m { - line-height: 18px; - height:auto; -} - -.t-tabs__nav--card.t-tabs__nav-item:not(.t-is-disabled):not(.t-is-active):hover { - background:linear-gradient(103.13deg,#2b8ffe 0%,#0062d9 100%); - border-radius:24px; -} - -// 单选框样式 -.t-radio-group.t-radio-group--filled{ - background-color: #08527b; - border-color: #08527b; -} - -.t-radio-group.t-radio-group--filled .t-radio-button.t-is-checked { - background-color: #07324c; -} - -.markdown-body{ - background: transparent !important; - color: #FFFFFF !important; -} \ No newline at end of file diff --git a/situation-overview-web/src/style/theme.less b/situation-overview-web/src/style/theme.less deleted file mode 100644 index b76c69a3..00000000 --- a/situation-overview-web/src/style/theme.less +++ /dev/null @@ -1,676 +0,0 @@ -:root { - --color-main: #0062d9; - --bg-color: #012044; - --fontSize: 18px; - --titleSize: 20px; - --fontSizes: 16px; - --chatSize: calc(18 * var(--px-to-vw)); - --router-bg-color: #f8ccce; - --three-color: #fbd8da; - --task-button-bgcolor: #feeded; - --tag-border-color: #006efe; - --antd-wave-shadow-color: #ce2d39; - --border-color: linear-gradient(180deg, #f86c73, #ce1322); - --theme-img: url("/assets/icon/layout-bg-theme-red.png"); - --them-icon: url("/assets/icon/pxcook-red.png"); - --ant-modal-header: url("/assets/overiew-logo/ant-modal-header-bg.svg"); - --theme-area-bg: rgba(3, 38, 80, 0.6); - --theme-area-border-color: rgba(43, 143, 254, 0.6); - --theme-box-shadow: 0px 8px var(--fontSize) rgba(139, 139, 139, 0.06); - --theme-font-color: #ffffff; - --theme-font-text: rgba(255, 255, 255, 0.6); - --theme-font-details: rgba(255, 255, 255, 0.8); - --theme-card-bg: rgba(0, 98, 217, 0.2); - --theme-card-border: rgba(85, 166, 254, 0.1); - --theme-card-active: rgba(0, 98, 217, 0.4); - --theme-active-border: #0062d9; - --theme-border-color: #559ffe; - --index-color: #ffffff; - --extract-content-bg: rgba(3, 38, 80, 0.6); - --logo-color: #45c3f3; - --user-item-bg: rgba(0, 98, 217, 0.3); - --chat-item-bg: rgba(0, 98, 217, 0.2); - --chat-content-bg: rgba(0, 98, 217, 0.1); - --think-content-bg: rgba(0, 98, 217, 0.2); - --think-border-color: #0062d9; - --think-logo-color: #45c3f3; - --think-font-color: rgba(255, 255, 255, 0.6); - --chat-source-color: #0079fe; - --chat-source-bg: rgba(0, 98, 217, 0.2); - --extraction-content-bg: #00368c; - --extraction-content-border: #0056c6; - --extraction-content-color: rgba(255, 255, 255, 0.8); - --chat-input-border: #0062d9; - --list-item-bg: var(--chat-item-bg); - --list-item-border: var(--theme-card-border); - --list-item-active: var(--theme-card-active); - --list-item-active-border: var(--theme-active-border); - --drawer-bg-color: #021e3e; - --table-border-color: #1592e6; - --table-bg-color: #01316d; - --time-range-th-bg-color: #012b6e; - --time-range-th-font-color: #ffffff; - --time-range-border-color: #006efe; - --time-range-font-color: #2b86fe; - --time-range-icon-color: #022043; - --time-range-tag-bg-color: #02387a; - --grap-container-bg: var(--chat-item-bg); - --full-screen: var(--bg-color); - --xwt-linear-gradient: linear-gradient(165.07deg, #0066cc 0%, #003366 100%); - --card-border: rgba(43, 143, 254, 0.6); - --item-borer-line: rgba(85, 159, 254, 0.2); - --gray-color: rgba(255, 255, 255, 0.6); - --item-index: var(--color-main); - --item-active-color: #0062d9; - --item-expand-color: #002c57; - --item-expand-active: #002d61; - --tag-bg-color: rgba(69, 195, 243, 0.5); - --theme-option-color: #023064; - --tag-border-bg: rgba(43, 143, 254, 0.6); - --file-tag-color: rgba(43, 143, 254, 0.6); - --ant-title-color: rgba(255, 255, 255, 0.8); - /* --heightVh: 920px; */ -} - -@font-face { - font-family: DDIN; - font-weight: normal; - src: url("../assets/font/D-Din/D-DIN.ttf"); - unicode-range: U+0030-0039; -} - -@font-face { - font-family: DDINBold; - font-weight: bold; - src: url("../assets/font/D-Din/D-DIN-Bold.ttf"); - unicode-range: U+0030-0039; -} - -@font-face { - font-family: Douyu; - src: url("../assets/font/DouyuFont/douyuFont-2.otf") format("opentype"); -} - -@font-face { - font-family: Noto Sans S Chinese; - font-weight: 100; - src: url("../assets/font/NotoSansHans/NotoSansHans-Thin-Windows.otf") - format("opentype"); -} - -@font-face { - font-family: Noto Sans S Chinese; - font-weight: 300; - src: url("../assets/font/NotoSansHans/NotoSansHans-Light.otf") - format("opentype"); -} - -@font-face { - font-family: Noto Sans S Chinese; - font-weight: 400; - src: url("../assets/font/NotoSansHans/NotoSansHans-Regular.otf") - format("opentype"); -} - -@font-face { - font-family: Noto Sans S Chinese; - font-weight: 500; - src: url("../assets/font/NotoSansHans/NotoSansHans-Medium.otf") - format("opentype"); -} - -@font-face { - font-family: Noto Sans S Chinese; - font-weight: 700; - src: url("../assets/font/NotoSansHans/NotoSansHans-Bold.otf") - format("opentype"); -} - -@font-face { - font-family: Noto Sans S Chinese; - font-weight: 900; - src: url("../assets/font/NotoSansHans/NotoSansHans-Black.otf") - format("opentype"); -} - -@font-face { - font-family: DS-Digital; - font-weight: 300; - src: url("../assets/font/DS-Digital/DS-DIGI-1.ttf") format("opentype"); -} - -@font-face { - font-family: DS-Digital; - font-weight: 400; - src: url("../assets/font/DS-Digital/DS-DIGIB-2.ttf") format("opentype"); -} - -@font-face { - font-family: DS-Digital; - font-weight: 500; - src: url("../assets/font/DS-Digital/DS-DIGII-3.ttf") format("opentype"); -} - -@font-face { - font-family: DS-Digital; - font-weight: 700; - src: url("../assets/font/DS-Digital/DS-DIGIT-4.ttf") format("opentype"); -} - -// flex 布局 -.flex-center-center { - display: flex; - justify-content: center; - align-items: center; -} - -.flex-start-center { - display: flex; - justify-content: flex-start; - align-items: center; -} - -.flex-start-baseline { - display: flex; - justify-content: flex-start; - align-items: baseline; -} - -.flex-start-start { - display: flex; - justify-content: flex-start; - align-items: start; -} - -.flex-end-center { - display: flex; - justify-content: flex-end; - align-items: center; -} - -.flex-end-start { - display: flex; - justify-content: flex-end; - align-items: start; -} - -.flex-between-center { - display: flex; - justify-content: space-between; - align-items: center; -} - -.flex-between-baseline { - display: flex; - justify-content: space-between; - align-items: baseline; -} - -.flex-between-start { - display: flex; - justify-content: space-between; - align-items: flex-start; -} - -.flex-content { - display: flex; - justify-content: space-between; -} - -.font-weight-bold { - font-family: "Noto Sans S Chinese"; - font-weight: 700; -} - -.margin-bottom-5 { - margin-bottom: 5px; -} - -.margin-bottom-10 { - margin-bottom: 10px; -} - -.margin-bottom-15 { - margin-bottom: 15px; -} - -.margin-top-5 { - margin-top: 5px; -} - -.margin-top-10 { - margin-top: 10px; -} - -.margin-top-15 { - margin-top: 15px; -} - -.padding-10 { - padding: 10px; -} - -.cursor-pointer { - cursor: pointer; -} - -// 字体设置 -span, -p, -div, -li { - font-family: "Noto Sans S Chinese"; -} - -.markdown-body table tr { - background: transparent !important; -} - -// 单选框样式 -.tabs-box { - .sortBtn { - font-size: var(--fontSize); - line-height: var(--fontSize); - color: #fff; - display: inline-block; - padding: 5px 10px; - border-radius: 4px; - border: 1px solid #2b8ffe99 !important; - margin: 0 5px; - cursor: pointer; - } - - .sort-active { - background: linear-gradient(123.69deg, #2b8ffe, #0062d9) !important; - } -} - -// tab颜色 -.tab-green { - background: rgba(0, 140, 119, 0.5); - border-color: #008c77 !important; -} - -.tab-blue { - background: rgba(0, 121, 254, 0.1); - border-color: #0079fe !important; -} - -.tab-lightblue { - background: rgba(69, 195, 243, 0.5); - border-color: #45c3f3 !important; -} - -.tab-yellow { - background: #ff990080; - border-color: #f90 !important; -} - -.tab-red { - background: rgba(207, 19, 34, 0.5); - border-color: #cf1322 !important; -} - -// tab标签页 -.tabs-list { - text-align: center; - - .tabs-item { - background: rgba(0, 12, 28, 0.2); - color: rgba(255, 255, 255, 0.6); - display: inline-block; - font-size: var(--fontSize); - font-family: "Noto Sans S Chinese"; - padding: 5px 15px; - cursor: pointer; - - &:hover { - color: #ffffff; - background: rgba(255, 255, 255, 0.1); - border-bottom: 1.5px solid #ffffff; - } - } - - .item-active { - color: #ffffff; - background: rgba(255, 255, 255, 0.1); - border-bottom: 1.5px solid #ffffff; - } -} - -// 标题 -.title-content-item { - line-height: 22px; - font-family: Noto Sans S Chinese; - font-weight: 500; - color: #ffffff; - font-size: var(--titleSize); - border-bottom: 1px solid rgba(0, 98, 217, 0.4); - padding: 10px 15px; - position: relative; - - &::after { - content: ""; - display: block; - width: 4px; - height: var(--titleSize); - background: linear-gradient(167.47deg, #a2e1f9 0%, #45c3f3 100%); - border-radius: 2px 0px 2px 0px; - position: absolute; - top: 13px; - left: 0px; - } -} - -.drawer-head { - font-size: 20px; - font-family: Noto Sans S Chinese; - font-weight: 300; - display: flex; - align-items: center; - cursor: pointer; - - span { - margin-right: 5px; - } -} - -.chat-source { - color: #80b7ff; - background-color: rgba(85, 159, 254, 0.3); - border-radius: 5px; - padding: 1px 5px; - text-align: center; - width: auto; - height: auto; - font-size: var(--fontSizes); - display: inline-block; - margin: 5px; - cursor: pointer; -} - -.markdown-body hr { - height: 1.5px !important; - background: #559ffe !important; - border-color: #559ffe !important; -} - -// 文字省略号 -.text-ellipsis { - display: -webkit-box; - -webkit-box-orient: vertical; - /* 限制显示的行数 */ - overflow: hidden; - text-overflow: ellipsis; -} - -.ellipsis1 { - -webkit-line-clamp: 1; -} - -.ellipsis2 { - -webkit-line-clamp: 2; -} - -.ellipsis3 { - -webkit-line-clamp: 3; -} - -.ellipsis4 { - -webkit-line-clamp: 4; -} - -.ellipsis5 { - -webkit-line-clamp: 5; -} - -// 逻辑图样式 -.treemap-darkblue { - width: 100%; - // border: 2px solid; - // height: 100%; - color: lightblue; - padding: 0px; - user-select: none; - // padding: 10px; - border: 1px solid; - border-radius: 4px; - background-color: var(--chat-item-bg); - box-sizing: border-box; - box-shadow: 0px 0px 9px rgba(252, 131, 131, 0.27); - - .treemap-title { - border-radius: 0; - } - - .treemap-body { - color: #ffffff; - } - - .node-red { - background: linear-gradient( - 90deg, - rgba(245, 34, 45, 0.5) 0%, - rgba(138, 0, 8, 0.3) 100% - ); - box-shadow: 0px 1px var(--fontSize) rgba(0, 0, 0, 0.08); - } - - .node-orange { - background: rgba(255, 153, 0, 0.5); - border-bottom: 1px solid; - border-color: #ff9900; - } - - .node-yellow { - background: rgba(255, 196, 0, 0.5); - border-bottom: 1px solid; - border-color: #ffc400; - } - - .node-lightblue { - background: rgba(69, 195, 243, 0.5); - border-bottom: 1px solid; - border-color: #45c3f3; - } - - .node-blue { - background: rgba(0, 121, 254, 0.5); - border-bottom: 1px solid; - border-color: #0079fe; - } - - .node-purple { - background: rgba(125, 80, 255, 0.5); - border-bottom: 1px solid; - border-color: #7d50ff; - } -} - -.pulse-content { - width: 34px; - height: 40px; - background: url("../assets/map-icon/map-point.svg") no-repeat; - background-size: cover; - display: flex; - align-items: center; - justify-content: center; - - .user-logo { - width: 26px; - height: 26px; - margin-top: -5px; - border-radius: 50%; - overflow: hidden; - img { - width: 100%; - height: 100%; - } - } -} - -.overiew-content { - width: 400px; - padding: 10px; - box-sizing: border-box; - color: #ffffff; - border: 1px solid #2b8ffe99; - border-radius: 5px; - background-color: rgba(3, 38, 80, 0.8); - position: absolute; - top: -117px; - left: 310px; - z-index: 500; - - .font-weight-bold { - font-size: 17px; - font-family: "Noto Sans S Chinese"; - font-weight: 700; - } - .overiew-head { - padding: 10px 0; - display: flex; - align-items: center; - justify-content: space-between; - .user-logo { - width: 60px; - height: 60px; - border-radius: 50%; - overflow: hidden; - img { - width: 100%; - height: 100%; - vertical-align: middle; - object-fit: cover; - } - } - .user-right { - flex: 1; - margin-left: 10px; - .user-title { - font-family: Noto Sans S Chinese; - font-weight: 500; - color: #fff; - font-size: 18px; - line-height: 24px; - } - .user-text { - font-family: Noto Sans S Chinese; - font-weight: 300; - color: #fff; - font-size: 16px; - line-height: 26px; - margin-top: 4px; - } - } - } - .overiew-body { - padding: 10px 0; - .typeLabel { - margin: 5px; - line-height: 28px; - font-family: Noto Sans S Chinese; - font-weight: 500; - color: #55a6fe; - font-size: 16px; - display: flex; - align-items: center; - .details-logo { - width: 20px; - height: 14px; - background: url("../assets/icon/make-logo.svg") no-repeat; - background-size: cover; - margin-right: 5px; - } - } - .text-content { - font-family: Noto Sans S Chinese; - font-size: 16px; - padding: 0 10px; - } - } - - .item-line { - border-bottom: 1px solid #2b8ffe99; - } - - &::after { - content: ""; - width: 200px; - height: 80px; - display: block; - background: url("../assets/map-icon/line-logo.png") no-repeat; - z-index: 1000; - position: absolute; - top: 75px; - left: -112px; - } - - .text-content { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - overflow: hidden; - word-break: break-all; /* 自动换行 */ - white-space: normal; /* 允许正常换行 */ - } -} - -.item-line { - height: 1px; - background: rgba(85, 159, 254, 0.25); - margin: 10px 0; -} - -.leaflet-container a.leaflet-popup-close-button { - position: absolute; - top: -115px; - right: -305px; - z-index: 600; -} - -.leaflet-popup-content-wrapper, -.leaflet-popup-tip { - background: transparent; - box-shadow: none; -} - -.leaflet-popup-tip { - background: transparent !important; -} -.leaflet-left { - z-index: 100; -} -// 滚动条样式 -// 滚动条整体样式 -::-webkit-scrollbar { - /*滚动条整体样式*/ - width: 6px !important; - height: 6px; -} - -::-webkit-scrollbar-thumbk { - /*滚动条里面小方块*/ - background: #ddd; - background: transparent; - border-radius: 3px; -} - -::-webkit-scrollbar-thumb:hover { - /*滚动条里面小方块*/ - background: #555; - border-radius: 3px; -} - -::-webkit-scrollbar-track { - /*滚动条里面轨道*/ - background: transparent; - border-radius: 3px; -} -.t-dialog__body { - height: 70vh; - overflow-y: auto; -} -.t-dialog__ctx .t-dialog__position.t-dialog--top { - padding-top: 10vh; -} diff --git a/situation-overview-web/src/utils/request.js b/situation-overview-web/src/utils/request.js deleted file mode 100644 index 4b6af133..00000000 --- a/situation-overview-web/src/utils/request.js +++ /dev/null @@ -1,34 +0,0 @@ -import axios from "axios"; - -const request = axios.create({ - baseURL: "/", - timeout: 10000000, -}); - -request.interceptors.request.use( - (config) => { - const token = localStorage.getItem("token"); - // if (token) { - // config.headers.authorization = `Bearer admin` - // } - config.headers.Authorization = `Bearer admin`; - console.log(config.headers.authorization); - - return config; - }, - (error) => { - return Promise.reject(error); - } -); - -request.interceptors.response.use( - (response) => { - return response.data; - }, - (error) => { - console.error("Request error:", error); - return Promise.reject(error); - } -); - -export default request; diff --git a/situation-overview-web/src/views/Chart.vue b/situation-overview-web/src/views/Chart.vue deleted file mode 100644 index 94534ce2..00000000 --- a/situation-overview-web/src/views/Chart.vue +++ /dev/null @@ -1,128 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/Dashboard.vue b/situation-overview-web/src/views/Dashboard.vue deleted file mode 100644 index 56f153de..00000000 --- a/situation-overview-web/src/views/Dashboard.vue +++ /dev/null @@ -1,130 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/Graph.vue b/situation-overview-web/src/views/Graph.vue deleted file mode 100644 index 13c482cd..00000000 --- a/situation-overview-web/src/views/Graph.vue +++ /dev/null @@ -1,91 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/GroupContent.vue b/situation-overview-web/src/views/GroupContent.vue deleted file mode 100644 index 4aa8a101..00000000 --- a/situation-overview-web/src/views/GroupContent.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/Home.vue b/situation-overview-web/src/views/Home.vue deleted file mode 100644 index c5ab0765..00000000 --- a/situation-overview-web/src/views/Home.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/Map.vue b/situation-overview-web/src/views/Map.vue deleted file mode 100644 index b461cc37..00000000 --- a/situation-overview-web/src/views/Map.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/action/components/actionDetail.vue b/situation-overview-web/src/views/action/components/actionDetail.vue deleted file mode 100644 index 4b555e03..00000000 --- a/situation-overview-web/src/views/action/components/actionDetail.vue +++ /dev/null @@ -1,206 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/action/components/bociDetail.vue b/situation-overview-web/src/views/action/components/bociDetail.vue deleted file mode 100644 index 937de378..00000000 --- a/situation-overview-web/src/views/action/components/bociDetail.vue +++ /dev/null @@ -1,260 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/action/index.vue b/situation-overview-web/src/views/action/index.vue deleted file mode 100644 index eba91b6a..00000000 --- a/situation-overview-web/src/views/action/index.vue +++ /dev/null @@ -1,280 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/control/components/g6Tp.vue b/situation-overview-web/src/views/control/components/g6Tp.vue deleted file mode 100644 index a9563656..00000000 --- a/situation-overview-web/src/views/control/components/g6Tp.vue +++ /dev/null @@ -1,228 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/control/components/timeline.vue b/situation-overview-web/src/views/control/components/timeline.vue deleted file mode 100644 index 8e8b62e7..00000000 --- a/situation-overview-web/src/views/control/components/timeline.vue +++ /dev/null @@ -1,144 +0,0 @@ - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/control/components/zxtp.vue b/situation-overview-web/src/views/control/components/zxtp.vue deleted file mode 100644 index d7ba6f29..00000000 --- a/situation-overview-web/src/views/control/components/zxtp.vue +++ /dev/null @@ -1,761 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/control/index.vue b/situation-overview-web/src/views/control/index.vue deleted file mode 100644 index 026ea043..00000000 --- a/situation-overview-web/src/views/control/index.vue +++ /dev/null @@ -1,2145 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/homeOverview/index.vue b/situation-overview-web/src/views/homeOverview/index.vue deleted file mode 100644 index f29e00ac..00000000 --- a/situation-overview-web/src/views/homeOverview/index.vue +++ /dev/null @@ -1,1337 +0,0 @@ - - - - - - - diff --git a/situation-overview-web/src/views/reply/components/G6NetworkGraph.vue b/situation-overview-web/src/views/reply/components/G6NetworkGraph.vue deleted file mode 100644 index beb484bf..00000000 --- a/situation-overview-web/src/views/reply/components/G6NetworkGraph.vue +++ /dev/null @@ -1,1061 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/reply/components/all-asp.vue b/situation-overview-web/src/views/reply/components/all-asp.vue deleted file mode 100644 index 95e1df78..00000000 --- a/situation-overview-web/src/views/reply/components/all-asp.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/asp-echarts.vue b/situation-overview-web/src/views/reply/components/asp-echarts.vue deleted file mode 100644 index b20260fa..00000000 --- a/situation-overview-web/src/views/reply/components/asp-echarts.vue +++ /dev/null @@ -1,221 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/edit-group.vue b/situation-overview-web/src/views/reply/components/edit-group.vue deleted file mode 100644 index e47709fb..00000000 --- a/situation-overview-web/src/views/reply/components/edit-group.vue +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/reply/components/information-list.vue b/situation-overview-web/src/views/reply/components/information-list.vue deleted file mode 100644 index c0c2fe1a..00000000 --- a/situation-overview-web/src/views/reply/components/information-list.vue +++ /dev/null @@ -1,668 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/reply/components/information-putin.vue b/situation-overview-web/src/views/reply/components/information-putin.vue deleted file mode 100644 index d2d51e7f..00000000 --- a/situation-overview-web/src/views/reply/components/information-putin.vue +++ /dev/null @@ -1,610 +0,0 @@ - - - - diff --git a/situation-overview-web/src/views/reply/components/input-recomendations.vue b/situation-overview-web/src/views/reply/components/input-recomendations.vue deleted file mode 100644 index a42c2014..00000000 --- a/situation-overview-web/src/views/reply/components/input-recomendations.vue +++ /dev/null @@ -1,210 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/office.vue b/situation-overview-web/src/views/reply/components/office.vue deleted file mode 100644 index 71a2efd5..00000000 --- a/situation-overview-web/src/views/reply/components/office.vue +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/reply/components/part/Media-list.vue b/situation-overview-web/src/views/reply/components/part/Media-list.vue deleted file mode 100644 index 44d91771..00000000 --- a/situation-overview-web/src/views/reply/components/part/Media-list.vue +++ /dev/null @@ -1,259 +0,0 @@ - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/reply/components/part/action-unit.vue b/situation-overview-web/src/views/reply/components/part/action-unit.vue deleted file mode 100644 index 33c0bf9f..00000000 --- a/situation-overview-web/src/views/reply/components/part/action-unit.vue +++ /dev/null @@ -1,167 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/part/big-v.vue b/situation-overview-web/src/views/reply/components/part/big-v.vue deleted file mode 100644 index c70d4590..00000000 --- a/situation-overview-web/src/views/reply/components/part/big-v.vue +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - - diff --git a/situation-overview-web/src/views/reply/components/part/hot-trend.vue b/situation-overview-web/src/views/reply/components/part/hot-trend.vue deleted file mode 100644 index f21f285e..00000000 --- a/situation-overview-web/src/views/reply/components/part/hot-trend.vue +++ /dev/null @@ -1,514 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/part/media-port.vue b/situation-overview-web/src/views/reply/components/part/media-port.vue deleted file mode 100644 index 5e8b3798..00000000 --- a/situation-overview-web/src/views/reply/components/part/media-port.vue +++ /dev/null @@ -1,395 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/reply/components/part/narr-theme.vue b/situation-overview-web/src/views/reply/components/part/narr-theme.vue deleted file mode 100644 index 8d77209f..00000000 --- a/situation-overview-web/src/views/reply/components/part/narr-theme.vue +++ /dev/null @@ -1,298 +0,0 @@ - - - - diff --git a/situation-overview-web/src/views/reply/components/part/relevantActors-item.vue b/situation-overview-web/src/views/reply/components/part/relevantActors-item.vue deleted file mode 100644 index 65412e88..00000000 --- a/situation-overview-web/src/views/reply/components/part/relevantActors-item.vue +++ /dev/null @@ -1,274 +0,0 @@ - - - - - - - diff --git a/situation-overview-web/src/views/reply/components/part/stand-area.vue b/situation-overview-web/src/views/reply/components/part/stand-area.vue deleted file mode 100644 index acb040ee..00000000 --- a/situation-overview-web/src/views/reply/components/part/stand-area.vue +++ /dev/null @@ -1,202 +0,0 @@ - - - - diff --git a/situation-overview-web/src/views/reply/components/part/table-line.vue b/situation-overview-web/src/views/reply/components/part/table-line.vue deleted file mode 100644 index 34f24414..00000000 --- a/situation-overview-web/src/views/reply/components/part/table-line.vue +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/reply/components/part/trans-plat.vue b/situation-overview-web/src/views/reply/components/part/trans-plat.vue deleted file mode 100644 index d741e18c..00000000 --- a/situation-overview-web/src/views/reply/components/part/trans-plat.vue +++ /dev/null @@ -1,302 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/reply/components/part/word-cloud.vue b/situation-overview-web/src/views/reply/components/part/word-cloud.vue deleted file mode 100644 index e791689d..00000000 --- a/situation-overview-web/src/views/reply/components/part/word-cloud.vue +++ /dev/null @@ -1,240 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/reply/components/pie-echarts.vue b/situation-overview-web/src/views/reply/components/pie-echarts.vue deleted file mode 100644 index 07bfba49..00000000 --- a/situation-overview-web/src/views/reply/components/pie-echarts.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/reply/components/pivotket.vue b/situation-overview-web/src/views/reply/components/pivotket.vue deleted file mode 100644 index a7d7d986..00000000 --- a/situation-overview-web/src/views/reply/components/pivotket.vue +++ /dev/null @@ -1,348 +0,0 @@ - - - - diff --git a/situation-overview-web/src/views/reply/components/point-list.vue b/situation-overview-web/src/views/reply/components/point-list.vue deleted file mode 100644 index af57d285..00000000 --- a/situation-overview-web/src/views/reply/components/point-list.vue +++ /dev/null @@ -1,227 +0,0 @@ - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/reply/components/pointDialog-morelevel.vue b/situation-overview-web/src/views/reply/components/pointDialog-morelevel.vue deleted file mode 100644 index ecccbac0..00000000 --- a/situation-overview-web/src/views/reply/components/pointDialog-morelevel.vue +++ /dev/null @@ -1,469 +0,0 @@ - - - - diff --git a/situation-overview-web/src/views/reply/components/prehensiveEvaluation-fangan.vue b/situation-overview-web/src/views/reply/components/prehensiveEvaluation-fangan.vue deleted file mode 100644 index d997972d..00000000 --- a/situation-overview-web/src/views/reply/components/prehensiveEvaluation-fangan.vue +++ /dev/null @@ -1,128 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/prehensiveEvaluation.vue b/situation-overview-web/src/views/reply/components/prehensiveEvaluation.vue deleted file mode 100644 index cb933570..00000000 --- a/situation-overview-web/src/views/reply/components/prehensiveEvaluation.vue +++ /dev/null @@ -1,458 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/reply/components/radar-echart.vue b/situation-overview-web/src/views/reply/components/radar-echart.vue deleted file mode 100644 index 99ef45f6..00000000 --- a/situation-overview-web/src/views/reply/components/radar-echart.vue +++ /dev/null @@ -1,142 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/reachAudience.vue b/situation-overview-web/src/views/reply/components/reachAudience.vue deleted file mode 100644 index 905338c8..00000000 --- a/situation-overview-web/src/views/reply/components/reachAudience.vue +++ /dev/null @@ -1,344 +0,0 @@ - - - - diff --git a/situation-overview-web/src/views/reply/components/replyComparison-one.vue b/situation-overview-web/src/views/reply/components/replyComparison-one.vue deleted file mode 100644 index 5083fb77..00000000 --- a/situation-overview-web/src/views/reply/components/replyComparison-one.vue +++ /dev/null @@ -1,636 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/replyComparison-two.vue b/situation-overview-web/src/views/reply/components/replyComparison-two.vue deleted file mode 100644 index c7752d32..00000000 --- a/situation-overview-web/src/views/reply/components/replyComparison-two.vue +++ /dev/null @@ -1,864 +0,0 @@ - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/reply/components/replyComparison.vue b/situation-overview-web/src/views/reply/components/replyComparison.vue deleted file mode 100644 index bc5a46e7..00000000 --- a/situation-overview-web/src/views/reply/components/replyComparison.vue +++ /dev/null @@ -1,54 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/rzyx.vue b/situation-overview-web/src/views/reply/components/rzyx.vue deleted file mode 100644 index 628e3ec7..00000000 --- a/situation-overview-web/src/views/reply/components/rzyx.vue +++ /dev/null @@ -1,289 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/svg-link.vue b/situation-overview-web/src/views/reply/components/svg-link.vue deleted file mode 100644 index 77f6bb28..00000000 --- a/situation-overview-web/src/views/reply/components/svg-link.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/reply/components/table-two.vue b/situation-overview-web/src/views/reply/components/table-two.vue deleted file mode 100644 index ae59a699..00000000 --- a/situation-overview-web/src/views/reply/components/table-two.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - - diff --git a/situation-overview-web/src/views/reply/components/task-detail.vue b/situation-overview-web/src/views/reply/components/task-detail.vue deleted file mode 100644 index 64738044..00000000 --- a/situation-overview-web/src/views/reply/components/task-detail.vue +++ /dev/null @@ -1,286 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/task-list.vue b/situation-overview-web/src/views/reply/components/task-list.vue deleted file mode 100644 index 52f32955..00000000 --- a/situation-overview-web/src/views/reply/components/task-list.vue +++ /dev/null @@ -1,281 +0,0 @@ - - - - diff --git a/situation-overview-web/src/views/reply/components/title-logo.vue b/situation-overview-web/src/views/reply/components/title-logo.vue deleted file mode 100644 index eaffea40..00000000 --- a/situation-overview-web/src/views/reply/components/title-logo.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/translateEnTo.js b/situation-overview-web/src/views/reply/components/translateEnTo.js deleted file mode 100644 index 1f38415e..00000000 --- a/situation-overview-web/src/views/reply/components/translateEnTo.js +++ /dev/null @@ -1,37 +0,0 @@ -import axios from "@/utils/request"; - -// 翻译方法 content数组 -export default async function translateEnTo(content) { - if (content && content.length > 0) { - - // 并行调用n个接口 - let promises = content.map(async (item) => { - if(item){ - let res = await fetchData(item) - return res?.data?.body?.target || null - }else{ - // return item || null - return '' - } - - }) - const updatedArray = await Promise.all(promises); - return updatedArray - } else { - return null - } -} - -async function fetchData(item) { - return new Promise((resolve) => { - // 需要改成实际ip和接口,这个暂时用的其他占位 - let params = { - "id": "string", - "type": "encn", - content: item - } - const res = axios.post('http://127.0.0.1:18890/' + "/transfer/langDetectTrans", params) - resolve(res) - }); -} - diff --git a/situation-overview-web/src/views/reply/components/truncatedTooltipItem.vue b/situation-overview-web/src/views/reply/components/truncatedTooltipItem.vue deleted file mode 100644 index 9ca7047d..00000000 --- a/situation-overview-web/src/views/reply/components/truncatedTooltipItem.vue +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/situation-overview-web/src/views/reply/components/type.js b/situation-overview-web/src/views/reply/components/type.js deleted file mode 100644 index 43ff2f36..00000000 --- a/situation-overview-web/src/views/reply/components/type.js +++ /dev/null @@ -1,467 +0,0 @@ - - -// 直播视频状态 -const liveVideoOpt = { - 0: { - name: '未分析', - color: '#c1c1c1' - }, - 1: { - name: '分析中', - color: '#80bcff' - }, - 2: { - name: '分析完成', - color: '#74e4bc' - }, - 3: { - name: '分析失败', - color: '#bcb5b9' - } -} - -const dealWithTypeNumber = { - relationShip(value) { - switch (value) { - case 0: - return '未研判' - case 1: - return '相关' - case 2: - return '不相关' - default: - '' - } - }, - infoDir(value) { - switch (value) { - case 0: - return '同向' - case 1: - return '中立' - case 2: - return '负向' - default: - '' - } - }, - hotLevelList: [ - { - name: '热帖', - value: 8 - }, - { - name: '爆贴', - value: 9 - }, - { - name: '普通贴', - value: 7 - } - ], - infoDirStyle(value) { - switch (value) { - case 0: - return { - color: 'rgb(122, 202, 164)', - backgroundColor: 'rgba(122, 202, 164, 0.2)' - } - case 1: - return { - color: 'rgb(200, 205, 213)', - backgroundColor: 'rgba(200, 205, 213,0.2)' - } - case 2: - return { - color: 'rgb(245, 164, 68)', - backgroundColor: 'rgba(245, 164, 68,0.2)' - } - default: - '' - } - }, - infoRelationShipStyle(value) { - switch (value) { - case 0: - return { - color: 'rgb(161, 166, 182)', - backgroundColor: 'rgb(161, 166, 182, 0.2)' - } - case 1: - return { - color: 'rgb(122, 202, 164)', - backgroundColor: 'rgba(122, 202, 164, 0.2)' - } - case 2: - return { - color: 'rgb(161, 166, 182)', - backgroundColor: 'rgb(161, 166, 182, 0.2)' - } - } - }, - infoArrData: [ - { - name: '同向', - value: 0 - }, - { - name: '中立', - value: 1 - }, - { - name: '负向', - value: 2 - } - ], - infoArrDataFilter: [ - { - name: '全部', - value: null - }, - { - name: '同向', - value: 0 - }, - { - name: '中立', - value: 1 - }, - { - name: '负向', - value: 2 - } - ], - infoArrDataFilter1: [ - { - name: '全部', - value: 4 - }, - { - name: '泛蓝', - value: 1 - }, - { - name: '泛绿', - value: 2 - }, - { - name: '中立', - value: 3 - }, - { - name: '其他', - value: 0 - } - ], - infoArrDataFilter2(type) { - switch (type) { - case 4: - return '全部' - case 3: - return '中立' - case 2: - return '泛绿' - case 1: - return '泛蓝' - case 0: - return '其他' - } - }, - relationArrData: [ - { - type: '未研判', - value: 0 - }, - { - type: '相关', - value: 1 - }, - { - type: '不相关', - value: 2 - } - ], - relationArrStatus: [ - { - type: '已纳入评估数据池', - value: 1 - }, - { - type: '未纳入评估数据池', - value: 0 - } - ], - relationArrDataFilter: [ - { - type: '全部', - value: null - }, - { - type: '未研判', - value: 0 - }, - { - type: '相关', - value: 1 - }, - { - type: '不相关', - value: 2 - } - ], - shortcuts: [ - { - text: '一周', - value: () => { - const end = new Date() - const start = new Date() - start.setDate(start.getDate() - 7) - return [start, end] - } - }, - { - text: '一个月', - value: () => { - const end = new Date() - const start = new Date() - start.setMonth(start.getMonth() - 1) - return [start, end] - } - }, - { - text: '一个季度', - value: () => { - const end = new Date() - const start = new Date() - start.setMonth(start.getMonth() - 3) - return [start, end] - } - }, - { - text: '一年', - value: () => { - const end = new Date() - const start = new Date() - start.setFullYear(start.getFullYear() - 1) - return [start, end] - } - } - ], - TSstatus(status, message) { - if (status == -1) { - return '未下发' - } else if (status == 1) { - return '已下发' - } else { - if (message == null) { - return '采集中' - } else { - let messageObj = JSON.parse(message) - if (messageObj && messageObj?.data?.msg != '') { - return messageObj?.data?.msg - } else if (messageObj && messageObj?.data == null) { - return messageObj?.msg - } else { - return '' - } - } - } - }, - - TSstatus_InformationList(item) { - let msg = { txt: '', status: 0, msg: '' } - let status = item.bsLink?.status - let message = item.bsLink?.responseBody - if (status == -1) { - msg.txt = '未下发' - msg.status = 0 - } else if ( - (item.linkStatus == 0 && item.bsLink == null) || - status == 0 || - (item.linkStatus == 0 && status == 1) - ) { - msg.txt = '采集中' - msg.status = 1 - } else if ( - (item.linkStatus == 1 && item.bsLink == null) || - (status == 1 && item.linkStatus == 1) - ) { - msg.txt = '已完成' - msg.status = 2 - } else if (status == 2) { - msg.txt = '采集失败' - msg.status = 3 - let messageObj = JSON.parse(message) - if (messageObj && messageObj?.data?.msg != '') { - msg.msg = messageObj?.data?.msg - } else if (messageObj && messageObj?.data == null) { - msg.msg = messageObj?.msg - } else { - msg.msg = '' - } - } - return msg - }, - - // 实时播报/行动脉络 infoType值的含义 - infoType(value) { - const typeName = { - 1: 'ts信息', - 2: '官方回应', - 3: '线下活动', - 4: '首发大V', - 5: '关键节点', - 6: '首发媒体', - 7: '首发大V关键节点', - 8: '官方媒体', - // 260120 修改 增加新类型 - 9: '首发账号' - } - return typeName[value] || '' - }, - - // 关键词类型 - wordType(value) { - let opt = { - 0: { - name: '手动配置', - style: { - background: 'rgba(126, 187, 255, 0.2)', - 'border-color': '#7ebbff', - color: '#60a5e1' - } - }, - 1: { - name: '自动推荐', - style: { - background: 'rgba(240, 174, 126, 0.2)', - 'border-color': '#f0ae7e', - color: '#db9265' - } - }, - 2: { - name: '信息推荐', - style: { - background: 'rgba(149, 235, 204, 0.2)', - 'border-color': '#95ebcc', - color: '#7eb19b' - } - }, - 3: { - name: '引接方案', - style: { - background: 'rgba(252, 163, 141, 0.2)', - 'border-color': '#fca38d', - color: '#d37d6b' - } - }, - 4: { - name: '引接生成', - style: { - background: 'rgba(174, 212, 167, 0.2)', - 'border-color': '#b8e1b1', - color: '#9aba8c' - } - } - } - - return ( - opt[value] || { - name: '', - style: null - } - ) - }, - - positionStyle(type) { - console.log(type) - const obj = { - 同向: ['#7acaa4', 'rgba(122,202,164,0.15)'], - 中立: ['#c8cdd5', 'rgba(161,166,182,0.15)'], - 负向: ['#f5a444', 'rgba(245,164,68,0.15)'] - } - return obj[type] || ['#c8cdd5', 'rgba(161,166,182,0.15)'] - }, - - // 卡片紧急程度配置 - rankOpt(type) { - let opt = { - 0: { - name: '一般', - color:['#bdb176', 'rgba(220, 214, 152, 0.2)'] - }, - 1: { - name: '重要', - color:['#db9265', 'rgba(240, 174, 126, 0.2)'] - }, - 2: { - name: '紧急', - color:['#d37d6b', 'rgba(252, 163, 141, 0.2)'] - }, - 3: { - name: '加急', - color: ['#cc686f', 'rgba(250, 143, 148, 0.2)'] - } - } - return opt[type] || { name: '暂无', color: ['', ''] } - }, - - getLiveVideoOpt(type) { - return liveVideoOpt[type] || { name: '--中', color: '#c1c1c1' } - }, - - liveVideoOpt: liveVideoOpt, - - // 卡片等级颜色 - levelColor(level) { - switch (level) { - case '一级': - return '#667dff' - case '二级': - return '#006dcc' - case '三级': - return '#00b35f' - case '四级': - return '#ccad00' //"#f7e685"; - case '五级': - return '#ffa333' - case '六级': - return '#ff6666' - default: - return '#a6a6a6' - } - }, - - // 行动状态颜色 - actionStatusStyle(status) { - let opt = { - 进行中: { - background: 'var(--warning-bg-color)', - border: '1px solid var(--warning-border-color)', - color: 'var(--warning-text-color)' - }, - 未开始: { - 'border-radius': '2px', - background: 'var(--default-bg-color)', - border: '1px solid var(--default-border-color)', - color: 'var(--default-text-color)' - }, - 已完成: { - 'border-radius': '2px', - background: 'var(--success-bg-color)', - border: '1px solid var(--success-border-color)', - color: 'var(--success-text-color)' - }, - 已结束: { - 'border-radius': ' 2px', - background: 'var(--success-bg-color)', - border: '1px solid var(--success-border-color)', - color: 'var(--success-text-color)' - } - } - - return opt[status] - } -} - -export default dealWithTypeNumber diff --git a/situation-overview-web/src/views/reply/components/vulnerability.vue b/situation-overview-web/src/views/reply/components/vulnerability.vue deleted file mode 100644 index ffa2fc76..00000000 --- a/situation-overview-web/src/views/reply/components/vulnerability.vue +++ /dev/null @@ -1,408 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/reply/components/xd-trend.vue b/situation-overview-web/src/views/reply/components/xd-trend.vue deleted file mode 100644 index 33aded8a..00000000 --- a/situation-overview-web/src/views/reply/components/xd-trend.vue +++ /dev/null @@ -1,219 +0,0 @@ - - - diff --git a/situation-overview-web/src/views/reply/components/xdcloud.vue b/situation-overview-web/src/views/reply/components/xdcloud.vue deleted file mode 100644 index fb86023b..00000000 --- a/situation-overview-web/src/views/reply/components/xdcloud.vue +++ /dev/null @@ -1,148 +0,0 @@ - - - - - diff --git a/situation-overview-web/src/views/reply/index.vue b/situation-overview-web/src/views/reply/index.vue deleted file mode 100644 index cd900d25..00000000 --- a/situation-overview-web/src/views/reply/index.vue +++ /dev/null @@ -1,489 +0,0 @@ -