wanshenmean
2026-03-13 d18970b451b863b465e356e2a5e4576707a17355
重构: 将 Razor Pages 前端改为 Vue 3 项目

技术栈:
- Vue 3 + TypeScript + Vite
- Vue Router (路由管理)
- Pinia (状态管理)
- Axios (HTTP 请求)
- Bootstrap 5 (UI 框架)

功能:
- 实例列表展示 (实时刷新)
- 创建/编辑/删除实例
- 启动/停止实例
- 实例详情查看

目录结构:
- src/api: API 调用封装
- src/stores: Pinia 状态管理
- src/views: 页面组件
- src/router: 路由配置
- src/types: TypeScript 类型定义

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
已添加19个文件
已删除35个文件
已修改3个文件
6526 ■■■■■ 文件已修改
Code/WCS/.claude/settings.local.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/.vs/WIDESEAWCS_S7Simulator.slnx/v18/DocumentLayout.backup.json 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/.vs/WIDESEAWCS_S7Simulator.slnx/v18/DocumentLayout.json 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/.gitignore 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Data/instance-GWSC1/config.json 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Data/instance-GWSC1/memory.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/BasePageModel.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Create.cshtml 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Create.cshtml.cs 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Details.cshtml 338 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Details.cshtml.cs 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Edit.cshtml 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Edit.cshtml.cs 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Error.cshtml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Error.cshtml.cs 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Privacy.cshtml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Privacy.cshtml.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Shared/_Layout.cshtml 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Shared/_Layout.cshtml.css 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Shared/_ValidationScriptsPartial.cshtml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/_ViewImports.cshtml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/_ViewStart.cshtml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Program.cs 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Properties/launchSettings.json 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Services/ApiHttpClient.cs 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/WIDESEAWCS_S7Simulator.Web.csproj 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/appsettings.Development.json 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/appsettings.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/index.html 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/package-lock.json 1899 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/package.json 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/App.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/main.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/router/index.ts 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/stores/instances.ts 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/style.css 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/types/index.ts 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue 275 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/DetailsView.vue 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/EditView.vue 330 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue 251 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/vite-env.d.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/tsconfig.json 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/tsconfig.node.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/vite.config.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/css/site.css 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/js/site.js 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/bootstrap/LICENSE 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js 432 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery-validation/LICENSE.md 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery/LICENSE.txt 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/.claude/settings.local.json
@@ -31,7 +31,8 @@
      "Bash(cd \"D:/Git/ShanMeiXinNengYuan/Code/WCS/WIDESEAWCS_S7Simulator\" && dotnet test --no-build)",
      "Bash(cd \"D:/Git/ShanMeiXinNengYuan/Code/WCS/WIDESEAWCS_S7Simulator\" && dotnet test 2>&1 | tail -20)",
      "mcp__web-search-prime__web_search_prime",
      "mcp__web-reader__webReader"
      "mcp__web-reader__webReader",
      "Bash(cd \"D:\\\\Git\\\\ShanMeiXinNengYuan\\\\Code\\\\WCS\\\\WIDESEAWCS_S7Simulator\" && npm create vite@latest WIDESEAWCS_S7Simulator.Web -- --template vue-ts)"
    ]
  }
}
Code/WCS/WIDESEAWCS_S7Simulator/.vs/WIDESEAWCS_S7Simulator.slnx/v18/DocumentLayout.backup.json
@@ -3,16 +3,20 @@
  "WorkspaceRootPath": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\",
  "Documents": [
    {
      "AbsoluteMoniker": "D:0:0:{34B63567-0A18-7E94-9249-33A42106FAAB}|WIDESEAWCS_S7Simulator.Web\\WIDESEAWCS_S7Simulator.Web.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.web\\pages\\edit.cshtml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{34B63567-0A18-7E94-9249-33A42106FAAB}|WIDESEAWCS_S7Simulator.Web\\WIDESEAWCS_S7Simulator.Web.csproj|solutionrelative:wideseawcs_s7simulator.web\\pages\\edit.cshtml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.core\\manager\\simulatorinstancemanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|solutionrelative:wideseawcs_s7simulator.core\\manager\\simulatorinstancemanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.core\\persistence\\filepersistenceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|solutionrelative:wideseawcs_s7simulator.core\\persistence\\filepersistenceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.core\\server\\s7serverinstance.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|solutionrelative:wideseawcs_s7simulator.core\\server\\s7serverinstance.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.core\\persistence\\filepersistenceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|solutionrelative:wideseawcs_s7simulator.core\\persistence\\filepersistenceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    }
  ],
  "DocumentGroupContainers": [
@@ -22,7 +26,7 @@
      "DocumentGroups": [
        {
          "DockedWidth": 200,
          "SelectedChildIndex": 4,
          "SelectedChildIndex": 3,
          "Children": [
            {
              "$type": "Bookmark",
@@ -38,33 +42,46 @@
            },
            {
              "$type": "Document",
              "DocumentIndex": 0,
              "Title": "Edit.cshtml.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Web\\Pages\\Edit.cshtml.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_S7Simulator.Web\\Pages\\Edit.cshtml.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Web\\Pages\\Edit.cshtml.cs",
              "RelativeToolTip": "WIDESEAWCS_S7Simulator.Web\\Pages\\Edit.cshtml.cs",
              "ViewState": "AgIAADYAAAAAAAAAAAAQwCsAAAAoAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-13T07:51:30.349Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 2,
              "Title": "S7ServerInstance.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Core\\Server\\S7ServerInstance.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_S7Simulator.Core\\Server\\S7ServerInstance.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Core\\Server\\S7ServerInstance.cs",
              "RelativeToolTip": "WIDESEAWCS_S7Simulator.Core\\Server\\S7ServerInstance.cs",
              "ViewState": "AgIAAN0AAAAAAAAAAAAAAD4AAAAgAAAAAAAAAA==",
              "ViewState": "AgIAAL8AAAAAAAAAAAAAAD4AAAAgAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-13T07:12:02.925Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 0,
              "DocumentIndex": 1,
              "Title": "SimulatorInstanceManager.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Core\\Manager\\SimulatorInstanceManager.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_S7Simulator.Core\\Manager\\SimulatorInstanceManager.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Core\\Manager\\SimulatorInstanceManager.cs",
              "RelativeToolTip": "WIDESEAWCS_S7Simulator.Core\\Manager\\SimulatorInstanceManager.cs",
              "ViewState": "AgIAAE0AAAAAAAAAAAAkwGkAAABIAAAAAAAAAA==",
              "ViewState": "AgIAADcAAAAAAAAAAAAiwGkAAABIAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-13T06:55:20.346Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 1,
              "DocumentIndex": 3,
              "Title": "FilePersistenceService.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Core\\Persistence\\FilePersistenceService.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_S7Simulator.Core\\Persistence\\FilePersistenceService.cs",
Code/WCS/WIDESEAWCS_S7Simulator/.vs/WIDESEAWCS_S7Simulator.slnx/v18/DocumentLayout.json
@@ -3,12 +3,16 @@
  "WorkspaceRootPath": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\",
  "Documents": [
    {
      "AbsoluteMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.core\\server\\s7serverinstance.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|solutionrelative:wideseawcs_s7simulator.core\\server\\s7serverinstance.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
      "AbsoluteMoniker": "D:0:0:{34B63567-0A18-7E94-9249-33A42106FAAB}|WIDESEAWCS_S7Simulator.Web\\WIDESEAWCS_S7Simulator.Web.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.web\\pages\\edit.cshtml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{34B63567-0A18-7E94-9249-33A42106FAAB}|WIDESEAWCS_S7Simulator.Web\\WIDESEAWCS_S7Simulator.Web.csproj|solutionrelative:wideseawcs_s7simulator.web\\pages\\edit.cshtml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.core\\manager\\simulatorinstancemanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|solutionrelative:wideseawcs_s7simulator.core\\manager\\simulatorinstancemanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.core\\server\\s7serverinstance.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|solutionrelative:wideseawcs_s7simulator.core\\server\\s7serverinstance.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{559E6124-CE06-87A7-E890-9BA8EA7CF3C5}|WIDESEAWCS_S7Simulator.Core\\WIDESEAWCS_S7Simulator.Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_s7simulator\\wideseawcs_s7simulator.core\\persistence\\filepersistenceservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
@@ -39,12 +43,25 @@
            {
              "$type": "Document",
              "DocumentIndex": 0,
              "Title": "Edit.cshtml.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Web\\Pages\\Edit.cshtml.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_S7Simulator.Web\\Pages\\Edit.cshtml.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Web\\Pages\\Edit.cshtml.cs",
              "RelativeToolTip": "WIDESEAWCS_S7Simulator.Web\\Pages\\Edit.cshtml.cs",
              "ViewState": "AgIAADYAAAAAAAAAAAAQwCsAAAAoAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-13T07:51:30.349Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 2,
              "Title": "S7ServerInstance.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Core\\Server\\S7ServerInstance.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_S7Simulator.Core\\Server\\S7ServerInstance.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Core\\Server\\S7ServerInstance.cs",
              "RelativeToolTip": "WIDESEAWCS_S7Simulator.Core\\Server\\S7ServerInstance.cs",
              "ViewState": "AgIAAN0AAAAAAAAAAAAAAD4AAAAgAAAAAAAAAA==",
              "ViewState": "AgIAAL8AAAAAAAAAAAAAAD4AAAAgAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-13T07:12:02.925Z",
              "EditorCaption": ""
@@ -57,14 +74,14 @@
              "RelativeDocumentMoniker": "WIDESEAWCS_S7Simulator.Core\\Manager\\SimulatorInstanceManager.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Core\\Manager\\SimulatorInstanceManager.cs",
              "RelativeToolTip": "WIDESEAWCS_S7Simulator.Core\\Manager\\SimulatorInstanceManager.cs",
              "ViewState": "AgIAAE0AAAAAAAAAAAAkwGkAAABIAAAAAAAAAA==",
              "ViewState": "AgIAADcAAAAAAAAAAAAiwGkAAABIAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-13T06:55:20.346Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 2,
              "DocumentIndex": 3,
              "Title": "FilePersistenceService.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_S7Simulator\\WIDESEAWCS_S7Simulator.Core\\Persistence\\FilePersistenceService.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_S7Simulator.Core\\Persistence\\FilePersistenceService.cs",
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/.gitignore
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Data/instance-GWSC1/config.json
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Data/instance-GWSC1/memory.json
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/BasePageModel.cs
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Create.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Create.cshtml.cs
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Details.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Details.cshtml.cs
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Edit.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Edit.cshtml.cs
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Error.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Error.cshtml.cs
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Index.cshtml.cs
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Privacy.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Privacy.cshtml.cs
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Shared/_Layout.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Shared/_Layout.cshtml.css
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/Shared/_ValidationScriptsPartial.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/_ViewImports.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Pages/_ViewStart.cshtml
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Program.cs
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Properties/launchSettings.json
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/Services/ApiHttpClient.cs
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/WIDESEAWCS_S7Simulator.Web.csproj
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/appsettings.Development.json
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/appsettings.json
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/index.html
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>S7 PLC Simulator</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/package-lock.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1899 @@
{
  "name": "wideseawcs-s7simulator-web",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "wideseawcs-s7simulator-web",
      "version": "1.0.0",
      "dependencies": {
        "axios": "^1.7.9",
        "bootstrap": "^5.3.3",
        "bootstrap-icons": "^1.11.3",
        "pinia": "^2.3.0",
        "vue": "^3.5.13",
        "vue-router": "^4.5.0"
      },
      "devDependencies": {
        "@vitejs/plugin-vue": "^5.2.1",
        "typescript": "~5.7.2",
        "vite": "^6.0.11",
        "vue-tsc": "^2.2.0"
      }
    },
    "node_modules/@babel/helper-string-parser": {
      "version": "7.27.1",
      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/helper-validator-identifier": {
      "version": "7.28.5",
      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
      "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/parser": {
      "version": "7.29.0",
      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
      "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
      "license": "MIT",
      "dependencies": {
        "@babel/types": "^7.29.0"
      },
      "bin": {
        "parser": "bin/babel-parser.js"
      },
      "engines": {
        "node": ">=6.0.0"
      }
    },
    "node_modules/@babel/types": {
      "version": "7.29.0",
      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
      "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
      "license": "MIT",
      "dependencies": {
        "@babel/helper-string-parser": "^7.27.1",
        "@babel/helper-validator-identifier": "^7.28.5"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@esbuild/aix-ppc64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
      "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
      "cpu": [
        "ppc64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "aix"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/android-arm": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
      "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
      "cpu": [
        "arm"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/android-arm64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
      "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/android-x64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
      "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/darwin-arm64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
      "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/darwin-x64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
      "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/freebsd-arm64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
      "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "freebsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/freebsd-x64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
      "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "freebsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-arm": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
      "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
      "cpu": [
        "arm"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-arm64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
      "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-ia32": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
      "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
      "cpu": [
        "ia32"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-loong64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
      "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
      "cpu": [
        "loong64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-mips64el": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
      "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
      "cpu": [
        "mips64el"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-ppc64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
      "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
      "cpu": [
        "ppc64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-riscv64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
      "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
      "cpu": [
        "riscv64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-s390x": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
      "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
      "cpu": [
        "s390x"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-x64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
      "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/netbsd-arm64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
      "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "netbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/netbsd-x64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
      "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "netbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/openbsd-arm64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
      "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/openbsd-x64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
      "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/openharmony-arm64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
      "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openharmony"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/sunos-x64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
      "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "sunos"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/win32-arm64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
      "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/win32-ia32": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
      "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
      "cpu": [
        "ia32"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/win32-x64": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
      "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@jridgewell/sourcemap-codec": {
      "version": "1.5.5",
      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
      "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
      "license": "MIT"
    },
    "node_modules/@popperjs/core": {
      "version": "2.11.8",
      "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
      "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
      "license": "MIT",
      "peer": true,
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/popperjs"
      }
    },
    "node_modules/@rollup/rollup-android-arm-eabi": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
      "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
      "cpu": [
        "arm"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ]
    },
    "node_modules/@rollup/rollup-android-arm64": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
      "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ]
    },
    "node_modules/@rollup/rollup-darwin-arm64": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
      "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ]
    },
    "node_modules/@rollup/rollup-darwin-x64": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
      "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ]
    },
    "node_modules/@rollup/rollup-freebsd-arm64": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
      "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "freebsd"
      ]
    },
    "node_modules/@rollup/rollup-freebsd-x64": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
      "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "freebsd"
      ]
    },
    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
      "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
      "cpu": [
        "arm"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
      "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
      "cpu": [
        "arm"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-arm64-gnu": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
      "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-arm64-musl": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
      "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-loong64-gnu": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
      "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
      "cpu": [
        "loong64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-loong64-musl": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
      "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
      "cpu": [
        "loong64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-ppc64-gnu": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
      "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
      "cpu": [
        "ppc64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-ppc64-musl": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
      "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
      "cpu": [
        "ppc64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
      "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
      "cpu": [
        "riscv64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-riscv64-musl": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
      "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
      "cpu": [
        "riscv64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-s390x-gnu": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
      "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
      "cpu": [
        "s390x"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-x64-gnu": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
      "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-linux-x64-musl": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
      "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ]
    },
    "node_modules/@rollup/rollup-openbsd-x64": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
      "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openbsd"
      ]
    },
    "node_modules/@rollup/rollup-openharmony-arm64": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
      "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openharmony"
      ]
    },
    "node_modules/@rollup/rollup-win32-arm64-msvc": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
      "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ]
    },
    "node_modules/@rollup/rollup-win32-ia32-msvc": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
      "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
      "cpu": [
        "ia32"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ]
    },
    "node_modules/@rollup/rollup-win32-x64-gnu": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
      "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ]
    },
    "node_modules/@rollup/rollup-win32-x64-msvc": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
      "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ]
    },
    "node_modules/@types/estree": {
      "version": "1.0.8",
      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@vitejs/plugin-vue": {
      "version": "5.2.4",
      "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
      "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": "^18.0.0 || >=20.0.0"
      },
      "peerDependencies": {
        "vite": "^5.0.0 || ^6.0.0",
        "vue": "^3.2.25"
      }
    },
    "node_modules/@volar/language-core": {
      "version": "2.4.15",
      "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.15.tgz",
      "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@volar/source-map": "2.4.15"
      }
    },
    "node_modules/@volar/source-map": {
      "version": "2.4.15",
      "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.15.tgz",
      "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==",
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@volar/typescript": {
      "version": "2.4.15",
      "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.15.tgz",
      "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@volar/language-core": "2.4.15",
        "path-browserify": "^1.0.1",
        "vscode-uri": "^3.0.8"
      }
    },
    "node_modules/@vue/compiler-core": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.30.tgz",
      "integrity": "sha512-s3DfdZkcu/qExZ+td75015ljzHc6vE+30cFMGRPROYjqkroYI5NV2X1yAMX9UeyBNWB9MxCfPcsjpLS11nzkkw==",
      "license": "MIT",
      "dependencies": {
        "@babel/parser": "^7.29.0",
        "@vue/shared": "3.5.30",
        "entities": "^7.0.1",
        "estree-walker": "^2.0.2",
        "source-map-js": "^1.2.1"
      }
    },
    "node_modules/@vue/compiler-dom": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.30.tgz",
      "integrity": "sha512-eCFYESUEVYHhiMuK4SQTldO3RYxyMR/UQL4KdGD1Yrkfdx4m/HYuZ9jSfPdA+nWJY34VWndiYdW/wZXyiPEB9g==",
      "license": "MIT",
      "dependencies": {
        "@vue/compiler-core": "3.5.30",
        "@vue/shared": "3.5.30"
      }
    },
    "node_modules/@vue/compiler-sfc": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.30.tgz",
      "integrity": "sha512-LqmFPDn89dtU9vI3wHJnwaV6GfTRD87AjWpTWpyrdVOObVtjIuSeZr181z5C4PmVx/V3j2p+0f7edFKGRMpQ5A==",
      "license": "MIT",
      "dependencies": {
        "@babel/parser": "^7.29.0",
        "@vue/compiler-core": "3.5.30",
        "@vue/compiler-dom": "3.5.30",
        "@vue/compiler-ssr": "3.5.30",
        "@vue/shared": "3.5.30",
        "estree-walker": "^2.0.2",
        "magic-string": "^0.30.21",
        "postcss": "^8.5.8",
        "source-map-js": "^1.2.1"
      }
    },
    "node_modules/@vue/compiler-ssr": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.30.tgz",
      "integrity": "sha512-NsYK6OMTnx109PSL2IAyf62JP6EUdk4Dmj6AkWcJGBvN0dQoMYtVekAmdqgTtWQgEJo+Okstbf/1p7qZr5H+bA==",
      "license": "MIT",
      "dependencies": {
        "@vue/compiler-dom": "3.5.30",
        "@vue/shared": "3.5.30"
      }
    },
    "node_modules/@vue/compiler-vue2": {
      "version": "2.7.16",
      "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz",
      "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "de-indent": "^1.0.2",
        "he": "^1.2.0"
      }
    },
    "node_modules/@vue/devtools-api": {
      "version": "6.6.4",
      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
      "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
      "license": "MIT"
    },
    "node_modules/@vue/language-core": {
      "version": "2.2.12",
      "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.12.tgz",
      "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@volar/language-core": "2.4.15",
        "@vue/compiler-dom": "^3.5.0",
        "@vue/compiler-vue2": "^2.7.16",
        "@vue/shared": "^3.5.0",
        "alien-signals": "^1.0.3",
        "minimatch": "^9.0.3",
        "muggle-string": "^0.4.1",
        "path-browserify": "^1.0.1"
      },
      "peerDependencies": {
        "typescript": "*"
      },
      "peerDependenciesMeta": {
        "typescript": {
          "optional": true
        }
      }
    },
    "node_modules/@vue/reactivity": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.30.tgz",
      "integrity": "sha512-179YNgKATuwj9gB+66snskRDOitDiuOZqkYia7mHKJaidOMo/WJxHKF8DuGc4V4XbYTJANlfEKb0yxTQotnx4Q==",
      "license": "MIT",
      "dependencies": {
        "@vue/shared": "3.5.30"
      }
    },
    "node_modules/@vue/runtime-core": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.30.tgz",
      "integrity": "sha512-e0Z+8PQsUTdwV8TtEsLzUM7SzC7lQwYKePydb7K2ZnmS6jjND+WJXkmmfh/swYzRyfP1EY3fpdesyYoymCzYfg==",
      "license": "MIT",
      "dependencies": {
        "@vue/reactivity": "3.5.30",
        "@vue/shared": "3.5.30"
      }
    },
    "node_modules/@vue/runtime-dom": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.30.tgz",
      "integrity": "sha512-2UIGakjU4WSQ0T4iwDEW0W7vQj6n7AFn7taqZ9Cvm0Q/RA2FFOziLESrDL4GmtI1wV3jXg5nMoJSYO66egDUBw==",
      "license": "MIT",
      "dependencies": {
        "@vue/reactivity": "3.5.30",
        "@vue/runtime-core": "3.5.30",
        "@vue/shared": "3.5.30",
        "csstype": "^3.2.3"
      }
    },
    "node_modules/@vue/server-renderer": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.30.tgz",
      "integrity": "sha512-v+R34icapydRwbZRD0sXwtHqrQJv38JuMB4JxbOxd8NEpGLny7cncMp53W9UH/zo4j8eDHjQ1dEJXwzFQknjtQ==",
      "license": "MIT",
      "dependencies": {
        "@vue/compiler-ssr": "3.5.30",
        "@vue/shared": "3.5.30"
      },
      "peerDependencies": {
        "vue": "3.5.30"
      }
    },
    "node_modules/@vue/shared": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.30.tgz",
      "integrity": "sha512-YXgQ7JjaO18NeK2K9VTbDHaFy62WrObMa6XERNfNOkAhD1F1oDSf3ZJ7K6GqabZ0BvSDHajp8qfS5Sa2I9n8uQ==",
      "license": "MIT"
    },
    "node_modules/alien-signals": {
      "version": "1.0.13",
      "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-1.0.13.tgz",
      "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==",
      "dev": true,
      "license": "MIT"
    },
    "node_modules/asynckit": {
      "version": "0.4.0",
      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
      "license": "MIT"
    },
    "node_modules/axios": {
      "version": "1.13.6",
      "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
      "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
      "license": "MIT",
      "dependencies": {
        "follow-redirects": "^1.15.11",
        "form-data": "^4.0.5",
        "proxy-from-env": "^1.1.0"
      }
    },
    "node_modules/balanced-match": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
      "dev": true,
      "license": "MIT"
    },
    "node_modules/bootstrap": {
      "version": "5.3.8",
      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz",
      "integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/twbs"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/bootstrap"
        }
      ],
      "license": "MIT",
      "peerDependencies": {
        "@popperjs/core": "^2.11.8"
      }
    },
    "node_modules/bootstrap-icons": {
      "version": "1.13.1",
      "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.13.1.tgz",
      "integrity": "sha512-ijombt4v6bv5CLeXvRWKy7CuM3TRTuPEuGaGKvTV5cz65rQSY8RQ2JcHt6b90cBBAC7s8fsf2EkQDldzCoXUjw==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/twbs"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/bootstrap"
        }
      ],
      "license": "MIT"
    },
    "node_modules/brace-expansion": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
      "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "balanced-match": "^1.0.0"
      }
    },
    "node_modules/call-bind-apply-helpers": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/combined-stream": {
      "version": "1.0.8",
      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
      "license": "MIT",
      "dependencies": {
        "delayed-stream": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/csstype": {
      "version": "3.2.3",
      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
      "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
      "license": "MIT"
    },
    "node_modules/de-indent": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
      "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
      "dev": true,
      "license": "MIT"
    },
    "node_modules/delayed-stream": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
      "license": "MIT",
      "engines": {
        "node": ">=0.4.0"
      }
    },
    "node_modules/dunder-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.1",
        "es-errors": "^1.3.0",
        "gopd": "^1.2.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/entities": {
      "version": "7.0.1",
      "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
      "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
      "license": "BSD-2-Clause",
      "engines": {
        "node": ">=0.12"
      },
      "funding": {
        "url": "https://github.com/fb55/entities?sponsor=1"
      }
    },
    "node_modules/es-define-property": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-errors": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-object-atoms": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-set-tostringtag": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.6",
        "has-tostringtag": "^1.0.2",
        "hasown": "^2.0.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/esbuild": {
      "version": "0.25.12",
      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
      "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
      "dev": true,
      "hasInstallScript": true,
      "license": "MIT",
      "bin": {
        "esbuild": "bin/esbuild"
      },
      "engines": {
        "node": ">=18"
      },
      "optionalDependencies": {
        "@esbuild/aix-ppc64": "0.25.12",
        "@esbuild/android-arm": "0.25.12",
        "@esbuild/android-arm64": "0.25.12",
        "@esbuild/android-x64": "0.25.12",
        "@esbuild/darwin-arm64": "0.25.12",
        "@esbuild/darwin-x64": "0.25.12",
        "@esbuild/freebsd-arm64": "0.25.12",
        "@esbuild/freebsd-x64": "0.25.12",
        "@esbuild/linux-arm": "0.25.12",
        "@esbuild/linux-arm64": "0.25.12",
        "@esbuild/linux-ia32": "0.25.12",
        "@esbuild/linux-loong64": "0.25.12",
        "@esbuild/linux-mips64el": "0.25.12",
        "@esbuild/linux-ppc64": "0.25.12",
        "@esbuild/linux-riscv64": "0.25.12",
        "@esbuild/linux-s390x": "0.25.12",
        "@esbuild/linux-x64": "0.25.12",
        "@esbuild/netbsd-arm64": "0.25.12",
        "@esbuild/netbsd-x64": "0.25.12",
        "@esbuild/openbsd-arm64": "0.25.12",
        "@esbuild/openbsd-x64": "0.25.12",
        "@esbuild/openharmony-arm64": "0.25.12",
        "@esbuild/sunos-x64": "0.25.12",
        "@esbuild/win32-arm64": "0.25.12",
        "@esbuild/win32-ia32": "0.25.12",
        "@esbuild/win32-x64": "0.25.12"
      }
    },
    "node_modules/estree-walker": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
      "license": "MIT"
    },
    "node_modules/fdir": {
      "version": "6.5.0",
      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
      "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=12.0.0"
      },
      "peerDependencies": {
        "picomatch": "^3 || ^4"
      },
      "peerDependenciesMeta": {
        "picomatch": {
          "optional": true
        }
      }
    },
    "node_modules/follow-redirects": {
      "version": "1.15.11",
      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
      "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
      "funding": [
        {
          "type": "individual",
          "url": "https://github.com/sponsors/RubenVerborgh"
        }
      ],
      "license": "MIT",
      "engines": {
        "node": ">=4.0"
      },
      "peerDependenciesMeta": {
        "debug": {
          "optional": true
        }
      }
    },
    "node_modules/form-data": {
      "version": "4.0.5",
      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
      "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
      "license": "MIT",
      "dependencies": {
        "asynckit": "^0.4.0",
        "combined-stream": "^1.0.8",
        "es-set-tostringtag": "^2.1.0",
        "hasown": "^2.0.2",
        "mime-types": "^2.1.12"
      },
      "engines": {
        "node": ">= 6"
      }
    },
    "node_modules/fsevents": {
      "version": "2.3.3",
      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
      "dev": true,
      "hasInstallScript": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
      }
    },
    "node_modules/function-bind": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-intrinsic": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "es-define-property": "^1.0.1",
        "es-errors": "^1.3.0",
        "es-object-atoms": "^1.1.1",
        "function-bind": "^1.1.2",
        "get-proto": "^1.0.1",
        "gopd": "^1.2.0",
        "has-symbols": "^1.1.0",
        "hasown": "^2.0.2",
        "math-intrinsics": "^1.1.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
      "license": "MIT",
      "dependencies": {
        "dunder-proto": "^1.0.1",
        "es-object-atoms": "^1.0.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/gopd": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/has-symbols": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/has-tostringtag": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
      "license": "MIT",
      "dependencies": {
        "has-symbols": "^1.0.3"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/hasown": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
      "license": "MIT",
      "dependencies": {
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/he": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
      "dev": true,
      "license": "MIT",
      "bin": {
        "he": "bin/he"
      }
    },
    "node_modules/magic-string": {
      "version": "0.30.21",
      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
      "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
      "license": "MIT",
      "dependencies": {
        "@jridgewell/sourcemap-codec": "^1.5.5"
      }
    },
    "node_modules/math-intrinsics": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/mime-db": {
      "version": "1.52.0",
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/mime-types": {
      "version": "2.1.35",
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
      "license": "MIT",
      "dependencies": {
        "mime-db": "1.52.0"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/minimatch": {
      "version": "9.0.9",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
      "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "brace-expansion": "^2.0.2"
      },
      "engines": {
        "node": ">=16 || 14 >=14.17"
      },
      "funding": {
        "url": "https://github.com/sponsors/isaacs"
      }
    },
    "node_modules/muggle-string": {
      "version": "0.4.1",
      "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
      "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
      "dev": true,
      "license": "MIT"
    },
    "node_modules/nanoid": {
      "version": "3.3.11",
      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/ai"
        }
      ],
      "license": "MIT",
      "bin": {
        "nanoid": "bin/nanoid.cjs"
      },
      "engines": {
        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
      }
    },
    "node_modules/path-browserify": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
      "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
      "dev": true,
      "license": "MIT"
    },
    "node_modules/picocolors": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
      "license": "ISC"
    },
    "node_modules/picomatch": {
      "version": "4.0.3",
      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
      "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=12"
      },
      "funding": {
        "url": "https://github.com/sponsors/jonschlinkert"
      }
    },
    "node_modules/pinia": {
      "version": "2.3.1",
      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz",
      "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
      "license": "MIT",
      "dependencies": {
        "@vue/devtools-api": "^6.6.3",
        "vue-demi": "^0.14.10"
      },
      "funding": {
        "url": "https://github.com/sponsors/posva"
      },
      "peerDependencies": {
        "typescript": ">=4.4.4",
        "vue": "^2.7.0 || ^3.5.11"
      },
      "peerDependenciesMeta": {
        "typescript": {
          "optional": true
        }
      }
    },
    "node_modules/postcss": {
      "version": "8.5.8",
      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
      "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
      "funding": [
        {
          "type": "opencollective",
          "url": "https://opencollective.com/postcss/"
        },
        {
          "type": "tidelift",
          "url": "https://tidelift.com/funding/github/npm/postcss"
        },
        {
          "type": "github",
          "url": "https://github.com/sponsors/ai"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "nanoid": "^3.3.11",
        "picocolors": "^1.1.1",
        "source-map-js": "^1.2.1"
      },
      "engines": {
        "node": "^10 || ^12 || >=14"
      }
    },
    "node_modules/proxy-from-env": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
      "license": "MIT"
    },
    "node_modules/rollup": {
      "version": "4.59.0",
      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
      "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/estree": "1.0.8"
      },
      "bin": {
        "rollup": "dist/bin/rollup"
      },
      "engines": {
        "node": ">=18.0.0",
        "npm": ">=8.0.0"
      },
      "optionalDependencies": {
        "@rollup/rollup-android-arm-eabi": "4.59.0",
        "@rollup/rollup-android-arm64": "4.59.0",
        "@rollup/rollup-darwin-arm64": "4.59.0",
        "@rollup/rollup-darwin-x64": "4.59.0",
        "@rollup/rollup-freebsd-arm64": "4.59.0",
        "@rollup/rollup-freebsd-x64": "4.59.0",
        "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
        "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
        "@rollup/rollup-linux-arm64-gnu": "4.59.0",
        "@rollup/rollup-linux-arm64-musl": "4.59.0",
        "@rollup/rollup-linux-loong64-gnu": "4.59.0",
        "@rollup/rollup-linux-loong64-musl": "4.59.0",
        "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
        "@rollup/rollup-linux-ppc64-musl": "4.59.0",
        "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
        "@rollup/rollup-linux-riscv64-musl": "4.59.0",
        "@rollup/rollup-linux-s390x-gnu": "4.59.0",
        "@rollup/rollup-linux-x64-gnu": "4.59.0",
        "@rollup/rollup-linux-x64-musl": "4.59.0",
        "@rollup/rollup-openbsd-x64": "4.59.0",
        "@rollup/rollup-openharmony-arm64": "4.59.0",
        "@rollup/rollup-win32-arm64-msvc": "4.59.0",
        "@rollup/rollup-win32-ia32-msvc": "4.59.0",
        "@rollup/rollup-win32-x64-gnu": "4.59.0",
        "@rollup/rollup-win32-x64-msvc": "4.59.0",
        "fsevents": "~2.3.2"
      }
    },
    "node_modules/source-map-js": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
      "license": "BSD-3-Clause",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/tinyglobby": {
      "version": "0.2.15",
      "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
      "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "fdir": "^6.5.0",
        "picomatch": "^4.0.3"
      },
      "engines": {
        "node": ">=12.0.0"
      },
      "funding": {
        "url": "https://github.com/sponsors/SuperchupuDev"
      }
    },
    "node_modules/typescript": {
      "version": "5.7.3",
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
      "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
      "devOptional": true,
      "license": "Apache-2.0",
      "bin": {
        "tsc": "bin/tsc",
        "tsserver": "bin/tsserver"
      },
      "engines": {
        "node": ">=14.17"
      }
    },
    "node_modules/vite": {
      "version": "6.4.1",
      "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
      "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "esbuild": "^0.25.0",
        "fdir": "^6.4.4",
        "picomatch": "^4.0.2",
        "postcss": "^8.5.3",
        "rollup": "^4.34.9",
        "tinyglobby": "^0.2.13"
      },
      "bin": {
        "vite": "bin/vite.js"
      },
      "engines": {
        "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
      },
      "funding": {
        "url": "https://github.com/vitejs/vite?sponsor=1"
      },
      "optionalDependencies": {
        "fsevents": "~2.3.3"
      },
      "peerDependencies": {
        "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
        "jiti": ">=1.21.0",
        "less": "*",
        "lightningcss": "^1.21.0",
        "sass": "*",
        "sass-embedded": "*",
        "stylus": "*",
        "sugarss": "*",
        "terser": "^5.16.0",
        "tsx": "^4.8.1",
        "yaml": "^2.4.2"
      },
      "peerDependenciesMeta": {
        "@types/node": {
          "optional": true
        },
        "jiti": {
          "optional": true
        },
        "less": {
          "optional": true
        },
        "lightningcss": {
          "optional": true
        },
        "sass": {
          "optional": true
        },
        "sass-embedded": {
          "optional": true
        },
        "stylus": {
          "optional": true
        },
        "sugarss": {
          "optional": true
        },
        "terser": {
          "optional": true
        },
        "tsx": {
          "optional": true
        },
        "yaml": {
          "optional": true
        }
      }
    },
    "node_modules/vscode-uri": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
      "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
      "dev": true,
      "license": "MIT"
    },
    "node_modules/vue": {
      "version": "3.5.30",
      "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.30.tgz",
      "integrity": "sha512-hTHLc6VNZyzzEH/l7PFGjpcTvUgiaPK5mdLkbjrTeWSRcEfxFrv56g/XckIYlE9ckuobsdwqd5mk2g1sBkMewg==",
      "license": "MIT",
      "dependencies": {
        "@vue/compiler-dom": "3.5.30",
        "@vue/compiler-sfc": "3.5.30",
        "@vue/runtime-dom": "3.5.30",
        "@vue/server-renderer": "3.5.30",
        "@vue/shared": "3.5.30"
      },
      "peerDependencies": {
        "typescript": "*"
      },
      "peerDependenciesMeta": {
        "typescript": {
          "optional": true
        }
      }
    },
    "node_modules/vue-demi": {
      "version": "0.14.10",
      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
      "hasInstallScript": true,
      "license": "MIT",
      "bin": {
        "vue-demi-fix": "bin/vue-demi-fix.js",
        "vue-demi-switch": "bin/vue-demi-switch.js"
      },
      "engines": {
        "node": ">=12"
      },
      "funding": {
        "url": "https://github.com/sponsors/antfu"
      },
      "peerDependencies": {
        "@vue/composition-api": "^1.0.0-rc.1",
        "vue": "^3.0.0-0 || ^2.6.0"
      },
      "peerDependenciesMeta": {
        "@vue/composition-api": {
          "optional": true
        }
      }
    },
    "node_modules/vue-router": {
      "version": "4.6.4",
      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz",
      "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
      "license": "MIT",
      "dependencies": {
        "@vue/devtools-api": "^6.6.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/posva"
      },
      "peerDependencies": {
        "vue": "^3.5.0"
      }
    },
    "node_modules/vue-tsc": {
      "version": "2.2.12",
      "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.12.tgz",
      "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@volar/typescript": "2.4.15",
        "@vue/language-core": "2.2.12"
      },
      "bin": {
        "vue-tsc": "bin/vue-tsc.js"
      },
      "peerDependencies": {
        "typescript": ">=5.0.0"
      }
    }
  }
}
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/package.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
{
  "name": "wideseawcs-s7simulator-web",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "vue": "^3.5.13",
    "vue-router": "^4.5.0",
    "pinia": "^2.3.0",
    "axios": "^1.7.9",
    "bootstrap": "^5.3.3",
    "bootstrap-icons": "^1.11.3"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.2.1",
    "typescript": "~5.7.2",
    "vite": "^6.0.11",
    "vue-tsc": "^2.2.0"
  }
}
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/App.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
<template>
  <div id="app">
    <nav class="navbar navbar-expand-sm navbar-dark bg-primary shadow-sm mb-4">
      <div class="container-fluid">
        <router-link class="navbar-brand" to="/">
          <i class="bi bi-cpu-fill me-2"></i>S7 PLC Simulator
        </router-link>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="navbar-collapse collapse">
          <ul class="navbar-nav flex-grow-1">
            <li class="nav-item">
              <router-link class="nav-link" to="/">
                <i class="bi bi-house-door me-1"></i>实例列表
              </router-link>
            </li>
          </ul>
        </div>
      </div>
    </nav>
    <div class="container-fluid px-4">
      <router-view />
    </div>
    <footer class="border-top py-3 mt-4 bg-light">
      <div class="container-fluid text-center text-muted">
        <small>&copy; 2026 - S7 PLC Simulator Management UI</small>
      </div>
    </footer>
  </div>
</template>
<script setup lang="ts">
</script>
<style>
#app {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.container-fluid {
  flex: 1;
}
.navbar-nav .nav-link.router-link-active {
  font-weight: bold;
}
</style>
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/api/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
import axios from 'axios'
import type {
  InstanceListItem,
  InstanceState,
  InstanceConfig
} from '../types'
const api = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
  headers: {
    'Content-Type': 'application/json'
  }
})
// èŽ·å–æ‰€æœ‰å®žä¾‹
export async function getAllInstances(): Promise<InstanceListItem[]> {
  const response = await api.get<InstanceListItem[]>('/SimulatorInstances')
  return response.data
}
// èŽ·å–æŒ‡å®šå®žä¾‹çŠ¶æ€
export async function getInstance(id: string): Promise<InstanceState | null> {
  try {
    const response = await api.get<InstanceState>(`/SimulatorInstances/${encodeURIComponent(id)}`)
    return response.data
  } catch (error) {
    if (axios.isAxiosError(error) && error.response?.status === 404) {
      return null
    }
    throw error
  }
}
// èŽ·å–å®žä¾‹é…ç½®
export async function getInstanceConfig(id: string): Promise<InstanceConfig | null> {
  try {
    const response = await api.get<InstanceConfig>(`/SimulatorInstances/${encodeURIComponent(id)}/config`)
    return response.data
  } catch (error) {
    if (axios.isAxiosError(error) && error.response?.status === 404) {
      return null
    }
    throw error
  }
}
// åˆ›å»ºå®žä¾‹
export async function createInstance(config: InstanceConfig): Promise<InstanceState | null> {
  try {
    const response = await api.post<InstanceState>('/SimulatorInstances', config)
    return response.data
  } catch (error) {
    console.error('创建实例失败:', error)
    return null
  }
}
// æ›´æ–°å®žä¾‹
export async function updateInstance(id: string, config: InstanceConfig): Promise<InstanceState | null> {
  try {
    const response = await api.put<InstanceState>(`/SimulatorInstances/${encodeURIComponent(id)}`, config)
    return response.data
  } catch (error) {
    console.error('更新实例失败:', error)
    return null
  }
}
// åˆ é™¤å®žä¾‹
export async function deleteInstance(id: string, deleteConfig: boolean = true): Promise<boolean> {
  try {
    await api.delete(`/SimulatorInstances/${encodeURIComponent(id)}?deleteConfig=${deleteConfig}`)
    return true
  } catch (error) {
    console.error('删除实例失败:', error)
    return false
  }
}
// å¯åŠ¨å®žä¾‹
export async function startInstance(id: string): Promise<InstanceState | null> {
  try {
    const response = await api.post<InstanceState>(`/SimulatorInstances/${encodeURIComponent(id)}/start`)
    return response.data
  } catch (error) {
    console.error('启动实例失败:', error)
    return null
  }
}
// åœæ­¢å®žä¾‹
export async function stopInstance(id: string): Promise<InstanceState | null> {
  try {
    const response = await api.post<InstanceState>(`/SimulatorInstances/${encodeURIComponent(id)}/stop`)
    return response.data
  } catch (error) {
    console.error('停止实例失败:', error)
    return null
  }
}
// é‡å¯å®žä¾‹
export async function restartInstance(id: string): Promise<InstanceState | null> {
  try {
    const response = await api.post<InstanceState>(`/SimulatorInstances/${encodeURIComponent(id)}/restart`)
    return response.data
  } catch (error) {
    console.error('重启实例失败:', error)
    return null
  }
}
export default api
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/main.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import './style.css'
// Bootstrap CSS
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap-icons/font/bootstrap-icons.css'
import 'bootstrap/dist/js/bootstrap.bundle.min.js'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/router/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'home',
    component: () => import('../views/HomeView.vue')
  },
  {
    path: '/create',
    name: 'create',
    component: () => import('../views/CreateView.vue')
  },
  {
    path: '/edit/:id',
    name: 'edit',
    component: () => import('../views/EditView.vue'),
    props: true
  },
  {
    path: '/details/:id',
    name: 'details',
    component: () => import('../views/DetailsView.vue'),
    props: true
  }
]
const router = createRouter({
  history: createWebHistory(),
  routes
})
export default router
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/stores/instances.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,119 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { InstanceListItem } from '../types'
import * as api from '../api'
export const useInstancesStore = defineStore('instances', () => {
  // çŠ¶æ€
  const instances = ref<InstanceListItem[]>([])
  const loading = ref(false)
  const error = ref<string | null>(null)
  const autoRefreshEnabled = ref(true)
  let refreshTimer: number | null = null
  // è®¡ç®—属性
  const runningCount = computed(() =>
    instances.value.filter(i => i.status === 'Running').length
  )
  const stoppedCount = computed(() =>
    instances.value.filter(i => i.status === 'Stopped').length
  )
  const errorCount = computed(() =>
    instances.value.filter(i => i.status === 'Error').length
  )
  // æ–¹æ³•
  async function loadInstances() {
    loading.value = true
    error.value = null
    try {
      instances.value = await api.getAllInstances()
    } catch (err) {
      error.value = '加载实例列表失败'
      console.error(err)
    } finally {
      loading.value = false
    }
  }
  async function startInstance(id: string) {
    try {
      await api.startInstance(id)
      await loadInstances()
    } catch (err) {
      console.error('启动实例失败:', err)
      throw err
    }
  }
  async function stopInstance(id: string) {
    try {
      await api.stopInstance(id)
      await loadInstances()
    } catch (err) {
      console.error('停止实例失败:', err)
      throw err
    }
  }
  async function deleteInstance(id: string) {
    try {
      await api.deleteInstance(id)
      await loadInstances()
    } catch (err) {
      console.error('删除实例失败:', err)
      throw err
    }
  }
  function startAutoRefresh(interval: number = 2000) {
    stopAutoRefresh()
    if (autoRefreshEnabled.value) {
      refreshTimer = window.setInterval(() => {
        loadInstances()
      }, interval)
    }
  }
  function stopAutoRefresh() {
    if (refreshTimer !== null) {
      clearInterval(refreshTimer)
      refreshTimer = null
    }
  }
  function setAutoRefreshEnabled(enabled: boolean) {
    autoRefreshEnabled.value = enabled
    if (!enabled) {
      stopAutoRefresh()
    }
  }
  // èŽ·å–å•ä¸ªå®žä¾‹
  function getInstance(id: string) {
    return instances.value.find(i => i.instanceId === id)
  }
  return {
    // çŠ¶æ€
    instances,
    loading,
    error,
    autoRefreshEnabled,
    // è®¡ç®—属性
    runningCount,
    stoppedCount,
    errorCount,
    // æ–¹æ³•
    loadInstances,
    startInstance,
    stopInstance,
    deleteInstance,
    startAutoRefresh,
    stopAutoRefresh,
    setAutoRefreshEnabled,
    getInstance
  }
})
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/style.css
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,87 @@
/* Global Styles */
:root {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
}
body {
  margin: 0;
  min-height: 100vh;
}
/* Status Colors */
.status-stopped {
  border-left: 4px solid #6c757d;
}
.status-starting {
  border-left: 4px solid #0dcaf0;
}
.status-running {
  border-left: 4px solid #198754;
}
.status-stopping {
  border-left: 4px solid #ffc107;
}
.status-error {
  border-left: 4px solid #dc3545;
}
/* Loading Spinner Overlay */
.spinner-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}
/* Spin icon animation */
.spin-icon {
  animation: spin 1s linear infinite;
}
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
/* Card hover effect */
.card {
  transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}
.card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
/* Custom scrollbar */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-track {
  background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
  background: #888;
  border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
  background: #555;
}
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/types/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,91 @@
// å®žä¾‹çŠ¶æ€æžšä¸¾
export enum InstanceStatus {
  Stopped = 'Stopped',
  Starting = 'Starting',
  Running = 'Running',
  Stopping = 'Stopping',
  Error = 'Error'
}
// PLC åž‹å·æžšä¸¾
export enum SiemensPLCType {
  S7200Smart = 'S7200Smart',
  S71200 = 'S71200',
  S71500 = 'S71500',
  S7300 = 'S7300',
  S7400 = 'S7400'
}
// å†…存区域配置
export interface MemoryRegionConfig {
  mRegionSize: number
  dBBBlockCount: number
  dBBBlockSize: number
  iRegionSize: number
  qRegionSize: number
  tRegionCount: number
  cRegionCount: number
}
// å®žä¾‹é…ç½®
export interface InstanceConfig {
  id: string
  name: string
  plcType: SiemensPLCType
  port: number
  activationKey: string
  autoStart: boolean
  memoryConfig: MemoryRegionConfig
}
// å®¢æˆ·ç«¯è¿žæŽ¥ä¿¡æ¯
export interface ClientConnection {
  endpoint: string
  connectTime: string
  lastActivityTime: string
}
// å®žä¾‹çŠ¶æ€
export interface InstanceState {
  instanceId: string
  name: string
  plcType: string
  port: number
  status: InstanceStatus
  clientCount: number
  totalRequests: number
  startTime: string | null
  lastActivityTime: string | null
  errorMessage: string | null
}
// å®žä¾‹åˆ—表项
export interface InstanceListItem {
  instanceId: string
  name: string
  plcType: string
  port: number
  status: string
  clientCount: number
  totalRequests: number
  startTime: string | null
  lastActivityTime: string | null
  errorMessage: string | null
}
// åˆ›å»ºå®žä¾‹è¾“å…¥
export interface CreateInstanceInput {
  id: string
  name: string
  plcType: SiemensPLCType
  port: number
  activationKey?: string
  autoStart: boolean
  mRegionSize: number
  dBBBlockCount: number
  dBBBlockSize: number
  iRegionSize: number
  qRegionSize: number
  tRegionCount: number
  cRegionCount: number
}
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/CreateView.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,275 @@
<template>
  <div>
    <div class="d-flex justify-content-between align-items-center mb-4">
      <div>
        <h2 class="mb-0">
          <i class="bi bi-plus-circle me-2"></i>创建实例
        </h2>
        <p class="text-muted mb-0 mt-1">创建新的 S7 PLC ä»¿çœŸå™¨å®žä¾‹</p>
      </div>
      <router-link to="/" class="btn btn-outline-secondary">
        <i class="bi bi-arrow-left me-1"></i>返回列表
      </router-link>
    </div>
    <div class="row justify-content-center">
      <div class="col-lg-8">
        <div class="card">
          <div class="card-body">
            <form @submit.prevent="handleSubmit">
              <!-- åŸºæœ¬ä¿¡æ¯ -->
              <h5 class="card-title mb-3">基本信息</h5>
              <div class="row mb-3">
                <div class="col-md-6">
                  <label for="id" class="form-label">实例ID *</label>
                  <input
                    type="text"
                    class="form-control"
                    id="id"
                    v-model="form.id"
                    pattern="[a-zA-Z0-9_-]+"
                    required
                    placeholder="例如: PLC_001"
                  >
                  <div class="form-text">只能包含字母、数字、下划线和连字符</div>
                </div>
                <div class="col-md-6">
                  <label for="name" class="form-label">实例名称 *</label>
                  <input
                    type="text"
                    class="form-control"
                    id="name"
                    v-model="form.name"
                    required
                    placeholder="例如: 1号PLC"
                  >
                </div>
              </div>
              <div class="row mb-3">
                <div class="col-md-6">
                  <label for="plcType" class="form-label">PLC型号 *</label>
                  <select class="form-select" id="plcType" v-model="form.plcType" required>
                    <option value="S7200Smart">S7-200 Smart</option>
                    <option value="S71200">S7-1200</option>
                    <option value="S71500">S7-1500</option>
                    <option value="S7300">S7-300</option>
                    <option value="S7400">S7-400</option>
                  </select>
                </div>
                <div class="col-md-6">
                  <label for="port" class="form-label">监听端口 *</label>
                  <input
                    type="number"
                    class="form-control"
                    id="port"
                    v-model.number="form.port"
                    min="1"
                    max="65535"
                    required
                    placeholder="102"
                  >
                </div>
              </div>
              <div class="row mb-3">
                <div class="col-md-6">
                  <label for="activationKey" class="form-label">HSL激活码</label>
                  <input
                    type="text"
                    class="form-control"
                    id="activationKey"
                    v-model="form.activationKey"
                    placeholder="可选,留空使用默认"
                  >
                </div>
                <div class="col-md-6 d-flex align-items-center">
                  <div class="form-check">
                    <input class="form-check-input" type="checkbox" id="autoStart" v-model="form.autoStart">
                    <label class="form-check-label" for="autoStart">
                      è‡ªåŠ¨å¯åŠ¨
                    </label>
                  </div>
                </div>
              </div>
              <!-- å†…存配置 -->
              <h5 class="card-title mb-3 mt-4">内存配置</h5>
              <div class="row mb-3">
                <div class="col-md-4">
                  <label for="mRegionSize" class="form-label">M区域大小</label>
                  <input
                    type="number"
                    class="form-control"
                    id="mRegionSize"
                    v-model.number="form.mRegionSize"
                    min="0"
                    placeholder="1024"
                  >
                </div>
                <div class="col-md-4">
                  <label for="iRegionSize" class="form-label">I区域大小</label>
                  <input
                    type="number"
                    class="form-control"
                    id="iRegionSize"
                    v-model.number="form.iRegionSize"
                    min="0"
                    placeholder="256"
                  >
                </div>
                <div class="col-md-4">
                  <label for="qRegionSize" class="form-label">Q区域大小</label>
                  <input
                    type="number"
                    class="form-control"
                    id="qRegionSize"
                    v-model.number="form.qRegionSize"
                    min="0"
                    placeholder="256"
                  >
                </div>
              </div>
              <div class="row mb-3">
                <div class="col-md-4">
                  <label for="dbBlockCount" class="form-label">DB块数量</label>
                  <input
                    type="number"
                    class="form-control"
                    id="dbBlockCount"
                    v-model.number="form.dbBlockCount"
                    min="0"
                    placeholder="100"
                  >
                </div>
                <div class="col-md-4">
                  <label for="dbBlockSize" class="form-label">DB块大小</label>
                  <input
                    type="number"
                    class="form-control"
                    id="dbBlockSize"
                    v-model.number="form.dbBlockSize"
                    min="0"
                    placeholder="1024"
                  >
                </div>
                <div class="col-md-2">
                  <label for="tRegionCount" class="form-label">定时器数量</label>
                  <input
                    type="number"
                    class="form-control"
                    id="tRegionCount"
                    v-model.number="form.tRegionCount"
                    min="0"
                    placeholder="64"
                  >
                </div>
                <div class="col-md-2">
                  <label for="cRegionCount" class="form-label">计数器数量</label>
                  <input
                    type="number"
                    class="form-control"
                    id="cRegionCount"
                    v-model.number="form.cRegionCount"
                    min="0"
                    placeholder="64"
                  >
                </div>
              </div>
              <!-- æäº¤æŒ‰é’® -->
              <div class="d-flex gap-2 mt-4">
                <button type="submit" class="btn btn-primary" :disabled="submitting">
                  <span v-if="submitting" class="spinner-border spinner-border-sm me-1"></span>
                  <i v-else class="bi bi-check-lg me-1"></i>
                  {{ submitting ? '创建中...' : '创建实例' }}
                </button>
                <router-link to="/" class="btn btn-outline-secondary">取消</router-link>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import * as api from '../api'
import type { InstanceConfig, MemoryRegionConfig, SiemensPLCType } from '../types'
const router = useRouter()
const form = ref({
  id: '',
  name: '',
  plcType: 'S71200' as SiemensPLCType,
  port: 102,
  activationKey: '',
  autoStart: false,
  mRegionSize: 1024,
  dbBlockCount: 100,
  dbBlockSize: 1024,
  iRegionSize: 256,
  qRegionSize: 256,
  tRegionCount: 64,
  cRegionCount: 64
})
const submitting = ref(false)
async function handleSubmit() {
  submitting.value = true
  try {
    const memoryConfig: MemoryRegionConfig = {
      mRegionSize: form.value.mRegionSize > 0 ? form.value.mRegionSize : 1024,
      dBBBlockCount: form.value.dbBlockCount > 0 ? form.value.dbBlockCount : 100,
      dBBBlockSize: form.value.dbBlockSize > 0 ? form.value.dbBlockSize : 1024,
      iRegionSize: form.value.iRegionSize > 0 ? form.value.iRegionSize : 256,
      qRegionSize: form.value.qRegionSize > 0 ? form.value.qRegionSize : 256,
      tRegionCount: form.value.tRegionCount > 0 ? form.value.tRegionCount : 64,
      cRegionCount: form.value.cRegionCount > 0 ? form.value.cRegionCount : 64
    }
    const config: InstanceConfig = {
      id: form.value.id,
      name: form.value.name,
      plcType: form.value.plcType,
      port: form.value.port,
      activationKey: form.value.activationKey || '',
      autoStart: form.value.autoStart,
      memoryConfig
    }
    const result = await api.createInstance(config)
    if (result) {
      alert(`实例 "${form.value.id}" åˆ›å»ºæˆåŠŸ!`)
      router.push('/')
    } else {
      alert('创建实例失败,请检查输入')
    }
  } catch (err) {
    console.error('创建实例失败:', err)
    alert('创建实例失败,请查看控制台')
  } finally {
    submitting.value = false
  }
}
</script>
<style scoped>
.card-title {
  color: #495057;
  font-weight: 600;
}
.form-label {
  font-weight: 500;
  color: #495057;
}
</style>
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/DetailsView.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,266 @@
<template>
  <div>
    <div v-if="loading" class="text-center py-5">
      <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">加载中...</span>
      </div>
    </div>
    <div v-else-if="errorMsg">
      <div class="alert alert-danger">{{ errorMsg }}</div>
      <router-link to="/" class="btn btn-primary">返回列表</router-link>
    </div>
    <div v-else-if="instance">
      <div class="d-flex justify-content-between align-items-center mb-4">
        <div>
          <h2 class="mb-0">
            <i class="bi bi-info-circle me-2"></i>实例详情
          </h2>
          <p class="text-muted mb-0 mt-1">{{ instance.name }} ({{ instance.instanceId }})</p>
        </div>
        <router-link to="/" class="btn btn-outline-secondary">
          <i class="bi bi-arrow-left me-1"></i>返回列表
        </router-link>
      </div>
      <!-- çŠ¶æ€å¡ç‰‡ -->
      <div class="row mb-4">
        <div class="col-md-3">
          <div class="card text-center">
            <div class="card-body">
              <h6 class="card-subtitle mb-2 text-muted">状态</h6>
              <h4 :class="['mb-0', getStatusClass(instance.status)]">
                {{ getStatusText(instance.status) }}
              </h4>
            </div>
          </div>
        </div>
        <div class="col-md-3">
          <div class="card text-center">
            <div class="card-body">
              <h6 class="card-subtitle mb-2 text-muted">连接客户端</h6>
              <h4 class="mb-0">
                <i class="bi bi-people-fill me-1"></i>{{ instance.clientCount }}
              </h4>
            </div>
          </div>
        </div>
        <div class="col-md-3">
          <div class="card text-center">
            <div class="card-body">
              <h6 class="card-subtitle mb-2 text-muted">总请求数</h6>
              <h4 class="mb-0">{{ instance.totalRequests }}</h4>
            </div>
          </div>
        </div>
        <div class="col-md-3">
          <div class="card text-center">
            <div class="card-body">
              <h6 class="card-subtitle mb-2 text-muted">端口</h6>
              <h4 class="mb-0">{{ instance.port }}</h4>
            </div>
          </div>
        </div>
      </div>
      <!-- è¯¦ç»†ä¿¡æ¯ -->
      <div class="card mb-4">
        <div class="card-header">
          <h5 class="mb-0">基本信息</h5>
        </div>
        <div class="card-body">
          <table class="table table-bordered">
            <tbody>
              <tr>
                <th style="width: 30%">实例ID</th>
                <td>{{ instance.instanceId }}</td>
              </tr>
              <tr>
                <th>实例名称</th>
                <td>{{ instance.name }}</td>
              </tr>
              <tr>
                <th>PLC型号</th>
                <td>{{ getPlcTypeText(instance.plcType) }}</td>
              </tr>
              <tr>
                <th>监听端口</th>
                <td>{{ instance.port }}</td>
              </tr>
              <tr v-if="instance.startTime">
                <th>启动时间</th>
                <td>{{ formatDate(instance.startTime) }}</td>
              </tr>
              <tr v-if="instance.lastActivityTime">
                <th>最后活动时间</th>
                <td>{{ formatDate(instance.lastActivityTime) }}</td>
              </tr>
              <tr v-if="instance.errorMessage">
                <th>错误信息</th>
                <td class="text-danger">{{ instance.errorMessage }}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <!-- æ“ä½œæŒ‰é’® -->
      <div class="card">
        <div class="card-body">
          <div class="d-flex gap-2">
            <button
              v-if="instance.status === 'Stopped' || instance.status === 'Error'"
              class="btn btn-success"
              @click="handleStart"
            >
              <i class="bi bi-play-fill me-1"></i>启动
            </button>
            <button
              v-if="instance.status === 'Running'"
              class="btn btn-warning"
              @click="handleStop"
            >
              <i class="bi bi-stop-fill me-1"></i>停止
            </button>
            <router-link :to="`/edit/${instance.instanceId}`" class="btn btn-primary">
              <i class="bi bi-pencil-fill me-1"></i>编辑
            </router-link>
            <router-link to="/" class="btn btn-outline-secondary">
              <i class="bi bi-arrow-left me-1"></i>返回列表
            </router-link>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { useRoute } from 'vue-router'
import * as api from '../api'
import type { InstanceState, InstanceStatus } from '../types'
const route = useRoute()
const instance = ref<InstanceState | null>(null)
const loading = ref(true)
const errorMsg = ref('')
let refreshTimer: number | null = null
const id = route.params.id as string
async function loadInstance() {
  try {
    instance.value = await api.getInstance(id)
    if (!instance.value) {
      errorMsg.value = `实例 "${id}" ä¸å­˜åœ¨`
    }
  } catch (err) {
    console.error('加载实例失败:', err)
    errorMsg.value = '加载实例失败,请查看控制台'
  } finally {
    loading.value = false
  }
}
onMounted(() => {
  loadInstance()
  // æ¯2秒刷新一次状态
  refreshTimer = window.setInterval(() => {
    if (instance.value && instance.value.status !== 'Stopped') {
      loadInstance()
    }
  }, 2000)
})
onUnmounted(() => {
  if (refreshTimer !== null) {
    clearInterval(refreshTimer)
  }
})
async function handleStart() {
  if (confirm(`确定要启动实例 "${id}" å—?`)) {
    try {
      await api.startInstance(id)
      await loadInstance()
    } catch (err) {
      console.error('启动实例失败:', err)
      alert('启动失败,请查看控制台')
    }
  }
}
async function handleStop() {
  if (confirm(`确定要停止实例 "${id}" å—?`)) {
    try {
      await api.stopInstance(id)
      await loadInstance()
    } catch (err) {
      console.error('停止实例失败:', err)
      alert('停止失败,请查看控制台')
    }
  }
}
function getStatusClass(status: InstanceStatus): string {
  const map: Record<InstanceStatus, string> = {
    'Stopped': 'text-secondary',
    'Starting': 'text-info',
    'Running': 'text-success',
    'Stopping': 'text-warning',
    'Error': 'text-danger'
  }
  return map[status] || ''
}
function getStatusText(status: InstanceStatus): string {
  const map: Record<InstanceStatus, string> = {
    'Stopped': '已停止',
    'Starting': '启动中',
    'Running': '运行中',
    'Stopping': '停止中',
    'Error': '错误'
  }
  return map[status] || status
}
function getPlcTypeText(plcType: string): string {
  const map: Record<string, string> = {
    'S7200Smart': 'S7-200 Smart',
    'S71200': 'S7-1200',
    'S71500': 'S7-1500',
    'S7300': 'S7-300',
    'S7400': 'S7-400'
  }
  return map[plcType] || plcType
}
function formatDate(dateString: string | null): string {
  if (!dateString) return '-'
  const date = new Date(dateString)
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  })
}
</script>
<style scoped>
.card-subtitle {
  font-size: 0.875rem;
  font-weight: 600;
}
table th {
  background-color: #f8f9fa;
  font-weight: 600;
}
</style>
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/EditView.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,330 @@
<template>
  <div>
    <div v-if="loading" class="text-center py-5">
      <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">加载中...</span>
      </div>
    </div>
    <div v-else-if="errorMsg">
      <div class="alert alert-danger">{{ errorMsg }}</div>
      <router-link to="/" class="btn btn-primary">返回列表</router-link>
    </div>
    <div v-else>
      <div class="d-flex justify-content-between align-items-center mb-4">
        <div>
          <h2 class="mb-0">
            <i class="bi bi-pencil me-2"></i>编辑实例
          </h2>
          <p class="text-muted mb-0 mt-1">编辑实例配置: {{ form.id }}</p>
        </div>
        <router-link to="/" class="btn btn-outline-secondary">
          <i class="bi bi-arrow-left me-1"></i>返回列表
        </router-link>
      </div>
      <div v-if="isRunning" class="alert alert-warning">
        <i class="bi bi-exclamation-triangle-fill me-2"></i>
        å®žä¾‹æ­£åœ¨è¿è¡Œä¸­ï¼Œä¿®æ”¹é…ç½®åŽéœ€è¦é‡å¯å®žä¾‹æ‰èƒ½ç”Ÿæ•ˆ
      </div>
      <div class="row justify-content-center">
        <div class="col-lg-8">
          <div class="card">
            <div class="card-body">
              <form @submit.prevent="handleSubmit">
                <!-- åŸºæœ¬ä¿¡æ¯ -->
                <h5 class="card-title mb-3">基本信息</h5>
                <div class="row mb-3">
                  <div class="col-md-6">
                    <label for="id" class="form-label">实例ID</label>
                    <input
                      type="text"
                      class="form-control"
                      id="id"
                      v-model="form.id"
                      disabled
                    >
                    <div class="form-text">实例ID创建后不可修改</div>
                  </div>
                  <div class="col-md-6">
                    <label for="name" class="form-label">实例名称 *</label>
                    <input
                      type="text"
                      class="form-control"
                      id="name"
                      v-model="form.name"
                      required
                    >
                  </div>
                </div>
                <div class="row mb-3">
                  <div class="col-md-6">
                    <label for="plcType" class="form-label">PLC型号 *</label>
                    <select class="form-select" id="plcType" v-model="form.plcType" required>
                      <option value="S7200Smart">S7-200 Smart</option>
                      <option value="S71200">S7-1200</option>
                      <option value="S71500">S7-1500</option>
                      <option value="S7300">S7-300</option>
                      <option value="S7400">S7-400</option>
                    </select>
                  </div>
                  <div class="col-md-6">
                    <label for="port" class="form-label">监听端口 *</label>
                    <input
                      type="number"
                      class="form-control"
                      id="port"
                      v-model.number="form.port"
                      min="1"
                      max="65535"
                      required
                    >
                  </div>
                </div>
                <div class="row mb-3">
                  <div class="col-md-6">
                    <label for="activationKey" class="form-label">HSL激活码</label>
                    <input
                      type="text"
                      class="form-control"
                      id="activationKey"
                      v-model="form.activationKey"
                    >
                  </div>
                  <div class="col-md-6 d-flex align-items-center">
                    <div class="form-check">
                      <input class="form-check-input" type="checkbox" id="autoStart" v-model="form.autoStart">
                      <label class="form-check-label" for="autoStart">
                        è‡ªåŠ¨å¯åŠ¨
                      </label>
                    </div>
                  </div>
                </div>
                <!-- å†…存配置 -->
                <h5 class="card-title mb-3 mt-4">内存配置</h5>
                <div class="row mb-3">
                  <div class="col-md-4">
                    <label for="mRegionSize" class="form-label">M区域大小</label>
                    <input
                      type="number"
                      class="form-control"
                      id="mRegionSize"
                      v-model.number="form.mRegionSize"
                      min="0"
                    >
                  </div>
                  <div class="col-md-4">
                    <label for="iRegionSize" class="form-label">I区域大小</label>
                    <input
                      type="number"
                      class="form-control"
                      id="iRegionSize"
                      v-model.number="form.iRegionSize"
                      min="0"
                    >
                  </div>
                  <div class="col-md-4">
                    <label for="qRegionSize" class="form-label">Q区域大小</label>
                    <input
                      type="number"
                      class="form-control"
                      id="qRegionSize"
                      v-model.number="form.qRegionSize"
                      min="0"
                    >
                  </div>
                </div>
                <div class="row mb-3">
                  <div class="col-md-4">
                    <label for="dbBlockCount" class="form-label">DB块数量</label>
                    <input
                      type="number"
                      class="form-control"
                      id="dbBlockCount"
                      v-model.number="form.dbBlockCount"
                      min="0"
                    >
                  </div>
                  <div class="col-md-4">
                    <label for="dbBlockSize" class="form-label">DB块大小</label>
                    <input
                      type="number"
                      class="form-control"
                      id="dbBlockSize"
                      v-model.number="form.dbBlockSize"
                      min="0"
                    >
                  </div>
                  <div class="col-md-2">
                    <label for="tRegionCount" class="form-label">定时器数量</label>
                    <input
                      type="number"
                      class="form-control"
                      id="tRegionCount"
                      v-model.number="form.tRegionCount"
                      min="0"
                    >
                  </div>
                  <div class="col-md-2">
                    <label for="cRegionCount" class="form-label">计数器数量</label>
                    <input
                      type="number"
                      class="form-control"
                      id="cRegionCount"
                      v-model.number="form.cRegionCount"
                      min="0"
                    >
                  </div>
                </div>
                <!-- æäº¤æŒ‰é’® -->
                <div class="d-flex gap-2 mt-4">
                  <button type="submit" class="btn btn-primary" :disabled="submitting">
                    <span v-if="submitting" class="spinner-border spinner-border-sm me-1"></span>
                    <i v-else class="bi bi-check-lg me-1"></i>
                    {{ submitting ? '保存中...' : '保存更改' }}
                  </button>
                  <router-link to="/" class="btn btn-outline-secondary">取消</router-link>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import * as api from '../api'
import type { InstanceConfig, MemoryRegionConfig, SiemensPLCType } from '../types'
const router = useRouter()
const route = useRoute()
const form = ref({
  id: '',
  name: '',
  plcType: 'S71200' as SiemensPLCType,
  port: 102,
  activationKey: '',
  autoStart: false,
  mRegionSize: 1024,
  dbBlockCount: 100,
  dbBlockSize: 1024,
  iRegionSize: 256,
  qRegionSize: 256,
  tRegionCount: 64,
  cRegionCount: 64
})
const loading = ref(true)
const errorMsg = ref('')
const submitting = ref(false)
const isRunning = ref(false)
const id = route.params.id as string
onMounted(async () => {
  try {
    // èŽ·å–å®žä¾‹çŠ¶æ€
    const state = await api.getInstance(id)
    if (!state) {
      errorMsg.value = `实例 "${id}" ä¸å­˜åœ¨`
      loading.value = false
      return
    }
    isRunning.value = state.status === 'Running'
    // èŽ·å–å®žä¾‹é…ç½®
    const config = await api.getInstanceConfig(id)
    if (!config) {
      errorMsg.value = `无法加载实例 "${id}" çš„配置`
      loading.value = false
      return
    }
    form.value = {
      id: config.id,
      name: config.name,
      plcType: config.plcType,
      port: config.port,
      activationKey: config.activationKey,
      autoStart: config.autoStart,
      mRegionSize: config.memoryConfig.mRegionSize,
      dbBlockCount: config.memoryConfig.dBBBlockCount,
      dbBlockSize: config.memoryConfig.dBBBlockSize,
      iRegionSize: config.memoryConfig.iRegionSize,
      qRegionSize: config.memoryConfig.qRegionSize,
      tRegionCount: config.memoryConfig.tRegionCount,
      cRegionCount: config.memoryConfig.cRegionCount
    }
  } catch (err) {
    console.error('加载实例配置失败:', err)
    errorMsg.value = '加载实例配置失败,请查看控制台'
  } finally {
    loading.value = false
  }
})
async function handleSubmit() {
  submitting.value = true
  try {
    const memoryConfig: MemoryRegionConfig = {
      mRegionSize: form.value.mRegionSize > 0 ? form.value.mRegionSize : 1024,
      dBBBlockCount: form.value.dbBlockCount > 0 ? form.value.dbBlockCount : 100,
      dBBBlockSize: form.value.dbBlockSize > 0 ? form.value.dbBlockSize : 1024,
      iRegionSize: form.value.iRegionSize > 0 ? form.value.iRegionSize : 256,
      qRegionSize: form.value.qRegionSize > 0 ? form.value.qRegionSize : 256,
      tRegionCount: form.value.tRegionCount > 0 ? form.value.tRegionCount : 64,
      cRegionCount: form.value.cRegionCount > 0 ? form.value.cRegionCount : 64
    }
    const config: InstanceConfig = {
      id: form.value.id,
      name: form.value.name,
      plcType: form.value.plcType,
      port: form.value.port,
      activationKey: form.value.activationKey,
      autoStart: form.value.autoStart,
      memoryConfig
    }
    const result = await api.updateInstance(form.value.id, config)
    if (result) {
      alert(`实例 "${form.value.id}" æ›´æ–°æˆåŠŸ!`)
      router.push('/')
    } else {
      alert('更新实例失败')
    }
  } catch (err) {
    console.error('更新实例失败:', err)
    alert('更新实例失败,请查看控制台')
  } finally {
    submitting.value = false
  }
}
</script>
<style scoped>
.card-title {
  color: #495057;
  font-weight: 600;
}
.form-label {
  font-weight: 500;
  color: #495057;
}
</style>
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/views/HomeView.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,251 @@
<template>
  <div>
    <div class="d-flex justify-content-between align-items-center mb-4">
      <div>
        <h2 class="mb-0">
          <i class="bi bi-cpu-fill me-2"></i>S7 PLC ä»¿çœŸå™¨å®žä¾‹
        </h2>
        <p class="text-muted mb-0 mt-1">管理和监控 S7 PLC ä»¿çœŸå™¨å®žä¾‹</p>
      </div>
      <div class="d-flex align-items-center gap-3">
        <div class="text-muted small">
          è¿è¡Œä¸­: {{ runningCount }} | å·²åœæ­¢: {{ stoppedCount }}
          <span v-if="errorCount > 0" class="text-danger">| é”™è¯¯: {{ errorCount }}</span>
        </div>
        <router-link to="/create" class="btn btn-primary">
          <i class="bi bi-plus-lg me-1"></i>创建实例
        </router-link>
      </div>
    </div>
    <!-- Loading state -->
    <div v-if="loading && instances.length === 0" class="text-center py-5">
      <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">加载中...</span>
      </div>
      <p class="mt-3 text-muted">正在加载实例列表...</p>
    </div>
    <!-- Empty state -->
    <div v-else-if="instances.length === 0" class="empty-state">
      <i class="bi bi-inbox"></i>
      <h3>暂无实例</h3>
      <p>点击上方"创建实例"按钮来创建您的第一个仿真器实例</p>
    </div>
    <!-- Instances grid -->
    <div v-else class="row row-cols-1 row-cols-md-2 row-cols-xl-3 g-4">
      <div v-for="instance in instances" :key="instance.instanceId" class="col">
        <div :class="['card', 'instance-card', 'h-100', getStatusClass(instance.status)]">
          <div class="card-header d-flex justify-content-between align-items-center">
            <h5 class="card-title mb-0">{{ instance.instanceId }}</h5>
            <span :class="['badge', getStatusClass(instance.status)]">
              {{ getStatusText(instance.status) }}
            </span>
          </div>
          <div class="card-body">
            <div class="instance-info mb-3">
              <div class="row mb-2">
                <div class="col-6">
                  <small class="instance-info-label">名称</small>
                  <div class="instance-info-value">{{ instance.name || '-' }}</div>
                </div>
                <div class="col-6">
                  <small class="instance-info-label">PLC型号</small>
                  <div class="instance-info-value">{{ getPlcTypeText(instance.plcType) }}</div>
                </div>
              </div>
              <div class="row mb-2">
                <div class="col-6">
                  <small class="instance-info-label">端口</small>
                  <div class="instance-info-value">{{ instance.port || '-' }}</div>
                </div>
                <div class="col-6">
                  <small class="instance-info-label">客户端</small>
                  <div class="instance-info-value">
                    <i class="bi bi-people-fill me-1"></i>{{ instance.clientCount || 0 }}
                  </div>
                </div>
              </div>
              <div v-if="instance.startTime" class="row">
                <div class="col-12">
                  <small class="instance-info-label">启动时间</small>
                  <div class="instance-info-value small">{{ formatDate(instance.startTime) }}</div>
                </div>
              </div>
              <div v-if="instance.errorMessage" class="alert alert-danger alert-sm mt-2 mb-0 py-2 small">
                <i class="bi bi-exclamation-triangle-fill me-1"></i>{{ instance.errorMessage }}
              </div>
            </div>
          </div>
          <div class="card-footer bg-white">
            <div class="action-buttons d-flex gap-2">
              <button
                v-if="instance.status === 'Running'"
                class="btn btn-warning btn-sm flex-fill"
                @click="handleStop(instance.instanceId)"
              >
                <i class="bi bi-stop-fill me-1"></i>停止
              </button>
              <button
                v-if="instance.status === 'Stopped'"
                class="btn btn-success btn-sm flex-fill"
                @click="handleStart(instance.instanceId)"
              >
                <i class="bi bi-play-fill me-1"></i>启动
              </button>
              <router-link :to="`/details/${instance.instanceId}`" class="btn btn-info btn-sm text-white flex-fill">
                <i class="bi bi-info-circle-fill me-1"></i>详情
              </router-link>
              <router-link :to="`/edit/${instance.instanceId}`" class="btn btn-primary btn-sm flex-fill">
                <i class="bi bi-pencil-fill me-1"></i>编辑
              </router-link>
              <button class="btn btn-danger btn-sm" @click="handleDelete(instance.instanceId)">
                <i class="bi bi-trash-fill"></i>
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue'
import { storeToRefs } from 'pinia'
import { useInstancesStore } from '../stores/instances'
const store = useInstancesStore()
const { instances, loading, runningCount, stoppedCount, errorCount } = storeToRefs(store)
onMounted(() => {
  store.loadInstances()
  store.startAutoRefresh(2000)
})
onUnmounted(() => {
  store.stopAutoRefresh()
})
function handleStart(id: string) {
  if (confirm(`确定要启动实例 "${id}" å—?`)) {
    store.startInstance(id).catch(() => {
      alert('启动失败,请查看控制台')
    })
  }
}
function handleStop(id: string) {
  if (confirm(`确定要停止实例 "${id}" å—?`)) {
    store.stopInstance(id).catch(() => {
      alert('停止失败,请查看控制台')
    })
  }
}
function handleDelete(id: string) {
  if (confirm(`确定要删除实例 "${id}" å—?此操作不可撤销!`)) {
    store.deleteInstance(id).catch(() => {
      alert('删除失败,请查看控制台')
    })
  }
}
function getStatusClass(status: string): string {
  const map: Record<string, string> = {
    'Stopped': 'status-stopped',
    'Starting': 'status-starting',
    'Running': 'status-running',
    'Stopping': 'status-stopping',
    'Error': 'status-error'
  }
  return map[status] || ''
}
function getStatusText(status: string): string {
  const map: Record<string, string> = {
    'Stopped': '已停止',
    'Starting': '启动中',
    'Running': '运行中',
    'Stopping': '停止中',
    'Error': '错误'
  }
  return map[status] || status
}
function getPlcTypeText(plcType: string): string {
  const map: Record<string, string> = {
    'S7200Smart': 'S7-200 Smart',
    'S71200': 'S7-1200',
    'S71500': 'S7-1500',
    'S7300': 'S7-300',
    'S7400': 'S7-400'
  }
  return map[plcType] || plcType
}
function formatDate(dateString: string | null): string {
  if (!dateString) return '-'
  const date = new Date(dateString)
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  })
}
</script>
<style scoped>
.instance-card {
  transition: transform 0.2s, box-shadow 0.2s;
}
.instance-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.instance-info-label {
  color: #6c757d;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.instance-info-value {
  font-weight: 500;
}
.action-buttons {
  flex-wrap: wrap;
}
.status-stopped { border-left: 4px solid #6c757d; }
.status-starting { border-left: 4px solid #0dcaf0; }
.status-running { border-left: 4px solid #198754; }
.status-stopping { border-left: 4px solid #ffc107; }
.status-error { border-left: 4px solid #dc3545; }
.empty-state {
  text-align: center;
  padding: 4rem 2rem;
  color: #6c757d;
}
.empty-state i {
  font-size: 4rem;
  margin-bottom: 1rem;
}
.empty-state h3 {
  margin-bottom: 0.5rem;
}
.alert-sm {
  font-size: 0.875rem;
}
</style>
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/src/vite-env.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
/// <reference types="vite/client" />
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/tsconfig.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/tsconfig.node.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
{
  "compilerOptions": {
    "composite": true,
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/vite.config.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
  plugins: [vue()],
  server: {
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:5000',
        changeOrigin: true
      }
    }
  }
})
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/css/site.css
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/favicon.ico
Binary files differ
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/js/site.js
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/bootstrap/LICENSE
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery-validation/LICENSE.md
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Web/wwwroot/lib/jquery/LICENSE.txt
ÎļþÒÑɾ³ý